/*
* This file is part of JMatLink
* visit JMatLink at http://jmatlink.sourceforge.net
*/
package jmatlink;
import java.io.*;
import java.awt.*;
import java.util.*;
//import java.awt.image.*;
//#if defined(V5_COMPAT)
//#define engPutArray(ep, ap) engPutVariable(ep, mxGetName(ap), ap)
//#define engGetArray(ep, name) engGetVariable(ep, name)
//#else
//#define engPutArray() engPutArray_is_obsolete
//#define engGetArray() engGetArray_is_obsolete
public class JMatLink { //implements ImageObserver {
// the core class of JMatLink
private CoreJMatLink coreJMatLink;
// flag to indicate if debugging is set / unset
private boolean debugB = false;
// current version of JMatLink
private final String VERSION = "JMatLink_V1.3.0";
// random number generator for image generation
private Random randomGenerator = new Random();
// storage for filenames of temporary created images
private Vector imageVector = new Vector();
/** This is the constructor for the JMatLink library.
*
* <p>E.g.:<br>
* <pre>
* <b>JMatLink</b> engine = new <b>JMatLink()</b>;
* engine.engOpen();
* engine.engEvalString("surf(peaks)");
* engine.engClose();
* </pre>
*/
public JMatLink() {
if (debugB) System.out.println("JMatLink constructor");
// create an instance of the core class
coreJMatLink = new CoreJMatLink();
}
/** Returns the current version of JMatLink
*
* <p>E.g.:<br>
* <pre>
* JMatLink engine = new JMatLink();
* System.out.println("version 0 "+ <b>engine.getVersion()</b>);
* </pre>
* @return VERSION of JMatLink
*/
public String getVersion() {
return VERSION;
}
/**
* obsolete method
*
*/
public void kill() {
//coreJMatLink.kill();
System.out.println("JMatLink.kill() is obsolete. Automatic thread start-kill implemented.");
}
/** Open engine. This command is used to open a <b>single</b> connection
* to matlab.
*
* <p>E.g.:<br>
* <pre>
* JMatLink engine = new JMatLink();
* engine.<b>engOpen()</b>;
* engine.engEvalString("surf(peaks)");
* engine.engClose();
* </pre>
*/
public synchronized void engOpen()
{
engOpen( "" );
}
/** Open engine. This command is used to open a <b>single</b> connection
* to matlab.<p> This command is only useful on unix systems. On windows
* the optional parameter <b>must</b> be NULL.
*
* <p>E.g.:<br>
* <pre>
* JMatLink engine = new JMatLink();
* engine.<b>engOpen("commands to start matlab")</b>;
* engine.engEvalString("surf(peaks)");
* engine.engClose();
* </pre>
*/
public void engOpen(String startCmdS)
{
int i=0;
// try to start the engine 10 times
while (i<10)
{
// check if engine is running or dead, and then try to open a new engine connection
if ((coreJMatLink.getThreadStatus() == CoreJMatLink.THREAD_RUNNING) ||
(coreJMatLink.getThreadStatus() == CoreJMatLink.THREAD_DEAD))
{
// thread is running or dead -> call engine open function
coreJMatLink.engOpen(startCmdS);
return;
}
// if this code part is reached the engine thread is starting or dying
// -> wait some time and then check all over again
if (debugB) System.out.println("J starting or dying");
i++;
try {
Thread.sleep(500);
}
catch (InterruptedException e){}
}
// if this part is reached the engine thread has been in a transition phase
// dying or starting for a very long period of time without completion
throw(new JMatLinkException("engine still starting or dying"));
}
/** ************************** engOpenSingleUse *****************************
* Open engine for single use. This command is used to open
* <b>multiple</b> connections to matlab.
*
* <p>E.g.:<br>
* <pre>
* long a,b;
* JMatLink engine = new JMatLink();
* a = engine.<b>engOpenSingleUse()</b>; // start first matlab session
* b = engine.<b>engOpenSingleUse()</b>; // start second matlab session
* engine.engEvalString(a, "surf(peaks)");
* engine.engEvalString(b, "foo=ones(10,0)");
* engine.engClose(a);
* engine.engClose(b);
* </pre>
***************************************************************************/
public long engOpenSingleUse()
{
return engOpenSingleUse("");
}
/**Open engine for single use. This command is used to open
* <b>multiple</b> connections to matlab.
*
* <p>E.g.:<br>
* <pre>
* long a,b;
* JMatLink engine = new JMatLink();
* a = engine.<b>engOpenSingleUse("start matlab")</b>; // start first matlab session
* b = engine.<b>engOpenSingleUse("start matlab")</b>; // start second matlab session
* engine.engEvalString(a, "surf(peaks)");
* engine.engEvalString(b, "foo=ones(10,0)");
* engine.engClose(a);
* engine.engClose(b);
* </pre>
***************************************************************************/
public long engOpenSingleUse(String startCmdS)
{
int i=0;
// try to start the engine 10 times
while (i<10)
{
// check if engine is running or dead, and then try to open a new engine connection
if ((coreJMatLink.getThreadStatus() == CoreJMatLink.THREAD_RUNNING) ||
(coreJMatLink.getThreadStatus() == CoreJMatLink.THREAD_DEAD))
{
// thread is running or dead -> call engine open function
return coreJMatLink.engOpenSingleUse(startCmdS);
}
// if this code part is reached the engine thread is starting or dying
// -> wait some time and then check all over again
if (debugB) System.out.println("J starting or dying");
i++;
try {
Thread.sleep(500);
}
catch (InterruptedException e){}
}
// if this part is reached the engine thread has been in a transition phase
// dying or starting for a very long period of time without completion
throw(new JMatLinkException("engine still starting or dying"));
}
/** Close the connection to matlab.
*
* <p>E.g.:<br>
* <pre>
* JMatLink engine = new JMatLink();
* engine.engOpen();
* engine.engEvalString("surf(peaks)");
* engine.<b>engClose()</b>;
* </pre>
***************************************************************************/
public void engClose()
{
coreJMatLink.engClose( );
deleteTempImages();
}
/** Close a specified connection to an instance of matlab.
*
* <p>E.g.:<br>
* <pre>
* long a,b;
* JMatLink engine = new JMatLink();
* a = engine.engOpenSingleUse(); // start first matlab session
* b = engine.engOpenSingleUse(); // start second matlab session
* engine.engEvalString(b, "surf(peaks)");
* engine.engEvalString(a, "array = randn(23)");
* engine.<b>engClose</b>(a); // Close the first connection to matlab
* engine.<b>engClose</b>(b); // Close the second connection to matlab
* </pre>
***************************************************************************/
public void engClose( long epI)
{
coreJMatLink.engClose(epI);
deleteTempImages();
}
/** Close all connections to matlab
* <p>E.g.:<br>
* <pre>
* long a,b;
* JMatLink engine = new JMatLink();
* engine.engOpen(); // start the general session
* engine.engEvalString("x=sin(5)");
* a = engine.engOpenSingleUse(); // start first matlab session
* b = engine.engOpenSingleUse(); // start second matlab session
* engine.engEvalString(b, "surf(peaks)");
* engine.engEvalString(a, "array = randn(23)");
* engine.<b>engCloseAll</b>(); // Close all connections to matlab
*/
public void engCloseAll()
{
coreJMatLink.engCloseAll();
deleteTempImages();
}
/** Set the visibility of the Matlab window
*
* @param epI engine handle
* @param visB desired visiblity true/false
*/
public void engSetVisible(long epI, boolean visB)
{
coreJMatLink.engSetVisible(epI, visB);
}
/** return the visibility status of the Matlab window
*
* @param epI engine handle
* @return visiblity true/false
*/
public boolean engGetVisible(long epI)
{
return coreJMatLink.engGetVisible(epI);
}
/** Evaluate an expression in matlab's workspace.
*
* E.g.:<br>
* <pre>
* JMatLink engine = new JMatLink();
* engine.engOpen();
* engine.<b>engEvalString</b>("surf(peaks)");
* engine.engClose();
* </pre>
***************************************************************************/
public void engEvalString(String evalS)
{
coreJMatLink.engEvalString( evalS );
}
/** Evaluate an expression in a specified workspace.
*
* <p>E.g.:<br>
* <pre>
* long a,b;
* JMatLink engine = new JMatLink();
* a = engine.engOpenSingleUse();
* engine.<b>engEvalString</b>(a, "surf(peaks)");
* engine.engClose();
* </pre>
***************************************************************************/
public void engEvalString(long epI, String evalS)
{
coreJMatLink.engEvalString(epI, evalS);
}
/** Get a scalar value from matlab's workspace.
*
* <p>E.g.:<br>
* <pre>
* double a;
* JMatLink engine = new JMatLink();
* engine.engOpen();
* engine.engEvalString("foo = sin( 3 )");
* a = engine.<b>engGetScalar</b>("foo");
* engine.engClose();
* </pre>
***************************************************************************/
public double engGetScalar(String arrayS)
{
return coreJMatLink.engGetScalar(arrayS);
}
/** Get a scalar value from a specified workspace.
*
* <p>E.g.:<br>
* <pre>
* double a;
* long b;
* JMatLink engine = new JMatLink();
* b = engine.engOpenSigleUse();
* engine.engEvalString(b, "foo = sin( 3 )");
* a = engine.<b>engGetScalar</b>(b, "foo");
* engine.engClose();
* </pre>
***************************************************************************/
public double engGetScalar(long epI, String arrayS)
{
// Get scalar value or element (1,1) of an array from
// MATLAB's workspace
// Only real values are supported right now
return coreJMatLink.engGetScalar(epI, arrayS);
}
//public double[] engGetRowVector(String arrayS)
//{
// return coreJMatLink.engGetScalar(arrayS);
//}
//public double[] engGetColumnVector(String arrayS)
//{
// return coreJMatLink.engGetScalar(arrayS);
//}
/** Get an array from matlab's workspace.
*
* <p>E.g.:<br>
* <pre>
* double[][] array;
* JMatLink engine = new JMatLink();
* engine.engOpen();
* engine.engEvalString("array = rand(10);");
* array = engine.<b>engGetArray</b>("array");
* engine.engClose();
* </pre>
***************************************************************************/
public double[][] engGetArray(String arrayS)
{
return coreJMatLink.engGetVariable( arrayS );
}
/** Get an array from a specified instance/workspace of matlab.
*
* <p>E.g.:<br>
* <pre>
* long b;
* double[][] array;
* JMatLink engine = new JMatLink();
* b = engine.engOpenSingleUse();
* engine.engEvalString(b, "array = randn(10);");
* array = engine.<b>engGetArray</b>(b, "array");
* engine.engClose(b);
* </pre>
***************************************************************************/
public double[][] engGetArray( long epI, String arrayS )
{
return coreJMatLink.engGetVariable( epI, arrayS );
}
/** Get an 'char' array (string) from matlab's workspace.
*
* <p>E.g.:<br>
* <pre>
* String array;
* JMatLink engine = new JMatLink();
* engine.engOpen();
* engine.engEvalString("array = 'hello world';");
* array = engine.<b>engGetCharArray</b>("array");
* System.out.println("output = "+ array);
* engine.engClose();
* </pre>
***************************************************************************/
public String[] engGetCharArray(String arrayS)
{
// convert to double array
engEvalString( "engGetCharArrayD=double(" + arrayS +")" );
// get double array
double[][] arrayD = engGetArray("engGetCharArrayD");
// delete temporary double array
engEvalString("clear engGetCharArrayD");
// If array "engGetCharArrayD" does not exist in matlab's workspace
// immediately return null
if (arrayD == null) return null;
// convert double back to char
return double2String( arrayD );
}
/** Get an 'char' array (string) from matlab's workspace.
*
* <p>E.g.:<br>
* <pre>
* JMatLink engine = new JMatLink();
* long b = engine.engOpenSingleUse();
* engine.engEvalString(b, "array = 'hello world';");
* String array = engine.<b>engGetCharArray</b>(b,"array");
* System.out.println("output = "+ array);
* engine.engClose(b);
* </pre>
***************************************************************************/
public String[] engGetCharArray(long epI, String arrayS)
{
// convert to double array
engEvalString(epI, "engGetCharArrayD=double(" + arrayS +")" );
// get double array
double[][] arrayD = engGetArray(epI, "engGetCharArrayD");
// delete temporary double array
engEvalString(epI, "clear engGetCharArrayD");
// If array "engGetCharArrayD" does not exist in matlab's workspace
// immediately return null
if (arrayD == null) return null;
// convert double back to char
return double2String( arrayD );
}
/** Put an array into a specified workspace.
*
* <p>E.g.:<br>
* <pre>
* int array = 1;
* JMatLink engine = new JMatLink();
* engine.engOpen();
* engine.<b>engPutArray</b>("array", array);
* engine.engClose();
* </pre>
***************************************************************************/
public void engPutArray( String arrayS, int valueI )
{
engPutArray( arrayS, new Integer(valueI).doubleValue());
}
// public void engPutArray( String arrayS, int[] valuesI )
// {
// engPutArray( this.epI, arrayS, (double[])valuesI );
// }
// public void engPutArray( String arrayS, long valuesI )
// {
// engPutArray( this.epI, arrayS, (double[])valuesI );
// }
// public void engPutArray( String arrayS, long[] valuesI )
// {
// engPutArray( this.epI, arrayS, (double[])valuesI );
// }
// public void engPutArray( String arrayS, byte valuesI )
// {
// engPutArray( this.epI, arrayS, (double[])valuesI );
// }
// public void engPutArray( String arrayS, byte[] valuesI )
// {
// engPutArray( this.epI, arrayS, (double[])valuesI );
// }
/** Put an array into matlab's workspace.
*
* <p>E.g.:<br>
* <pre>
* double array = 1;
* JMatLink engine = new JMatLink();
* engine.engOpen();
* engine.<b>engPutArray</b>("array", array);
* engine.engClose();
* </pre>
***************************************************************************/
public void engPutArray( String arrayS, double valueD )
{
double vDD[][] = {{0.0}};
vDD[0][0] = valueD;
engPutArray( arrayS, vDD ); // nxn dimensional
}
/** Put an array into a specified instance/workspace of matlab.
*
* <p>E.g.:<br>
* <pre>
* long b;
* double array = 1;
* JMatLink engine = new JMatLink();
* b = engine.engOpenSingleUse();
* engine.<b>engPutArray</b>(b, "array", array);
* engine.engClose(b);
* </pre>
***************************************************************************/
public void engPutArray( long epI, String arrayS, double valueD )
{
double vDD[][] = {{0.0}};
vDD[0][0] = valueD;
engPutArray( epI, arrayS, vDD ); // nxn dimensional
}
/** Put an array (1 dimensional) into a specified instance/workspace of
* matlab.
*
* <p>E.g.:<br>
* <pre>
* double[] array = {1.0 , 2.0 , 3.0};
* JMatLink engine = new JMatLink();
* engine.engOpen();
* engine.<b>engPutArray</b>("array", array);
* engine.engClose();
* </pre>
***************************************************************************/
public void engPutArray(String arrayS, double[] valuesD)
{
double[][] vDD = new double[1][valuesD.length]; // 1xn array
if (debugB) System.out.println("length = "+valuesD.length);
vDD[0] = valuesD; // copy row
engPutArray( arrayS, vDD );
}
/** Put an array (1 dimensional) into a specified instance/workspace of
* matlab.
*
* <p>E.g.:<br>
* <pre>
* long b;
* double[] array = {1.0 , 2.0 , 3.0};
* JMatLink engine = new JMatLink();
* b = engine.engOpenSingleUse();
* engine.<b>engPutArray</b>(b, "array", array);
* engine.engClose(b);
* </pre>
***************************************************************************/
public void engPutArray(long epI, String arrayS, double[] valuesD)
{
double[][] vDD = new double[1][valuesD.length]; // 1xn array
if (debugB) System.out.println("length = "+valuesD.length);
vDD[0] = valuesD; // copy row
engPutArray( epI, arrayS, vDD );
}
/** Put an array (2 dimensional) into matlab's workspace.
*
* <p>E.g.:<br>
* <pre>
* double[][] array={{1.0 , 2.0 , 3.0},
* {4.0 , 5.0 , 6.0}};
* JMatLink engine = new JMatLink();
* engine.engOpenSingleUse();
* engine.<b>engPutArray</b>("array", array);
* engine.engClose();
* </pre>
***************************************************************************/
public void engPutArray( String arrayS, double[][] valuesDD )
{
coreJMatLink.engPutVariable( arrayS, valuesDD );
}
/** Put an array (2 dimensional) into a specified instance/workspace of
* matlab.
*
* <p>E.g.:<br>
* <pre>
* long b;
* double[][] array={{1.0 , 2.0 , 3.0},
* {4.0 , 5.0 , 6.0}};
* JMatLink engine = new JMatLink();
* b = engine.engOpenSingleUse();
* engine.engPutArray(b, "array", array);
* engine.engClose(b);
* </pre>
***************************************************************************/
public void engPutArray(long epI, String arrayS, double[][] valuesDD)
{
// send an array to MATLAB
// only real values are supported so far
coreJMatLink.engPutVariable( epI, arrayS, valuesDD );
}
/** Return the outputs of previous commands from matlab's workspace.
*
* <p>E.g.:<br>
* <pre>
* String buffer;
* JMatLink engine = new JMatLink();
* engine.engOpen();
* engine.<b>engOutputBuffer</b>();
* engine.engEvalString("surf(peaks)");
* buffer = engine.<b>engGetOutputBuffer</b>();
* System.out.println("workspace " + buffer);
* engine.engClose();
* </pre>
***************************************************************************/
public int engOutputBuffer( )
{
return coreJMatLink.engOutputBuffer( );
}
/** Return the outputs of previous commands from a specified instance/
* workspace form matlab.
*
* <p>E.g.:<br>
* <pre>
* String buffer;
* long b;
* JMatLink engine = new JMatLink();
* b= engine.engOpenSingleUse();
* engine.<b>engOutputBuffer</b>(b);
* engine.engEvalString("surf(peaks), a=555");
* buffer = engine.<b>engGetOutputBuffer</b>(b);
* System.out.println("workspace " + buffer);
* engine.engClose(b);
* </pre>
***************************************************************************/
public int engOutputBuffer(long epI)
{
return engOutputBuffer( epI, 10000 );
}
/** Return the ouputs of previous commands in matlab's workspace.
*
* Right now the parameter <i>buflen</i> is not supported.
*
* <p>E.g.:<br>
* <pre>
* String buffer;
* long b;
* JMatLink engine = new JMatLink();
* b = engine.engOpen();
* engine.engEvalString(b, "surf(peaks)");
* buffer = engine.<b>engOutputBuffer</b>(b, 10000);
* System.out.println("workspace " + buffer);
* engine.engClose(b);
* </pre>
***************************************************************************/
public int engOutputBuffer( long epI, int buflenI )
{
return coreJMatLink.engOutputBuffer( epI, buflenI );
}
/** Return the outputs of previous commands from a specified instance/
* workspace form matlab.
*
* <p>E.g.:<br>
* <pre>
* String buffer;
* JMatLink engine = new JMatLink();
* engine.engOpen();
* engine.engEvalString("surf(peaks)");
* buffer = engine.<b>engGetOutputBuffer</b>();
* System.out.println("workspace " + buffer);
* engine.engClose();
* </pre>
***************************************************************************/
public String engGetOutputBuffer( )
{
return coreJMatLink.engGetOutputBuffer( );
}
/** Return the ouputs of previous commands in matlab's workspace.
*
* Right now the parameter <i>buflen</i> is not supported.
*
* <p>E.g.:<br>
* <pre>
* String buffer;
* long b;
* JMatLink engine = new JMatLink();
* b = engine.engOpen();
* engine.engEvalString(b, "surf(peaks)");
* buffer = engine.<b>engOutputBuffer</b>(b);
* System.out.println("workspace " + buffer);
* engine.engClose(b);
* </pre>
***************************************************************************/
public String engGetOutputBuffer( long epI )
{
return coreJMatLink.engGetOutputBuffer( epI );
}
/** Return image of figure from Matlab
*
* @param epI handle to matlab engine
* @param figure handle to matlab figure n
* @param dx columns of image in pixels
* @param dy rows of image in pixels
* @return image of the requested figure window from matlab
*/
public Image engGetFigure(long epI, int figure, int dx, int dy)
{
// try to delete old images, maybe they haven't been destroyed
// during the last generation process
deleteTempImages();
// random filename
String tmpDirS = System.getProperty("java.io.tmpdir");
int randomInt = Math.abs(randomGenerator.nextInt());
String imageFileS = tmpDirS + "jmatlink" + figure + "_" + randomInt + ".jpg";
if (debugB) System.out.println("file "+imageFileS);
// image creation
engEvalString(epI, "figure("+ figure +")");
engEvalString(epI, "set(gcf,'PaperUnits','inches')");
engEvalString(epI, "set(gcf,'PaperPosition',[0,0,"+ dx/100 +","+ dy/100 +"])");
engEvalString(epI, "print("+ figure +",'-djpeg100','-r100','" +imageFileS+ "')");
// start loading the image via the default toolkit
// use a media tracker to wait until the image is completely loaded
Image image = Toolkit.getDefaultToolkit().createImage(imageFileS);
Frame iframe = new Frame();
MediaTracker tracker = new MediaTracker(iframe);
tracker.addImage(image,0);
try{
tracker.waitForID(0);
}
catch (InterruptedException e) {}
//System.out.println("tracker: image loaded: "+tracker.checkID(0));
iframe = null;
// add filename to image vector to keep track of created images/files.
imageVector.add(imageFileS);
// return loaded image
return image;
}
/** Return image of figure from Matlab
*
* @param figure handle to matlab figure n
* @param dx columns of image in pixels
* @param dy rows of image in pixels
* @return image of the requested figure window from matlab
*/
public Image engGetFigure(int figure, int dx, int dy)
{
// try to delete old images, maybe they haven't been destroyed
// during the last generation process
deleteTempImages();
// random filename
String tmpDirS = System.getProperty("java.io.tmpdir");
int randomInt = Math.abs(randomGenerator.nextInt());
String imageFileS = tmpDirS + "jmatlink" + figure + "_" + randomInt + ".jpg";
if (debugB) System.out.println("file "+imageFileS);
// image creation
engEvalString("figure("+ figure +")");
engEvalString("set(gcf,'PaperUnits','inches')");
engEvalString("set(gcf,'PaperPosition',[0,0,"+ dx/100 +","+ dy/100 +"])");
engEvalString("print("+ figure +",'-djpeg100','-r100','" +imageFileS+ "')");
// start loading the image via the default toolkit
// use a media tracker to wait until the image is completely loaded
Image image = Toolkit.getDefaultToolkit().createImage(imageFileS);
Frame iframe = new Frame();
MediaTracker tracker = new MediaTracker(iframe);
tracker.addImage(image,0);
try{
tracker.waitForID(0);
}
catch (InterruptedException e) {}
//System.out.println("tracker: image loaded: "+tracker.checkID(0));
iframe = null;
// add filename to image vector to keep track of created images/files.
imageVector.add(imageFileS);
// return loaded image
return image;
}
// delete all temporary images which have been created for engGetFigure
private void deleteTempImages()
{
// start counting backwards, in order to remove images from the top
// (otherwise vector positions are deleted and size is shrinking during
// deletion of elements)
for (int i=imageVector.size()-1; i>=0; i--)
{
String name = (String)(imageVector.elementAt(i));
//System.out.println("image "+name);
File imageF = new File(name);
// check if
//if (imageF.exists())
//{
// try to delete image
boolean status = imageF.delete();
//System.out.println("imageVector("+imageVector.size()+"): del="+i+" status:"+status);
// if image has been deleted successfully remove from vector
if (status)
imageVector.remove(name);
//}
}
}
//public boolean imageUpdate(Image img, int x, int y, int z, int a, int b){
// System.out.println("image Update "+x+" "+y+z+a+b);
// return true;
//}
/** Switch on or disable debug information printed to standard output.
*
* <p>Default setting is debug info disabled.
* <p>E.g.:<br>
* <pre>
* JMatLink engine = new JMatLink();
* engine.engOpenSingleUse();
* engine.<b>setDebug(true)</b>;
* engine.engEvalString("a=ones(10,5);");
* engine.engClose();
* </pre>
***************************************************************************/
public void setDebug( boolean debugB )
{
coreJMatLink.setDebug( debugB );
}
////////////////////////////////////////////////////////////////////////////////
//// Utility methods ////
// Convert an n*n double array to n*1 String vector
private String[] double2String(double[][] d)
{
// Check if array is not empty
if (d == null)
{
/* double[][] array is NULL */
return null;
}
String encodeS[]=new String[d.length]; // String vector
// for all rows
for (int n=0; n<d.length; n++){
byte b[] = new byte[d[n].length];
// convert row from double to byte
for (int i=0; i<d[n].length ;i++) b[i]=(byte)d[n][i];
// convert byte to String
try { encodeS[n] = new String(b, "UTF8");}
catch (UnsupportedEncodingException e) {}
}
return encodeS;
} // end double2String
} // end class JMatLink