ScalaSci implements many high-level Scala classes, that wrap usually Java classes of many scientific libraries. However, although it is more convenient to work with those Scala classes, some lower-level functionality is lost. We present how we can adopt a mixed mode programming style, in order to exploit both the lower-level functionality and to have the convenience of Scala based operations where it is applicable.
We call that style as "mixed mode" since it consists of both ScalaSci code and library dependent code patterns. Clearly, the engineer that uses the later type of code, should be familiar with the relevant library. The key to developing this type of code is the getNativeMatrixRef method of the scalaSciMatrix class. The getNativeMatrixRef method returns the library dependent class that implements native operations. This allows ScalaLab code to combine Scala implemented operations, with the existing native operations provided by the Java library. In this way the full potential of the underlying Java class can be utilized. The definition of getNativeMatrixRef is:
def getNativeMatrixRef: AnyRef
This abstract method is implemented for the various concrete ScalaSci classes as:
def getNativeMatrixRef() = sm // the scalaSci.EJML.EJMLMat wraps an EJML SimpleMatrix
def getNativeMatrixRef() = dm // the scalaSci.JBLAS.Mat class wraps the org.jblas.DoubleMatrix class, thus return simply the data representation
def getNativeMatrixRef() = dm // the scalaSci.MTJ.Mat class wraps the no.uib.cipr.matrix.DenseMatrix class, thus return simply the data representation
def getNativeMatrixRef() = rm // the scalaSci.CommonMaths.Mat class wraps the org.apache.commons.math.linear.Array2DRowRealMatrix class
def getNativeMatrixRef() = v // the scalaSci.RichDoubleDoubleArray does not wrap a Matrix class of a specific library, thus return simply the data representation
def getNativeMatrixRef() = v // the scalaSci.Mat does not wrap a Matrix class of a specific library, thus return simply the data representation
def getNativeMatrixRef() = v // the scalaSci.Matrix does not wrap a Matrix class of a specific library, thus return simply the data representation
Another important routine, the matFromNative ,converts from the lower level matrix representation back to the higher level scalaSci matrix. Therefore, the getNativeMatrixRef can be used to take a reference to the lower level representation, transform it using routines of the native library and then convert back to the higher level scalaSci matrix using matFromNative
The matFromNative can be called using the scalaSci matrix reference on which getNativeMatrixRef is called, e.g.
var x = new scalaSci.Mat(4,5)
var xv = x.getNativeMatrixRef // take the internal representation
xv(0)(0) = 200 // change the internal representation
var xrecons = x.matFromNative
Alternatively, we can perform computations in different internal matrix structures and then reconstruct, as e.g.
var x = new scalaSci.Mat(4,5)
var xv = x.getNativeMatrixRef // take the internal representation
xv(0)(0) = 200 // change the internal representation
var xnew = Array.ofDim[Double](7,8) // differently sized matrix
xnew(2)(3) = xv(0)(0)
var xrecons2 = x.matFromNative(xnew) // reconstruct a differently sized matrix
Also, very useful routines, for gluing multiple libraries are the following:
// converts any matrix type to a simple Array[Array[Double]]
def toDoubleArray()
// converts from an Array[Array[Double]] to any matrix representation
def fromDoubleArray(x: Array[Array[Double]])
For example:
var x = Array(Array(9.3, -0.3, 2.8), Array(4.5, 3.4, 2))
// construct an EJML matrix
var xEJML = scalaSci.EJML.StaticMathsEJML.fromDoubleArray(x)
// construct an MTJ matrix
var xMTJ = scalaSci.MTJ.StaticMathsMTJ.fromDoubleArray(x)
// the matrix type depends on which library we are switched on
var xy = fromDoubleArray(x)
// now convert back from the EJML matrix to double array
var xEJMLrecover = xEJML.toDoubleArray
// now convert back from the MTJ matrix to double array
var xMTJrecover = xMTJ.toDoubleArray
We provide additional examples of mixed type code for some libraries.
We demonstate low-level EJML functionality by importing the static definitions of the org.ejml.simple.SimpleMatrix class and exploting the native SimpleMatrix ,which thescalaSci.EJML.Mat wraps. The following code can be executed in ScalaLab directly, however an EJML type of Interpreter should be active, and not one with minimal imports (i.e. not a fast EJML Interpreter) .
import org.ejml.simple.SimpleMatrix._ // static methods of EJML SimpleMatrix class
val x = rand0(8, 8) // create an EJML.Mat random matrix
val xsm = x.getNativeMatrixRef // get a reference to the EJML SimpleMatrix, which the scalaSci.EJML.Mat wraps
// demonstrating directly using the SimpleMatrix
val sm20 = identity(20) // create a SimpleMatrix with 1s at the diagonal
val diagArray = Array(2.3, 7.8, 6.7)
val smDiagonal = diag(diagArray:_*) // create a diagonal SimpleMatrix
// creates a new SimpleMatrix with random elements drawn from a uniform distribution from minValue to maxValue
val smr = random(4, 5, -4.0, 5.8, new Random())
// compute the invert matrix
var xsmi = xsm.invert
// wrap the invert SimpleMatrix to a scalaSci.EJML.Mat
var xsmiToEJMLMat = new scalaSci.EJML.Mat(xsmi)
// .. now we can verify more easily that the inversion succeded
var shouldBeIdentity = x*xsmiToEJMLMat
// and we can more conveniently construct the EJML matrix as
var reconsEJML = x.matFromNative(xsmi)
// if we perform changes directly on the native matrix reference we can reconstruct more conveniently,
// by calling directly the matFromNative() e.g.
xsm.set(0, 40); xsm.set(1, 3.3); // some direct changes to the low level matrix representation
xsm
var reconsDirectEJML = x.matFromNative