smooth-spiral

Is calling Java from Scala as easy as it seems? (part 1)

on May 19, 16 • by Ed Stewart • with No Comments

As a Java developer exploring Scala, I am relating what I found when trying to learn this language through calling a familiar Java library (JMSL)...

Home » Analytics and Data Mining » Is calling Java from Scala as easy as it seems? (part 1)

The JMSL Numerical Library, a pure Java implementation of the IMSL algorithms, is used easily in environments that utilize Java code. Scala is a prime example of such cross-language functionality. Each language has its own traits and idiosyncrasies, especially for users new to the language. As a Java developer exploring Scala, I am relating what I found when trying to learn this language through calling a familiar Java library.

Scala fundamentals

Anyone reading this is likely savvy enough to find, install and configure Scala on their own. For the examples shown here, I’m using CentOS 6 in a virtual machine. The only trickiness at all encountered during configuration is that my favorite Linux editor gedit does not recognize .scala files out of the box. While it’s certainly possible to write code without syntax highlighting, why would you? I packed up my vi shortcut muscle memory long ago. Adding syntax highlighting for a new language just requires a definition file, which is easy to install. You can find a README along with the scala.lang file here.

Scala is designed to work smoothly with Java and Java libraries like JMSL. This is clearly evident in how Scala picks up the same CLASSPATH environment variable Java uses, so if the Java library you wish to use is already there in the CLASSPATH, then you’re good to go. The CLASSPATH can also be configured at compile-time and run-time through switches, again very similar to Java. Scala also uses import statements to simplify writing and reading code so the full class name isn’t required. The syntax is very similar with a key difference being the ability to use a comma-separated of classes used in the same package. While Java allows you to import all classes from a package with import com.imsl.math.* or individual classes, Scala allows writing import com.imsl.math.{PrintMatrix, LU} for example to import just two classes from the package. Each of the examples below use classes from the com.imsl.math package of the JMSL library. For brevity, the import statements, object definition and main method definition are not repeated after the first example.

JMSL basics

Java static method calls are generally the best place to start when looking at cross-language functionality because they require no object to be created. The JMSL library has numerous static methods, most with a method signature that requires passing one or more values. The method then computes an answer and returns it, often as a double precision value or array. Scala is designed to be more object-oriented, with singleton objects rather than mimicking the procedural tricks of C++ and Java, but thankfully this does not prevent Java static methods from being referenced easily. With many to choose from, I picked one of the “special function” calculations to compute the error function, erf, and the complete Scala code is presented below:

import com.imsl.math.Sfun

object HelloJmsl {
	def main(args: Array[String]): Unit = {
		/* easy case of static method */
		val erf = Sfun.erf(0.5)
		println("erf(0.5) = " + erf)
	}
}

This example is contained in a source file named HelloJmsl.scala, which is compiled with the command scalac HelloJmsl.scala and executed with scala HelloJmsl (again, all very similar to Java). These commands and the output are shown below:

[~/dev/scala]% scalac HelloJmsl.scala
[~/dev/scala]% scala HelloJmsl
erf(0.5) = 0.5204998778130465

Instantiating a class is not much more complex. For this example, I want to solve the polynomial equation 5x2 + 2x + 1= 0 for x. As a second-order polynomial, there will be two roots, which may be complex numbers. The JMSL ZeroPolynomial class is used, which will return an array of complex numbers; the Complex class includes its own toString() method allowing printing of the results. The code and result are shown below, without the surrounding import, object and main method as mentioned above:

 	val zp = new ZeroPolynomial
	val coef = Array(1.0, 2.0, 5.0)
	val roots = zp.computeRoots(coef)
	println("x_1 = " + roots(0))
	println("x_2 = " + roots(1))

x_1 = -0.20000000000000004+0.39999999999999997i
x_2 = -0.2-0.4i

Using the quadratic formula, one can easily verify the roots for this problem are x=-0.2 ± 0.4i which is what the algorithm found, within the precision of a standard 64-bit double.

Arrays

Most classes in the JMSL Library require the use of arrays. There are some fundamental differences in the syntax between Java and Scala when dealing with arrays, especially multi-dimensional arrays. However, they are both identical in helpful ways as well; for example, multi-dimensional arrays are implemented as “arrays of arrays” in both languages. While numeric types in Java are primitives compared to everything, even numbers, being objects in Scala, no marshalling is required to pass numeric values or arrays between the two languages.

To a Java developer, the Scala way of assigning an array appears more verbose, especially hard coding values for tests or prototypes. For example, in Java you can quickly define a matrix (a rectangular 2D array) with something like the following:

        double a[][] = {
		{1, 3, 3},
		{1, 3, 4},
		{1, 4, 3}
	};

The equivalent syntax in Scala would be:

 	val a: Array[Array[Double]] = Array(
		Array(1, 3, 3),
		Array(1, 3, 4),
		Array(1, 4, 3))

The repeated use of Array can get verbose. The type declaration is required to designate that these are doubles and not integers; this can be avoided if you use 1.0 instead of 1 to specify that you want double Arrays. Again, this is a challenge limited to prototyping and testing rather than writing production code, but that’s where many of us spend a lot of time.

To cut down on the verboseness, it’s possible in Scala to define an alias for the word Array such as using the symbol “>”. For developers who cut their teeth on languages with very strict syntax, this is an interesting feature, but I have not yet found it to be useful in my short examples. The readability of the code is significantly reduced while the reduction of verboseness is minimal.

With Scala version 2.10, it’s also possible to create a macro that allows you to define arbitrary matrices using strings. From what I’ve read, this is another powerful and interesting feature, but not easily accessible to someone getting starting with the language. Given a year or two, I’m sure very smart people will solve this trivial problem cleanly. Until then, I’ll just deal with the verbose, but readable, code.

The JMSL Library API relies extensively on 1D and 2D double arrays. Thankfully, there is no marshalling or conversions required to pass Scala Array variables to Java methods expecting double[] or double[][] arguments. An example, computing an LU factorization of a small matrix, is shown below:

        val a = Array(
		Array(1.0, 3.0, 3.0), 
		Array(1.0, 3.0, 4.0), 
		Array(1.0, 4.0, 3.0))
	val b = Array(12.0, 13.0, 14.0)
	val lu = new LU(a)
	val x = lu.solve(b)
	println("LU answer = " + x(0) + "\t" + x(1) + "\t" + x(2))
	new PrintMatrix("x").print(x)
	println("LU condition number = " + lu.condition(a))

LU answer = 3.000000000000001     2.0       1.0
  x
   0
0  3
1  2
2  3

LU condition number = 0.015120274914089344

In this example, both a 1D vector (b) and a 2D matrix (a) are defined. The matrix a is passed to the LU constructor, and the vector b is passed when calling the solve() method. Since the answer is only three values, it’s straightforward to print them out. The IMSL helper function PrintMatrix is also shown, which is valuable when printing out more complex matrices.

Now that we’ve covered the basics, next time we’ll look at how user-defined functions are used to create solutions to unique problems and how the charting functionality in JMSL lets you visualize results.

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *

Scroll to top