Nevertheless, we intend to use Jest for large scale problems. To improve Jest's performance, we implement computationally intensive routines in C and link them with Jest objects. Java's native method mechanism easily facilitates the linking of C and Java routines. A Java program that invokes a C routine remains platform-independent if the method invocation is programmed to default to the Java version, when a native version is unavailable.
Typically, a Jest programmer prototypes and tests his program in an all-Java version. If the performance is insufficient, the programmer can profile the application and decide which part of the code to replace by a native method. We expect that straightforward numerical code, such as a convolution kernel, might need to be translated from Java to C, while algorithmically complex code, such as a solver, will not.
Alternatively, Jacob and Karrenbach 1997 report a performance comparable to Fortran when they combine Jest, a specialized compiler (JavaParty), and parallel computers in the optimization of a a large-scale geophysical inversion problem. Unfortunately, to yield that performance, their compiler required a non-standard class modifier regarding the distribution of parallelized objects.
Besides better performance, I wish Java contained a primitive type for complex numbers and the ability to overload the array index operator []. For the same reasons that Java offers float and double primitive types, it should include a complex-number primitive type: (1) a complex-number primitive is important in many applications, (2) a class implementation incurs unacceptable inefficiencies, and (3) only a primitive type offers the concise and intuitive arithmetic operators, such as `+'. Alternatively, a complex number can be simply represented by two floats. However, the lack of a single complex-number type and its associated methods is error-prone, tedious, and not object-oriented.
For example, the methods below compute one root of the quadratic equation a x2 + b x + c = 0. The concise first method does not exist in Java, since it uses a complex primitive type. The second method computes the same root but uses a user-defined complex class: It unfortunately obfuscates the simple, original mathematical operation.
Desired method:
static Complex root(Complex a, Complex b, Complex c) {
return (b - Complex.sqrt(b*b - 4*a*c)) / (2*a) ;
Available method:
static Complex root(Complex a, Complex b, Complex c) {
Complex b2 = Complex.multiply(b,b);
Complex ac4 = Complex.multiply(4,Complex.multiply(a,c));
Complex discrim = Complex.sqrt(Complex.subtract(b2,ac4));
return Complex.divide(Complex.subtract(discrim,b)),
Complex.multiply(2,a))); }
Without a primitive type for complex numbers, we must choose between an encapsulating complex-number class or an error-prone representation by a pair of floats. We partially side-stepped this difficulty by implementing a class for an array of complex numbers. Such an array justifies the class overhead, which was prohibitive for a single complex number, and simultaneously hides the representation of a complex number as a pair of floats. However, using individual complex numbers remains inefficient or tedious unless Java adds a complex-number primitive type.
I wish the [] indexing operator could be overloaded in Java. Again, a multi-dimensional array is a fundamental structure in science and engineering applications. Internally the array might be stored as a Java array, a Java vector, or a huge out-of-core data file. Independent of the internal structure, applications need to index the array elements with a general indexing operation. Only the [] indexing operator offers the conciseness that matches the operation's simplicity. Since Java generally does not permit overloading operators, only classes with an internal Java array representation can offer the desired [] indexing operator.
For example, the program fragments approximate the second derivative of a one-dimensional array. The first formulation with its natural index expressions is only available if the array is implemented as a native Java array. If the array is a user-defined array (e.g., an out-of-core, a complex number array) or a Java vector, Java's inability to overload the index operator leads to the verbose formulation of the second program fragment.
Desired method:
float x[] = new float[10]; // only native Java arrays
float y[] = new float[10];
...
y[i] = (-x[i+1] + 2*x[i] - x[i-1]) / 4.0;
Available method:
Myarray x = new Myarray(10); // using Java's Vector
Myarray y = new Myarray(10); // or complex array class
...
y.setElement(i,(- x.ElementAt(i+1)
+ x.ElementAt(i )
- x.ElementAt(i-1)) / 4.0);
In our applications, we could not forego the conciseness and simplicity of the array index expression and consequently had to pierce the encapsulation of our array-like vector classes to ensure access by index for operators. Therefore, the array-like Rsf vector and its operators are more closely linked than I wish. Additionally, our classes offer function calls to access individual array elements. However, I find such calls unintuitive, especially when the arguments include index and element values (f.setDatum(3,3.f)). I was not able to devise a general solution based on enumerations. In summary, I do not know how to write application classes with concise, but general, indexing operators for array-type data implemented by structures other than the original Java array.
I believe Java's future in science and engineering will be greatly enhanced if those two shortcomings - a primitive complex-number type and overloading the index operator - were redressed. Java designers should not underestimate the importance of science and engineering as sources of innovation and education.