I'm learning the Processing 4 programming app along with Java, which it uses. I have created a sketch and now want to add a library I downloaded, name Jama, to solve a system of linear equations. According to the Processing help, I need to create a directory named libraries in the sketch folder and put the library there, which I did. However, when I try and import it (import Jama.*), the app complains that it can't find it. As downloaded, the Jama package includes .java and .class files for each class. Is there something more I need to do to make this library available?
For the Contribution Manager (Add Library..." from the "Import Library..." submen) to work with the Jama library, it needs to be wrapped as a Processing library ideally.
If you simply want to use the library in a test sketch you can do so without wrapping Jama as a Processing library:
You should be able to test importing the library and running the sketch (e.g. import Jama.*;
).
Here is the Jama example as a Processing sketch:
import Jama.*;
import java.util.Date;
/*
| Tests LU, QR, SVD and symmetric Eig decompositions.
|
| n = order of magic square.
| trace = diagonal sum, should be the magic sum, (n^3 + n)/2.
| max_eig = maximum eigenvalue of (A + A')/2, should equal trace.
| rank = linear algebraic rank,
| should equal n if n is odd, be less than n if n is even.
| cond = L_2 condition number, ratio of singular values.
| lu_res = test of LU factorization, norm1(L*U-A(p,:))/(n*eps).
| qr_res = test of QR factorization, norm1(Q*R-A)/(n*eps).
*/
void setup(){
print("\n Test of Matrix Class, using magic squares.\n");
println("Test");
print(" See MagicSquareExample.main() for an explanation.\n");
print("\n n trace max_eig rank cond lu_res qr_res\n\n");
Date start_time = new Date();
double eps = Math.pow(2.0,-52.0);
for (int n = 3; n <= 32; n++) {
print(fixedWidthIntegertoString(n,7));
Matrix M = magic(n);
int t = (int) M.trace();
print(fixedWidthIntegertoString(t,10));
EigenvalueDecomposition E =
new EigenvalueDecomposition(M.plus(M.transpose()).times(0.5));
double[] d = E.getRealEigenvalues();
print(fixedWidthDoubletoString(d[n-1],14,3));
int r = M.rank();
print(fixedWidthIntegertoString(r,7));
double c = M.cond();
print(c < 1/eps ? fixedWidthDoubletoString(c,12,3) :
" Inf");
LUDecomposition LU = new LUDecomposition(M);
Matrix L = LU.getL();
Matrix U = LU.getU();
int[] p = LU.getPivot();
Matrix R = L.times(U).minus(M.getMatrix(p,0,n-1));
double res = R.norm1()/(n*eps);
print(fixedWidthDoubletoString(res,12,3));
QRDecomposition QR = new QRDecomposition(M);
Matrix Q = QR.getQ();
R = QR.getR();
R = Q.times(R).minus(M);
res = R.norm1()/(n*eps);
print(fixedWidthDoubletoString(res,12,3));
print("\n");
}
Date stop_time = new Date();
double etime = (stop_time.getTime() - start_time.getTime())/1000.;
print("\nElapsed Time = " +
fixedWidthDoubletoString(etime,12,3) + " seconds\n");
print("Adios\n");
}
Matrix magic (int n) {
double[][] M = new double[n][n];
// Odd order
if ((n % 2) == 1) {
int a = (n+1)/2;
int b = (n+1);
for (int j = 0; j < n; j++) {
for (int i = 0; i < n; i++) {
M[i][j] = n*((i+j+a) % n) + ((i+2*j+b) % n) + 1;
}
}
// Doubly Even Order
} else if ((n % 4) == 0) {
for (int j = 0; j < n; j++) {
for (int i = 0; i < n; i++) {
if (((i+1)/2)%2 == ((j+1)/2)%2) {
M[i][j] = n*n-n*i-j;
} else {
M[i][j] = n*i+j+1;
}
}
}
// Singly Even Order
} else {
int p = n/2;
int k = (n-2)/4;
Matrix A = magic(p);
for (int j = 0; j < p; j++) {
for (int i = 0; i < p; i++) {
double aij = A.get(i,j);
M[i][j] = aij;
M[i][j+p] = aij + 2*p*p;
M[i+p][j] = aij + 3*p*p;
M[i+p][j+p] = aij + p*p;
}
}
for (int i = 0; i < p; i++) {
for (int j = 0; j < k; j++) {
double t = M[i][j]; M[i][j] = M[i+p][j]; M[i+p][j] = t;
}
for (int j = n-k+1; j < n; j++) {
double t = M[i][j]; M[i][j] = M[i+p][j]; M[i+p][j] = t;
}
}
double t = M[k][0]; M[k][0] = M[k+p][0]; M[k+p][0] = t;
t = M[k][k]; M[k][k] = M[k+p][k]; M[k+p][k] = t;
}
return new Matrix(M);
}
String fixedWidthDoubletoString (double x, int w, int d) {
java.text.DecimalFormat fmt = new java.text.DecimalFormat();
fmt.setMaximumFractionDigits(d);
fmt.setMinimumFractionDigits(d);
fmt.setGroupingUsed(false);
String s = fmt.format(x);
while (s.length() < w) {
s = " " + s;
}
return s;
}
String fixedWidthIntegertoString (int n, int w) {
String s = Integer.toString(n);
while (s.length() < w) {
s = " " + s;
}
return s;
}
Output:
Test of Matrix Class, using magic squares.
Test
See MagicSquareExample.main() for an explanation.
n trace max_eig rank cond lu_res qr_res
3 15 15.000 3 4.330 0.000 11.333
4 34 34.000 3 Inf 0.000 13.500
5 65 65.000 5 5.462 0.000 14.400
6 111 111.000 5 Inf 5.333 16.000
7 175 175.000 7 7.111 2.286 37.714
8 260 260.000 3 Inf 0.000 59.000
9 369 369.000 9 9.102 7.111 53.333
10 505 505.000 7 Inf 3.200 159.200
11 671 671.000 11 11.102 2.909 215.273
12 870 870.000 3 Inf 0.000 185.333
13 1105 1105.000 13 13.060 4.923 313.846
14 1379 1379.000 9 Inf 4.571 540.571
15 1695 1695.000 15 15.062 4.267 242.133
16 2056 2056.000 3 Inf 0.000 488.500
17 2465 2465.000 17 17.042 7.529 267.294
18 2925 2925.000 11 Inf 7.111 520.889
19 3439 3439.000 19 19.048 16.842 387.368
20 4010 4010.000 3 Inf 14.400 584.800
21 4641 4641.000 21 21.035 6.095 1158.095
22 5335 5335.000 13 Inf 6.545 1132.364
23 6095 6095.000 23 23.037 11.130 1268.870
24 6924 6924.000 3 Inf 10.667 827.500
25 7825 7825.000 25 25.029 35.840 1190.400
26 8801 8801.000 15 Inf 4.923 1859.077
27 9855 9855.000 27 27.032 37.926 1365.333
28 10990 10990.000 3 Inf 34.286 1365.714
29 12209 12209.000 29 29.025 30.897 1647.448
30 13515 13515.000 17 Inf 8.533 2571.733
31 14911 14911.000 31 31.027 33.032 1426.581
32 16400 16400.000 3 Inf 0.000 1600.125
Elapsed Time = 0.046 seconds
Adios
If you don't want to keep copying the Jama-1.0.3.jar file into every new sketch, you can try this:
Documents/Processing/libraries/Jama/library
Documents/Processing/libraries/Jama/library
Once you restart Processing you should be able to import Jama.*;
from any new sketch.
Note that if you switch computers/want to work collaborately you need to share the Jama/library
so it can be placed in Documents/Processing/libraries
.
With a tiny bit of extra effort it won't be complicated to wrap as a Processing library and share with community (so your future self and others can find it in the Contribution Manager). This is also an opportunity to add wrapper functions to simplify syntax as needed (e.g. override methods to work with floats where needed, utilities to plot/draw results, etc.)