diff --git a/.classpath b/.classpath index e8b194e..e353bd8 100644 --- a/.classpath +++ b/.classpath @@ -2,9 +2,12 @@ - + + + + diff --git a/.gitignore b/.gitignore index f911be7..e0de47b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ /bin -benchmark-rosenbrock*-manual.cpp +benchmark-rosenbrock[0-9]*-manual.cpp run[0-9]* diff --git a/.project b/.project index d5cfb79..af67f8c 100644 --- a/.project +++ b/.project @@ -18,7 +18,7 @@ main 2 - /home/yliu/workspace_java/matrix-toolkits-java/src/main + /home/yliu/Desktop/tools/eclipse-kepler/E::/home/yliu/workspace_java/matrix-toolkits-java/src/main diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs index 7341ab1..a698e59 100644 --- a/.settings/org.eclipse.jdt.core.prefs +++ b/.settings/org.eclipse.jdt.core.prefs @@ -1,11 +1,12 @@ eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 +org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.7 +org.eclipse.jdt.core.compiler.compliance=1.8 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.7 +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/LICENSE b/LICENSE index e946767..dc988e0 100644 --- a/LICENSE +++ b/LICENSE @@ -1,29 +1,21 @@ -Copyright (c) 2015 SymJava development Team +MIT License -All rights reserved. +Copyright (c) 2020 Yueming Liu (nkliuyueming@gmail.com) -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: - a. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - b. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - c. Neither the name of SymPy nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -DAMAGE. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 1721101..d72fbd6 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,31 @@ # SymJava -SymJava is a Java library for symbolic mathematics. +SymJava is a Java library for symbolic-numeric computation. -There are two interesting features: +There are two unique features which make SymJava different: -1. Operator Overloading is implemented by using https://github.com/amelentev/java-oo +1. Operator Overloading is implemented by using Java-OO (https://github.com/amelentev/java-oo) -2. Lambdify in sympy is implemented in SymJava by using BCEL library. The java Bytecode are generated in runtime for the math expressions. - -SymJava is developed under Java 7 and Eclipse-Kepler (SR2 4.3.2, https://www.eclipse.org/downloads/packages/release/kepler/sr2) +2. Java bytecode is generated at runtime for symbolic expressions which make the numerical evaluation really fast. Install java-oo Eclipse plugin for Java Operator Overloading support (https://github.com/amelentev/java-oo): Click in menu: Help -> Install New Software. Enter in "Work with" field: http://amelentev.github.io/eclipse.jdt-oo-site/ -Examples: +If you are using Eclipse-Kepler you need to install SR2 4.3.2 here https://www.eclipse.org/downloads/packages/release/kepler/sr2) + +If you are using Eclipse 4.4+, you need Scalar IDE plugin. see https://github.com/amelentev/java-oo + +Both Java 7 and 8 are supported. + +### Citing Our Papers ### + +If you were using Futureye_JIT for academic research, you are encouraged to cite the following papers: + +[Y. Liu, P. Zhang, M. Qiu, "Fast Numerical Evaluation for Symbolic Expressions in Java", 17th IEEE International Conference on High Performance and Communications (HPCC 2015), New York, USA, August 24-26, 2015.](http://ieeexplore.ieee.org/document/7336223/) + +[Y. Liu, P. Zhang, M. Qiu, "SNC: A Cloud Service Platform for Symbolic-Numeric Computation using Just-In-Time Compilation", IEEE Transactions on Cloud Computing, 2017](http://ieeexplore.ieee.org/abstract/document/7828007/) + +### Examples ### ```Java package symjava.examples; @@ -323,3 +335,59 @@ y_0=0.01624 y_1=0.08735 y_2=0.15765 y_3=0.19518 y_4=0.25469 y_5=0.29667 y_6=0.31 y_0=0.02256 y_1=0.09240 y_2=0.15593 y_3=0.19116 y_4=0.25076 y_5=0.29644 y_6=0.31550 \lambda_0=0.05487 \lambda_1=0.06919 \lambda_2=-0.12387 \lambda_3=0.04207 \lambda_4=0.04428 \lambda_5=-0.05989 \lambda_6=0.03240 a=0.36223 b=0.55462 y_0=0.02314 y_1=0.09356 y_2=0.15671 y_3=0.19159 y_4=0.25059 y_5=0.29598 y_6=0.31499 \lambda_0=0.05373 \lambda_1=0.06689 \lambda_2=-0.12542 \lambda_3=0.04123 \lambda_4=0.04463 \lambda_5=-0.05896 \lambda_6=0.03342 a=0.36185 b=0.55631 ``` + +```Java +package symjava.examples; + import static symjava.symbolic.Symbol.*; +import symjava.matrix.*; +import symjava.symbolic.*; + /** + * Example for PDE Constrained Parameters Optimization + * + */ +public class Example4 { + public static void main(String[] args) { + Func u = new Func("u", x,y,z); + Func u0 = new Func("u0", x,y,z); + Func q = new Func("q", x,y,z); + Func q0 = new Func("q0", x,y,z); + Func f = new Func("f", x,y,z); + Func lamd = new Func("\\lambda ", x,y,z); + + Expr reg_term = (q-q0)*(q-q0)*0.5*0.1; + Func L = new Func("L",(u-u0)*(u-u0)/2 + reg_term + q*Dot.apply(Grad.apply(u), Grad.apply(lamd)) - f*lamd); + System.out.println("Lagrange L(u, \\lambda, q) = \n"+L); + + Func phi = new Func("\\phi ", x,y,z); + Func psi = new Func("\\psi ", x,y,z); + Func chi = new Func("\\chi ", x,y,z); + Expr[] xs = new Expr[]{u, lamd, q }; + Expr[] dxs = new Expr[]{phi, psi, chi }; + SymVector Lx = Grad.apply(L, xs, dxs); + System.out.println("\nGradient Lx = (Lu, Llamd, Lq) ="); + System.out.println(Lx); + + Func du = new Func("\\delta{u}", x,y,z); + Func dl = new Func("\\delta{\\lambda}", x,y,z); + Func dq = new Func("\\delta{q}", x,y,z); + Expr[] dxs2 = new Expr[] { du, dl, dq }; + SymMatrix Lxx = new SymMatrix(); + for(Expr Lxi : Lx) { + Lxx.add(Grad.apply(Lxi, xs, dxs2)); + } + System.out.println("\nHessian Matrix ="); + System.out.println(Lxx); + } +} +``` +Output in Latex: + Lagrange= +![](https://github.com/yuemingl/SymJava/blob/master/images/ex4_L.png) + Hessian= +![](https://github.com/yuemingl/SymJava/blob/master/images/ex4_hessian.png) + Grad(L)= +![](https://github.com/yuemingl/SymJava/blob/master/images/ex4_grad.png) + + + Example6: Finite Element Solver for Laplace Equation + ![](https://raw.githubusercontent.com/yuemingl/SymJava/master/images/ex6.png) diff --git a/benchmark/benchmarkFEM_aws.bat b/benchmark/benchmarkFEM_aws.bat new file mode 100755 index 0000000..5d988db --- /dev/null +++ b/benchmark/benchmarkFEM_aws.bat @@ -0,0 +1,9 @@ +java lambdacloud.examples.ExampleFEM job_aws.conf 100 10000 +java lambdacloud.examples.ExampleFEM job_aws.conf 200 40000 +java lambdacloud.examples.ExampleFEM job_aws.conf 400 160000 +java lambdacloud.examples.ExampleFEM job_aws.conf 800 640000 +java lambdacloud.examples.ExampleFEM job_aws.conf 1600 2560000 +java lambdacloud.examples.ExampleFEM job_aws.conf 3200 10240000 +java lambdacloud.examples.ExampleFEM job_aws.conf 6400 40960000 +java lambdacloud.examples.ExampleFEM job_aws.conf 12800 163840000 + diff --git a/benchmark/benchmarkFEM_aws.sh b/benchmark/benchmarkFEM_aws.sh new file mode 100755 index 0000000..5d988db --- /dev/null +++ b/benchmark/benchmarkFEM_aws.sh @@ -0,0 +1,9 @@ +java lambdacloud.examples.ExampleFEM job_aws.conf 100 10000 +java lambdacloud.examples.ExampleFEM job_aws.conf 200 40000 +java lambdacloud.examples.ExampleFEM job_aws.conf 400 160000 +java lambdacloud.examples.ExampleFEM job_aws.conf 800 640000 +java lambdacloud.examples.ExampleFEM job_aws.conf 1600 2560000 +java lambdacloud.examples.ExampleFEM job_aws.conf 3200 10240000 +java lambdacloud.examples.ExampleFEM job_aws.conf 6400 40960000 +java lambdacloud.examples.ExampleFEM job_aws.conf 12800 163840000 + diff --git a/benchmark/benchmarkFEM_azure.bat b/benchmark/benchmarkFEM_azure.bat new file mode 100755 index 0000000..8120bc9 --- /dev/null +++ b/benchmark/benchmarkFEM_azure.bat @@ -0,0 +1,9 @@ +java lambdacloud.examples.ExampleFEM job_azure.conf 100 10000 +java lambdacloud.examples.ExampleFEM job_azure.conf 200 40000 +java lambdacloud.examples.ExampleFEM job_azure.conf 400 160000 +java lambdacloud.examples.ExampleFEM job_azure.conf 800 640000 +java lambdacloud.examples.ExampleFEM job_azure.conf 1600 2560000 +java lambdacloud.examples.ExampleFEM job_azure.conf 3200 10240000 +java lambdacloud.examples.ExampleFEM job_azure.conf 6400 40960000 +java lambdacloud.examples.ExampleFEM job_azure.conf 12800 163840000 + diff --git a/benchmark/benchmarkFEM_azure.sh b/benchmark/benchmarkFEM_azure.sh new file mode 100755 index 0000000..8120bc9 --- /dev/null +++ b/benchmark/benchmarkFEM_azure.sh @@ -0,0 +1,9 @@ +java lambdacloud.examples.ExampleFEM job_azure.conf 100 10000 +java lambdacloud.examples.ExampleFEM job_azure.conf 200 40000 +java lambdacloud.examples.ExampleFEM job_azure.conf 400 160000 +java lambdacloud.examples.ExampleFEM job_azure.conf 800 640000 +java lambdacloud.examples.ExampleFEM job_azure.conf 1600 2560000 +java lambdacloud.examples.ExampleFEM job_azure.conf 3200 10240000 +java lambdacloud.examples.ExampleFEM job_azure.conf 6400 40960000 +java lambdacloud.examples.ExampleFEM job_azure.conf 12800 163840000 + diff --git a/benchmark/benchmarkFEM_google.bat b/benchmark/benchmarkFEM_google.bat new file mode 100755 index 0000000..028e107 --- /dev/null +++ b/benchmark/benchmarkFEM_google.bat @@ -0,0 +1,9 @@ +java lambdacloud.examples.ExampleFEM job_google.conf 100 10000 +java lambdacloud.examples.ExampleFEM job_google.conf 200 40000 +java lambdacloud.examples.ExampleFEM job_google.conf 400 160000 +java lambdacloud.examples.ExampleFEM job_google.conf 800 640000 +java lambdacloud.examples.ExampleFEM job_google.conf 1600 2560000 +java lambdacloud.examples.ExampleFEM job_google.conf 3200 10240000 +java lambdacloud.examples.ExampleFEM job_google.conf 6400 40960000 +java lambdacloud.examples.ExampleFEM job_google.conf 12800 163840000 + diff --git a/benchmark/benchmarkFEM_google.sh b/benchmark/benchmarkFEM_google.sh new file mode 100755 index 0000000..028e107 --- /dev/null +++ b/benchmark/benchmarkFEM_google.sh @@ -0,0 +1,9 @@ +java lambdacloud.examples.ExampleFEM job_google.conf 100 10000 +java lambdacloud.examples.ExampleFEM job_google.conf 200 40000 +java lambdacloud.examples.ExampleFEM job_google.conf 400 160000 +java lambdacloud.examples.ExampleFEM job_google.conf 800 640000 +java lambdacloud.examples.ExampleFEM job_google.conf 1600 2560000 +java lambdacloud.examples.ExampleFEM job_google.conf 3200 10240000 +java lambdacloud.examples.ExampleFEM job_google.conf 6400 40960000 +java lambdacloud.examples.ExampleFEM job_google.conf 12800 163840000 + diff --git a/benchmark/benchmarkFEM_hp.bat b/benchmark/benchmarkFEM_hp.bat new file mode 100755 index 0000000..27cb1e2 --- /dev/null +++ b/benchmark/benchmarkFEM_hp.bat @@ -0,0 +1,9 @@ +java lambdacloud.examples.ExampleFEM job_hp.conf 100 10000 +java lambdacloud.examples.ExampleFEM job_hp.conf 200 40000 +java lambdacloud.examples.ExampleFEM job_hp.conf 400 160000 +java lambdacloud.examples.ExampleFEM job_hp.conf 800 640000 +java lambdacloud.examples.ExampleFEM job_hp.conf 1600 2560000 +java lambdacloud.examples.ExampleFEM job_hp.conf 3200 10240000 +java lambdacloud.examples.ExampleFEM job_hp.conf 6400 40960000 +java lambdacloud.examples.ExampleFEM job_hp.conf 12800 163840000 + diff --git a/benchmark/benchmarkFEM_hp.sh b/benchmark/benchmarkFEM_hp.sh new file mode 100755 index 0000000..27cb1e2 --- /dev/null +++ b/benchmark/benchmarkFEM_hp.sh @@ -0,0 +1,9 @@ +java lambdacloud.examples.ExampleFEM job_hp.conf 100 10000 +java lambdacloud.examples.ExampleFEM job_hp.conf 200 40000 +java lambdacloud.examples.ExampleFEM job_hp.conf 400 160000 +java lambdacloud.examples.ExampleFEM job_hp.conf 800 640000 +java lambdacloud.examples.ExampleFEM job_hp.conf 1600 2560000 +java lambdacloud.examples.ExampleFEM job_hp.conf 3200 10240000 +java lambdacloud.examples.ExampleFEM job_hp.conf 6400 40960000 +java lambdacloud.examples.ExampleFEM job_hp.conf 12800 163840000 + diff --git a/benchmark/benchmarkFEM_local.bat b/benchmark/benchmarkFEM_local.bat new file mode 100755 index 0000000..69ec854 --- /dev/null +++ b/benchmark/benchmarkFEM_local.bat @@ -0,0 +1,9 @@ +java lambdacloud.examples.ExampleFEM local 100 10000 +java lambdacloud.examples.ExampleFEM local 200 40000 +java lambdacloud.examples.ExampleFEM local 400 160000 +java lambdacloud.examples.ExampleFEM local 800 640000 +java lambdacloud.examples.ExampleFEM local 1600 2560000 +java lambdacloud.examples.ExampleFEM local 3200 10240000 +java lambdacloud.examples.ExampleFEM local 6400 40960000 +java lambdacloud.examples.ExampleFEM local 12800 163840000 + diff --git a/benchmark/benchmarkFEM_local.sh b/benchmark/benchmarkFEM_local.sh new file mode 100755 index 0000000..69ec854 --- /dev/null +++ b/benchmark/benchmarkFEM_local.sh @@ -0,0 +1,9 @@ +java lambdacloud.examples.ExampleFEM local 100 10000 +java lambdacloud.examples.ExampleFEM local 200 40000 +java lambdacloud.examples.ExampleFEM local 400 160000 +java lambdacloud.examples.ExampleFEM local 800 640000 +java lambdacloud.examples.ExampleFEM local 1600 2560000 +java lambdacloud.examples.ExampleFEM local 3200 10240000 +java lambdacloud.examples.ExampleFEM local 6400 40960000 +java lambdacloud.examples.ExampleFEM local 12800 163840000 + diff --git a/benchmark/benchmarkFEM_rackspace.bat b/benchmark/benchmarkFEM_rackspace.bat new file mode 100755 index 0000000..173c8d1 --- /dev/null +++ b/benchmark/benchmarkFEM_rackspace.bat @@ -0,0 +1,9 @@ +java lambdacloud.examples.ExampleFEM job_rackspace.conf 100 10000 +java lambdacloud.examples.ExampleFEM job_rackspace.conf 200 40000 +java lambdacloud.examples.ExampleFEM job_rackspace.conf 400 160000 +java lambdacloud.examples.ExampleFEM job_rackspace.conf 800 640000 +java lambdacloud.examples.ExampleFEM job_rackspace.conf 1600 2560000 +java lambdacloud.examples.ExampleFEM job_rackspace.conf 3200 10240000 +java lambdacloud.examples.ExampleFEM job_rackspace.conf 6400 40960000 +java lambdacloud.examples.ExampleFEM job_rackspace.conf 12800 163840000 + diff --git a/benchmark/benchmarkFEM_rackspace.sh b/benchmark/benchmarkFEM_rackspace.sh new file mode 100755 index 0000000..173c8d1 --- /dev/null +++ b/benchmark/benchmarkFEM_rackspace.sh @@ -0,0 +1,9 @@ +java lambdacloud.examples.ExampleFEM job_rackspace.conf 100 10000 +java lambdacloud.examples.ExampleFEM job_rackspace.conf 200 40000 +java lambdacloud.examples.ExampleFEM job_rackspace.conf 400 160000 +java lambdacloud.examples.ExampleFEM job_rackspace.conf 800 640000 +java lambdacloud.examples.ExampleFEM job_rackspace.conf 1600 2560000 +java lambdacloud.examples.ExampleFEM job_rackspace.conf 3200 10240000 +java lambdacloud.examples.ExampleFEM job_rackspace.conf 6400 40960000 +java lambdacloud.examples.ExampleFEM job_rackspace.conf 12800 163840000 + diff --git a/benchmark/benchmarkFEM_vmware.bat b/benchmark/benchmarkFEM_vmware.bat new file mode 100755 index 0000000..f0cf4b6 --- /dev/null +++ b/benchmark/benchmarkFEM_vmware.bat @@ -0,0 +1,9 @@ +java lambdacloud.examples.ExampleFEM job_vmware.conf 100 10000 +java lambdacloud.examples.ExampleFEM job_vmware.conf 200 40000 +java lambdacloud.examples.ExampleFEM job_vmware.conf 400 160000 +java lambdacloud.examples.ExampleFEM job_vmware.conf 800 640000 +java lambdacloud.examples.ExampleFEM job_vmware.conf 1600 2560000 +java lambdacloud.examples.ExampleFEM job_vmware.conf 3200 10240000 +java lambdacloud.examples.ExampleFEM job_vmware.conf 6400 40960000 +java lambdacloud.examples.ExampleFEM job_vmware.conf 12800 163840000 + diff --git a/benchmark/benchmarkFEM_vmware.sh b/benchmark/benchmarkFEM_vmware.sh new file mode 100755 index 0000000..f0cf4b6 --- /dev/null +++ b/benchmark/benchmarkFEM_vmware.sh @@ -0,0 +1,9 @@ +java lambdacloud.examples.ExampleFEM job_vmware.conf 100 10000 +java lambdacloud.examples.ExampleFEM job_vmware.conf 200 40000 +java lambdacloud.examples.ExampleFEM job_vmware.conf 400 160000 +java lambdacloud.examples.ExampleFEM job_vmware.conf 800 640000 +java lambdacloud.examples.ExampleFEM job_vmware.conf 1600 2560000 +java lambdacloud.examples.ExampleFEM job_vmware.conf 3200 10240000 +java lambdacloud.examples.ExampleFEM job_vmware.conf 6400 40960000 +java lambdacloud.examples.ExampleFEM job_vmware.conf 12800 163840000 + diff --git a/benchmark/benchmarkMC_aws.bat b/benchmark/benchmarkMC_aws.bat new file mode 100755 index 0000000..9c1e2a0 --- /dev/null +++ b/benchmark/benchmarkMC_aws.bat @@ -0,0 +1,6 @@ +java lambdacloud.examples.ExampleMonteCarlo 10000 job_aws.conf true +java lambdacloud.examples.ExampleMonteCarlo 100000 job_aws.conf true +java lambdacloud.examples.ExampleMonteCarlo 1000000 job_aws.conf true +java lambdacloud.examples.ExampleMonteCarlo 10000000 job_aws.conf true +java lambdacloud.examples.ExampleMonteCarlo 100000000 job_aws.conf true + diff --git a/benchmark/benchmarkMC_aws.sh b/benchmark/benchmarkMC_aws.sh new file mode 100755 index 0000000..9c1e2a0 --- /dev/null +++ b/benchmark/benchmarkMC_aws.sh @@ -0,0 +1,6 @@ +java lambdacloud.examples.ExampleMonteCarlo 10000 job_aws.conf true +java lambdacloud.examples.ExampleMonteCarlo 100000 job_aws.conf true +java lambdacloud.examples.ExampleMonteCarlo 1000000 job_aws.conf true +java lambdacloud.examples.ExampleMonteCarlo 10000000 job_aws.conf true +java lambdacloud.examples.ExampleMonteCarlo 100000000 job_aws.conf true + diff --git a/benchmark/benchmarkMC_azure.bat b/benchmark/benchmarkMC_azure.bat new file mode 100755 index 0000000..a03326e --- /dev/null +++ b/benchmark/benchmarkMC_azure.bat @@ -0,0 +1,6 @@ +java lambdacloud.examples.ExampleMonteCarlo 10000 job_vm2.conf true +java lambdacloud.examples.ExampleMonteCarlo 100000 job_vm2.conf true +java lambdacloud.examples.ExampleMonteCarlo 1000000 job_vm2.conf true +java lambdacloud.examples.ExampleMonteCarlo 10000000 job_vm2.conf true +java lambdacloud.examples.ExampleMonteCarlo 100000000 job_vm2.conf true + diff --git a/benchmark/benchmarkMC_azure.sh b/benchmark/benchmarkMC_azure.sh new file mode 100755 index 0000000..f6e83b2 --- /dev/null +++ b/benchmark/benchmarkMC_azure.sh @@ -0,0 +1,6 @@ +java lambdacloud.examples.ExampleMonteCarlo 10000 job_azure.conf true +java lambdacloud.examples.ExampleMonteCarlo 100000 job_azure.conf true +java lambdacloud.examples.ExampleMonteCarlo 1000000 job_azure.conf true +java lambdacloud.examples.ExampleMonteCarlo 10000000 job_azure.conf true +java lambdacloud.examples.ExampleMonteCarlo 100000000 job_azure.conf true + diff --git a/benchmark/benchmarkMC_google.bat b/benchmark/benchmarkMC_google.bat new file mode 100755 index 0000000..67142ee --- /dev/null +++ b/benchmark/benchmarkMC_google.bat @@ -0,0 +1,6 @@ +java lambdacloud.examples.ExampleMonteCarlo 10000 job_google.conf true +java lambdacloud.examples.ExampleMonteCarlo 100000 job_google.conf true +java lambdacloud.examples.ExampleMonteCarlo 1000000 job_google.conf true +java lambdacloud.examples.ExampleMonteCarlo 10000000 job_google.conf true +java lambdacloud.examples.ExampleMonteCarlo 100000000 job_google.conf true + diff --git a/benchmark/benchmarkMC_google.sh b/benchmark/benchmarkMC_google.sh new file mode 100755 index 0000000..67142ee --- /dev/null +++ b/benchmark/benchmarkMC_google.sh @@ -0,0 +1,6 @@ +java lambdacloud.examples.ExampleMonteCarlo 10000 job_google.conf true +java lambdacloud.examples.ExampleMonteCarlo 100000 job_google.conf true +java lambdacloud.examples.ExampleMonteCarlo 1000000 job_google.conf true +java lambdacloud.examples.ExampleMonteCarlo 10000000 job_google.conf true +java lambdacloud.examples.ExampleMonteCarlo 100000000 job_google.conf true + diff --git a/benchmark/benchmarkMC_hp.bat b/benchmark/benchmarkMC_hp.bat new file mode 100755 index 0000000..adfcb40 --- /dev/null +++ b/benchmark/benchmarkMC_hp.bat @@ -0,0 +1,6 @@ +java lambdacloud.examples.ExampleMonteCarlo 10000 job_hp.conf true +java lambdacloud.examples.ExampleMonteCarlo 100000 job_hp.conf true +java lambdacloud.examples.ExampleMonteCarlo 1000000 job_hp.conf true +java lambdacloud.examples.ExampleMonteCarlo 10000000 job_hp.conf true +java lambdacloud.examples.ExampleMonteCarlo 100000000 job_hp.conf true + diff --git a/benchmark/benchmarkMC_hp.sh b/benchmark/benchmarkMC_hp.sh new file mode 100755 index 0000000..adfcb40 --- /dev/null +++ b/benchmark/benchmarkMC_hp.sh @@ -0,0 +1,6 @@ +java lambdacloud.examples.ExampleMonteCarlo 10000 job_hp.conf true +java lambdacloud.examples.ExampleMonteCarlo 100000 job_hp.conf true +java lambdacloud.examples.ExampleMonteCarlo 1000000 job_hp.conf true +java lambdacloud.examples.ExampleMonteCarlo 10000000 job_hp.conf true +java lambdacloud.examples.ExampleMonteCarlo 100000000 job_hp.conf true + diff --git a/benchmark/benchmarkMC_local.bat b/benchmark/benchmarkMC_local.bat new file mode 100755 index 0000000..5631fe5 --- /dev/null +++ b/benchmark/benchmarkMC_local.bat @@ -0,0 +1,6 @@ +java lambdacloud.examples.ExampleMonteCarlo 10000 local true +java lambdacloud.examples.ExampleMonteCarlo 100000 local true +java lambdacloud.examples.ExampleMonteCarlo 1000000 local true +java lambdacloud.examples.ExampleMonteCarlo 10000000 local true +java lambdacloud.examples.ExampleMonteCarlo 100000000 local true + diff --git a/benchmark/benchmarkMC_local.sh b/benchmark/benchmarkMC_local.sh new file mode 100755 index 0000000..5631fe5 --- /dev/null +++ b/benchmark/benchmarkMC_local.sh @@ -0,0 +1,6 @@ +java lambdacloud.examples.ExampleMonteCarlo 10000 local true +java lambdacloud.examples.ExampleMonteCarlo 100000 local true +java lambdacloud.examples.ExampleMonteCarlo 1000000 local true +java lambdacloud.examples.ExampleMonteCarlo 10000000 local true +java lambdacloud.examples.ExampleMonteCarlo 100000000 local true + diff --git a/benchmark/benchmarkMC_rackspace.bat b/benchmark/benchmarkMC_rackspace.bat new file mode 100755 index 0000000..f7efee4 --- /dev/null +++ b/benchmark/benchmarkMC_rackspace.bat @@ -0,0 +1,6 @@ +java lambdacloud.examples.ExampleMonteCarlo 10000 job_rackspace.conf true +java lambdacloud.examples.ExampleMonteCarlo 100000 job_rackspace.conf true +java lambdacloud.examples.ExampleMonteCarlo 1000000 job_rackspace.conf true +java lambdacloud.examples.ExampleMonteCarlo 10000000 job_rackspace.conf true +java lambdacloud.examples.ExampleMonteCarlo 100000000 job_rackspace.conf true + diff --git a/benchmark/benchmarkMC_rackspace.sh b/benchmark/benchmarkMC_rackspace.sh new file mode 100755 index 0000000..f7efee4 --- /dev/null +++ b/benchmark/benchmarkMC_rackspace.sh @@ -0,0 +1,6 @@ +java lambdacloud.examples.ExampleMonteCarlo 10000 job_rackspace.conf true +java lambdacloud.examples.ExampleMonteCarlo 100000 job_rackspace.conf true +java lambdacloud.examples.ExampleMonteCarlo 1000000 job_rackspace.conf true +java lambdacloud.examples.ExampleMonteCarlo 10000000 job_rackspace.conf true +java lambdacloud.examples.ExampleMonteCarlo 100000000 job_rackspace.conf true + diff --git a/benchmark/benchmarkMC_vmware.bat b/benchmark/benchmarkMC_vmware.bat new file mode 100755 index 0000000..adfcb40 --- /dev/null +++ b/benchmark/benchmarkMC_vmware.bat @@ -0,0 +1,6 @@ +java lambdacloud.examples.ExampleMonteCarlo 10000 job_hp.conf true +java lambdacloud.examples.ExampleMonteCarlo 100000 job_hp.conf true +java lambdacloud.examples.ExampleMonteCarlo 1000000 job_hp.conf true +java lambdacloud.examples.ExampleMonteCarlo 10000000 job_hp.conf true +java lambdacloud.examples.ExampleMonteCarlo 100000000 job_hp.conf true + diff --git a/benchmark/benchmarkMC_vmware.sh b/benchmark/benchmarkMC_vmware.sh new file mode 100755 index 0000000..4ab905c --- /dev/null +++ b/benchmark/benchmarkMC_vmware.sh @@ -0,0 +1,6 @@ +java lambdacloud.examples.ExampleMonteCarlo 10000 job_vmware.conf true +java lambdacloud.examples.ExampleMonteCarlo 100000 job_vmware.conf true +java lambdacloud.examples.ExampleMonteCarlo 1000000 job_vmware.conf true +java lambdacloud.examples.ExampleMonteCarlo 10000000 job_vmware.conf true +java lambdacloud.examples.ExampleMonteCarlo 100000000 job_vmware.conf true + diff --git a/conf/job1.conf b/conf/job1.conf new file mode 100644 index 0000000..13e750b --- /dev/null +++ b/conf/job1.conf @@ -0,0 +1,6 @@ +104.130.29.188:8322 +vm2-yliu.cloudapp.net:8322 +104.197.57.20:8322 +15.126.216.80:8322 +107.189.111.104:8322 +ec2-54-200-107-134.us-west-2.compute.amazonaws.com:8322 diff --git a/conf/job_aws.conf b/conf/job_aws.conf new file mode 100755 index 0000000..9bbb724 --- /dev/null +++ b/conf/job_aws.conf @@ -0,0 +1 @@ +ec2-54-200-107-134.us-west-2.compute.amazonaws.com:8322 diff --git a/conf/job_azure.conf b/conf/job_azure.conf new file mode 100755 index 0000000..b6b1c53 --- /dev/null +++ b/conf/job_azure.conf @@ -0,0 +1 @@ +vm2-yliu.cloudapp.net:8322 diff --git a/conf/job_google.conf b/conf/job_google.conf new file mode 100755 index 0000000..0f64dc3 --- /dev/null +++ b/conf/job_google.conf @@ -0,0 +1 @@ +104.197.57.20:8322 diff --git a/conf/job_hp.conf b/conf/job_hp.conf new file mode 100755 index 0000000..94f8673 --- /dev/null +++ b/conf/job_hp.conf @@ -0,0 +1 @@ +15.126.216.80:8322 diff --git a/conf/job_local.conf b/conf/job_local.conf new file mode 100644 index 0000000..8ccd9da --- /dev/null +++ b/conf/job_local.conf @@ -0,0 +1,3 @@ +127.0.0.1:8322 +127.0.0.1:8323 +127.0.0.1:8324 diff --git a/conf/job_rackspace.conf b/conf/job_rackspace.conf new file mode 100755 index 0000000..bdd7b59 --- /dev/null +++ b/conf/job_rackspace.conf @@ -0,0 +1 @@ +104.130.29.188:8322 diff --git a/conf/job_vmware.conf b/conf/job_vmware.conf new file mode 100755 index 0000000..96ba970 --- /dev/null +++ b/conf/job_vmware.conf @@ -0,0 +1 @@ +107.189.111.104:8322 diff --git a/images/class_diagram1.png b/images/class_diagram1.png new file mode 100644 index 0000000..fe0c373 Binary files /dev/null and b/images/class_diagram1.png differ diff --git a/images/expression_tree_compile.png b/images/expression_tree_compile.png new file mode 100644 index 0000000..57dc270 Binary files /dev/null and b/images/expression_tree_compile.png differ diff --git a/images/interface_diagram.png b/images/interface_diagram.png new file mode 100644 index 0000000..575f52d Binary files /dev/null and b/images/interface_diagram.png differ diff --git a/job1.conf b/job1.conf new file mode 100644 index 0000000..efcd130 --- /dev/null +++ b/job1.conf @@ -0,0 +1,3 @@ +ec2-54-200-107-134.us-west-2.compute.amazonaws.com:8322 +104.197.57.20:8322 +vm1-yliu.cloudapp.net:8322 diff --git a/job_vm2.conf b/job_vm2.conf new file mode 100644 index 0000000..b6b1c53 --- /dev/null +++ b/job_vm2.conf @@ -0,0 +1 @@ +vm2-yliu.cloudapp.net:8322 diff --git a/lib/jzlib.jar b/lib/jzlib.jar new file mode 100644 index 0000000..0e342c0 Binary files /dev/null and b/lib/jzlib.jar differ diff --git a/lib/netty-all-5.0.0.Alpha2.jar b/lib/netty-all-5.0.0.Alpha2.jar new file mode 100644 index 0000000..adcaa31 Binary files /dev/null and b/lib/netty-all-5.0.0.Alpha2.jar differ diff --git a/release/SymJava.jar b/release/SymJava.jar new file mode 100644 index 0000000..fc6bc7a Binary files /dev/null and b/release/SymJava.jar differ diff --git a/src/InterfaceDiagram.ucls b/src/InterfaceDiagram.ucls new file mode 100644 index 0000000..0fe3783 --- /dev/null +++ b/src/InterfaceDiagram.ucls @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/class_diagram1.ucls b/src/class_diagram1.ucls new file mode 100644 index 0000000..3842fdc --- /dev/null +++ b/src/class_diagram1.ucls @@ -0,0 +1,693 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/lambdacloud/core/CloudConfig.java b/src/lambdacloud/core/CloudConfig.java new file mode 100644 index 0000000..63b0541 --- /dev/null +++ b/src/lambdacloud/core/CloudConfig.java @@ -0,0 +1,141 @@ +package lambdacloud.core; + +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; + +import lambdacloud.net.CloudClient; + +/** + * An instance of CloudConfig contains the information of available servers. + * A global instance of CloudConfig (call getGlobalConfg()) is used in the + * computation if no CloudConfig is provided. The default value of the global + * configure of servers is simulated by multi-thread locally. + * + */ +public class CloudConfig { + protected String configFile; + protected static CloudConfig globalConfig = new CloudConfig(); + + protected List clients = new ArrayList(); + protected CloudClient currentClient; + + /** + * Construct a CloudConfig object which allows all the computations + * run on local machine and the servers are simulated by multi-thread + */ + public CloudConfig() { + } + + /** + * Construct a instance from a configuration file + * + * @param configFile + */ + public CloudConfig(String configFile) { + if(configFile == null) { + System.out.println("Using local config."); + return; + } + this.configFile = configFile; + try { + Path path = Paths.get(System.getProperty("user.dir")+"/conf/"+configFile); + System.out.println("Using config file: "+path); + List hosts = Files.readAllLines(path, Charset.forName("UTF-8")); + for(String host : hosts) { + if(host.trim().length() == 0) + continue; + String[] arr = host.split(":"); + if(arr.length == 2) { + CloudClient c = new CloudClient(arr[0], Integer.valueOf(arr[1])); + c.connect(); + System.out.println(host); + clients.add(c); + if(currentClient == null) { + currentClient = c; + } + } else { + System.out.println("Can not parse host: "+host); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Set the global configuration by providing a configuration file + * + * @param configFile + */ + public static CloudConfig setGlobalConfig(String configFile) { + globalConfig = new CloudConfig(configFile); + return globalConfig; + } + + /** + * Set config as the global configuration + * @param config + * @return + */ + public static CloudConfig setGlobalConfig(CloudConfig config) { + globalConfig = config; + return globalConfig; + } + + public static CloudConfig getGlobalConfig() { + if(globalConfig == null) { + throw new RuntimeException("Global CloudConfig is not specified!"); + } + return globalConfig; + } + + public boolean isLocalConfig() { + return null == configFile; + } + + public CloudClient getClientByIndex(int index) { + if(this.isLocalConfig()) + return null; + return clients.get(index); + } + + public int getNumClients() { + if(this.isLocalConfig()) + return 1; + return clients.size(); + } + + public CloudClient getCurrentClient() { + return currentClient; + } + + public void setCurrentClient(CloudClient client) { + if(this.isLocalConfig()) + return; + this.currentClient = client; + } + + public void setCurrentClient(int index) { + if(this.currentClient == null) + return; + this.currentClient = clients.get(index); + } + + public void reconnectAll() { + for(CloudClient client : clients) + try { + client.connect(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void disconnectAll() { + for(CloudClient client : clients) + client.shutDown(); + } +} diff --git a/src/lambdacloud/core/CloudFunc.java b/src/lambdacloud/core/CloudFunc.java new file mode 100644 index 0000000..e02aef1 --- /dev/null +++ b/src/lambdacloud/core/CloudFunc.java @@ -0,0 +1,636 @@ +package lambdacloud.core; + +import io.netty.channel.Channel; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Method; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +import lambdacloud.core.lang.LCBase; +import lambdacloud.core.lang.LCReturn; +import lambdacloud.core.utils.FuncEvalThread; +import lambdacloud.net.CloudClient; +import lambdacloud.net.CloudFuncHandler; +import lambdacloud.net.CloudQuery; +import lambdacloud.net.CloudResp; +import lambdacloud.net.CloudSDHandler; +import lambdacloud.test.CompileUtils; +import symjava.bytecode.BytecodeBatchFunc; +import symjava.bytecode.BytecodeFunc; +import symjava.bytecode.BytecodeVecFunc; +import symjava.bytecode.IR; +import symjava.symbolic.Expr; +import symjava.symbolic.TypeInfo; +import symjava.symbolic.utils.Utils; + +/** + * Cloud Function (CloudFunc) + *
+ * This class represents a function on cloud. + * A function is defined by giving a symbolic expression and arguments (optional). + * + */ +public class CloudFunc extends LCBase { + + /** + * Supported types of functions + * @see BytecodeFunc + * @see BytecodeVecFunc + * @see BytecodeBatchFunc + */ + public static enum FUNC_TYPE { + SCALAR, // BytecodeFunc + VECTOR, // BytecodeVecFunc + BATCH // BytecodeBatchFunc + } + + protected String name; //TODO use label? + protected BytecodeFunc func; + protected BytecodeVecFunc vecFunc; + protected BytecodeBatchFunc batchFunc; + + private static AtomicInteger cfuncNameGenerator = new AtomicInteger(0); + + //Info for BytecodeBatchFunc + protected int outAryLen; + protected int numArgs; // + + protected boolean isOnCloud = false; + + protected Class clazz; //a java class of func + protected Method method; + + protected CloudConfig localConfig = null; + protected boolean isAsync = false; + + //1=BytecodeFunc, 2=BytecodeVecFunc, 3=BytecodeBatchFunc + protected FUNC_TYPE funcType; + protected IR funcIR = null; + + //Need improving + private int device; + + + /** + * Construct a CloudFunc by providing an expression. + * The arguments of the function is extracted automatically. + * + * @param expr + */ + public CloudFunc(Expr expr) { + this.name = generateName(); + this.compile(expr); + } + + /** + * Construct a CloudFunc by providing an expression and the arguments. + * + * @param expr + * @param args + */ + public CloudFunc(Expr expr, Expr... args) { + this.name = generateName(); + this.compile(expr, args); + } + + /** + * Construct a CloudFunc by providing a list of expressions. + * The arguments of the function is extracted automatically. + * + * @param expr + * @param args + */ + public CloudFunc(Expr[] expr) { + this.name = generateName(); + this.compile(expr); + } + + /** + * Construct a CloudFunc by providing a list of expressions and the arguments. + * + * @param expr + * @param args + */ + public CloudFunc(Expr[] expr, Expr... args) { + this.name = generateName(); + this.compile(expr, args); + } + + /** + * What purpose by providing only a name? Get an existing function from cloud? + * @param name + */ + public CloudFunc(String name) { + this.name = name; + } + + public CloudFunc(String name, Expr expr) { + this.name = name; + this.compile(expr); + } + + public CloudFunc(String name, Expr expr, Expr... args) { + this.name = name; + this.compile(expr, args); + } + + public CloudFunc(String name, Expr[] exprs) { + this.name = name; + this.compile(exprs); + } + + public CloudFunc(String name, Expr[] exprs, Expr... args) { + this.name = name; + this.compile(exprs, args); + } + + public CloudFunc(CloudConfig config, Expr expr) { + this.name = generateName(); + this.localConfig = config; + this.compile(expr); + } + + public CloudFunc(CloudConfig config, Expr expr, Expr... args) { + this.name = generateName(); + this.localConfig = config; + this.compile(expr, args); + } + + public CloudFunc(CloudConfig config, Expr[] expr) { + this.name = generateName(); + this.localConfig = config; + this.compile(expr); + } + + public CloudFunc(CloudConfig config, Expr[] expr, Expr... args) { + this.name = generateName(); + this.localConfig = config; + this.compile(expr, args); + } + + public CloudFunc(CloudConfig config, String name) { + this.name = name; + this.localConfig = config; + } + + public CloudFunc(CloudConfig config, String name, Expr expr) { + this.name = name; + this.localConfig = config; + this.compile(expr); + } + + public CloudFunc(CloudConfig config, String name, Expr expr, Expr... args) { + this.name = name; + this.localConfig = config; + this.compile(expr, args); + } + + public CloudFunc(CloudConfig config, String name, Expr[] expr) { + this.name = name; + this.localConfig = config; + this.compile(expr); + } + + public CloudFunc(CloudConfig config, String name, Expr[] expr, Expr... args) { + this.name = name; + this.localConfig = config; + this.compile(expr, args); + } + + /** + * Use the given cloud configuration other than the global one + * @param conf + */ + public void setCloudConfig(CloudConfig conf) { + this.localConfig = conf; + } + + /** + * Return current cloud configuration. Default is the global configuration. + * @return + */ + public CloudConfig getCloudConfig() { + if(this.localConfig != null) + return this.localConfig; + return CloudConfig.getGlobalConfig(); + } + + /** + * flag=true: run apply() method asynchronously + * flag=false: run apply() method synchronously + * + * @param flag + */ + public void isAsyncApply(boolean flag) { + this.isAsync = flag; + } + + public void apply(CloudSD output, CloudSD ...inputs) { + CloudConfig config = getCloudConfig(); + config.setCurrentClient(this.device); + + //Make sure the output has the same CloudConfig as CloudFunc + output.setCloudConfig(config); + + //for input see the priority of cloud config + //TODO need better implementation for the priority in CloudSD + for(int i=0; i= 0) { + //Set the flag before starting evaluating thread + output.setIsReady(false); + //Start a thread to do evaluation, the result will be write back to output once + //it is done. Call the method output.fetch() will block until the data is ready + new Thread(new FuncEvalThread(this, output, inputs)).start(); + return; + } + + if(inputs.length == 0) { + switch(funcType) { + case SCALAR: + output.resize(1); + output.setData(0, func.apply()); + break; + case VECTOR: + throw new UnsupportedOperationException(); + case BATCH: + throw new UnsupportedOperationException(); + default: + throw new RuntimeException(); + } + } else if(inputs.length == 1) { + double[] data = null; + double d; + switch(funcType) { + case SCALAR: + //TODO Support multiple CloudSD inputs + data = inputs[0].getData(); + d = func.apply(data); + output.resize(1); + output.setData(0, d); + break; + case VECTOR: + throw new UnsupportedOperationException(); + case BATCH: + data = inputs[0].getData(); + double[] out = output.getData(); + batchFunc.apply(out, 0, data); + break; + default: + throw new RuntimeException(); + } + } else { + + } + } else { + //Store argument on cloud first if necessary + for(int i=0; i clazz) { + this.name = clazz.getSimpleName(); + this.clazz = clazz; + + if(getCloudConfig().isLocalConfig()) { + try { + method = clazz.getMethod("apply", new Class[] {double[].class}); + } catch (Exception e) { + e.printStackTrace(); + } + } else { + String filePath = System.getProperty("user.dir")+"/"+clazz.getName().replace(".", "/")+".class"; + File f = new File(filePath); + if(!f.exists()) { + filePath = System.getProperty("user.dir")+"/bin/"+clazz.getName().replace(".", "/")+".class"; + f = new File(filePath); + if(!f.exists()) { + filePath = clazz.getProtectionDomain().getCodeSource().getLocation().getPath()+ + clazz.getName().replace(".", "/")+".class"; + } + } + Path path = Paths.get(filePath); + try { + byte[] data = Files.readAllBytes(path); + IR ir = new IR(); + ir.type = FUNC_TYPE.SCALAR; + ir.name = clazz.getName(); + ir.bytes = data; + this.funcIR = ir; + CloudFuncHandler handler =getCloudConfig().getCurrentClient().getCloudFuncHandler(); + Channel ch = getCloudConfig().getCurrentClient().getChannel(); + try { + ch.writeAndFlush(this).sync(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + CloudResp resp = handler.getCloudResp(); + if(resp.status == 0) + this.isOnCloud = true; + else + this.isOnCloud = false; + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + private CloudFunc compile(Expr expr) { + List args = Utils.extractSymbols(expr); + return compile(expr, args.toArray(new Expr[0])); + } + + private CloudFunc compile(Expr expr, Expr[] args) { + Expr compileExpr = expr; + + this.device = 0; + if(null != expr.getDevice()) + this.device = Integer.parseInt(expr.getDevice().name); + //System.out.println("CloudFunc: compile " + expr + ", send to device: " + expr.getDevice().name); + + CloudConfig config = getCloudConfig(); + config.setCurrentClient(config.getClientByIndex(this.device)); + + //TODO Do we need LCReturn? It depends on how the compile function treat the return value of an expr + if(!(expr instanceof LCBase)) { + compileExpr = new LCReturn(expr); + } + + if(config.isLocalConfig()) { + //Reset flags to generate matrix, vector declaration in a new func + CompileUtils.bytecodeGenResetAll(expr); + + if(expr.getType() == TYPE.MATRIX || expr.getType() == TYPE.VECTOR) { + this.vecFunc = CompileUtils.compileVecFunc(name, compileExpr, args); + this.funcType = FUNC_TYPE.VECTOR; //BytecodeVecFunc + if(expr.getType() == TYPE.VECTOR) + this.outAryLen = expr.getTypeInfo().dim[0]; + else if(expr.getType() == TYPE.MATRIX) + this.outAryLen = expr.getTypeInfo().dim[0]*expr.getTypeInfo().dim[1]; + this.numArgs = args.length; + } else { + funcType = FUNC_TYPE.SCALAR; + func = CompileUtils.compile(name, compileExpr, args); + //func = JIT.compile(args, expr); + + } + } else { + //send the expression to the server + this.funcIR = CompileUtils.getIR(name, compileExpr, args); + this.funcType = funcIR.type; + this.outAryLen = funcIR.outAryLen; + this.numArgs = funcIR.numArgs; + + //funcIR = JIT.getIR(name, args, expr); + CloudFuncHandler handler = config.getCurrentClient().getCloudFuncHandler(); + Channel ch = config.getCurrentClient().getChannel(); + try { + ch.writeAndFlush(this).sync(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + CloudResp resp = handler.getCloudResp(); + if(resp.status == 0) + this.isOnCloud = true; + else + this.isOnCloud = false; + } + return this; + } + + private CloudFunc compile(Expr[] exprs) { + List args = Utils.extractSymbols(exprs); + compile(args.toArray(new Expr[0]), exprs); + return this; + } + + private CloudFunc compile(Expr[] exprs, Expr[] args) { + if(getCloudConfig().isLocalConfig()) { + this.funcType = FUNC_TYPE.BATCH; + this.outAryLen = -1; //Determined by input CloudSD + this.numArgs = args.length; + //both works: + //this.batchFunc = JIT.compileBatchFunc(args, exprs); + this.batchFunc = CompileUtils.compileBatchFunc(name, exprs, args); + } else { + //Need reconsider + //method 1: See CompileUtils.compileBatchFunc which follows the implementation of JIT.compileBatchFunc() + //BytecodeBatchFunc func = CompileUtils.compileBatchFunc(name, exprs, args); + //this.funcType = FUNC_TYPE.BATCH; + //this.batchFunc = func; + + //method 2: use output for vecfunction (not work, return a BytecodeVecFunc) +// int dim = exprs.length; +// LCStatements lcs = new LCStatements(); +// LCArray outAry = new LCDoubleArray("outAry"); +// for(int i=0; i + * An instance of CloudSD represents a shared data set on the cloud server. + * The data set can be created on local machine and stored to the cloud side. + * A data set on the cloud server can be download to local machine by + * providing its name. + *
+ * + * priority: + * 1. csd://ip_address/var_name + * 2. useCloudConfig + * 3. globalCloudConfig + * + * + *
+ * Example: + *

+ *     CloudSD data = new CloudSD("myvar").init(new double[]{1, 2, 3, 4, 5});
+ *     data.push(); // Push data onto cloud
+ *     if(data.fetch()) {
+ *       for(double d : data.getData()) {
+ *         System.out.println(d);
+ *       }
+ *     }
+ * 
+ * + */ +public class CloudSD extends Symbol { + protected double[] data = new double[0]; + protected boolean isOnCloud = false; + + protected CloudConfig localConfig = null; + + protected boolean isReady = true;//Indicate if the result of a function is under evaluating + protected boolean isAsync = false; //Test purpose: isAsync==true when isReady==false + + private static AtomicInteger cdsVarNameGenerator = new AtomicInteger(0); + protected boolean isGenName = false; //A flag to indicate if the name is a generated name + + /** + * Construct an instance with a generated name + */ + public CloudSD() { + super(generateName()); + this.isGenName = true; + } + + /** + * Construct an instance with a given name + * + * @param name + */ + public CloudSD(String name) { + super(name); + } + + /** + * Construct a CloudSD object with a generated name based on a given expression. + * This constructor is used to create a new instance of CloudSD from other CloudSD. + *
+ * An example application is in the iterating algorithms as below: + * for(int i=0; i data.length) { + System.arraycopy(this.data, 0, newdata, 0, this.data.length); + } else { + System.arraycopy(this.data, 0, newdata, 0, size); + } + this.data = newdata; + } + return this; + } + + /** + * Return the length of the backed array + * @return + */ + public int size() { + return data.length; + } + + /** + * Return the length of the backed array + * @return + */ + public int length() { + return data.length; + } + + /** + * Return the name of the cloud variable. The name is the identifier + * of the cloud variable on the cloud server. Any local instance of + * CloudSD has the same name will be assumed to be the same variable + * on the cloud side. + * @return + */ + public String getName() { + String[] arr = this.label.split("/"); + if(arr.length > 1) + return arr[arr.length-1]; + else + return this.label; + } + + public String getFullName() { + return this.label; + } + + private String[] parseName(String name) { + if(name.startsWith("csd://")) { + String host_ip = this.label.substring(6); + host_ip = host_ip.substring(0, host_ip.indexOf('/')); + String[] arr = host_ip.split(":"); + if(arr.length == 2) return arr; + } + return null; + } + + /** + * Store the local variable to the cloud. + * priority: + * 1. csd://ip_address/var_name + * 2. useCloudConfig + * 3. globalCloudConfig + * TODO change name to store() + */ + public boolean push() { + String[] host_ip = parseName(this.getFullName()); + if(host_ip != null) { + CloudClient c = new CloudClient(host_ip[0], Integer.valueOf(host_ip[1])); + try { + c.connect(); + } catch (Exception e) { + e.printStackTrace(); + } + return push(c); + } + CloudClient client = getCloudConfig().getCurrentClient(); + if(!getCloudConfig().isLocalConfig()) { + return push(client); + } else { + this.isOnCloud = false; + } + return this.isOnCloud; + } + + private boolean push(CloudClient client) { + CloudSDRespHandler handler = client.getCloudSDRespHandler(); + try { + System.err.println("Pushing data: "+this.toString()+" to "+client.toString()); + client.getChannel().writeAndFlush(this).sync(); + CloudSDResp resp = handler.getCloudResp(); + if(resp.status == 0) + this.isOnCloud = true; + else + this.isOnCloud = false; + } catch (InterruptedException e) { + e.printStackTrace(); + } + return this.isOnCloud; + } + + /** + * Fetch a cloud variable to local. The name of the variable + * on the cloud must be specified. Return true if success. + * Call getData() to access the data in the cloud variable + * TODO change name to fetch() + * @return + */ + public boolean fetch() { + String[] host_ip = parseName(this.getFullName()); + if(host_ip != null && host_ip.length == 2) { + CloudClient c = new CloudClient(host_ip[0], Integer.valueOf(host_ip[1])); + try { + c.connect(); + } catch (Exception e) { + e.printStackTrace(); + } + System.err.println("Fetching data "+this.getFullName()); + return fetch(c); + } + if(getCloudConfig().isLocalConfig()) { + synchronized(this) { + while(!isReady) { //Return immediately if it is ready + //Block until it is ready + try { + System.out.println("Fetching: "+this.toString()); + wait(); + System.out.println("Fetched: "+this.toString()); + return true; + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + if(isAsync) //only for test purpose + System.out.println("Fetched without waiting: "+this.toString()); + return true; + } else { + CloudClient client = getCloudConfig().getCurrentClient(); + return fetch(client); + } + } + + private boolean fetch(CloudClient client) { + Channel ch = client.getChannel(); + CloudQuery qry = new CloudQuery(); + qry.objName = this.getFullName(); + qry.qryType = CloudQuery.CLOUD_SD; + try { + ch.writeAndFlush(qry).sync(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + CloudSDHandler h = client.getCloudSDHandler(); + + //while(true) { + CloudSD var = h.getCloudSD(); + this.data = var.data; + this.isOnCloud = var.isOnCloud(); + if(this.data.length > 0) + return this.isOnCloud; + return false; + //} + } + + public boolean isOnCloud() { + return isOnCloud; + } + + public void setOnCloudFlag(boolean flag) { + this.isOnCloud = flag; + } + + @Override + public Expr simplify() { + return null; + } + + @Override + public boolean symEquals(Expr other) { + return false; + } + + @Override + public Expr diff(Expr expr) { + return null; + } + + public static CloudSD valueOf(Expr expr) { + return new CloudSD(expr); + } + + public Expr assign(Expr expr) { + return new LCAssign(this, expr); + } + + public Expr assign(double val) { + return new LCAssign(this, Expr.valueOf(val)); + } + + public Expr assign(int val) { + return new LCAssign(this, Expr.valueOf(val)); + } + + public String toString() { + if(isOnCloud) + return this.getFullName()+" = "+printData() + " (On Cloud)"; + else + return this.getFullName()+" = "+printData(); + } + + private String printData() { + if(data == null || data.length == 0) + return "[]"; + int max = 10; + if(data.length < max) max = data.length; + StringBuilder sb = new StringBuilder(); + sb.append("[").append(data[0]); + for(int i=1; i max) + sb.append(", ...]; len="+data.length); + else + sb.append("]"); + return sb.toString(); + } + + public void setIsReady(boolean flag) { + isReady = flag; + if(!isReady) isAsync = true; + } + + /** + * Return true if the name is a generated name other than + * a user specified name. + *
+ * The generated name of the return value of a function will + * always be replaced by the generated name from a cloud server + * + * @return + */ + public boolean isGenName() { + return this.isGenName; + } + + private CloudSD compile(String name, Expr expr) { + if(getCloudConfig().isLocalConfig()) { + CloudSD[] args = Utils.extractCloudSDs(expr).toArray(new CloudSD[0]); + BytecodeVecFunc fexpr = JIT.compileVecFunc(args, expr); + data = new double[args[0].size()]; + fexpr.apply(data, 0, Utils.getDataFromCloudSDs(args)); + } else { + //expr contains server references + //TODO Is it possible to lazy eval the expr at cloud side? + // that is to say this CloudSD is the return value of a CloudFunc + // which constructed from the given expr? + + + + } + return this; + } + +} + diff --git a/src/lambdacloud/core/LambdaCloud.java b/src/lambdacloud/core/LambdaCloud.java new file mode 100644 index 0000000..7188c20 --- /dev/null +++ b/src/lambdacloud/core/LambdaCloud.java @@ -0,0 +1,20 @@ +package lambdacloud.core; + +import lambdacloud.core.lang.LCDevice; +import symjava.symbolic.Expr; + +public class LambdaCloud { + //Just for test + public static int maxNumCPU = 3; + public static int currentCPU = 0; + public static Expr CPU(Expr expr) { + expr.runOn(new LCDevice(String.valueOf(currentCPU%maxNumCPU))); + currentCPU++;//round robin + return expr; + } + + public static Expr GPU(Expr expr) { + expr.runOn(new LCDevice("/gpu")); + return expr; + } +} diff --git a/src/lambdacloud/core/Session.java b/src/lambdacloud/core/Session.java new file mode 100644 index 0000000..a9a4347 --- /dev/null +++ b/src/lambdacloud/core/Session.java @@ -0,0 +1,248 @@ +package lambdacloud.core; + +import java.util.Map; + +import lambdacloud.core.graph.GraphBuilder; +import lambdacloud.core.graph.Node; +import symjava.symbolic.Expr; +import symjava.symbolic.Matrix; +import symjava.symbolic.Vector; + +public class Session { + CloudConfig config; + + public Session() { + config = CloudConfig.setGlobalConfig("job_local.conf"); + } + + public Session(CloudConfig config) { + this.config = config; + } + + /** + * In this mode (either in local or on server), we always fetch data to local before evaluating a function + * + * @param expr + * @param dict + * @return + */ + public double runSimple(Expr expr, Map dict) { + //CloudConfig.setGlobalTarget("job_local.conf"); + GraphBuilder gb = new GraphBuilder(config); + Node n = gb.build(expr); + return runSimple(n, dict); + } + + /** + * + * @param expr + * @param dict + * @return + */ + public double runSimpleAsync(Expr expr, Map dict) { + //CloudConfig.setGlobalTarget("job_local.conf"); + GraphBuilder gb = new GraphBuilder(config); + Node n = gb.build(expr); + CloudSD output = runSimpleAsync(n, dict); + output.fetch(); + return output.getData(0); + } + + /** + * For matrix and vector + * + * Allow data fetch from server node + * + * @param expr + * @param dict + * @return + */ + public CloudSD runVec(Expr expr, Map dict) { + //CloudConfig.setGlobalTarget("job_local.conf"); + GraphBuilder gb = new GraphBuilder(config); + Node n = gb.build(expr); + return runVec(n, dict); + } + + /** + * Allow data fetch from server node + * It is use to test for scalar. The optimization is suitable for matrix and vectors + * + * @param expr + * @param dict + * @return + */ + public CloudSD runOpt(Expr expr, Map dict) { + //CloudConfig.setGlobalTarget("job_local.conf"); + GraphBuilder gb = new GraphBuilder(config); + Node n = gb.build(expr); + return runOpt(n, dict); + } + + public CloudSD runVec(Node root, Map dict) { + int nArgs = root.args.size(); + CloudSD[] inputs = new CloudSD[nArgs]; + + for(int i=0; i>Session eval: "+root.cfunc.getFullName()+"="+root+"; args:\n["); + for(int i=0; i dict) { + double[] args = new double[root.args.size()]; + + for(int i=0; i dict) { + CloudSD[] args = new CloudSD[root.args.size()]; + + for(int i=0; i dict) { + CloudSD[] args = new CloudSD[root.args.size()]; + + for(int i=0; i>Session eval: "+root.cfunc.getFullName()+"="+root+"; args:\n["); + //Utils.joinLabels(args, ", "); + for(int i=0; i dict) { + GraphBuilder gb = new GraphBuilder(config); + gb.enableRunLocal(); + Node n = gb.build(expr); + return runLocal(n, dict); + } + + public double runLocal(Node root, Map dict) { + double[] args = new double[root.args.size()]; + for(int i=0; i args = new ArrayList(); //arguments of expr; added at compile time + + public BytecodeFunc func; //for test purpose + + public CloudFunc cfunc; // All the server info are stored in CloudFunc + public Map children = new HashMap(); //Map of the child nodes if an argument is a node + + public boolean isDevice() { + return expr.getDevice()!=null; + } + + public Node(Expr expr) { + this.expr = expr; + } + + public String toString() { + return expr.toString(); + } +} diff --git a/src/lambdacloud/core/lang/LCArray.java b/src/lambdacloud/core/lang/LCArray.java new file mode 100644 index 0000000..d8becb1 --- /dev/null +++ b/src/lambdacloud/core/lang/LCArray.java @@ -0,0 +1,166 @@ +package lambdacloud.core.lang; + +import java.util.Map; + +import symjava.symbolic.Expr; +import symjava.symbolic.TypeInfo; + +import com.sun.org.apache.bcel.internal.generic.ALOAD; +import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.InstructionConstants; +import com.sun.org.apache.bcel.internal.generic.InstructionFactory; +import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.MethodGen; +import com.sun.org.apache.bcel.internal.generic.PUSH; + +public abstract class LCArray extends LCVar { + protected LCArray arrayRef; + protected Expr index; + + protected int argsDim = 2; // e.g. apply(..., double[][] args), argsDim = 2 + + public LCArray(String name) { + super(name); + arrayRef = null; + index = null; + } + + public LCArray(LCArray array, Expr index) { + super(array + "["+index+"]"); + this.arrayRef = array; + this.index = index; + } + + public LCArray(LCArray array, int index) { + super(array + "["+index+"]"); + this.arrayRef = array; + this.index = Expr.valueOf(index); + } + + public LCArray getArrayRef() { + return arrayRef; + } + + public Expr getIndex() { + return index; + } + + public LCLength getLength() { + return new LCLength(this); + } + + public LCLength size() { + return new LCLength(this); + } + + public String getName() { + LCArray tmp = this; + while(tmp.arrayRef != null) { + tmp = tmp.arrayRef; + } + return tmp.getLabel(); + } + + public void setArgsDim(int dim) { + this.argsDim = dim; + } + + public int getArgsDim() { + return this.argsDim; + } + + @Override + public InstructionHandle bytecodeGen(String clsName, MethodGen mg, + ConstantPoolGen cp, InstructionFactory factory, + InstructionList il, Map argsMap, int argsStartPos, + Map funcRefsMap) { + InstructionHandle startPos = null; + if(this.isLocalVar()) { + startPos = il.append(new ALOAD(indexLVT)); + index.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + LCArray tmp = this; + while(tmp.arrayRef.index != null) { + il.append(InstructionConstants.AALOAD); + il.append(new ALOAD(tmp.arrayRef.indexLVT)); + tmp.arrayRef.index.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + tmp = tmp.arrayRef; + } + TYPE ty = this.getType(); + if(ty == TYPE.DOUBLE) + return il.append(InstructionConstants.DALOAD); + if(ty == TYPE.INT) + return il.append(InstructionConstants.IALOAD); + if(ty == TYPE.LONG) + return il.append(InstructionConstants.LALOAD); + if(ty == TYPE.FLOAT) + return il.append(InstructionConstants.FALOAD); + return il.append(InstructionConstants.IALOAD); + } else { + LCArray tmp = this; + while(tmp.arrayRef.index != null) { + tmp = tmp.arrayRef; + } + //TODO need refactor + this.argsDim = tmp.arrayRef.argsDim; + + // Load from arguments + startPos = il.append(new ALOAD(argsStartPos)); + // Support both compile() and compileVec() + for(int i=0; i argsMap, int argsStartPos, + Map funcRefsMap) { + boolean find = false; + InstructionHandle pos = null; + LCBase tmp = this; + while(tmp.parent != null) { + if(tmp.parent instanceof LCLoop) { + pos = il.append(InstructionConstants.NOP); + ((LCLoop)tmp.parent).addBreakPos(pos); + find = true; + break; + } + tmp = tmp.parent; + } + if(!find) + throw new RuntimeException(); + return pos; + + } +} diff --git a/src/lambdacloud/core/lang/LCBuilder.java b/src/lambdacloud/core/lang/LCBuilder.java new file mode 100644 index 0000000..f2dd774 --- /dev/null +++ b/src/lambdacloud/core/lang/LCBuilder.java @@ -0,0 +1,167 @@ +package lambdacloud.core.lang; + +import java.util.ArrayList; +import java.util.List; + +import lambdacloud.core.CloudConfig; +import lambdacloud.core.CloudFunc; +import lambdacloud.core.CloudSD; +import symjava.symbolic.Expr; + +/** + * Lambda Cloud instruction builder + * + */ +public class LCBuilder { + protected CloudConfig config; + List stmts = new ArrayList(); + + public LCBuilder(CloudConfig config) { + this.config = config; + } + + public LCBuilder(String configFile) { + this.config = new CloudConfig(configFile); + } + + public LCLoop For(Expr initExpr, Expr conditionExpr, Expr incrementExpr) { + LCLoop cl = new LCLoop(initExpr, conditionExpr, incrementExpr); + stmts.add(cl); + return cl; + } + + public LCLoop While(Expr conditionExpr) { + LCLoop stmt = new LCLoop(conditionExpr); + stmts.add(stmt); + return stmt; + } + + public LCIf If(Expr condition) { + LCIf stmt = new LCIf(condition); + stmts.add(stmt); + return stmt; + } + + public LCReturn Return(Expr expr) { + LCReturn stmt = new LCReturn(expr); + stmts.add(stmt); + return stmt; + } + + public LCReturn Return(double expr) { + LCReturn stmt = new LCReturn(expr); + stmts.add(stmt); + return stmt; + } + + public LCBuilder append(Expr expr) { + stmts.add(expr); + return this; + } + + public CloudSD declareCloudSD(String name) { + return new CloudSD(name); + } + + public LCInt declareInt(String name) { + return new LCInt(name); + } + + public LCLong declareLong(String name) { + return new LCLong(name); + } + + public LCFloat declareFloat(String name) { + return new LCFloat(name); + } + + public LCDouble declareDouble(String name) { + return new LCDouble(name); + } + + public LCShort declareShort(String name) { + return new LCShort(name); + } + + public LCVar declareChar(String name) { + return new LCChar(name); + } + + public LCByte declareByte(String name) { + return new LCByte(name); + } + + public CloudFunc build(LCVar ...args) { + CloudFunc func = new CloudFunc(this.config, new LCStatements(this.stmts), args); + return func; + } + +// public BytecodeFunc compile(Expr ...args) { +// String packageName = "symjava.bytecode"; +// String clsName = "LC" + java.util.UUID.randomUUID().toString().replaceAll("-", ""); +// String fullClsName = packageName+"."+clsName; +// ClassGen cg = new ClassGen(fullClsName, "java.lang.Object", +// "", ACC_PUBLIC | ACC_SUPER, new String[]{"symjava.bytecode.BytecodeFunc"}); +// ConstantPoolGen cp = cg.getConstantPool(); // cg creates constant pool +// InstructionList il = new InstructionList(); +// InstructionFactory factory = new InstructionFactory(cg); +// +// short acc_flags = ACC_PUBLIC; +// MethodGen mg = new MethodGen(acc_flags, // access flags +// Type.DOUBLE, // return type +// new Type[] { // argument types +// new ArrayType(Type.DOUBLE, 1) +// }, +// new String[] { "args" }, // arg names +// "apply", fullClsName, // method, class +// il, cp); +// +// List vars = Utils.extractSymbols(this.stmts.toArray(new Expr[0])); +// for(Expr var : vars) { +// if(var instanceof LCVar) { +// LCVar cv = (LCVar)var; +// int indexLVT = BytecodeUtils.declareLocal(cv, mg, il); +// cv.setLVTIndex(indexLVT); +// } +// } +// +// HashMap argsMap = new HashMap(); +// if(args != null) { +// for(int i=0; i fcl = new FuncClassLoader(); +// BytecodeFunc fun = fcl.newInstance(cg); +// return fun; +// } + + public String toString() { + StringBuilder sb = new StringBuilder(); + for(Expr e : stmts) { + sb.append(e).append("\n"); + } + return sb.toString(); + } +} diff --git a/src/lambdacloud/core/lang/LCByte.java b/src/lambdacloud/core/lang/LCByte.java new file mode 100644 index 0000000..7188280 --- /dev/null +++ b/src/lambdacloud/core/lang/LCByte.java @@ -0,0 +1,14 @@ +package lambdacloud.core.lang; + +import symjava.symbolic.TypeInfo; + +public class LCByte extends LCVar { + public LCByte(String name) { + super(name); + } + + @Override + public TypeInfo getTypeInfo() { + return TypeInfo.tiByte; + } +} diff --git a/src/lambdacloud/core/lang/LCByteArray.java b/src/lambdacloud/core/lang/LCByteArray.java new file mode 100644 index 0000000..d49194e --- /dev/null +++ b/src/lambdacloud/core/lang/LCByteArray.java @@ -0,0 +1,31 @@ +package lambdacloud.core.lang; + +import symjava.symbolic.Expr; + +public class LCByteArray extends LCArray { + + public LCByteArray(String name) { + super(name); + } + + public LCByteArray(LCByteArray array, int index) { + super(array + "["+index+"]"); + this.arrayRef = array; + this.index = Expr.valueOf(index); + } + public LCByteArray(LCByteArray array, Expr index) { + super(array + "["+index+"]"); + this.arrayRef = array; + this.index = index; + } + + @Override + public LCByteArray get(int index) { + return new LCByteArray(this, index); + } + + @Override + public LCByteArray get(Expr index) { + return new LCByteArray(this, index); + } +} diff --git a/src/lambdacloud/core/lang/LCChar.java b/src/lambdacloud/core/lang/LCChar.java new file mode 100644 index 0000000..c808e01 --- /dev/null +++ b/src/lambdacloud/core/lang/LCChar.java @@ -0,0 +1,15 @@ +package lambdacloud.core.lang; + +import symjava.symbolic.TypeInfo; + + +public class LCChar extends LCVar { + public LCChar(String name) { + super(name); + } + + @Override + public TypeInfo getTypeInfo() { + return TypeInfo.tiChar; + } +} diff --git a/src/lambdacloud/core/lang/LCCharArray.java b/src/lambdacloud/core/lang/LCCharArray.java new file mode 100644 index 0000000..5594a78 --- /dev/null +++ b/src/lambdacloud/core/lang/LCCharArray.java @@ -0,0 +1,32 @@ +package lambdacloud.core.lang; + +import symjava.symbolic.Expr; + +public class LCCharArray extends LCArray { + + public LCCharArray(String name) { + super(name); + } + + public LCCharArray(LCCharArray array, int index) { + super(array + "["+index+"]"); + this.arrayRef = array; + this.index = Expr.valueOf(index); + } + + public LCCharArray(LCCharArray array, Expr index) { + super(array + "["+index+"]"); + this.arrayRef = array; + this.index = index; + } + + @Override + public LCCharArray get(int index) { + return new LCCharArray(this, index); + } + + @Override + public LCCharArray get(Expr index) { + return new LCCharArray(this, index); + } +} diff --git a/src/lambdacloud/core/lang/LCDevice.java b/src/lambdacloud/core/lang/LCDevice.java new file mode 100644 index 0000000..99f1add --- /dev/null +++ b/src/lambdacloud/core/lang/LCDevice.java @@ -0,0 +1,12 @@ +package lambdacloud.core.lang; + +public class LCDevice { + public String name; + public LCDevice(int indexNum) { + this.name = String.valueOf(indexNum); + } + + public LCDevice(String name) { + this.name = name; + } +} diff --git a/src/lambdacloud/core/lang/LCDouble.java b/src/lambdacloud/core/lang/LCDouble.java new file mode 100644 index 0000000..4a86b7a --- /dev/null +++ b/src/lambdacloud/core/lang/LCDouble.java @@ -0,0 +1,15 @@ +package lambdacloud.core.lang; + +import symjava.symbolic.TypeInfo; + + +public class LCDouble extends LCVar { + public LCDouble(String name) { + super(name); + } + + @Override + public TypeInfo getTypeInfo() { + return TypeInfo.tiDouble; + } +} diff --git a/src/lambdacloud/core/lang/LCDoubleArray.java b/src/lambdacloud/core/lang/LCDoubleArray.java new file mode 100644 index 0000000..f889fea --- /dev/null +++ b/src/lambdacloud/core/lang/LCDoubleArray.java @@ -0,0 +1,33 @@ +package lambdacloud.core.lang; + +import symjava.symbolic.Expr; + +public class LCDoubleArray extends LCArray { + + public LCDoubleArray(String name) { + super(name); + } + + public LCDoubleArray(LCDoubleArray array, int index) { + super(array + "["+index+"]"); + this.arrayRef = array; + this.index = Expr.valueOf(index); + } + + public LCDoubleArray(LCDoubleArray array, Expr index) { + super(array + "["+index+"]"); + this.arrayRef = array; + this.index = index; + } + + @Override + public LCDoubleArray get(int index) { + return new LCDoubleArray(this, index); + } + + @Override + public LCArray get(Expr index) { + return new LCDoubleArray(this, index); + } + +} diff --git a/src/lambdacloud/core/lang/LCFloat.java b/src/lambdacloud/core/lang/LCFloat.java new file mode 100644 index 0000000..e9b9429 --- /dev/null +++ b/src/lambdacloud/core/lang/LCFloat.java @@ -0,0 +1,15 @@ +package lambdacloud.core.lang; + +import symjava.symbolic.TypeInfo; + + +public class LCFloat extends LCVar { + public LCFloat(String name) { + super(name); + } + + @Override + public TypeInfo getTypeInfo() { + return TypeInfo.tiFloat; + } +} diff --git a/src/lambdacloud/core/lang/LCFloatArray.java b/src/lambdacloud/core/lang/LCFloatArray.java new file mode 100644 index 0000000..532662e --- /dev/null +++ b/src/lambdacloud/core/lang/LCFloatArray.java @@ -0,0 +1,31 @@ +package lambdacloud.core.lang; + +import symjava.symbolic.Expr; + +public class LCFloatArray extends LCArray { + + public LCFloatArray(String name) { + super(name); + } + + public LCFloatArray(LCFloatArray array, int index) { + super(array + "["+index+"]"); + this.arrayRef = array; + this.index = Expr.valueOf(index); + } + public LCFloatArray(LCFloatArray array, Expr index) { + super(array + "["+index+"]"); + this.arrayRef = array; + this.index = index; + } + + @Override + public LCFloatArray get(int index) { + return new LCFloatArray(this, index); + } + + @Override + public LCFloatArray get(Expr index) { + return new LCFloatArray(this, index); + } +} diff --git a/src/lambdacloud/core/lang/LCIf.java b/src/lambdacloud/core/lang/LCIf.java new file mode 100644 index 0000000..0d1cfd5 --- /dev/null +++ b/src/lambdacloud/core/lang/LCIf.java @@ -0,0 +1,213 @@ +package lambdacloud.core.lang; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import lambdacloud.core.CloudSD; +import symjava.logic.Logic; +import symjava.relational.Eq; +import symjava.relational.Ge; +import symjava.relational.Gt; +import symjava.relational.Lt; +import symjava.relational.Relation; +import symjava.symbolic.Expr; +import symjava.symbolic.utils.BytecodeUtils; +import symjava.symbolic.utils.Utils; + +import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.GOTO; +import com.sun.org.apache.bcel.internal.generic.IFGE; +import com.sun.org.apache.bcel.internal.generic.IFLE; +import com.sun.org.apache.bcel.internal.generic.IF_ICMPGT; +import com.sun.org.apache.bcel.internal.generic.IF_ICMPLE; +import com.sun.org.apache.bcel.internal.generic.IF_ICMPNE; +import com.sun.org.apache.bcel.internal.generic.InstructionConstants; +import com.sun.org.apache.bcel.internal.generic.InstructionFactory; +import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.MethodGen; + +public class LCIf extends LCBase { + + Expr condition; + List trueStmts = new ArrayList(); + List falseStmts = new ArrayList(); + public LCIf(Expr condition, CloudSD ...args) { + this.condition = condition; + updateLabel(); + } + + public void updateLabel() { + StringBuilder sb = new StringBuilder(); + sb.append(indent).append("if( ").append(condition).append(" ) {\n"); + for(Expr e : trueStmts) { + if(e instanceof LCBase) { + sb.append(indent).append(e).append("\n"); + } else + sb.append(indent).append("\t").append(e).append(";\n"); + } + if(falseStmts.size() > 0) { + sb.append("} else {\n"); + for(Expr e : falseStmts) { + if(e instanceof LCBase) { + sb.append(indent).append(e).append("\n"); + } else + sb.append(indent).append("\t").append(e).append(";\n"); + } + } + sb.append(indent).append("}"); + this.label = sb.toString(); + + } + + public LCIf appendTrue(Expr expr) { + if(expr instanceof LCBase) { + ((LCBase) expr).setParent(this).indent(); + } + trueStmts.add(expr); + updateLabel(); + return this; + } + + public LCIf appendFalse(Expr expr) { + if(expr instanceof LCBase) { + ((LCBase) expr).setParent(this).indent(); + } + falseStmts.add(expr); + updateLabel(); + return this; + } + + @Override + public InstructionHandle bytecodeGen(String clsName, MethodGen mg, + ConstantPoolGen cp, InstructionFactory factory, + InstructionList il, Map argsMap, int argsStartPos, + Map funcRefsMap) { + if(condition instanceof Logic) { + il.append(InstructionConstants.ICONST_1); + InstructionHandle startPos = condition.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + + InstructionHandle trueBranchStart = null; + for(Expr te : trueStmts) { + InstructionHandle pos = te.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + if(trueBranchStart == null) + trueBranchStart = pos; + } + if(trueBranchStart == null) trueBranchStart = il.append(InstructionConstants.NOP); + + InstructionHandle falseBranchStart = null; + for(Expr fe : falseStmts) { + InstructionHandle pos = fe.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + if(falseBranchStart == null) + falseBranchStart = pos; + } + if(falseBranchStart == null) falseBranchStart = il.append(InstructionConstants.NOP); + + InstructionHandle endPos = il.append(InstructionConstants.NOP); + + il.insert(trueBranchStart, new IF_ICMPGT(falseBranchStart)); + il.insert(falseBranchStart, new GOTO(endPos)); + return startPos; + } + + if(!(condition instanceof Relation)) + throw new RuntimeException(); + + Relation cond = (Relation)condition; + InstructionHandle startPos = null; + InstructionHandle endPos = null; + if(cond instanceof Gt) { // l > r + TYPE ty = Utils.getConvertedType(cond.lhs().getType(), cond.rhs().getType()); + cond.lhs().bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + BytecodeUtils.typeCast(il, cond.lhs().getType(), ty); + cond.rhs().bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + BytecodeUtils.typeCast(il, cond.lhs().getType(), ty); + + InstructionHandle trueBranchStart = null; + for(Expr te : trueStmts) { + InstructionHandle pos = te.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + if(trueBranchStart == null) + trueBranchStart = pos; + } + if(trueBranchStart == null) trueBranchStart = il.append(InstructionConstants.NOP); + + InstructionHandle falseBranchStart = null; + for(Expr fe : falseStmts) { + InstructionHandle pos = fe.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + if(falseBranchStart == null) + falseBranchStart = pos; + } + if(falseBranchStart == null) falseBranchStart = il.append(InstructionConstants.NOP); + + endPos = il.append(InstructionConstants.NOP); + + il.insert(trueBranchStart, InstructionConstants.DCMPL); + il.insert(trueBranchStart, new IFLE(falseBranchStart)); + il.insert(falseBranchStart, new GOTO(endPos)); + + } else if(cond instanceof Lt) { // l < r + TYPE ty = Utils.getConvertedType(cond.lhs().getType(), cond.rhs().getType()); + startPos = cond.lhs().bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + BytecodeUtils.typeCast(il, cond.lhs().getType(), ty); + cond.rhs().bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + BytecodeUtils.typeCast(il, cond.lhs().getType(), ty); + + InstructionHandle trueBranchStart = null; + for(Expr te : trueStmts) { + InstructionHandle pos = te.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + if(trueBranchStart == null) + trueBranchStart = pos; + } + if(trueBranchStart == null) trueBranchStart = il.append(InstructionConstants.NOP); + + InstructionHandle falseBranchStart = null; + for(Expr fe : falseStmts) { + InstructionHandle pos = fe.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + if(falseBranchStart == null) + falseBranchStart = pos; + } + if(falseBranchStart == null) falseBranchStart = il.append(InstructionConstants.NOP); + + endPos = il.append(InstructionConstants.NOP); + + il.insert(trueBranchStart, InstructionConstants.DCMPG); + il.insert(trueBranchStart, new IFGE(falseBranchStart)); + il.insert(falseBranchStart, new GOTO(endPos)); + + } else if(cond instanceof Eq) { // l == r + startPos = cond.lhs().bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + cond.rhs().bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + + InstructionHandle trueBranchStart = null; + for(Expr te : trueStmts) { + InstructionHandle pos = te.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + if(trueBranchStart == null) + trueBranchStart = pos; + } + if(trueBranchStart == null) trueBranchStart = il.append(InstructionConstants.NOP); + + InstructionHandle falseBranchStart = null; + for(Expr fe : falseStmts) { + InstructionHandle pos = fe.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + if(falseBranchStart == null) + falseBranchStart = pos; + } + if(falseBranchStart == null) falseBranchStart = il.append(InstructionConstants.NOP); + + endPos = il.append(InstructionConstants.NOP); + il.insert(trueBranchStart, new IF_ICMPNE(falseBranchStart)); + il.insert(falseBranchStart, new GOTO(endPos)); + } + return startPos; + } + + @Override + public Expr[] args() { + List ret = new ArrayList(); + ret.add(condition); + ret.addAll(this.trueStmts); + ret.addAll(this.falseStmts); + return ret.toArray(new Expr[0]); + } +} diff --git a/src/lambdacloud/core/lang/LCInc.java b/src/lambdacloud/core/lang/LCInc.java new file mode 100644 index 0000000..cef496d --- /dev/null +++ b/src/lambdacloud/core/lang/LCInc.java @@ -0,0 +1,47 @@ +package lambdacloud.core.lang; + +import java.util.Map; + +import symjava.symbolic.Expr; + +import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.IINC; +import com.sun.org.apache.bcel.internal.generic.InstructionFactory; +import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.MethodGen; + +/** + * i++ + * + */ +public class LCInc extends LCBase { + LCInt var; + int inc; + public LCInc(LCInt var) { + this.var = var; + this.inc = 1; + updateLabel(); + } + + public LCInc(LCInt var, int increment) { + this.var = var; + this.inc = increment; + updateLabel(); + } + + public void updateLabel() { + if(inc == 1) + this.label = this.indent + this.var+"++"; + else + this.label = this.indent + this.var+"+=" + this.inc; + } + + @Override + public InstructionHandle bytecodeGen(String clsName, MethodGen mg, + ConstantPoolGen cp, InstructionFactory factory, + InstructionList il, Map argsMap, int argsStartPos, + Map funcRefsMap) { + return il.append(new IINC(var.getLVTIndex(), inc)); + } +} diff --git a/src/lambdacloud/core/lang/LCInt.java b/src/lambdacloud/core/lang/LCInt.java new file mode 100644 index 0000000..37437ba --- /dev/null +++ b/src/lambdacloud/core/lang/LCInt.java @@ -0,0 +1,23 @@ +package lambdacloud.core.lang; + +import symjava.symbolic.TypeInfo; + + +public class LCInt extends LCVar { + public LCInt(String name) { + super(name); + } + + @Override + public TypeInfo getTypeInfo() { + return TypeInfo.tiInt; + } + + public LCInc inc() { + return new LCInc(this); + } + + public LCInc inc(int increment) { + return new LCInc(this, increment); + } +} diff --git a/src/lambdacloud/core/lang/LCIntArray.java b/src/lambdacloud/core/lang/LCIntArray.java new file mode 100644 index 0000000..f9d1f67 --- /dev/null +++ b/src/lambdacloud/core/lang/LCIntArray.java @@ -0,0 +1,32 @@ +package lambdacloud.core.lang; + +import symjava.symbolic.Expr; + +public class LCIntArray extends LCArray { + + public LCIntArray(String name) { + super(name); + } + + public LCIntArray(LCIntArray array, int index) { + super(array + "["+index+"]"); + this.arrayRef = array; + this.index = Expr.valueOf(index); + } + + public LCIntArray(LCIntArray array, Expr index) { + super(array + "["+index+"]"); + this.arrayRef = array; + this.index = index; + } + + @Override + public LCIntArray get(int index) { + return new LCIntArray(this, index); + } + + @Override + public LCIntArray get(Expr index) { + return new LCIntArray(this, index); + } +} diff --git a/src/lambdacloud/core/lang/LCLength.java b/src/lambdacloud/core/lang/LCLength.java new file mode 100644 index 0000000..8b74225 --- /dev/null +++ b/src/lambdacloud/core/lang/LCLength.java @@ -0,0 +1,52 @@ +package lambdacloud.core.lang; + +import java.util.Map; + +import symjava.symbolic.Expr; +import symjava.symbolic.TypeInfo; + +import com.sun.org.apache.bcel.internal.generic.ALOAD; +import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.InstructionConstants; +import com.sun.org.apache.bcel.internal.generic.InstructionFactory; +import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.MethodGen; +import com.sun.org.apache.bcel.internal.generic.PUSH; + +public class LCLength extends LCBase { + + protected LCArray arrayRef; + + public LCLength(LCArray array) { + this.arrayRef = array; + this.label = array + ".length"; + } + + @Override + public InstructionHandle bytecodeGen(String clsName, MethodGen mg, + ConstantPoolGen cp, InstructionFactory factory, + InstructionList il, Map argsMap, int argsStartPos, + Map funcRefsMap) { + + InstructionHandle startPos = il.append(new ALOAD(argsStartPos)); + for(int i=0; i bodyList = new ArrayList(); + // Store position for 'break' instruction + List breakPos = new ArrayList(); + + public LCLoop(Expr conditionExpr) { + this.conditionExpr = conditionExpr; + updateLabel(); + } + + public LCLoop(Expr initExpr, Expr conditionExpr) { + this.initExpr = initExpr; + this.conditionExpr = conditionExpr; + updateLabel(); + } + + public LCLoop(Expr initExpr, Expr conditionExpr, Expr incrementExpr) { + this.initExpr = initExpr; + this.conditionExpr = conditionExpr; + this.incrementExpr = incrementExpr; + updateLabel(); + } + + public LCLoop appendBody(Expr expr) { + if(expr instanceof LCBase) { + ((LCBase) expr).setParent(this).indent(); + } + bodyList.add(expr); + updateLabel(); + return this; + } + + public LCLoop breakIf(Expr condition) { + LCIf ifa = new LCIf(condition); + ifa.setParent(this); + ifa.appendTrue(new LCBreak()); + appendBody(ifa); + updateLabel(); + return this; + } + + public void addBreakPos(InstructionHandle pos) { + this.breakPos.add(pos); + } + + public void updateLabel() { + StringBuilder sb = new StringBuilder(); + sb.append(indent).append("for("); + if(initExpr != null) sb.append(initExpr); + sb.append("; "); + if(conditionExpr != null) sb.append(conditionExpr); + sb.append("; "); + if(incrementExpr != null) sb.append(incrementExpr); + sb.append(") {\n"); + for(Expr e : bodyList) { + if(e instanceof LCBase) { + sb.append(indent).append(e).append("\n"); + } else + sb.append(indent).append("\t").append(e).append(";\n"); + } + sb.append("}"); + this.label = sb.toString(); + } + + @Override + public InstructionHandle bytecodeGen(String clsName, MethodGen mg, + ConstantPoolGen cp, InstructionFactory factory, + InstructionList il, Map argsMap, int argsStartPos, + Map funcRefsMap) { + if(!(conditionExpr instanceof Relation)) + throw new RuntimeException(); + Relation cond = (Relation)conditionExpr; + + InstructionHandle loopStart = null; + if(initExpr != null) + loopStart = initExpr.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + + InstructionHandle bodyStart = null; //il.append(new NOP()); // Mark loop start position + for(int i=0; i ret = new ArrayList(); + ret.add(this.initExpr); + ret.add(this.conditionExpr); + ret.add(this.incrementExpr); + ret.addAll(this.bodyList); + return ret.toArray(new Expr[0]); + } +} diff --git a/src/lambdacloud/core/lang/LCReturn.java b/src/lambdacloud/core/lang/LCReturn.java new file mode 100644 index 0000000..0169dec --- /dev/null +++ b/src/lambdacloud/core/lang/LCReturn.java @@ -0,0 +1,119 @@ +package lambdacloud.core.lang; + +import java.util.Map; + +import symjava.symbolic.Expr; +import symjava.symbolic.TypeInfo; +import symjava.symbolic.Expr.TYPE; + +import com.sun.org.apache.bcel.internal.Constants; +import com.sun.org.apache.bcel.internal.generic.ArrayType; +import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.ILOAD; +import com.sun.org.apache.bcel.internal.generic.ISTORE; +import com.sun.org.apache.bcel.internal.generic.InstructionConstants; +import com.sun.org.apache.bcel.internal.generic.InstructionFactory; +import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.LocalVariableGen; +import com.sun.org.apache.bcel.internal.generic.MethodGen; +import com.sun.org.apache.bcel.internal.generic.PUSH; +import com.sun.org.apache.bcel.internal.generic.Type; + +public class LCReturn extends LCBase { + protected Expr arg; + public LCReturn() { + arg = null; + } + + public LCReturn(Expr expr) { + this.arg = expr; + updateLabel(); + } + + public LCReturn(double expr) { + this.arg = Expr.valueOf(expr); + updateLabel(); + } + + public void updateLabel() { + this.label = this.indent + "return " + arg; + + } + + @Override + public InstructionHandle bytecodeGen(String clsName, MethodGen mg, + ConstantPoolGen cp, InstructionFactory factory, + InstructionList il, Map argsMap, int argsStartPos, + Map funcRefsMap) { + if(arg == null) + il.append(InstructionConstants.RETURN); + + InstructionHandle startPos = arg.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + if(arg.getType() == TYPE.MATRIX || arg.getType() == TYPE.VECTOR) { + //Copy results to outAry + LocalVariableGen lg = mg.addLocalVariable("l_ret_len", + Type.INT, null, null); + int idx = lg.getIndex(); + il.append(factory.createInvoke("Jama.Matrix", "getColumnPackedCopy", + new ArrayType(Type.DOUBLE,1), new Type[] {}, + Constants.INVOKEVIRTUAL)); + il.append(InstructionConstants.DUP); + il.append(InstructionConstants.ARRAYLENGTH); + lg.setStart(il.append(new ISTORE(idx))); + + il.append(new PUSH(cp, 0)); + il.append(InstructionConstants.ALOAD_1); //outAry (output buffer) + il.append(InstructionConstants.ILOAD_2); //outPos (start position of output buffer) + il.append(new ILOAD(idx)); + //Call System.arraycopy(src, srcPos, dest, destPos, length); + il.append(factory.createInvoke("java.lang.System", "arraycopy", + Type.VOID, new Type[] { Type.OBJECT, Type.INT, Type.OBJECT, Type.INT, Type.INT }, + Constants.INVOKESTATIC)); + /* + 33: invokevirtual #20 // Method Jama/Matrix.getColumnPackedCopy:()[D + 36: dup + 37: arraylength + 38: istore 6 + 40: iconst_0 + 41: aload_1 + 42: iload_2 + 43: iload 6 + 45: invokestatic #26 // Method java/lang/System.arraycopy:(Ljava/lang/Object;ILjava/lang/Object;II)V + LocalVariableTable: + Start Length Slot Name Signature + 0 49 0 this Lsymjava/bytecode/Multiply1451587171120; + 0 49 1 outAry [D + 0 49 2 outPos I + 0 49 3 args [[D + 11 38 4 l_A LJama/Matrix; + 26 23 5 l_x LJama/Matrix; + 38 11 6 l_ret_len I + + */ + return startPos; + } + TYPE ty = arg.getType(); + if(ty == TYPE.DOUBLE) + il.append(InstructionConstants.DRETURN); + else if(ty == TYPE.INT) + il.append(InstructionConstants.IRETURN); + else if(ty == TYPE.LONG) + il.append(InstructionConstants.LRETURN); + else if(ty == TYPE.FLOAT) + il.append(InstructionConstants.FRETURN); + else + il.append(InstructionConstants.RETURN); + return startPos; + } + + @Override + public Expr[] args() { + return new Expr[]{arg}; + } + + @Override + public TypeInfo getTypeInfo() { + return arg.getTypeInfo(); + } +} diff --git a/src/lambdacloud/core/lang/LCShort.java b/src/lambdacloud/core/lang/LCShort.java new file mode 100644 index 0000000..6c53869 --- /dev/null +++ b/src/lambdacloud/core/lang/LCShort.java @@ -0,0 +1,14 @@ +package lambdacloud.core.lang; + +import symjava.symbolic.TypeInfo; + +public class LCShort extends LCVar { + public LCShort(String name) { + super(name); + } + + @Override + public TypeInfo getTypeInfo() { + return TypeInfo.tiShort; + } +} diff --git a/src/lambdacloud/core/lang/LCShortArray.java b/src/lambdacloud/core/lang/LCShortArray.java new file mode 100644 index 0000000..87c14ba --- /dev/null +++ b/src/lambdacloud/core/lang/LCShortArray.java @@ -0,0 +1,32 @@ +package lambdacloud.core.lang; + +import symjava.symbolic.Expr; + +public class LCShortArray extends LCArray { + + public LCShortArray(String name) { + super(name); + } + + public LCShortArray(LCShortArray array, int index) { + super(array + "["+index+"]"); + this.arrayRef = array; + this.index = Expr.valueOf(index); + } + + public LCShortArray(LCShortArray array, Expr index) { + super(array + "["+index+"]"); + this.arrayRef = array; + this.index = index; + } + + @Override + public LCShortArray get(int index) { + return new LCShortArray(this, index); + } + + @Override + public LCShortArray get(Expr index) { + return new LCShortArray(this, index); + } +} diff --git a/src/lambdacloud/core/lang/LCStatements.java b/src/lambdacloud/core/lang/LCStatements.java new file mode 100644 index 0000000..b0fa14e --- /dev/null +++ b/src/lambdacloud/core/lang/LCStatements.java @@ -0,0 +1,79 @@ +package lambdacloud.core.lang; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import symjava.symbolic.Expr; +import symjava.symbolic.TypeInfo; + +import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.InstructionFactory; +import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.MethodGen; + +public class LCStatements extends LCBase { + List exprList = new ArrayList(); + + public LCStatements() { + + } + + public LCStatements(List exprList) { + this.exprList.addAll(exprList); + updateLabel(); + } + + public LCStatements append(List exprList) { + this.exprList.addAll(exprList); + updateLabel(); + return this; + } + + public LCStatements append(Expr expr) { + exprList.add(expr); + updateLabel(); + return this; + } + + public void updateLabel() { + StringBuilder sb = new StringBuilder(); + for(Expr e : exprList) { + if(e instanceof LCBase) { + sb.append(indent).append(e).append("\n"); + } else + sb.append(indent).append(e).append(";\n"); + } + this.label = sb.toString(); + } + + + @Override + public InstructionHandle bytecodeGen(String clsName, MethodGen mg, + ConstantPoolGen cp, InstructionFactory factory, + InstructionList il, Map argsMap, int argsStartPos, + Map funcRefsMap) { + InstructionHandle loopStart = null; + for(int i=0; i 0) { + Expr last = this.exprList.get(this.exprList.size()-1); + return last.getTypeInfo(); + } + return null; + } +} diff --git a/src/lambdacloud/core/lang/LCVar.java b/src/lambdacloud/core/lang/LCVar.java new file mode 100644 index 0000000..077578b --- /dev/null +++ b/src/lambdacloud/core/lang/LCVar.java @@ -0,0 +1,119 @@ +package lambdacloud.core.lang; + +import java.util.Map; + +import symjava.symbolic.Expr; +import symjava.symbolic.Symbol; + +import com.sun.org.apache.bcel.internal.generic.ALOAD; +import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.DLOAD; +import com.sun.org.apache.bcel.internal.generic.FLOAD; +import com.sun.org.apache.bcel.internal.generic.ILOAD; +import com.sun.org.apache.bcel.internal.generic.InstructionConstants; +import com.sun.org.apache.bcel.internal.generic.InstructionFactory; +import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.LLOAD; +import com.sun.org.apache.bcel.internal.generic.MethodGen; +import com.sun.org.apache.bcel.internal.generic.PUSH; + +/** + * The base type of local variables in a compiled function. + * Type of a local variable is defined in sub-classes of LCVar. + *
+ * The local variables are the same as the local variables in a Java function, + * which is used to store temporary values. + * + */ +public abstract class LCVar extends Symbol { +// protected boolean isDeclaredAsLocal = false; + protected int indexLVT = -1; // index in local variable table + + public LCVar(String name) { + super(name); +// this.isDeclaredAsLocal = true; + } + + public Expr assign(Expr expr) { + return new LCAssign(this, expr); + } + + public Expr assign(double val) { + return new LCAssign(this, Expr.valueOf(val)); + } + + public Expr assign(int val) { + return new LCAssign(this, Expr.valueOf(val)); + } + + public void setLVTIndex(int index) { + this.indexLVT = index; + } + + public int getLVTIndex() { + return this.indexLVT; + } + + public String getName() { + return this.getLabel(); + } + + public boolean isLocalVar() { + return this.indexLVT >= 0; + } + + @Override + public InstructionHandle bytecodeGen(String clsName, MethodGen mg, + ConstantPoolGen cp, InstructionFactory factory, + InstructionList il, Map argsMap, int argsStartPos, + Map funcRefsMap) { + if(this.isLocalVar()) { + // Load from local variable table + TYPE ty = this.getType(); + if(ty == TYPE.DOUBLE) + return il.append(new DLOAD(indexLVT)); + if(ty == TYPE.INT) + return il.append(new ILOAD(indexLVT)); + if(ty == TYPE.LONG) + return il.append(new LLOAD(indexLVT)); + if(ty == TYPE.FLOAT) + return il.append(new FLOAD(indexLVT)); + return il.append(new ILOAD(indexLVT)); + } else { + // Load from a double array from arguments + InstructionHandle startPos = il.append(new ALOAD(argsStartPos)); + il.append(new PUSH(cp, argsMap.get(this.label))); + il.append(InstructionConstants.DALOAD); + return startPos; + } + } + + public static LCInt getInt(String name) { + return new LCInt(name); + } + + public static LCLong getLong(String name) { + return new LCLong(name); + } + + public static LCFloat getFloat(String name) { + return new LCFloat(name); + } + + public static LCDouble getDouble(String name) { + return new LCDouble(name); + } + + public static LCShort getShort(String name) { + return new LCShort(name); + } + + public static LCChar getChar(String name) { + return new LCChar(name); + } + + public static LCByte getByte(String name) { + return new LCByte(name); + } +} diff --git a/src/lambdacloud/core/utils/FuncEvalThread.java b/src/lambdacloud/core/utils/FuncEvalThread.java new file mode 100644 index 0000000..5d04a45 --- /dev/null +++ b/src/lambdacloud/core/utils/FuncEvalThread.java @@ -0,0 +1,79 @@ +package lambdacloud.core.utils; + +import lambdacloud.core.CloudFunc; +import lambdacloud.core.CloudSD; +import symjava.bytecode.BytecodeBatchFunc; +import symjava.bytecode.BytecodeFunc; +import symjava.bytecode.BytecodeVecFunc; + +public class FuncEvalThread implements Runnable { + CloudFunc func; + CloudSD output; + CloudSD[] args; + + public FuncEvalThread(CloudFunc func, CloudSD output, CloudSD... args) { + this.func = func; + this.output = output; + this.args = args; + } + + @Override + public void run() { + double[][] doubleArgs = new double[args.length][]; + for(int i=0; i>>"+Thread.currentThread().getName()+" evaluating "+func.getName()+"...; Return: "+output); + + switch(func.getFuncType()) { + case SCALAR: + BytecodeFunc bfunc = func.getBytecodeFunc(); + if(doubleArgs.length > 0) { + //Support multiple CloudSD inputs for BytecodeFunc + output.init(bfunc.apply(Utils.flatten(doubleArgs))); //Time consuming part + } else { + output.init(bfunc.apply()); + } + break; + case VECTOR: + BytecodeVecFunc bfunc2 = func.getBytecodeVecFunc(); + //The length of returned array can be obtained from CloundFunc + double[] outAry = new double[func.getOutAryLen()]; + if(args.length > 0) { + bfunc2.apply(outAry, 0, doubleArgs); + } else + bfunc2.apply(outAry, 0); + output.init(outAry); + break; + case BATCH: + BytecodeBatchFunc bfunc3 = func.getBytecodeBatchFunc(); + //The length of returned array can be obtained from CloundFunc + double[] outAry2 = new double[args[0].length()]; + if(args.length > 0) { + bfunc3.apply(outAry2, 0, Utils.flatten(doubleArgs)); + } else + bfunc3.apply(outAry2, 0); + output.init(outAry2); + break; + default: + throw new UnsupportedOperationException(); + } + + + +// try { +// Thread.sleep(5000); +// } catch (InterruptedException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } + synchronized(output) { + output.setIsReady(true); + output.notify(); + } + + } + +} diff --git a/src/lambdacloud/core/utils/Utils.java b/src/lambdacloud/core/utils/Utils.java new file mode 100644 index 0000000..425e463 --- /dev/null +++ b/src/lambdacloud/core/utils/Utils.java @@ -0,0 +1,18 @@ +package lambdacloud.core.utils; + +public class Utils { + + public static double[] flatten(double[][] args) { + int len = 0; + for(int i=0; i dict = new HashMap(); + dict.put(x.toString(), 3.0); + dict.put(y.toString(), 4.0); + + //Set device in the expression + Expr sum1 = CPU(x*x) + CPU(y*y); + double rlt1 = sess.runSimple(sum1, dict); + System.out.println("Example 1: "+sum1); + System.out.println("Result: "+rlt1); + + //use runOn() method of a term or an expression + LCDevice cpu1 = new LCDevice(0); + LCDevice cpu2 = new LCDevice(1); + Expr sum2 = (x*x).runOn(cpu1) + (y*y).runOn(cpu2); + double rlt2 = sess.runSimple(sum1, dict); + System.out.println("Example 2: "+sum2); + System.out.println("Result: "+rlt2); + + //Set device for each term of an expression (use args()) + Expr sum3 = x*x + y*y; + Expr[] ops = sum3.args(); + for(int i=0; i= 3) { + configFile = args[0]; + nData = Integer.valueOf(args[1]); + nEle = Integer.valueOf(args[2]); + } + if(args.length == 4) { + isAsync = Boolean.valueOf(args[3]); + } + } + + CloudConfig config = CloudConfig.setGlobalConfig(configFile); + + double[] data = new double[nData]; + for(int i=0; i 0.5) { + g2d.setColor(Color.red); + } else { + g2d.setColor(Color.blue); + } + int xx = (int)(320*x); + int yy = (int)(320*y); + g2d.drawLine(xx, yy, xx, yy); + } + } + + public void paintComponent(Graphics g) { + super.paintComponent(g); + doDrawing(g); + } + } + } + + public static void main(String[] args) { + System.out.println("Current working dir="+System.getProperty("user.dir")); + int N = 1000000; + String configFile = "job_google.conf"; + boolean isAsync = false; + if(args.length == 3) { + N = Integer.valueOf(args[0]); + configFile = args[1]; + isAsync = Boolean.valueOf(args[2]); + } + MonteCarloTwoAnnulusImp1(N, configFile, isAsync); + //MonteCarloTwoAnnulusImp2(); + MonteCarloTowAnnulusVerifiy(); + +// MyFrame frame = new MyFrame(); +// frame.setVisible(true); + } + +} diff --git a/src/lambdacloud/examples/ExamplePaper.java b/src/lambdacloud/examples/ExamplePaper.java new file mode 100644 index 0000000..2910611 --- /dev/null +++ b/src/lambdacloud/examples/ExamplePaper.java @@ -0,0 +1,42 @@ +package lambdacloud.examples; + +import lambdacloud.core.CloudConfig; +import lambdacloud.core.CloudFunc; +import lambdacloud.core.CloudSD; +import symjava.bytecode.BytecodeFunc; +import symjava.symbolic.Expr; +import symjava.symbolic.utils.JIT; +import static symjava.symbolic.Symbol.x; +import static symjava.symbolic.Symbol.y; + +public class ExamplePaper { + + public static void main(String[] args) { + CloudConfig.setGlobalConfig("job_local.conf"); + + Expr R = 0.127-(x*0.194/(y+0.194)); + //Derivative of expression R with respect to y + Expr Rdy = R.diff(y); + + //Define a function on the cloud + CloudFunc fun = new CloudFunc(Rdy, new Expr[]{x, y}); + + //Evaluate the function on the cloud by providing + //input and output parameters + CloudSD input = new CloudSD("input").init( + new double[]{0.362, 0.556}); + CloudSD output = new CloudSD("output"); + fun.apply(output, input); + + //Fetch the evaluation result to local + if(output.fetch()) { + System.out.println(output.getData(0)); + } + + //Just-In-Time compile the symbolic expression to native code + //and evaluate it locally to verify the result + BytecodeFunc func = JIT.compile(new Expr[]{x,y}, Rdy); + System.out.println(func.apply(0.362, 0.556)); + } + +} diff --git a/src/lambdacloud/examples/ExampleSqrt.java b/src/lambdacloud/examples/ExampleSqrt.java new file mode 100644 index 0000000..087597d --- /dev/null +++ b/src/lambdacloud/examples/ExampleSqrt.java @@ -0,0 +1,52 @@ +package lambdacloud.examples; + +import static symjava.symbolic.Symbol.C0; +import static symjava.symbolic.Symbol.x; +import lambdacloud.core.CloudConfig; +import lambdacloud.core.CloudLib; +import lambdacloud.core.CloudSD; +import symjava.examples.Newton; +import symjava.relational.Eq; +import symjava.symbolic.Expr; + +/** + * Square root of a number + * (http://en.wikipedia.org/wiki/Newton's_method) + */ +public class ExampleSqrt { + + public static void main(String[] args) { + example1(); + example2(); + } + public static void example1() { + CloudConfig.setGlobalConfig("job_local.conf"); + CloudLib lib = new CloudLib(); + Expr[] freeVars = {x}; + double num = 612; + Eq[] eq = new Eq[] { + new Eq(x*x-num, C0, freeVars) + }; + + double[] guess = new double[]{ 10 }; + + Newton.solve(eq, guess, 100, 1e-3); + //sever + CloudSD output = new CloudSD("bs_sol").init(1); + lib.solverNewton(eq, guess, 100, 1e-5, output); + output.fetch(); + System.out.println(output.getData(0)); + } + + public static void example2() { + CloudConfig.setGlobalConfig("job_local.conf"); + CloudLib lib = new CloudLib(); + + double[] guess = new double[]{ 10 }; + //sever + CloudSD output = new CloudSD("bs_sol").init(1); + lib.solverNewton(new String[]{" eq(x^2-612, 0) "}, guess, 100, 1e-5, output); + output.fetch(); + System.out.println(output.getData(0)); + } +} diff --git a/src/lambdacloud/net/CloudClient.java b/src/lambdacloud/net/CloudClient.java new file mode 100644 index 0000000..97ee25e --- /dev/null +++ b/src/lambdacloud/net/CloudClient.java @@ -0,0 +1,95 @@ +package lambdacloud.net; + + +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.util.InsecureTrustManagerFactory; + +/** + * + * A cloud client represents a connection to a server + * with host and port passed to the constructor + * + */ +public final class CloudClient { + public String host; + public int port; + + ChannelFuture f; + Channel ch; + EventLoopGroup group; + + CloudSDHandler csdHandler; + CloudSDRespHandler csdRespHandler; + CloudFuncHandler funcHandler; + + static final boolean SSL = System.getProperty("ssl") != null; + + public CloudClient(String host, int port) { + this.host = host; + this.port = port; + } + + public void connect() throws Exception { + // Configure SSL. + final SslContext sslCtx; + if (SSL) { + sslCtx = SslContext.newClientContext(InsecureTrustManagerFactory.INSTANCE); + } else { + sslCtx = null; + } + + group = new NioEventLoopGroup(); + try { + Bootstrap b = new Bootstrap(); + b.group(group) + .channel(NioSocketChannel.class) + .handler(new CloudClientInitializer(sslCtx, host, port)); + + // Make a new connection. + f = b.connect(host, port).sync(); + ch = f.channel(); + csdHandler = (CloudSDHandler)f.channel().pipeline().get("CloudSDHandler"); + csdRespHandler = (CloudSDRespHandler)f.channel().pipeline().get("CloudSDRespHandler"); + funcHandler = (CloudFuncHandler)f.channel().pipeline().get("CloudFuncHandler"); + + //ch.writeAndFlush(new CloudSD("xxxxxxx").init(1,2,3,4,5,6,7)); + + } finally { + //group.shutdownGracefully(); + } + } + + public CloudSDHandler getCloudSDHandler() { + // Get the handler instance to retrieve the answer. + return csdHandler; + } + + public CloudSDRespHandler getCloudSDRespHandler() { + // Get the handler instance to retrieve the answer. + return csdRespHandler; + } + + public CloudFuncHandler getCloudFuncHandler() { + // Get the handler instance to retrieve the answer. + return funcHandler; + + } + + public Channel getChannel() { + return ch; + } + + public void shutDown() { + group.shutdownGracefully(); + } + + public String toString() { + return this.host+":"+this.port; + } +} diff --git a/src/lambdacloud/net/CloudClientInitializer.java b/src/lambdacloud/net/CloudClientInitializer.java new file mode 100644 index 0000000..5a74703 --- /dev/null +++ b/src/lambdacloud/net/CloudClientInitializer.java @@ -0,0 +1,49 @@ +package lambdacloud.net; + +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.codec.compression.ZlibCodecFactory; +import io.netty.handler.codec.compression.ZlibWrapper; +import io.netty.handler.ssl.SslContext; + +/** + * Creates a newly configured {@link ChannelPipeline} for a client-side channel. + */ +public class CloudClientInitializer extends ChannelInitializer { + + private final SslContext sslCtx; + private final String host; + private final int port; + + public CloudClientInitializer(SslContext sslCtx, String host, int port) { + this.sslCtx = sslCtx; + this.host = host; + this.port = port; + } + + @Override + public void initChannel(SocketChannel ch) { + ChannelPipeline pipeline = ch.pipeline(); + + if (sslCtx != null) { + pipeline.addLast(sslCtx.newHandler(ch.alloc(), host, port)); + } + + // Enable stream compression (you can remove these two if unnecessary) + pipeline.addLast(ZlibCodecFactory.newZlibEncoder(ZlibWrapper.GZIP)); + pipeline.addLast(ZlibCodecFactory.newZlibDecoder(ZlibWrapper.GZIP)); + + // Add the number codec first, + pipeline.addLast(new CloudSDEncoder()); + pipeline.addLast(new CloudQueryEncoder()); + pipeline.addLast(new CloudFuncEncoder()); + pipeline.addLast(new MessageDecoder()); + + // and then business logic. + pipeline.addLast("CloudFuncHandler", new CloudFuncHandler()); + pipeline.addLast("CloudSDHandler", new CloudSDHandler()); + pipeline.addLast("CloudSDRespHandler", new CloudSDRespHandler()); + + } +} diff --git a/src/lambdacloud/net/CloudFuncEncoder.java b/src/lambdacloud/net/CloudFuncEncoder.java new file mode 100644 index 0000000..8cbf15c --- /dev/null +++ b/src/lambdacloud/net/CloudFuncEncoder.java @@ -0,0 +1,61 @@ +package lambdacloud.net; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToByteEncoder; + +import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; + +import symjava.bytecode.IR; +import lambdacloud.core.CloudFunc; +import lambdacloud.core.CloudFunc.FUNC_TYPE; + +/** + */ +public class CloudFuncEncoder extends MessageToByteEncoder { + + @Override + protected void encode(ChannelHandlerContext ctx, CloudFunc func, ByteBuf out) { + // Convert to a BigInteger first for easier implementation. + IR funcIR = func.getFuncIR(); + + int nameLen = 0; + int dataLen = funcIR.bytes.length; + int packageLen = 0; + byte[] nameBytes = null; + byte[] allData = null; + try { + nameBytes = funcIR.name.getBytes("UTF-8"); + nameLen = nameBytes.length; + packageLen = nameLen + dataLen; + allData = new byte[packageLen]; + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + ByteBuffer buf = ByteBuffer.wrap(allData); + buf.put(nameBytes); + buf.put(funcIR.bytes); + + // Write a message. + out.writeByte((byte) 'F'); // magic number + out.writeInt(getFuncType(funcIR.type)); + out.writeInt(func.getOutAryLen()); + out.writeInt(func.getNumArgs()); + out.writeInt(nameLen); + out.writeInt(dataLen); + out.writeBytes(allData); + } + + protected int getFuncType(FUNC_TYPE funcType) { + switch(funcType) { + case SCALAR: + return 1; + case VECTOR: + return 2; + case BATCH: + return 3; + } + return -1; + } +} diff --git a/src/lambdacloud/net/CloudFuncHandler.java b/src/lambdacloud/net/CloudFuncHandler.java new file mode 100644 index 0000000..045aff3 --- /dev/null +++ b/src/lambdacloud/net/CloudFuncHandler.java @@ -0,0 +1,41 @@ +package lambdacloud.net; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; + +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +public class CloudFuncHandler extends + SimpleChannelInboundHandler { + final BlockingQueue queue = new LinkedBlockingQueue(); + public CloudFuncResp getCloudResp() { + boolean interrupted = false; + try { + for (;;) { + try { + return queue.take(); + } catch (InterruptedException ignore) { + interrupted = true; + } + } + } finally { + if (interrupted) { + Thread.currentThread().interrupt(); + } + } + } + + @Override + public void messageReceived(ChannelHandlerContext ctx, + final CloudFuncResp msg) { + System.err.println("Received CloudFuncResp: "+msg); + queue.offer(msg); + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { + cause.printStackTrace(); + ctx.close(); + } +} diff --git a/src/lambdacloud/net/CloudFuncResp.java b/src/lambdacloud/net/CloudFuncResp.java new file mode 100644 index 0000000..f494466 --- /dev/null +++ b/src/lambdacloud/net/CloudFuncResp.java @@ -0,0 +1,8 @@ +package lambdacloud.net; + +public class CloudFuncResp extends CloudResp { + public CloudFuncResp() { + this.respType = 2; + } + +} diff --git a/src/lambdacloud/net/CloudFuncRespEncoder.java b/src/lambdacloud/net/CloudFuncRespEncoder.java new file mode 100644 index 0000000..2be754f --- /dev/null +++ b/src/lambdacloud/net/CloudFuncRespEncoder.java @@ -0,0 +1,14 @@ +package lambdacloud.net; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToByteEncoder; + +public class CloudFuncRespEncoder extends MessageToByteEncoder { + @Override + protected void encode(ChannelHandlerContext ctx, CloudFuncResp resp, ByteBuf out) { + out.writeByte((byte) 'R'); // magic number + byte[] bytes = resp.getBytes(); + out.writeBytes(bytes); + } +} \ No newline at end of file diff --git a/src/lambdacloud/net/CloudQuery.java b/src/lambdacloud/net/CloudQuery.java new file mode 100644 index 0000000..ef054dc --- /dev/null +++ b/src/lambdacloud/net/CloudQuery.java @@ -0,0 +1,68 @@ +package lambdacloud.net; + +import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; + +public class CloudQuery { + public static final int CLOUD_SD = 0; // Fetch a CloudSD from cloud + public static final int CLOUD_FUNC_EVAL = 1; // Evaluate a function on the cloud + public static final int TARGET_INFO = 2; // Query info of target machine on the cloud + public static final int CLOUD_LIB_INVOKE = 10; // Query info of target machine on the cloud + + + public int qryType; // One of the static integer define in this class + public String objName; // Name of CloudSD or CloudFunc + + + public List argNames = new ArrayList(); // Parameters for function when evaluating + public String outputName = ""; // Output of a function evaluation + + public byte[] getBytes() { + byte[] bytes = null; + try { + int len = 0; + len += 4; + + byte[] nameBytes = objName.getBytes("UTF-8"); + len += 4; + len += nameBytes.length; + + byte[] outputBytes = outputName.getBytes("UTF-8"); + len += 4; + len += outputBytes.length; + + len += 4; + List argNameBytes = new ArrayList(); + if(argNames.size() != 0) { + for(String s : argNames) { + byte[] bs = s.getBytes("UTF-8"); + argNameBytes.add(bs); + len += 4; + len += bs.length; + } + } + + bytes = new byte[len]; + ByteBuffer buf = ByteBuffer.wrap(bytes); + buf.putInt(qryType); + buf.putInt(nameBytes.length); + buf.putInt(outputBytes.length); + buf.put(nameBytes); + buf.put(outputBytes); + buf.putInt(argNameBytes.size()); + for(byte[] bs : argNameBytes) { + buf.putInt(bs.length); + buf.put(bs); + } + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return bytes; + } + + public String toString() { + return "CloudQuery: "+qryType+" "+objName; + } +} diff --git a/src/lambdacloud/net/CloudQueryEncoder.java b/src/lambdacloud/net/CloudQueryEncoder.java new file mode 100644 index 0000000..5f53214 --- /dev/null +++ b/src/lambdacloud/net/CloudQueryEncoder.java @@ -0,0 +1,14 @@ +package lambdacloud.net; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToByteEncoder; + +public class CloudQueryEncoder extends MessageToByteEncoder { + @Override + protected void encode(ChannelHandlerContext ctx, CloudQuery req, ByteBuf out) { + out.writeByte((byte) 'Q'); // magic number + byte[] bytes = req.getBytes(); + out.writeBytes(bytes); + } +} diff --git a/src/lambdacloud/net/CloudResp.java b/src/lambdacloud/net/CloudResp.java new file mode 100644 index 0000000..300e8bb --- /dev/null +++ b/src/lambdacloud/net/CloudResp.java @@ -0,0 +1,44 @@ +package lambdacloud.net; + +import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; + +public class CloudResp { + public int respType; + public int status; + public String objName; + public String message; + + public byte[] getBytes() { + byte[] bytes = null; + try { + int len = 0; + len += 8; + byte[] nameBytes = objName.getBytes("UTF-8"); + len += 4; + len += nameBytes.length; + byte[] messageBytes = message.getBytes("UTF-8"); + len += 4; + len += messageBytes.length; + + bytes = new byte[len]; + ByteBuffer buf = ByteBuffer.wrap(bytes); + buf.putInt(respType); + buf.putInt(status); + buf.putInt(nameBytes.length); + buf.putInt(messageBytes.length); + buf.put(nameBytes); + buf.put(messageBytes); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return bytes; + } + + public String toString() { + if(status != 0) + return objName+":"+String.valueOf(status)+" "+message; + else + return objName; + } +} diff --git a/src/lambdacloud/net/CloudRespEncoder.java b/src/lambdacloud/net/CloudRespEncoder.java new file mode 100644 index 0000000..b6864f6 --- /dev/null +++ b/src/lambdacloud/net/CloudRespEncoder.java @@ -0,0 +1,14 @@ +package lambdacloud.net; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToByteEncoder; + +public class CloudRespEncoder extends MessageToByteEncoder { + @Override + protected void encode(ChannelHandlerContext ctx, CloudResp resp, ByteBuf out) { + out.writeByte((byte) 'R'); // magic number + byte[] bytes = resp.getBytes(); + out.writeBytes(bytes); + } +} diff --git a/src/lambdacloud/net/CloudSDEncoder.java b/src/lambdacloud/net/CloudSDEncoder.java new file mode 100644 index 0000000..ae2c6f2 --- /dev/null +++ b/src/lambdacloud/net/CloudSDEncoder.java @@ -0,0 +1,43 @@ +package lambdacloud.net; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToByteEncoder; + +import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; + +import lambdacloud.core.CloudSD; + +public class CloudSDEncoder extends MessageToByteEncoder { + @Override + protected void encode(ChannelHandlerContext ctx, CloudSD var, ByteBuf out) { + // Convert to a BigInteger first for easier implementation. + int nameLen = 0; + int dataLen = var.getData().length * 8; + int packageLen = 0; + byte[] allData = null; + try { + byte[] nameBytes = var.getLabel().getBytes("UTF-8"); + nameLen = nameBytes.length; + packageLen = nameLen + dataLen; + allData = new byte[packageLen]; + System.arraycopy(nameBytes, 0, allData, 0, nameLen); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + byte[] data = new byte[dataLen]; + ByteBuffer buf = ByteBuffer.wrap(data); + for (double d : var.getData()) { + buf.putDouble(d); + } + System.arraycopy(buf.array(), 0, allData, nameLen, dataLen); + + // Write a message. + out.writeByte((byte) 'D'); // magic number + out.writeInt(nameLen); // name length + out.writeInt(var.isOnCloud()?1:0); + out.writeInt(dataLen); // data length + out.writeBytes(allData); // data + } +} diff --git a/src/lambdacloud/net/CloudSDHandler.java b/src/lambdacloud/net/CloudSDHandler.java new file mode 100644 index 0000000..b75089b --- /dev/null +++ b/src/lambdacloud/net/CloudSDHandler.java @@ -0,0 +1,43 @@ +package lambdacloud.net; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; + +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +import lambdacloud.core.CloudSD; + +public class CloudSDHandler extends SimpleChannelInboundHandler { + + final BlockingQueue queue = new LinkedBlockingQueue(); + + public CloudSD getCloudSD() { + boolean interrupted = false; + try { + for (;;) { + try { + return queue.take(); + } catch (InterruptedException ignore) { + interrupted = true; + } + } + } finally { + if (interrupted) { + Thread.currentThread().interrupt(); + } + } + } + + @Override + public void messageReceived(ChannelHandlerContext ctx, final CloudSD msg) { + System.err.println("Received CloudSD: "+msg); + queue.offer(msg); + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { + cause.printStackTrace(); + ctx.close(); + } +} diff --git a/src/lambdacloud/net/CloudSDResp.java b/src/lambdacloud/net/CloudSDResp.java new file mode 100644 index 0000000..8ac6fab --- /dev/null +++ b/src/lambdacloud/net/CloudSDResp.java @@ -0,0 +1,7 @@ +package lambdacloud.net; + +public class CloudSDResp extends CloudResp { + public CloudSDResp() { + this.respType = 1; + } +} diff --git a/src/lambdacloud/net/CloudSDRespEncoder.java b/src/lambdacloud/net/CloudSDRespEncoder.java new file mode 100644 index 0000000..262122b --- /dev/null +++ b/src/lambdacloud/net/CloudSDRespEncoder.java @@ -0,0 +1,14 @@ +package lambdacloud.net; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToByteEncoder; + +public class CloudSDRespEncoder extends MessageToByteEncoder { + @Override + protected void encode(ChannelHandlerContext ctx, CloudSDResp resp, ByteBuf out) { + out.writeByte((byte) 'R'); // magic number + byte[] bytes = resp.getBytes(); + out.writeBytes(bytes); + } +} diff --git a/src/lambdacloud/net/CloudSDRespHandler.java b/src/lambdacloud/net/CloudSDRespHandler.java new file mode 100644 index 0000000..ba8f31f --- /dev/null +++ b/src/lambdacloud/net/CloudSDRespHandler.java @@ -0,0 +1,42 @@ +package lambdacloud.net; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; + +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +public class CloudSDRespHandler extends + SimpleChannelInboundHandler { + final BlockingQueue queue = new LinkedBlockingQueue(); + + public CloudSDResp getCloudResp() { + boolean interrupted = false; + try { + for (;;) { + try { + return queue.take(); + } catch (InterruptedException ignore) { + interrupted = true; + } + } + } finally { + if (interrupted) { + Thread.currentThread().interrupt(); + } + } + } + + @Override + public void messageReceived(ChannelHandlerContext ctx, + final CloudSDResp msg) { + System.err.println("Received CloudSDResp: "+msg); + queue.offer(msg); + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { + cause.printStackTrace(); + ctx.close(); + } +} diff --git a/src/lambdacloud/net/MessageDecoder.java b/src/lambdacloud/net/MessageDecoder.java new file mode 100644 index 0000000..93065b5 --- /dev/null +++ b/src/lambdacloud/net/MessageDecoder.java @@ -0,0 +1,74 @@ +package lambdacloud.net; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageDecoder; +import io.netty.handler.codec.CorruptedFrameException; + +import java.util.List; + +import lambdacloud.core.CloudSD; + +public class MessageDecoder extends ByteToMessageDecoder { + + @Override + protected void decode(ChannelHandlerContext ctx, ByteBuf in, + List out) { + // Wait until the length prefix is available. + if (in.readableBytes() < 9) { + return; + } + + in.markReaderIndex(); + + // Check the magic number. + int magicNumber = in.readUnsignedByte(); + // System.err.println("Client: Magic number received: "+(char)magicNumber); + if (magicNumber == 'D') { // CloudSD + if (in.readableBytes() < 12) { + in.resetReaderIndex(); + return; // Wait until the whole data is available. + } + int nameLen = in.readInt(); + int onCloudFlag = in.readInt(); + int dataLen = in.readInt(); + if (in.readableBytes() < nameLen + dataLen) { + in.resetReaderIndex(); + return; // Wait until the whole data is available. + } + byte[] decoded = new byte[nameLen + dataLen]; + in.readBytes(decoded); + CloudSD var = NetIOUtils.createCloudSD(decoded, nameLen, dataLen); + var.setOnCloudFlag(onCloudFlag == 1 ? true : false); + out.add(var); + // System.out.println("decoded:"+var.getLabel()); + } else if (magicNumber == 'R') { // CloudResp + if (in.readableBytes() < 16) { + in.resetReaderIndex(); + return; + } + int respType = in.readInt(); + int status = in.readInt(); + int nameLen = in.readInt(); + int messageLen = in.readInt(); + if (in.readableBytes() < nameLen + messageLen) { + in.resetReaderIndex(); + return; + } + byte[] decoded = new byte[nameLen + messageLen]; + in.readBytes(decoded); + if (respType == 1) + out.add(NetIOUtils.createCloudSDResp(decoded, status, nameLen, + messageLen)); + else if (respType == 2) + out.add(NetIOUtils.createCloudFuncResp(decoded, status, + nameLen, messageLen)); + + } else { + in.resetReaderIndex(); + throw new CorruptedFrameException("Invalid magic number: " + + magicNumber); + } + + } +} diff --git a/src/lambdacloud/net/NetIOUtils.java b/src/lambdacloud/net/NetIOUtils.java new file mode 100644 index 0000000..6afa6ce --- /dev/null +++ b/src/lambdacloud/net/NetIOUtils.java @@ -0,0 +1,53 @@ +package lambdacloud.net; + +import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; + +import lambdacloud.core.CloudSD; + +public class NetIOUtils { + public static CloudSD createCloudSD(byte[] data, int nameLen, int dataLen) { + String name = null; + try { + name = new String(data, 0, nameLen, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + double[] ddata = toDoubleArray(data, nameLen, dataLen); + return new CloudSD(name).init(ddata); + } + + public static CloudSDResp createCloudSDResp(byte[] data, int status, int nameLen, int messageLen) { + CloudSDResp resp = new CloudSDResp(); + resp.status = status; + try { + resp.objName = new String(data, 0, nameLen, "UTF-8"); + resp.message = new String(data, nameLen, messageLen, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return resp; + } + + public static CloudFuncResp createCloudFuncResp(byte[] data, int status, int nameLen, int messageLen) { + CloudFuncResp resp = new CloudFuncResp(); + resp.status = status; + try { + resp.objName = new String(data, 0, nameLen, "UTF-8"); + resp.message = new String(data, nameLen, messageLen, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return resp; + } + + public static double[] toDoubleArray(byte[] byteArray, int offset, int length){ + int times = Double.SIZE / Byte.SIZE; + double[] doubles = new double[length / times]; + for(int i=0;i fcl = new FuncClassLoader(); + fcl.newInstance(cg); + ///////////The test code above can be deleted in prod env///////////////////// + + } else { + cg = _compile(name, expr, args); + ir.type = FUNC_TYPE.SCALAR; + } + ir.name = cg.getJavaClass().getClassName(); + ir.bytes = cg.getJavaClass().getBytes(); + + return ir; + } + + public static IR getIR(String name, Expr[] exprs, Expr ...args) { + ClassGen cg = null; + IR ir = new IR(); + + //Reset flags to generate matrix, vector declaration in a new func + for(int i=0; i fcl = new FuncClassLoader(); + BytecodeFunc fun = fcl.newInstance(cg); + return fun; + } + +// public static void compileGraph(List retGraph, Expr expr, Expr ...args) { +// } + + public static BytecodeFunc compile(String name, Expr expr, Expr ...args) { + ClassGen cg = _compile(name, expr, args); + FuncClassLoader fcl = new FuncClassLoader(); + BytecodeFunc fun = fcl.newInstance(cg); + return fun; + } + + public static ClassGen _compile(String name, Expr expr, Expr ...args) { + String packageName = "symjava.bytecode"; + String clsName = name; + if(clsName == null) + clsName = expr.getClass().getSimpleName() + System.currentTimeMillis(); + String fullClsName = packageName+"."+clsName; + ClassGen cg = new ClassGen(fullClsName, "java.lang.Object", + "", ACC_PUBLIC | ACC_SUPER, new String[]{"symjava.bytecode.BytecodeFunc"}); + ConstantPoolGen cp = cg.getConstantPool(); // cg creates constant pool + InstructionList il = new InstructionList(); + InstructionFactory factory = new InstructionFactory(cg); + + short acc_flags = ACC_PUBLIC; + MethodGen mg = new MethodGen(acc_flags, // access flags + Type.DOUBLE, // return type + new Type[] { // argument types + new ArrayType(Type.DOUBLE, 1) + }, + new String[] { "args" }, // arg names + "apply", fullClsName, // method, class + il, cp); + + HashMap argsMap = new HashMap(); + if(args.length == 1 && args[0] instanceof LCArray) { + //double apply(double[] args) + ((LCArray)args[0]).setArgsDim(1); + argsMap.put(args[0].getLabel(), 1); + System.out.println(fullClsName); + StringBuilder sb = new StringBuilder(); + sb.append("double apply(double[] ").append(args[0].getLabel()); + sb.append(") = "); + sb.append(expr); + System.out.println(sb.toString()); + } else { + //double apply(double x, double y, ...) + for(int i=0; i>CompileUtils: "+fullClsName+": "); + StringBuilder sb = new StringBuilder(); + sb.append("double apply("); + for(Expr a : args) + sb.append("double ").append(a).append(", "); + if(args.length > 0) + sb.delete(sb.length()-2, sb.length()); + sb.append(") = "); + sb.append(expr); + System.out.println(sb.toString()); + } + + // Declare local variables + List vars = Utils.extractSymbols(expr); + for(Expr var : vars) { + if(var instanceof LCVar) { + LCVar cv = (LCVar)var; + if(argsMap.get(cv.getName()) != null) + continue; // Skip arguments (non local variables) + int indexLVT = BytecodeUtils.declareLocal(cv, mg, il); + cv.setLVTIndex(indexLVT); + } + } + + expr.bytecodeGen(fullClsName, mg, cp, factory, il, argsMap, 1, null); + + mg.setMaxStack(); + cg.addMethod(mg.getMethod()); + il.dispose(); // Allow instruction handles to be reused + + cg.addEmptyConstructor(ACC_PUBLIC); + + try { + cg.getJavaClass().dump("bin/symjava/bytecode/"+clsName+".class"); + } catch (java.io.IOException e) { + System.err.println(e); + } + return cg; + } + + public static BytecodeBatchFunc compileBatchFunc(String name, Expr[] exprs, Expr ...args) { + ClassGen cg = _compileBatchFunc(name, exprs, args); + FuncClassLoader fcl = new FuncClassLoader(); + BytecodeBatchFunc fun = fcl.newInstance(cg); + return fun; + } + + /** + * Compile a list of expressions + * + * @param name + * @param expr + * @param args + * @return + */ + public static ClassGen _compileBatchFunc(String name, Expr[] exprs, Expr ...args) { + String packageName = "symjava.bytecode"; + String clsName = name; + if(clsName == null) + clsName = exprs[0].getClass().getSimpleName() + System.currentTimeMillis(); + String fullClsName = packageName+"."+clsName; + ClassGen cg = new ClassGen(fullClsName, "java.lang.Object", + "", ACC_PUBLIC | ACC_SUPER, new String[]{"symjava.bytecode.BytecodeBatchFunc"}); + ConstantPoolGen cp = cg.getConstantPool(); // cg creates constant pool + InstructionList il = new InstructionList(); + InstructionFactory factory = new InstructionFactory(cg); + + short acc_flags = ACC_PUBLIC; + MethodGen mg = new MethodGen(acc_flags, // access flags + Type.VOID, // return type + new Type[] { // argument types + new ArrayType(Type.DOUBLE, 1), + Type.INT, + new ArrayType(Type.DOUBLE, 1) + }, + new String[] { "outAry", "outPos", "args" }, // arg names + "apply", fullClsName, // method, class + il, cp); + + HashMap argsMap = new HashMap(); + + //The following are copied from _compile() + //Don't know how to change it accordingly. + if(args.length == 1 && args[0] instanceof LCArray) { + //double apply(double[] args) + ((LCArray)args[0]).setArgsDim(1); + argsMap.put(args[0].getLabel(), 1); + System.out.println(fullClsName); + StringBuilder sb = new StringBuilder(); + sb.append("double apply(double[] ").append(args[0].getLabel()); + sb.append(") = "); + sb.append(Utils.joinLabels(exprs,", ")); + System.out.println(sb.toString()); + } else { + //double apply(double x, double y, ...) + for(int i=0; i>CompileUtils: "+fullClsName+": "); + StringBuilder sb = new StringBuilder(); + sb.append("double apply("); + for(Expr a : args) + sb.append("double ").append(a).append(", "); + if(args.length > 0) + sb.delete(sb.length()-2, sb.length()); + sb.append(") = "); + sb.append(Utils.joinLabels(exprs,", ")); + System.out.println(sb.toString()); + } + + // Declare local variables + List vars = Utils.extractSymbols(exprs); + for(Expr var : vars) { + if(var instanceof LCVar) { + LCVar cv = (LCVar)var; + if(argsMap.get(cv.getName()) != null) + continue; // Skip arguments (non local variables) + int indexLVT = BytecodeUtils.declareLocal(cv, mg, il); + cv.setLVTIndex(indexLVT); + } + } + + for(int i=0; i fcl = new FuncClassLoader(); + BytecodeVecFunc fun = fcl.newInstance(cg); + return fun; + } + + public static BytecodeVecFunc compileVecFunc(String name, Expr expr, LCArray output, Expr ...args) { + ClassGen cg = _compileVecFunc(name, expr, output, args); + FuncClassLoader fcl = new FuncClassLoader(); + BytecodeVecFunc fun = fcl.newInstance(cg); + return fun; + } + + /** + * TODO: remove parameter output + * @param expr + * @param args + * @return + */ + public static BytecodeVecFunc compileVecFunc(Expr expr, Expr ...args) { + return compileVecFunc(null, expr, args); + } + + public static BytecodeVecFunc compileVecFunc(String name, Expr expr, Expr ...args) { + LCArray output = LCArray.getDoubleArray("output"); + ClassGen cg = _compileVecFunc(name, expr, output, args); + FuncClassLoader fcl = new FuncClassLoader(); + BytecodeVecFunc fun = fcl.newInstance(cg); + return fun; + } + + public static ClassGen _compileVecFunc(String name, Expr expr, LCArray output, Expr ...args) { + String packageName = "symjava.bytecode"; + String clsName = name; + if(clsName == null) + clsName = expr.getClass().getSimpleName() + System.currentTimeMillis(); + String fullClsName = packageName+"."+clsName; + ClassGen cg = new ClassGen(fullClsName, "java.lang.Object", + "", ACC_PUBLIC | ACC_SUPER, new String[]{"symjava.bytecode.BytecodeVecFunc"}); + ConstantPoolGen cp = cg.getConstantPool(); // cg creates constant pool + InstructionList il = new InstructionList(); + InstructionFactory factory = new InstructionFactory(cg); + + short acc_flags = ACC_PUBLIC; + MethodGen mg = new MethodGen(acc_flags, // access flags + Type.VOID, // return type + new Type[] { // argument types + new ArrayType(Type.DOUBLE, 1), + Type.INT, + new ArrayType(Type.DOUBLE, 2) + }, + new String[] { "outAry", "outPos", "args" }, // arg names + "apply", fullClsName, // method, class + il, cp); + + HashMap argsMap = new HashMap(); + //extract arguments automatically + if(args == null || args.length == 0) + args = Utils.extractSymbols(expr).toArray(new Expr[]{}); + for(int i=0; i", ACC_PUBLIC | ACC_SUPER, new String[]{"symjava.bytecode.BytecodeFunc"}); + ConstantPoolGen cp = cg.getConstantPool(); // cg creates constant pool + InstructionList il = new InstructionList(); + InstructionFactory factory = new InstructionFactory(cg); + + short acc_flags = ACC_PUBLIC; + MethodGen mg = new MethodGen(acc_flags, // access flags + Type.DOUBLE, // return type + new Type[] { // argument types + new ArrayType(Type.DOUBLE, 1) + }, + new String[] { "args" }, // arg names + "apply", fullClsName, // method, class + il, cp); + + //double sum = 0; + LocalVariableGen lg; + + HashMap argsMap = new HashMap(); + for(int i=0; i fcl = new FuncClassLoader(); + return fcl.newInstance(cg); + } + + public static void test1() { + /** + double apply(double[] args) { + if(args[0] > args[1]) + return args[0]; + else + return args[1]; + } + */ + LCIf cif = new LCIf(Gt.apply(x, y)); //x>y + cif.appendTrue(x); + cif.appendFalse(y); + BytecodeFunc func = gen(new Expr[]{x, y}, cif); + System.out.println(func.apply(new double[]{1,2})); + System.out.println(func.apply(new double[]{10,2})); + } + + public static void test2() { + /** + double apply(double[] args) { + if(args[0] > args[1]) + return args[0]; + else + return args[1]; + } + */ + LCIf cif = new LCIf(Gt.apply(x, y)); //x>y + cif.appendTrue(x+y*x-x/y); + cif.appendFalse(-x); + BytecodeFunc func = gen(new Expr[]{x, y}, cif); + System.out.println(func.apply(new double[]{1,2})); + System.out.println(func.apply(new double[]{10,2})); + } + + public static void main(String[] args) { + test1(); + test2(); + } +} diff --git a/src/lambdacloud/test/TestClassFile.java b/src/lambdacloud/test/TestClassFile.java new file mode 100644 index 0000000..05c5cf9 --- /dev/null +++ b/src/lambdacloud/test/TestClassFile.java @@ -0,0 +1,26 @@ +package lambdacloud.test; + +import lambdacloud.core.CloudConfig; +import lambdacloud.core.CloudFunc; +import lambdacloud.core.CloudSD; +import symjava.bytecode.BytecodeFuncImp1; + +public class TestClassFile { + + public static void main(String[] args) { + CloudConfig.setGlobalConfig("job_aws.conf"); + + CloudFunc f = new CloudFunc(BytecodeFuncImp1.class); + + CloudSD input = new CloudSD("input").init(new double[]{3, 4}); + + CloudSD output = new CloudSD("output").resize(1); + f.apply(output, input); + + if(output.fetch()) { + for(double d : output.getData()) { + System.out.println(d); + } + } + } +} diff --git a/src/lambdacloud/test/TestCloudFunc.java b/src/lambdacloud/test/TestCloudFunc.java new file mode 100644 index 0000000..8b87897 --- /dev/null +++ b/src/lambdacloud/test/TestCloudFunc.java @@ -0,0 +1,82 @@ +package lambdacloud.test; + +import static symjava.symbolic.Symbol.*; +import static lambdacloud.test.TestUtils.*; + +import lambdacloud.core.CloudConfig; +import lambdacloud.core.CloudFunc; +import lambdacloud.core.CloudSD; +import lambdacloud.core.lang.LCVar; + +public class TestCloudFunc { + public static void main(String[] args) { + CloudConfig.setGlobalConfig("job_local.conf"); + + testConstructors1(); + testConstructors2(); + testConstructors3(); + testConstructors4(); + + testLocalVar1(); + testLocalVar2(); + + + } + + public static void testConstructors1() { + CloudFunc func = new CloudFunc(x + y); + CloudSD output = new CloudSD(); + CloudSD input = new CloudSD().init(new double[]{1,2}); + func.apply(output, input); + output.fetch(); + assertEqual(new double[]{3}, output.getData()); + } + public static void testConstructors2() { + CloudFunc func = new CloudFunc(x + y, x, y); + CloudSD output = new CloudSD(); + CloudSD input = new CloudSD().init(new double[]{1,2}); + func.apply(output, input); + output.fetch(); + assertEqual(new double[]{3}, output.getData()); + } + public static void testConstructors3() { + CloudFunc func = new CloudFunc("func_test1",x + y, x, y); + CloudSD output = new CloudSD(); + CloudSD input = new CloudSD().init(new double[]{1,2}); + func.apply(output, input); + output.fetch(); + assertEqual(new double[]{3}, output.getData()); + } + public static void testConstructors4() { + CloudFunc func = new CloudFunc("func_test2",x + y, x, y); + CloudSD output = new CloudSD(); + CloudSD input = new CloudSD().init(new double[]{1,2}); + func.apply(output, input); + output.fetch(); + assertEqual(new double[]{3}, output.getData()); + } + + public static void testLocalVar1() { + LCVar x = LCVar.getDouble("x"); + LCVar y = LCVar.getDouble("y"); + CloudFunc func = new CloudFunc(x + y); + CloudSD output = new CloudSD(); + CloudSD input = new CloudSD().init(new double[]{1,2}); + func.apply(output, input); + output.fetch(); + assertEqual(new double[]{0}, output.getData()); + } + + public static void testLocalVar2() { + LCVar x = LCVar.getDouble("x"); + LCVar y = LCVar.getDouble("y"); + CloudFunc func = new CloudFunc(x + y, new LCVar[]{x,y}); + CloudSD output = new CloudSD(); + CloudSD input = new CloudSD().init(new double[]{1,2}); + func.apply(output, input); + output.fetch(); + assertEqual(new double[]{3}, output.getData()); + } + + +} diff --git a/src/lambdacloud/test/TestCloudFuncEval.java b/src/lambdacloud/test/TestCloudFuncEval.java new file mode 100644 index 0000000..0a1b321 --- /dev/null +++ b/src/lambdacloud/test/TestCloudFuncEval.java @@ -0,0 +1,38 @@ +package lambdacloud.test; + +import static symjava.math.SymMath.sqrt; +import static symjava.symbolic.Symbol.x; +import static symjava.symbolic.Symbol.y; +import lambdacloud.core.CloudConfig; +import lambdacloud.core.CloudFunc; +import lambdacloud.core.CloudSD; + +public class TestCloudFuncEval { + + public static void main(String[] args) { + CloudConfig.setGlobalConfig("job_local.conf"); + + double[] data = { 3, 4 }; + CloudSD input = new CloudSD("var123").init(data); + //input.push(); // The input will be pushed to cloud automatically when evaluating a function + + // This function will be sent to cloud + CloudFunc func = new CloudFunc(sqrt(x*x + y*y)); + + CloudSD output = new CloudSD(); + // Evaluate the function on the cloud and + // return the reference of the result + long begin = System.currentTimeMillis(); + for(int i=0; i<100; i++) { + func.apply(output, input); + } + long end = System.currentTimeMillis(); + System.out.println("Time: "+(end-begin)+"ms"); + + System.out.println(output.getName()); + if(output.fetch()) { + for (double d : output.getData()) + System.out.println(d); + } + } +} diff --git a/src/lambdacloud/test/TestCloudSD.java b/src/lambdacloud/test/TestCloudSD.java new file mode 100644 index 0000000..c345083 --- /dev/null +++ b/src/lambdacloud/test/TestCloudSD.java @@ -0,0 +1,52 @@ +package lambdacloud.test; + +import lambdacloud.core.CloudConfig; +import lambdacloud.core.CloudSD; + +public class TestCloudSD { + + public static void main(String[] args) { + //test1(); + test2(); + } + + public static void test1() { + CloudConfig.setGlobalConfig("job_aws.conf"); + + // Store var123 to the cloud + double[] data = {1,2,3,4,5,6}; + CloudSD var = new CloudSD("var123").init(data); + var.push(); + + // The variable var123 should be on the cloud now. + // We fetch it to local and print out the numbers + CloudSD var2 = new CloudSD("var123"); + var2.fetch(); + if(var2.isOnCloud()) { + for(double d : var2.getData()) { + System.out.println(d); + } + } + + // This variable should not be on the cloud + CloudSD var3 = new CloudSD("out123"); + var3.fetch(); + if(var3.isOnCloud()) { + for(double d : var3.getData()) { + System.out.println(d); + } + } + } + + public static void test2() { + CloudSD v1 = new CloudSD("csd://127.0.0.1:8322/var1"); + v1.init(new double[]{1,2,3,4,5,6,7,8,9,10,11}); + System.out.println(v1.getName()); + System.out.println(v1.getFullName()); + v1.push(); + v1.fetch(); + for(double d : v1.getData()) + System.out.println(d); + } + +} diff --git a/src/lambdacloud/test/TestCompile.java b/src/lambdacloud/test/TestCompile.java new file mode 100644 index 0000000..4c71534 --- /dev/null +++ b/src/lambdacloud/test/TestCompile.java @@ -0,0 +1,104 @@ +package lambdacloud.test; + +import static symjava.symbolic.Symbol.*; +import lambdacloud.core.lang.LCArray; +import lambdacloud.core.lang.LCDoubleArray; +import lambdacloud.core.lang.LCReturn; +import lambdacloud.core.lang.LCStatements; +import symjava.bytecode.BytecodeBatchFunc; +import symjava.bytecode.BytecodeVecFunc; +import symjava.symbolic.Expr; +import symjava.symbolic.Vector; +import symjava.symbolic.utils.JIT; + +public class TestCompile { + + /** + * test comiple, compileVec, compileBatch + * @param args + */ + public static void main(String[] args) { + testCompileBatchFunc(); + testCompileVecFunc1(); + testCompileVecFunc2(); + } + + public static void testCompileBatchFunc() { + BytecodeBatchFunc func = CompileUtils.compileBatchFunc("test1", new Expr[] + { + z, + y*y, + x+y+z + }, x,y,z); + double[] outAry = new double[3]; + func.apply(outAry, 0, new double[]{1,2,3}); + for(double d : outAry) { + System.out.println(d); + } + } + + /** + * Use Jama with LCReturn + */ + public static void testCompileVecFunc1() { + int dim = 3; + Vector a = new Vector("a",dim); + Vector b = new Vector("b",dim); + + BytecodeVecFunc func = CompileUtils.compileVecFunc(new LCReturn(a+b),a,b); + double[] outAry = new double[dim]; + double[][] args = { + new double[]{1,2,3}, + new double[]{4,5,6} + }; + func.apply(outAry, 0, args); + for(double d : outAry) { + System.out.println(d); + } + + } + + /** + * Use Jama with output + */ + public static void testCompileVecFunc2() { + int dim = 3; + LCStatements lcs = new LCStatements(); + LCArray x = new LCDoubleArray("x"); + LCArray y = new LCDoubleArray("y"); + LCArray output = new LCDoubleArray("outAry1"); + for(int i=0; i dict = new HashMap(); + /* + -1 2 3 4 + 1 2 1 3 + 1 2 2 1 + 2 3 1 4 + */ + //matrix stored in cloumnwise + dict.put(A.toString(), new double[]{-1,1,1,2,2,2,2,3,3,1,2,1,4,3,1,4}); + + Session sess1 = new Session(); + + CloudSD rlt1 = sess1.runVec(A, dict); + rlt1.fetch(); + for(double d : rlt1.getData()) + System.out.println(d); + + CloudSD rlt2 = sess1.runVec(sin(A), dict); + rlt2.fetch(); + for(double d : rlt2.getData()) + System.out.println(d); + + CloudSD rlt3 = sess1.runVec(abs(A), dict); + rlt3.fetch(); + for(double d : rlt3.getData()) + System.out.println(d); + } + +} diff --git a/src/lambdacloud/test/TestMatrix.java b/src/lambdacloud/test/TestMatrix.java new file mode 100644 index 0000000..0991432 --- /dev/null +++ b/src/lambdacloud/test/TestMatrix.java @@ -0,0 +1,291 @@ +package lambdacloud.test; + +import static lambdacloud.core.LambdaCloud.CPU; +import static lambdacloud.test.TestUtils.*; + +import java.util.HashMap; +import java.util.Map; + +import lambdacloud.core.CloudConfig; +import lambdacloud.core.CloudSD; +import lambdacloud.core.Session; +import lambdacloud.core.lang.LCDevice; +import lambdacloud.core.lang.LCReturn; +import symjava.bytecode.BytecodeVecFunc; +import symjava.matrix.ExprMatrix; +import symjava.matrix.ExprVector; +import symjava.symbolic.Concat; +import symjava.symbolic.Expr; +import symjava.symbolic.Matrix; +import symjava.symbolic.Vector; + +public class TestMatrix { + public static void main(String[] args) { + testBasic1(); + testBasic2(); + testBasic3(); + testBasic4(); + testConcat1(); + testConcat2(); + testMatrixSplit1(); + testMatrixSplit2(); + testMatrixSplit3(new CloudConfig("job_local.conf")); + } + + public static void testBasic1() { + Matrix A = new Matrix("A",3,3); + BytecodeVecFunc fun = CompileUtils.compileVecFunc(new LCReturn(A)); + /** + * 1 2 3 + * 4 5 6 + * 7 8 9 + */ + double[] data_A = new double[] {1,4,7,2,5,8,3,6,9}; // Column-wise + double[] outAry = new double[9]; + fun.apply(outAry, 0, data_A); + assertEqual(new double[]{1,4,7,2,5,8,3,6,9}, outAry); + } + + public static void testBasic2() { + Vector x = new Vector("x",3); + BytecodeVecFunc fun = CompileUtils.compileVecFunc(new LCReturn(x)); + double[] data_x = new double[] {1,2,3}; + double[] outAry = new double[3]; + fun.apply(outAry, 0, data_x); + assertEqual(new double[]{1,2,3}, outAry); + } + + public static void testBasic3() { + Matrix A = new Matrix("A",3,3); + Vector x = new Vector("x",3); + BytecodeVecFunc fun = CompileUtils.compileVecFunc(new LCReturn(A*x)); + /** + * 1 2 3 + * 4 5 6 + * 7 8 9 + */ + double[] data_A = new double[] {1,4,7,2,5,8,3,6,9}; // Column-wise + double[] data_x = new double[] {1,2,3}; + double[] outAry = new double[3]; + fun.apply(outAry, 0, data_A, data_x); + assertEqual(new double[]{14,32,50}, outAry); + } + + public static void testBasic4() { + Vector x = new Vector("x",3); + Vector y = new Vector("y",3); + + BytecodeVecFunc fun = CompileUtils.compileVecFunc(new LCReturn(x+y), x, y); + double[] outAry = new double[4]; + double[] data_x = new double[] {1,2,3}; + double[] data_y = new double[] {1,2,3}; + fun.apply(outAry, 1, data_x, data_y); //output at position 1 + assertEqual(new double[]{0,2,4,6}, outAry); + } + + public static void testConcat1() { + Vector x = new Vector("x",3); + Vector y = new Vector("y",2); + Vector z = new Vector("z",4); + + BytecodeVecFunc fun = CompileUtils.compileVecFunc(new LCReturn(new Concat(x,y,z)), x, y, z); + double[] outAry = new double[9]; + double[] data_x = new double[] {1,2,3}; + double[] data_y = new double[] {4,5}; + double[] data_z = new double[] {6,7,8,9}; + fun.apply(outAry, 0, data_x, data_y, data_z); + assertEqual(new double[]{1,2,3,4,5,6,7,8,9}, outAry); + } + + public static void testConcat2() { + Vector x = new Vector("x",3); + Vector y = new Vector("y",2); + Vector z = new Vector("z",5); + + BytecodeVecFunc fun = CompileUtils.compileVecFunc(new LCReturn(new Concat(x,y)+z), x, y, z); + double[] outAry = new double[5]; + double[] data_x = new double[] {1,2,3}; + double[] data_y = new double[] {4,5}; + double[] data_z = new double[] {1,2,3,4,5}; + fun.apply(outAry, 0, data_x, data_y, data_z); + assertEqual(new double[]{2,4,6,8,10}, outAry); + } + + public static void testMatrixSplit1() { + int dim = 4; + Matrix A = new Matrix("A", dim, dim); + Vector x = new Vector("x", dim); + Vector y0 = new Vector("y0", dim); + + ExprMatrix AA = A.split(2, 2); + ExprVector xx = x.split(2); + ExprVector yy = (ExprVector)(AA*xx); + System.out.println(yy); + yy[0].runOn(new LCDevice(0)); + yy[1].runOn(new LCDevice(1)); + + Expr res = new Concat(yy[0],yy[1])+y0; + + System.out.println(res); + //Doesn't work because the symbol AA[0][0] has no name? + //BytecodeVecFunc fun = CompileUtils.compileVec(new LCReturn(res), A,x,y0,AA[0][0],AA[1][0],xx[0],xx[1]); + BytecodeVecFunc fun = CompileUtils.compileVecFunc(new LCReturn(res)); +/* +1 2 3 4 0 1 13 +1 2 1 3 * 1 + 2 = 9 +1 2 2 1 2 3 10 +2 3 1 4 1 4 13 +*/ + double[] outAry = new double[4]; + double[] data_A_11 = new double[] {2,1,1,4}; + double[] data_A_10 = new double[] {1,2,2,3}; + double[] data_A_01 = new double[] {3,1,4,3}; + double[] data_A_00 = new double[] {1,1,2,2}; + double[] data_x_0 = new double[] {0,1}; + double[] data_x_1 = new double[] {2,1}; + double[] data_y0 = new double[] {1,2,3,4}; + //void apply(double[] output, int outPos, double[] A_1_1, double[] A_1_0, double[] A_0_1, double[] A_0_0, double[] x_0, double[] x_1, double[] y0); + fun.apply(outAry, 0, data_A_11, data_A_10, data_A_01, data_A_00, data_x_0, data_x_1, data_y0); + assertEqual(new double[]{13,9,10,13}, outAry); + } + + public static void testMatrixSplit2() { + int dim = 4; + Matrix A = new Matrix("A", dim, dim); + Vector x = new Vector("x", dim); + Vector y0 = new Vector("y0", dim); + + ExprMatrix AA = A.split(2, 2); + ExprVector xx = x.split(2); + ExprVector yy = (ExprVector)(AA*xx); + System.out.println(yy); + yy[0].runOn(new LCDevice(0)); + yy[1].runOn(new LCDevice(1)); + + Expr res = new Concat(yy[0],yy[1])+y0; + + Map dict = new HashMap(); + /* + 1 2 3 4 0 1 13 + 1 2 1 3 * 1 + 2 = 9 + 1 2 2 1 2 3 10 + 2 3 1 4 1 4 13 + */ + dict.put(A.toString(), new double[]{1,1,1,2,2,2,2,3,3,1,2,1,4,3,1,4}); + dict.put(x.toString(), new double[]{0,1,2,1}); + dict.put(y0.toString(), new double[]{1,2,3,4}); + + //those parameters should be able automatically generated according to the definition of AA and xx + //see testMatrixSplit3() + double[] data_A_11 = new double[] {2,1,1,4}; + double[] data_A_10 = new double[] {1,2,2,3}; + double[] data_A_01 = new double[] {3,1,4,3}; + double[] data_A_00 = new double[] {1,1,2,2}; + double[] data_x_0 = new double[] {0,1}; + double[] data_x_1 = new double[] {2,1}; + dict.put(AA[0][0].toString(), data_A_00); + dict.put(AA[0][1].toString(), data_A_01); + dict.put(AA[1][0].toString(), data_A_10); + dict.put(AA[1][1].toString(), data_A_11); + dict.put(xx[0].toString(), data_x_0); + dict.put(xx[1].toString(), data_x_1); + + Session sess1 = new Session(); + CloudSD rlt = sess1.runVec(res, dict); + rlt.fetch(); + assertEqual(new double[]{13,9,10,13}, rlt.getData()); + } + + /** + * Automatic data dict split for matrices and vectors + */ + public static void testMatrixSplit3(CloudConfig config) { + int dim = 4; + Matrix A = new Matrix("A", dim, dim); + Vector x = new Vector("x", dim); + Vector y0 = new Vector("y0", dim); + + ExprMatrix AA = A.split(2, 2); + ExprVector xx = x.split(2); + // yy = AA * xx + ExprVector yy = (ExprVector)(AA*xx); + // res = yy + y0 + Expr res = CPU( new Concat( CPU(yy[0]), CPU(yy[1]) )+y0 ); + System.out.println("Test: res="+res); + + Map dict = new HashMap(); + /* + 1 2 3 4 0 1 13 + 1 2 1 3 * 1 + 2 = 9 + 1 2 2 1 2 3 10 + 2 3 1 4 1 4 13 + */ + dict.put(A.toString(), new double[]{1,1,1,2,2,2,2,3,3,1,2,1,4,3,1,4}); + dict.put(x.toString(), new double[]{0,1,2,1}); + dict.put(y0.toString(), new double[]{1,2,3,4}); + + Session sess = new Session(config); + CloudSD rlt = sess.runVec(res, dict); + rlt.fetch(); + assertEqual(new double[]{13,9,10,13}, rlt.getData()); + /** +Using config file: /Users/yueming.liu/workspace/eclipse_kepler/SymJava/conf/job_local.conf +127.0.0.1:8322 +127.0.0.1:8323 +127.0.0.1:8324 +Test: res=[A_0_0*x_0 + A_0_1*x_1, A_1_0*x_0 + A_1_1*x_1] + y0 +Generating bytecode for: symjava.bytecode.cfunc4 +void apply(double[] output, int outPos, double[] A_1_1, double[] A_1_0, double[] x_0, double[] x_1) = return A_1_0*x_0 + A_1_1*x_1 +getIR(): create a new instance to test for: return A_1_0*x_0 + A_1_1*x_1 +Received CloudFuncResp: symjava.bytecode.cfunc4 +Generating bytecode for: symjava.bytecode.cfunc5 +void apply(double[] output, int outPos, double[] A_0_1, double[] A_0_0, double[] x_0, double[] x_1) = return A_0_0*x_0 + A_0_1*x_1 +getIR(): create a new instance to test for: return A_0_0*x_0 + A_0_1*x_1 +Received CloudFuncResp: symjava.bytecode.cfunc5 +Generating bytecode for: symjava.bytecode.cfunc6 +void apply(double[] output, int outPos, double[] __vec_3, double[] __vec_2, double[] y0) = return [__vec_2, __vec_3] + y0 +getIR(): create a new instance to test for: return [__vec_2, __vec_3] + y0 +Received CloudFuncResp: symjava.bytecode.cfunc6 +>>Session eval: cfunc4=A_1_0*x_0 + A_1_1*x_1; args: +[ A_1_1 = [2.0, 1.0, 1.0, 4.0] (Local) + A_1_0 = [1.0, 2.0, 2.0, 3.0] (Local) + x_0 = [0.0, 1.0] (Local) + x_1 = [2.0, 1.0] (Local) +]Received CloudSDResp: A_1_1 +Received CloudSDResp: A_1_0 +Received CloudSDResp: x_0 +Received CloudSDResp: x_1 +Received CloudSD: csd://127.0.0.1:8323/csd16 = [] (on Cloud) +Fetch data ( Connected to 127.0.0.1:8323 ) +Received CloudSD: csd://127.0.0.1:8323/csd16 = [7.0, 9.0] (on Cloud & Local) +Return: [7.0 9.0 ] +>>Session eval: cfunc5=A_0_0*x_0 + A_0_1*x_1; args: +[ A_0_1 = [3.0, 1.0, 4.0, 3.0] (Local) + A_0_0 = [1.0, 1.0, 2.0, 2.0] (Local) + x_0 = [0.0, 1.0] (Local) + x_1 = [2.0, 1.0] (Local) +]Received CloudSDResp: A_0_1 +Received CloudSDResp: A_0_0 +Received CloudSDResp: x_0 +Received CloudSDResp: x_1 +Received CloudSD: csd://127.0.0.1:8322/csd22 = [] (on Cloud) +Fetch data ( Connected to 127.0.0.1:8322 ) +Received CloudSD: csd://127.0.0.1:8322/csd22 = [12.0, 7.0] (on Cloud & Local) +Return: [12.0 7.0 ] +>>Session eval: cfunc6=[__vec_2, __vec_3] + y0; args: +[ csd://127.0.0.1:8323/csd16 = [7.0, 9.0] (on Cloud & Local) + csd://127.0.0.1:8322/csd22 = [12.0, 7.0] (on Cloud & Local) + y0 = [1.0, 2.0, 3.0, 4.0] (Local) +]Received CloudSDResp: y0 +Received CloudSD: csd://127.0.0.1:8324/csd7 = [] (on Cloud) +Fetch data ( Connected to 127.0.0.1:8324 ) +Received CloudSD: csd://127.0.0.1:8324/csd7 = [13.0, 9.0, 10.0, 13.0] (on Cloud & Local) +Return: [13.0 9.0 10.0 13.0 ] +Fetch data ( Connected to 127.0.0.1:8324 ) +Received CloudSD: csd://127.0.0.1:8324/csd7 = [13.0, 9.0, 10.0, 13.0] (on Cloud & Local) +Passed! + + */ + } + +} diff --git a/src/lambdacloud/test/TestNetwork.java b/src/lambdacloud/test/TestNetwork.java new file mode 100644 index 0000000..983aafb --- /dev/null +++ b/src/lambdacloud/test/TestNetwork.java @@ -0,0 +1,69 @@ +package lambdacloud.test; + +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.OutputStream; +import java.io.PrintStream; + +import lambdacloud.core.CloudConfig; +import lambdacloud.core.CloudSD; + +public class TestNetwork { + + public static void main(String[] args) { + OutputStream output; + try { + output = new FileOutputStream("/dev/null"); + PrintStream nullOut = new PrintStream(output); + System.setErr(nullOut); } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + int N = 100000; + if(args.length >= 1) { + N = Integer.parseInt(args[0]); + } + CloudConfig.setGlobalConfig("job1.conf"); + for(int i=0; i dict = new HashMap(); + dict.put(x.toString(), 3.0); + dict.put(y.toString(), 4.0); + + CloudSD output = sess.runOpt(expr, dict); + if(output.fetch()) { + for(double d : output.getData()) { + System.out.println(d); + } + } + } + +} diff --git a/src/lambdacloud/test/TestThread.java b/src/lambdacloud/test/TestThread.java new file mode 100644 index 0000000..7c993d0 --- /dev/null +++ b/src/lambdacloud/test/TestThread.java @@ -0,0 +1,112 @@ +package lambdacloud.test; + +import static lambdacloud.core.LambdaCloud.CPU; +import static symjava.math.SymMath.sqrt; +import static symjava.symbolic.Symbol.x; +import static symjava.symbolic.Symbol.y; +import static symjava.symbolic.Symbol.z; + +import java.util.HashMap; +import java.util.Map; + +import lambdacloud.core.CloudConfig; +import lambdacloud.core.CloudFunc; +import lambdacloud.core.CloudSD; +import lambdacloud.core.Session; +import symjava.symbolic.Expr; + +public class TestThread { + + public static void main(String[] args) { + test1(); + test2(); + testMatrixSplit3(); + } + public static void test1() { + CloudConfig config = new CloudConfig(); + //make sure the expression can be run on different thread + Expr expr = CPU(x*x); + System.out.println(expr); + + CloudFunc func = new CloudFunc(config, expr); + CloudSD input = new CloudSD().init(new double[]{3}); + CloudSD output = new CloudSD(); + func.apply(output, input); + if(output.fetch()) { + System.out.println(output); + } + } + + /** + * Test multi-thread + */ + public static void test2() { + CloudConfig config = new CloudConfig(); + Expr sum = CPU(x*x) + CPU(y*y) + CPU(z*z) + CPU(x+y+z); + //Expr sum = CPU(x*x) + CPU(y+z); + //Expr sum = CPU(x) + CPU(y) + CPU(z) + CPU(x); + Expr expr = CPU(sqrt(sum)); + System.out.println(expr); + + Session sess = new Session(config); + Map dict = new HashMap(); + dict.put(x.toString(), 2.0); + dict.put(y.toString(), 3.0); + dict.put(z.toString(), 4.0); + + double d = 0.0; + d = sess.runSimpleAsync(expr, dict); + System.out.println(d); //6.164414002968976 + + d = sess.runSimple(expr, dict); + System.out.println(d); //6.164414002968976 + + d = sess.runLocal(expr, dict); + System.out.println(d); //6.164414002968976 + } + + public static void testMatrixSplit3() { + CloudConfig config = new CloudConfig(); + TestMatrix.testMatrixSplit3(config); + /** +Using 'local' config. +Test: res=[A_0_0*x_0 + A_0_1*x_1, A_1_0*x_0 + A_1_1*x_1] + y0 +Generating bytecode for: symjava.bytecode.cfunc12 +void apply(double[] output, int outPos, double[] A_0_1, double[] A_0_0, double[] x_0, double[] x_1) = return A_0_0*x_0 + A_0_1*x_1 +Generating bytecode for: symjava.bytecode.cfunc13 +void apply(double[] output, int outPos, double[] A_1_1, double[] A_1_0, double[] x_0, double[] x_1) = return A_1_0*x_0 + A_1_1*x_1 +Generating bytecode for: symjava.bytecode.cfunc14 +void apply(double[] output, int outPos, double[] __vec_12, double[] __vec_13, double[] y0) = return [__vec_12, __vec_13] + y0 +>>Session eval: cfunc12=A_0_0*x_0 + A_0_1*x_1; args: +[ A_0_1 = [3.0, 1.0, 4.0, 3.0] (Local) + A_0_0 = [1.0, 1.0, 2.0, 2.0] (Local) + x_0 = [0.0, 1.0] (Local) + x_1 = [2.0, 1.0] (Local) +]Fetching: [csd24 = [] (Local)] + >>>Thread-11 evaluating cfunc12...; Return: csd24 = [] (Local) +Fetched: [csd24 = [12.0, 7.0] (Local)] +Return: [12.0 7.0 ] +>>Session eval: cfunc13=A_1_0*x_0 + A_1_1*x_1; args: +[ A_1_1 = [2.0, 1.0, 1.0, 4.0] (Local) + A_1_0 = [1.0, 2.0, 2.0, 3.0] (Local) + x_0 = [0.0, 1.0] (Local) + x_1 = [2.0, 1.0] (Local) +]Fetching: [csd25 = [] (Local)] + >>>Thread-12 evaluating cfunc13...; Return: csd25 = [] (Local) +Fetched: [csd25 = [7.0, 9.0] (Local)] +Return: [7.0 9.0 ] +>>Session eval: cfunc14=[__vec_12, __vec_13] + y0; args: +[ csd24 = [12.0, 7.0] (Local) + csd25 = [7.0, 9.0] (Local) + y0 = [1.0, 2.0, 3.0, 4.0] (Local) +]Fetching: [csd26 = [] (Local)] +Fetched without waiting: [csd24 = [12.0, 7.0] (Local)] +Fetched without waiting: [csd25 = [7.0, 9.0] (Local)] + >>>Thread-13 evaluating cfunc14...; Return: csd26 = [] (Local) +Fetched: [csd26 = [13.0, 9.0, 10.0, 13.0] (Local)] +Return: [13.0 9.0 10.0 13.0 ] +Fetched without waiting: [csd26 = [13.0, 9.0, 10.0, 13.0] (Local)] +Passed! + */ + } +} diff --git a/src/lambdacloud/test/TestUtils.java b/src/lambdacloud/test/TestUtils.java new file mode 100644 index 0000000..63fd4ea --- /dev/null +++ b/src/lambdacloud/test/TestUtils.java @@ -0,0 +1,18 @@ +package lambdacloud.test; + +public class TestUtils { + public static boolean assertEqual(double[] a, double[] b) { + if(a.length != b.length) { + System.err.println("Failed! a.length != b.length: "+a.length+" != "+b.length); + return false; + } + for(int i=0; i1e-8) { + System.err.println("Failed! a["+i+"] != b["+i+"]: "+a[i]+" != "+b[i]); + return false; + } + } + System.out.println("Passed!"); + return true; + } +} diff --git a/src/symjava/bytecode/BytecodeBatchFunc.java b/src/symjava/bytecode/BytecodeBatchFunc.java index 1f7712a..cfae3bb 100644 --- a/src/symjava/bytecode/BytecodeBatchFunc.java +++ b/src/symjava/bytecode/BytecodeBatchFunc.java @@ -1,5 +1,10 @@ package symjava.bytecode; +/** + * Interface for function that return a list of values that is to say + * the function evaluates a list of expressions with the same arguments + * + */ public interface BytecodeBatchFunc { - void apply(double[] outAry, int outPos, double[] ...args); + void apply(double[] outAry, int outPos, double ...args); } diff --git a/src/symjava/bytecode/BytecodeBatchVecFunc.java b/src/symjava/bytecode/BytecodeBatchVecFunc.java new file mode 100644 index 0000000..9b1703d --- /dev/null +++ b/src/symjava/bytecode/BytecodeBatchVecFunc.java @@ -0,0 +1,30 @@ +package symjava.bytecode; + +public class BytecodeBatchVecFunc implements BytecodeVecFunc { + BytecodeVecFunc func; + int vecLen; //Input vector length + int retLen; //Return vector length + + public BytecodeBatchVecFunc(BytecodeVecFunc func, int vecLen, int retLen) { + this.func = func; + this.vecLen = vecLen; + this.retLen = retLen; + } + + @Override + public void apply(double[] outAry, int outPos, double[]... args) { + double[] tmpBuf = new double[retLen]; + double[][] tmpArgs = new double[args.length][vecLen]; + int destPos = 0; + int argPos = 0; + for(int i=0; i map = new HashMap(); + map.put("x", fx); + map.put("y", fy); + MathFunc ff = f.compose(map); + + MathFunc[][] lhs = new MathFunc[3][3]; + MathFunc[] rhs = new MathFunc[3]; + for(int j=0; j<3; j++) { + MathFunc v = sf[j]; + for(int i=0; i<3; i++) { + MathFunc u = sf[i]; + //lhs[j][i] = (u.diff("x")*v.diff("x")+u.diff("y")*v.diff("y") + u*v)*jac; + lhs[j][i] = (grad(u,"x","y").dot(grad(v,"x","y")) + u*v)*jac; + } + rhs[j] = v*ff*jac; + rhs[j].setName("RHS"+j); + } + + CompiledFunc[][] clhs = new CompiledFunc[3][3]; + CompiledFunc[] crhs = new CompiledFunc[3]; + for(int j=0; j<3; j++) { + for(int i=0; i<3; i++) { + clhs[j][i] = lhs[j][i].compile(argsOrder); + } + crhs[j] = rhs[j].compile(argsOrder); + } + + double[][] A = new double[3][3]; + double[] b = new double[3]; + double[] params = new double[9]; + double[] coords = e.getNodeCoords(); + System.arraycopy(coords, 0, params, 0, coords.length); + + long start = System.currentTimeMillis(); + for(int k=0; k 0.5) + s++; + else + s--; + + 6: dcmpg + 7: ifge 17 + if(0.5 < s) + s++; + else + s--; + +// 6: dcmpl +// 7: iflt 17 + if(0.5 >= s) + s++; + else + s--; + +// 6: dcmpg +// 7: ifgt 17 + if(0.5 <= s) + s++; + else + s--; + */ +// double[] data = new double[] {1,2,3,4}; +// double sum = 0; +// for(int i=0; ij && d>e) s = 0; + else s = 1; + + if(d>e) s = 0; + else s = 1; + } +} diff --git a/src/symjava/bytecode/TestBytecodeVarArgs.java b/src/symjava/bytecode/TestBytecodeVarArgs.java new file mode 100644 index 0000000..9ae8dfc --- /dev/null +++ b/src/symjava/bytecode/TestBytecodeVarArgs.java @@ -0,0 +1,14 @@ +package symjava.bytecode; + +public class TestBytecodeVarArgs { + public static int fun(double ...args) { + return 0; + } + public static void main(String[] args) { + // TODO Auto-generated method stub + fun(1.0,2.0); + fun(1.0,2.0,3.0); + TestBytecodeVarArgs[] ary = new TestBytecodeVarArgs[10]; + } + +} diff --git a/src/symjava/bytecode/VecFuncs.java b/src/symjava/bytecode/VecFuncs.java index a73ef72..2f12f04 100644 --- a/src/symjava/bytecode/VecFuncs.java +++ b/src/symjava/bytecode/VecFuncs.java @@ -3,18 +3,18 @@ import java.util.ArrayList; import java.util.List; -public class VecFuncs implements BytecodeVecFunc { +public class VecFuncs implements BytecodeBatchFunc { public static class FuncInfo { - BytecodeVecFunc func; + BytecodeBatchFunc func; int outPos; - public FuncInfo(BytecodeVecFunc func, int outPos) { + public FuncInfo(BytecodeBatchFunc func, int outPos) { this.func = func; this.outPos = outPos; } } List funInfo = new ArrayList(); - public void addFunc(BytecodeVecFunc func, int outPos) { + public void addFunc(BytecodeBatchFunc func, int outPos) { funInfo.add(new FuncInfo(func, outPos)); } diff --git a/src/symjava/domains/Interval.java b/src/symjava/domains/Interval.java index 2952800..daab236 100644 --- a/src/symjava/domains/Interval.java +++ b/src/symjava/domains/Interval.java @@ -67,7 +67,7 @@ public static Interval apply(T1 start, T2 end, Expr coordVar) { @Override public String toString() { - return "["+start+","+end+"]"; + return "interval("+this.getCoordVars()[0]+","+start+","+end+","+this.getStepSize()+")"; } @Override diff --git a/src/symjava/examples/BenchmarkGriewank.java b/src/symjava/examples/BenchmarkGriewank.java new file mode 100644 index 0000000..d7f3d54 --- /dev/null +++ b/src/symjava/examples/BenchmarkGriewank.java @@ -0,0 +1,61 @@ +package symjava.examples; + +import symjava.bytecode.BytecodeBatchFunc; +import symjava.math.SymMath; +import symjava.symbolic.Expr; +import symjava.symbolic.Symbol; +import symjava.symbolic.Symbols; +import symjava.symbolic.utils.AddList; +import symjava.symbolic.utils.JIT; +import symjava.symbolic.utils.MulList; + +//http://www.sfu.ca/~ssurjano/griewank.html +public class BenchmarkGriewank { + + public static void main(String[] args) { + test(); + } + + public static void test() { + // TODO Auto-generated method stub + int N = 50; + long start; + Symbol i = new Symbol("i"); + Symbols xi = new Symbols("x", i); + + start = System.currentTimeMillis(); + AddList term1 = new AddList(); + for (int j = 0; j < N; j++) { + term1.add(xi.get(j) * xi.get(j) / 4000.0); + } + MulList term2 = new MulList(); + for (int j = 0; j < N; j++) { + term2.add(SymMath.cos(xi.get(j) / Math.sqrt(j + 1))); + } + + Expr griewank = term1.toExpr() - term2.toExpr() + 1.0; + //System.out.println(griewank); + + Expr[] grad = new Expr[N]; + for(int j=0;j funcs = new ArrayList(); + final ArrayList funcs = new ArrayList(); for(int i=0; i funcs = new ArrayList(); + ArrayList funcs = new ArrayList(); int batchLen = 10000; double[] outAry = new double[batchLen]; double[] args = new double[batchLen]; for(int i=0; i funcs = new ArrayList(); + ArrayList funcs = new ArrayList(); int batchLen = 100000; double[] outAry = new double[batchLen]; double[] args = new double[batchLen]; for(int i=0; i argsMap, int argsStartPos, + Map funcRefsMap) { + InstructionHandle startPos = arg1.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + arg2.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + il.append(new IAND()); + return startPos; + } + + @Override + public TypeInfo getTypeInfo() { + return TypeInfo.tiInt; + } + + @Override + public void updateLabel() { + // TODO Auto-generated method stub + + } + } \ No newline at end of file diff --git a/src/symjava/logic/Not.java b/src/symjava/logic/Not.java index 0bda63a..e55707b 100644 --- a/src/symjava/logic/Not.java +++ b/src/symjava/logic/Not.java @@ -1,6 +1,22 @@ package symjava.logic; +import java.util.Map; + +import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.DCMPL; +import com.sun.org.apache.bcel.internal.generic.GOTO; +import com.sun.org.apache.bcel.internal.generic.IFLE; +import com.sun.org.apache.bcel.internal.generic.IXOR; +import com.sun.org.apache.bcel.internal.generic.InstructionFactory; +import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.MethodGen; +import com.sun.org.apache.bcel.internal.generic.NOP; +import com.sun.org.apache.bcel.internal.generic.PUSH; + import symjava.symbolic.Expr; +import symjava.symbolic.Expr.TYPE; +import symjava.symbolic.TypeInfo; import symjava.symbolic.arity.UnaryOp; public class Not extends UnaryOp implements Logic { @@ -29,4 +45,26 @@ public Expr diff(Expr expr) { public static Expr simplifiedIns(Expr expr) { return new Not(expr); } + + public InstructionHandle bytecodeGen(String clsName, MethodGen mg, + ConstantPoolGen cp, InstructionFactory factory, + InstructionList il, Map argsMap, int argsStartPos, + Map funcRefsMap) { + InstructionHandle startPos = arg.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + il.append(new PUSH(cp, 1)); + il.append(new IXOR()); + return startPos; + } + + @Override + public TypeInfo getTypeInfo() { + return TypeInfo.tiInt; + } + + @Override + public void updateLabel() { + // TODO Auto-generated method stub + + } + } diff --git a/src/symjava/logic/Or.java b/src/symjava/logic/Or.java index eac0b74..270b155 100644 --- a/src/symjava/logic/Or.java +++ b/src/symjava/logic/Or.java @@ -1,6 +1,22 @@ package symjava.logic; +import java.util.Map; + +import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.DCMPL; +import com.sun.org.apache.bcel.internal.generic.GOTO; +import com.sun.org.apache.bcel.internal.generic.IFLE; +import com.sun.org.apache.bcel.internal.generic.IOR; +import com.sun.org.apache.bcel.internal.generic.InstructionFactory; +import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.MethodGen; +import com.sun.org.apache.bcel.internal.generic.NOP; +import com.sun.org.apache.bcel.internal.generic.PUSH; + import symjava.symbolic.Expr; +import symjava.symbolic.Expr.TYPE; +import symjava.symbolic.TypeInfo; import symjava.symbolic.arity.BinaryOp; public class Or extends BinaryOp implements Logic { @@ -28,4 +44,26 @@ public Expr diff(Expr expr) { public static Expr simplifiedIns(Expr lhs, Expr rhs) { return new Or(lhs, rhs); } + + public InstructionHandle bytecodeGen(String clsName, MethodGen mg, + ConstantPoolGen cp, InstructionFactory factory, + InstructionList il, Map argsMap, int argsStartPos, + Map funcRefsMap) { + InstructionHandle startPos = arg1.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + arg2.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + il.append(new IOR()); + return startPos; + } + + @Override + public TypeInfo getTypeInfo() { + return TypeInfo.tiInt; + } + + @Override + public void updateLabel() { + // TODO Auto-generated method stub + + } + } diff --git a/src/symjava/logic/Xor.java b/src/symjava/logic/Xor.java index 0a498c0..22c4836 100644 --- a/src/symjava/logic/Xor.java +++ b/src/symjava/logic/Xor.java @@ -1,6 +1,22 @@ package symjava.logic; +import java.util.Map; + +import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.DCMPL; +import com.sun.org.apache.bcel.internal.generic.GOTO; +import com.sun.org.apache.bcel.internal.generic.IFLE; +import com.sun.org.apache.bcel.internal.generic.IXOR; +import com.sun.org.apache.bcel.internal.generic.InstructionFactory; +import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.MethodGen; +import com.sun.org.apache.bcel.internal.generic.NOP; +import com.sun.org.apache.bcel.internal.generic.PUSH; + import symjava.symbolic.Expr; +import symjava.symbolic.Expr.TYPE; +import symjava.symbolic.TypeInfo; import symjava.symbolic.arity.BinaryOp; public class Xor extends BinaryOp implements Logic { @@ -29,4 +45,26 @@ public Expr diff(Expr expr) { public static Expr simplifiedIns(Expr lhs, Expr rhs) { return new Xor(lhs, rhs); } + + public InstructionHandle bytecodeGen(String clsName, MethodGen mg, + ConstantPoolGen cp, InstructionFactory factory, + InstructionList il, Map argsMap, int argsStartPos, + Map funcRefsMap) { + InstructionHandle startPos = arg1.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + arg2.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + il.append(new IXOR()); + return startPos; + } + + @Override + public TypeInfo getTypeInfo() { + return TypeInfo.tiInt; + } + + @Override + public void updateLabel() { + // TODO Auto-generated method stub + + } + } diff --git a/src/symjava/math/Div.java b/src/symjava/math/Div.java index 8bffa38..18f6071 100644 --- a/src/symjava/math/Div.java +++ b/src/symjava/math/Div.java @@ -3,8 +3,9 @@ import java.util.ArrayList; import java.util.List; -import symjava.matrix.SymVector; +import symjava.matrix.ExprVector; import symjava.symbolic.Expr; +import symjava.symbolic.TypeInfo; import symjava.symbolic.arity.NaryOp; import symjava.symbolic.utils.Utils; @@ -15,7 +16,7 @@ public class Div extends NaryOp { protected Expr expr; - public Div(SymVector vec) { + public Div(ExprVector vec) { super(null); if(vec instanceof Grad) { Grad g = (Grad)vec; @@ -30,12 +31,12 @@ public Div(SymVector vec) { create(vec, freeVars.toArray(new Expr[0])); } - public Div(SymVector vec, Expr... freeVars) { + public Div(ExprVector vec, Expr... freeVars) { super(null); create(vec, freeVars); } - private Div create(SymVector vec, Expr... freeVars) { + private Div create(ExprVector vec, Expr... freeVars) { if(vec.dim() != freeVars.length) { throw new RuntimeException("vec.dim() != freeVars.length"); } @@ -51,11 +52,11 @@ private Div create(SymVector vec, Expr... freeVars) { return this; } - public static Div apply(SymVector vec) { + public static Div apply(ExprVector vec) { return new Div(vec); } - public static Div apply(SymVector vec, Expr ...expr) { + public static Div apply(ExprVector vec, Expr ...expr) { return new Div(vec, expr); } @@ -85,5 +86,17 @@ public Expr diff(Expr expr) { // TODO Auto-generated method stub return null; } + + @Override + public TypeInfo getTypeInfo() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void updateLabel() { + // TODO Auto-generated method stub + + } } diff --git a/src/symjava/math/Dot.java b/src/symjava/math/Dot.java index 9de062a..c16acc7 100644 --- a/src/symjava/math/Dot.java +++ b/src/symjava/math/Dot.java @@ -1,42 +1,71 @@ package symjava.math; +import static com.sun.org.apache.bcel.internal.generic.InstructionConstants.DADD; +import static com.sun.org.apache.bcel.internal.generic.InstructionConstants.FADD; +import static com.sun.org.apache.bcel.internal.generic.InstructionConstants.IADD; +import static com.sun.org.apache.bcel.internal.generic.InstructionConstants.LADD; + import java.util.ArrayList; import java.util.List; +import java.util.Map; + +import com.sun.org.apache.bcel.internal.Constants; +import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.InstructionFactory; +import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.MethodGen; +import com.sun.org.apache.bcel.internal.generic.ObjectType; +import com.sun.org.apache.bcel.internal.generic.Type; -import symjava.matrix.SymVector; +import symjava.matrix.ExprVector; import symjava.symbolic.Add; import symjava.symbolic.Expr; import symjava.symbolic.SymReal; +import symjava.symbolic.TypeInfo; +import symjava.symbolic.Vector; +import symjava.symbolic.Expr.TYPE; +import symjava.symbolic.arity.BinaryOp; +import symjava.symbolic.utils.BytecodeUtils; import symjava.symbolic.utils.Utils; /** * Dot Product of two vectors * */ -public class Dot extends Expr { - protected SymVector left; - protected SymVector right; +public class Dot extends BinaryOp { protected Expr expr = null; - public Dot(SymVector l, SymVector r) { + public Dot(ExprVector l, ExprVector r) { + super(l,r); if(l.dim() != r.dim()) throw new IllegalArgumentException("The size of the two vector must be the same!"); - left = l; - right = r; - if(left instanceof Grad && right instanceof Grad) { - label = left + " \\cdot " + right; + arg1 = l; + arg2 = r; + if(arg1 instanceof Grad && arg2 instanceof Grad) { + label = arg1 + " \\cdot " + arg2; sortKey = label; return; } List list = new ArrayList(); - for(int i=0; i list = new ArrayList(); for(int i=0; i list = new ArrayList(); - for(int i=0; i argsMap, int argsStartPos, + Map funcRefsMap) { + InstructionHandle startPos = arg1.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + if(arg1.getType() == TYPE.VECTOR && arg2.getType() == TYPE.VECTOR) { + arg2.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + il.append(factory.createInvoke("symjava.symbolic.utils.BytecodeOpSupport", "dot", + //Type.DOUBLE, new Type[] { new ObjectType("Jama.Matrix"),new ObjectType("Jama.Matrix") }, + new ObjectType("Jama.Matrix"), new Type[] { new ObjectType("Jama.Matrix"),new ObjectType("Jama.Matrix") }, + Constants.INVOKESTATIC)); + return startPos; + } + //TODO + return startPos; + } + +// @Override +// public TypeInfo getTypeInfo() { +// return TypeInfo.tiDouble; +// } + + @Override + public void updateLabel() { + // TODO Auto-generated method stub + + } } diff --git a/src/symjava/math/Grad.java b/src/symjava/math/Grad.java index fae5516..fffad8d 100644 --- a/src/symjava/math/Grad.java +++ b/src/symjava/math/Grad.java @@ -2,7 +2,7 @@ import java.util.List; -import symjava.matrix.SymVector; +import symjava.matrix.ExprVector; import symjava.symbolic.Derivative; import symjava.symbolic.Expr; import symjava.symbolic.Func; @@ -12,7 +12,7 @@ * Gradient of a function or expression * */ -public class Grad extends SymVector { +public class Grad extends ExprVector { public Expr[] args = null; protected Func func = null; @@ -22,7 +22,7 @@ public class Grad extends SymVector { * @param data * @param args */ - public Grad(SymVector data, Expr... args) { + public Grad(ExprVector data, Expr... args) { for(Expr e : data) this.data.add(e); this.args = args; @@ -45,7 +45,7 @@ public Grad(Expr f) { for(Expr x : args) { data.add(f.diff(x)); } - } + } } public Grad(Expr f, Expr[] args) { @@ -91,15 +91,15 @@ public Grad(Expr F, Expr[] fs, Expr[] dfs) { } } - public static SymVector apply(Expr f) { + public static ExprVector apply(Expr f) { return new Grad(f); } - public static SymVector apply(Expr f, Expr[] args) { + public static ExprVector apply(Expr f, Expr[] args) { return new Grad(f, args); } - public static SymVector apply(Expr F, Expr[] fs, Expr[] dfs) { + public static ExprVector apply(Expr F, Expr[] fs, Expr[] dfs) { return new Grad(F, fs, dfs); } @@ -113,7 +113,7 @@ public boolean isAbstract() { return false; } - public SymVector subs(Expr from, Expr to) { + public ExprVector subs(Expr from, Expr to) { //if(Utils.symCompare(this, from)) { // return to; //} @@ -127,7 +127,7 @@ public SymVector subs(Expr from, Expr to) { return this; } - public SymVector diff(Expr expr) { + public ExprVector diff(Expr expr) { return new Grad(super.diff(expr), this.args); } @@ -139,7 +139,10 @@ public String toString() { return super.toString(); } } - return "\\nabla{"+((Derivative)this.data.get(0)).getFunc().toString()+"}"; + if(data.size() > 0) + return "\\nabla{"+((Derivative)this.data.get(0)).getFunc().toString()+"}"; + else + return "0"; } return "\\nabla{"+this.func.getLabel()+"}"; } diff --git a/src/symjava/math/SymMath.java b/src/symjava/math/SymMath.java index 8a97777..7304627 100644 --- a/src/symjava/math/SymMath.java +++ b/src/symjava/math/SymMath.java @@ -1,7 +1,8 @@ package symjava.math; -import symjava.matrix.SymMatrix; -import symjava.matrix.SymVector; +import symjava.matrix.ExprMatrix; +import symjava.matrix.ExprVector; +import symjava.symbolic.Abs; import symjava.symbolic.Cos; import symjava.symbolic.Exp; import symjava.symbolic.Expr; @@ -12,15 +13,17 @@ import symjava.symbolic.Sin; import symjava.symbolic.Sqrt; import symjava.symbolic.SymConst; +import symjava.symbolic.SymRandom; import symjava.symbolic.Tan; +import symjava.symbolic.Vector; import symjava.symbolic.utils.Utils; public class SymMath { /** * Pre defined constant symbols */ - public static SymConst PI = new SymConst("\\pi", Math.PI); - public static SymConst PI2 = new SymConst("2\\pi", 2*Math.PI); + public static SymConst PI = new SymConst("pi", Math.PI); + public static SymConst PI2 = new SymConst("2*pi", 2*Math.PI); public static SymConst E = new SymConst("e", Math.E); /** @@ -112,20 +115,35 @@ public static Expr tan(Expr x) { ////////////////////////////////////////////////////////////// - public static Expr dot(SymVector l, SymVector r) { + public static Expr random() { + return new SymRandom(); + } + + public static Expr dot(Vector l, Vector r) { + return Dot.apply(l, r); + } + + public static Expr dot(ExprVector l, ExprVector r) { return Dot.apply(l, r); } - public static Expr dot(double[] l, SymVector r) { - SymVector v = new SymVector(l, 0, r.dim()); + public static Expr dot(double[] l, ExprVector r) { + ExprVector v = new ExprVector(l, 0, r.dim()); return Dot.apply(v, r); } - public static Expr dot(SymVector l, double[] r) { - SymVector v = new SymVector(r, 0, l.dim()); + public static Expr dot(ExprVector l, double[] r) { + ExprVector v = new ExprVector(r, 0, l.dim()); return Dot.apply(l, v); } + //////////////////////////////////////////////////////////////// + public static Expr abs(Expr x) { + return Abs.simplifiedIns(x); + } + + + // public static Expr dot(double[] l, double[] r) { // double sum = 0.0; // for(int i=0; i data = new Vector(); + Vector data = new Vector();; - public SymMatrix() { + public ExprMatrix() { } - public SymMatrix(Expr[][] array) { + public ExprMatrix(String name) { + } + + public ExprMatrix(Expr[][] array) { for(Expr[] row : array) - data.add(new SymVector(row)); + data.add(new ExprVector(row)); } - public SymMatrix(int m, int n) { + public ExprMatrix(int[][] array) { + for(int[] row : array) + data.add(new ExprVector(row)); + } + + public ExprMatrix(double[][] array) { + for(double[] row : array) + data.add(new ExprVector(row)); + } + + public ExprMatrix(int m, int n) { data.setSize(m); for(int i=0; i { + protected boolean isRow = true; + protected Vector data = new Vector(); + + public ExprVector() { + } + + public ExprVector(int size) { + data.setSize(size); + } + + public ExprVector(Expr[] array) { + for(Expr e : array) + data.add(e); + } + + public ExprVector(Expr[] array, int startPos, int length) { + for(int i=startPos; i= data.size()) + data.setSize(i+1); + data.set(i, expr); + } + + public void append(Expr e) { + data.add(e); + } + + public int dim() { + return data.size(); + } + + public int length() { + return data.size(); + } + + public Expr[] getData() { + return data.toArray(new Expr[0]); + } + +// \left[ {\begin{array}{c} +// 1\\ +// 3\\ +// \end{array} } \right] + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("vector("); + if(data.size() >= 1) + sb.append(data.get(0)); + for(int j=1; j iterator() { + return data.iterator(); + } + + public ExprVector subs(Expr from, Expr to) { + ExprVector rlt = new ExprVector(); + for(Expr e : data) { + rlt.data.add(e.subs(from, to)); + } + return rlt; + } + + public ExprVector diff(Expr expr) { + ExprVector rlt = new ExprVector(); + for(Expr e : data) { + rlt.data.add(e.diff(expr)); + } + return rlt; + } + + public NumVector toNumVector(Expr[] args) { + NumVector ret = new NumVector(this, args); + return ret; + } + + public ExprVector trans() { + ExprVector rlt = new ExprVector(this.data.toArray(new Expr[0])); + rlt.isRow = !this.isRow; + return rlt; + } + + public Expr add(Expr other) { + ExprVector o = (ExprVector)other; + ExprVector ret = new ExprVector(); + for(int i=0; i { - protected Vector data = new Vector(); - - public SymVector() { - } - - public SymVector(int size) { - data.setSize(size); - } - - public SymVector(Expr[] array) { - for(Expr e : array) - data.add(e); - } - - public SymVector(Expr[] array, int startPos, int length) { - for(int i=startPos; i= data.size()) - data.setSize(i+1); - data.set(i, expr); - } - - public void add(Expr e) { - data.add(e); - } - - public int dim() { - return data.size(); - } - - public int length() { - return data.size(); - } - - public Expr[] getData() { - return data.toArray(new Expr[0]); - } - -// \left[ {\begin{array}{c} -// 1\\ -// 3\\ -// \end{array} } \right] - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("\\left[ {\\begin{array}{c}"); - for(int j=0; j iterator() { - return data.iterator(); - } - - public SymVector subs(Expr from, Expr to) { - SymVector rlt = new SymVector(); - for(Expr e : data) { - rlt.add(e.subs(from, to)); - } - return rlt; - } - - public SymVector diff(Expr expr) { - SymVector rlt = new SymVector(); - for(Expr e : data) { - rlt.add(e.diff(expr)); - } - return rlt; - } - - public NumVector toNumVector(Expr[] args) { - NumVector ret = new NumVector(this, args); - return ret; - } -} diff --git a/src/symjava/numeric/NumMatrix.java b/src/symjava/numeric/NumMatrix.java index 20098e1..b988f4a 100644 --- a/src/symjava/numeric/NumMatrix.java +++ b/src/symjava/numeric/NumMatrix.java @@ -1,12 +1,12 @@ package symjava.numeric; -import symjava.bytecode.BytecodeVecFunc; -import symjava.matrix.SymMatrix; +import symjava.bytecode.BytecodeBatchFunc; +import symjava.matrix.ExprMatrix; import symjava.symbolic.Expr; import symjava.symbolic.utils.JIT; public class NumMatrix { - BytecodeVecFunc func; + public BytecodeBatchFunc func; int nRow; int nCol; double[] lastEvalData; @@ -24,7 +24,7 @@ public NumMatrix(int m, int n) { this.nCol = n; } - public NumMatrix(SymMatrix sm, Expr[] args) { + public NumMatrix(ExprMatrix sm, Expr[] args) { this.nRow = sm.rowDim(); this.nCol = sm.colDim(); Expr[] exprs = new Expr[nRow*nCol]; @@ -34,7 +34,7 @@ public NumMatrix(SymMatrix sm, Expr[] args) { exprs[idx++] = sm.get(i, j); } } - this.func = JIT.compile(args, exprs); + this.func = JIT.compileBatchFunc(args, exprs); } public int rowDim() { diff --git a/src/symjava/numeric/NumVector.java b/src/symjava/numeric/NumVector.java index 32fc222..8e37ab3 100644 --- a/src/symjava/numeric/NumVector.java +++ b/src/symjava/numeric/NumVector.java @@ -1,12 +1,12 @@ package symjava.numeric; -import symjava.bytecode.BytecodeVecFunc; -import symjava.matrix.SymVector; +import symjava.bytecode.BytecodeBatchFunc; +import symjava.matrix.ExprVector; import symjava.symbolic.Expr; import symjava.symbolic.utils.JIT; public class NumVector { - BytecodeVecFunc func; + BytecodeBatchFunc func; int size; double[] lastEvalData; @@ -18,9 +18,9 @@ public NumVector(int size) { this.size = size; } - public NumVector(SymVector sv, Expr[] args) { + public NumVector(ExprVector sv, Expr[] args) { this.size = sv.dim(); - this.func = JIT.compile(args, sv.getData()); + this.func = JIT.compileBatchFunc(args, sv.getData()); } public int dim() { diff --git a/src/symjava/relational/Eq.java b/src/symjava/relational/Eq.java index 8689b4e..f774a42 100644 --- a/src/symjava/relational/Eq.java +++ b/src/symjava/relational/Eq.java @@ -2,14 +2,33 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; import symjava.symbolic.Expr; +import symjava.symbolic.Symbol; +import symjava.symbolic.TypeInfo; import symjava.symbolic.arity.BinaryOp; import symjava.symbolic.utils.Utils; +import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.DCMPL; +import com.sun.org.apache.bcel.internal.generic.GOTO; +import com.sun.org.apache.bcel.internal.generic.IFNE; +import com.sun.org.apache.bcel.internal.generic.InstructionFactory; +import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.MethodGen; +import com.sun.org.apache.bcel.internal.generic.NOP; +import com.sun.org.apache.bcel.internal.generic.PUSH; + /** - * An object of Eq represents an equation like - * y = a*x+b + * This class has two meanings: + *
+ * 1. Represents the relation: a == b + *
+ * 2. An object of Eq also represents an equation. For example: + *
+ * y == a*x+b * */ public class Eq extends BinaryOp implements Relation { @@ -19,28 +38,52 @@ public class Eq extends BinaryOp implements Relation { Expr[] unknowns; //freeVars + dependentVars, for example: x, y in y=a*x+b /** - * Create an equation without any symbolic parameters except free variables - * For example: - * Eq eq = new Eq(y, 2*x+1); //y = 2*x+1 + * Create an equation without any symbolic parameters. + * The free variables and dependent variables are extracted + * from the lhs and rhs expressions automatically * + * Examples: + * Eq eq1 = new Eq(y, 2*x+1); // y = 2*x+1 + * free variables: [x] + * dependent variables: [y] + * unknowns: [x,y] + * Eq eq2 = new Eq(x^2-2*x+1,0); // x^2-2*x+1 = 0 + * free variables: [x] + * dependent variables: + * unknowns: [x] + * Eq eq3 = new Eq(cos(x), x); // cos(x) = x + * free variables: [x] + * dependent variables: [x] + * unknowns: [x] + * Note: In definition of eq3, one may need to pass more parameters to exactly + * define free variables and dependent variables + * * @param lhs * @param rhs */ public Eq(Expr lhs, Expr rhs) { super(lhs, rhs); - this.label = arg1 + " = " + arg2; + this.label = arg1 + " == " + arg2; this.sortKey = this.label; - this.freeVars = Utils.extractSymbols(rhs).toArray(new Expr[0]); this.params = new Expr[0]; - this.dependentVars = Utils.extractSymbols(lhs).toArray(new Expr[0]); - computeUnknowns(); + Expr[] rhsVars = Utils.extractSymbols(rhs).toArray(new Expr[0]); + Expr[] lhsVars = Utils.extractSymbols(lhs).toArray(new Expr[0]); + if(rhsVars.length == 0) { + this.freeVars = lhsVars; + this.dependentVars = new Expr[0]; + } else { + this.freeVars = rhsVars; + this.dependentVars = lhsVars; + } + this.unknowns = Utils.extractSymbols(lhs, rhs).toArray(new Expr[0]); } /** - * Create an equation that may contain symbolic parameters on the right hand side + * Create an equation that may contain symbolic parameters on the right hand side. * The free variables are specified by the parameter freeVars - * The paramters on the right hand side of the equation can be extracted automatically. - * For example: + * The parameters on the right hand side of the equation are extracted automatically. + * + * Examples: * Eq eq = Eq(y, a*x+b, new Expr[]{x}); * This will create equation y=a*x+b with * freeVars = [x] @@ -54,7 +97,7 @@ public Eq(Expr lhs, Expr rhs) { */ public Eq(Expr lhs, Expr rhs, Expr[] freeVars) { super(lhs, rhs); - this.label = arg1 + " = " + arg2; + this.label = arg1 + " == " + arg2; this.sortKey = this.label; this.freeVars = freeVars; List list = Utils.extractSymbols(lhs, rhs); @@ -97,7 +140,7 @@ public Eq(Expr lhs, Expr rhs, Expr[] freeVars) { */ public Eq(Expr lhs, Expr rhs, Expr[] freeVars, Expr[] params) { super(lhs, rhs); - this.label = arg1 + " = " + arg2; + this.label = arg1 + " == " + arg2; this.sortKey = this.label; this.freeVars = freeVars; this.params = params; @@ -132,7 +175,7 @@ public Eq(Expr lhs, Expr rhs, Expr[] freeVars, Expr[] params) { */ public Eq(Expr lhs, Expr rhs, Expr[] freeVars, Expr[] params, Expr[] dependentVars) { super(lhs, rhs); - this.label = arg1 + " = " + arg2; + this.label = arg1 + " == " + arg2; this.sortKey = this.label; this.freeVars = freeVars; this.params = params; @@ -140,6 +183,20 @@ public Eq(Expr lhs, Expr rhs, Expr[] freeVars, Expr[] params, Expr[] dependentVa computeUnknowns(); } + public String toString() { + String sFreeVars = ""; + if(this.freeVars.length > 0) { + sFreeVars = ", array("+Utils.joinLabels(this.freeVars, ",")+")"; + } + + String sParams = ""; + if(this.params.length > 0) { + sParams += ", array("+Utils.joinLabels(this.params, ",")+")"; + } + + return "eq("+arg1+", "+arg2+sFreeVars+sParams+")"; + } + private void computeUnknowns() { this.unknowns = new Expr[freeVars.length + dependentVars.length]; int idx = 0; @@ -157,9 +214,15 @@ public static Eq apply(Expr lhs, Expr rhs) { public static Eq apply(double lhs, Expr rhs) { return new Eq(Expr.valueOf(lhs), rhs); } + public static Eq apply(int lhs, Expr rhs) { + return new Eq(Expr.valueOf(lhs), rhs); + } public static Eq apply(Expr lhs, double rhs) { return new Eq(lhs, Expr.valueOf(rhs)); } + public static Eq apply(Expr lhs, int rhs) { + return new Eq(lhs, Expr.valueOf(rhs)); + } public static Eq apply(Expr lhs, Expr rhs, Expr[] freeVars) { return new Eq(lhs, rhs, freeVars); @@ -253,6 +316,15 @@ public Expr[] getDependentVars() { return dependentVars; } + public Expr[] getAllArgs() { + List ret = new ArrayList(); + for(int i=0; i argsMap, int argsStartPos, + Map funcRefsMap) { + InstructionHandle startPos = arg1.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + arg2.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + il.append(new DCMPL()); + InstructionHandle iconst1 = il.append(new PUSH(cp, 1)); + InstructionHandle iconst0 = il.append(new PUSH(cp, 0)); + InstructionHandle nop = il.append(new NOP()); + il.insert(iconst1, new IFNE(iconst0)); + il.insert(iconst0, new GOTO(nop)); + return startPos; + } + + public void moveRHS2LHS() { + this.arg1 = this.arg1.subtract(this.arg2); + this.arg2 = Symbol.C0; + } + + @Override + public TypeInfo getTypeInfo() { + return TypeInfo.tiInt; + } + + @Override + public void updateLabel() { + // TODO Auto-generated method stub + + } } diff --git a/src/symjava/relational/Ge.java b/src/symjava/relational/Ge.java index 71197f5..0179af4 100644 --- a/src/symjava/relational/Ge.java +++ b/src/symjava/relational/Ge.java @@ -1,8 +1,26 @@ package symjava.relational; +import java.util.Map; + import symjava.symbolic.Expr; +import symjava.symbolic.TypeInfo; import symjava.symbolic.arity.BinaryOp; +import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.DCMPL; +import com.sun.org.apache.bcel.internal.generic.GOTO; +import com.sun.org.apache.bcel.internal.generic.IFLT; +import com.sun.org.apache.bcel.internal.generic.InstructionFactory; +import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.MethodGen; +import com.sun.org.apache.bcel.internal.generic.NOP; +import com.sun.org.apache.bcel.internal.generic.PUSH; + +/** + * a >= b + * + */ public class Ge extends BinaryOp implements Relation { public Ge(Expr arg1, Expr arg2) { @@ -37,4 +55,31 @@ public static Ge apply(double lhs, Expr rhs) { public static Ge apply(Expr lhs, double rhs) { return new Ge(lhs, Expr.valueOf(rhs)); } + + public InstructionHandle bytecodeGen(String clsName, MethodGen mg, + ConstantPoolGen cp, InstructionFactory factory, + InstructionList il, Map argsMap, int argsStartPos, + Map funcRefsMap) { + InstructionHandle startPos = arg1.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + arg2.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + il.append(new DCMPL()); + InstructionHandle iconst1 = il.append(new PUSH(cp, 1)); + InstructionHandle iconst0 = il.append(new PUSH(cp, 0)); + InstructionHandle nop = il.append(new NOP()); + il.insert(iconst1, new IFLT(iconst0)); + il.insert(iconst0, new GOTO(nop)); + return startPos; + } + + @Override + public TypeInfo getTypeInfo() { + return TypeInfo.tiInt; + } + + @Override + public void updateLabel() { + // TODO Auto-generated method stub + + } + } diff --git a/src/symjava/relational/Gt.java b/src/symjava/relational/Gt.java index 2bb4f15..23dc416 100644 --- a/src/symjava/relational/Gt.java +++ b/src/symjava/relational/Gt.java @@ -1,8 +1,26 @@ package symjava.relational; +import java.util.Map; + import symjava.symbolic.Expr; +import symjava.symbolic.TypeInfo; import symjava.symbolic.arity.BinaryOp; +import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.DCMPL; +import com.sun.org.apache.bcel.internal.generic.GOTO; +import com.sun.org.apache.bcel.internal.generic.IFLE; +import com.sun.org.apache.bcel.internal.generic.InstructionFactory; +import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.MethodGen; +import com.sun.org.apache.bcel.internal.generic.NOP; +import com.sun.org.apache.bcel.internal.generic.PUSH; + +/** + * a > b + * + */ public class Gt extends BinaryOp implements Relation { public Gt(Expr arg1, Expr arg2) { @@ -37,4 +55,32 @@ public static Gt apply(double lhs, Expr rhs) { public static Gt apply(Expr lhs, double rhs) { return new Gt(lhs, Expr.valueOf(rhs)); } + + public InstructionHandle bytecodeGen(String clsName, MethodGen mg, + ConstantPoolGen cp, InstructionFactory factory, + InstructionList il, Map argsMap, int argsStartPos, + Map funcRefsMap) { + InstructionHandle startPos = arg1.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + arg2.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + il.append(new DCMPL()); + InstructionHandle iconst1 = il.append(new PUSH(cp, 1)); + InstructionHandle iconst0 = il.append(new PUSH(cp, 0)); + InstructionHandle nop = il.append(new NOP()); + il.insert(iconst1, new IFLE(iconst0)); + il.insert(iconst0, new GOTO(nop)); + return startPos; + } + + + @Override + public TypeInfo getTypeInfo() { + return TypeInfo.tiInt; + } + + @Override + public void updateLabel() { + // TODO Auto-generated method stub + + } + } diff --git a/src/symjava/relational/Le.java b/src/symjava/relational/Le.java index 7520b05..5d26c09 100644 --- a/src/symjava/relational/Le.java +++ b/src/symjava/relational/Le.java @@ -1,8 +1,26 @@ package symjava.relational; +import java.util.Map; + import symjava.symbolic.Expr; +import symjava.symbolic.TypeInfo; import symjava.symbolic.arity.BinaryOp; +import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.DCMPL; +import com.sun.org.apache.bcel.internal.generic.GOTO; +import com.sun.org.apache.bcel.internal.generic.IFGT; +import com.sun.org.apache.bcel.internal.generic.InstructionFactory; +import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.MethodGen; +import com.sun.org.apache.bcel.internal.generic.NOP; +import com.sun.org.apache.bcel.internal.generic.PUSH; + +/** + * a <= b + * + */ public class Le extends BinaryOp implements Relation { public Le(Expr arg1, Expr arg2) { @@ -36,4 +54,31 @@ public static Le apply(double lhs, Expr rhs) { public static Le apply(Expr lhs, double rhs) { return new Le(lhs, Expr.valueOf(rhs)); } + + public InstructionHandle bytecodeGen(String clsName, MethodGen mg, + ConstantPoolGen cp, InstructionFactory factory, + InstructionList il, Map argsMap, int argsStartPos, + Map funcRefsMap) { + InstructionHandle startPos = arg1.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + arg2.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + il.append(new DCMPL()); + InstructionHandle iconst1 = il.append(new PUSH(cp, 1)); + InstructionHandle iconst0 = il.append(new PUSH(cp, 0)); + InstructionHandle nop = il.append(new NOP()); + il.insert(iconst1, new IFGT(iconst0)); + il.insert(iconst0, new GOTO(nop)); + return startPos; + } + + @Override + public TypeInfo getTypeInfo() { + return TypeInfo.tiInt; + } + + @Override + public void updateLabel() { + // TODO Auto-generated method stub + + } + } diff --git a/src/symjava/relational/Lt.java b/src/symjava/relational/Lt.java index cad4184..fedfde3 100644 --- a/src/symjava/relational/Lt.java +++ b/src/symjava/relational/Lt.java @@ -1,8 +1,26 @@ package symjava.relational; +import java.util.Map; + import symjava.symbolic.Expr; +import symjava.symbolic.TypeInfo; import symjava.symbolic.arity.BinaryOp; +import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.DCMPL; +import com.sun.org.apache.bcel.internal.generic.GOTO; +import com.sun.org.apache.bcel.internal.generic.IFGE; +import com.sun.org.apache.bcel.internal.generic.InstructionFactory; +import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.MethodGen; +import com.sun.org.apache.bcel.internal.generic.NOP; +import com.sun.org.apache.bcel.internal.generic.PUSH; + +/** + * a < b + * + */ public class Lt extends BinaryOp implements Relation { public Lt(Expr arg1, Expr arg2) { @@ -36,4 +54,36 @@ public static Lt apply(double lhs, Expr rhs) { public static Lt apply(Expr lhs, double rhs) { return new Lt(lhs, Expr.valueOf(rhs)); } + + public static Lt apply(Expr lhs, int rhs) { + return new Lt(lhs, Expr.valueOf(rhs)); + } + + public InstructionHandle bytecodeGen(String clsName, MethodGen mg, + ConstantPoolGen cp, InstructionFactory factory, + InstructionList il, Map argsMap, int argsStartPos, + Map funcRefsMap) { + InstructionHandle startPos = arg1.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + arg2.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + il.append(new DCMPL()); + InstructionHandle iconst1 = il.append(new PUSH(cp, 1)); + InstructionHandle iconst0 = il.append(new PUSH(cp, 0)); + InstructionHandle nop = il.append(new NOP()); + il.insert(iconst1, new IFGE(iconst0)); + il.insert(iconst0, new GOTO(nop)); + return startPos; + } + + + @Override + public TypeInfo getTypeInfo() { + return TypeInfo.tiInt; + } + + @Override + public void updateLabel() { + // TODO Auto-generated method stub + + } + } diff --git a/src/symjava/relational/Neq.java b/src/symjava/relational/Neq.java index 672eda2..2645b4c 100644 --- a/src/symjava/relational/Neq.java +++ b/src/symjava/relational/Neq.java @@ -1,8 +1,26 @@ package symjava.relational; +import java.util.Map; + import symjava.symbolic.Expr; +import symjava.symbolic.TypeInfo; import symjava.symbolic.arity.BinaryOp; +import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.DCMPL; +import com.sun.org.apache.bcel.internal.generic.GOTO; +import com.sun.org.apache.bcel.internal.generic.IFEQ; +import com.sun.org.apache.bcel.internal.generic.InstructionFactory; +import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.MethodGen; +import com.sun.org.apache.bcel.internal.generic.NOP; +import com.sun.org.apache.bcel.internal.generic.PUSH; + +/** + * a != b + * + */ public class Neq extends BinaryOp implements Relation { public Neq(Expr arg1, Expr arg2) { @@ -35,4 +53,31 @@ public static Neq apply(double lhs, Expr rhs) { public static Neq apply(Expr lhs, double rhs) { return new Neq(lhs, Expr.valueOf(rhs)); } + + public InstructionHandle bytecodeGen(String clsName, MethodGen mg, + ConstantPoolGen cp, InstructionFactory factory, + InstructionList il, Map argsMap, int argsStartPos, + Map funcRefsMap) { + InstructionHandle startPos = arg1.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + arg2.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + il.append(new DCMPL()); + InstructionHandle iconst1 = il.append(new PUSH(cp, 1)); + InstructionHandle iconst0 = il.append(new PUSH(cp, 0)); + InstructionHandle nop = il.append(new NOP()); + il.insert(iconst1, new IFEQ(iconst0)); + il.insert(iconst0, new GOTO(nop)); + return startPos; + } + + @Override + public TypeInfo getTypeInfo() { + return TypeInfo.tiInt; + } + + @Override + public void updateLabel() { + // TODO Auto-generated method stub + + } + } diff --git a/src/symjava/symbolic/Abs.java b/src/symjava/symbolic/Abs.java new file mode 100644 index 0000000..a66ca04 --- /dev/null +++ b/src/symjava/symbolic/Abs.java @@ -0,0 +1,77 @@ +package symjava.symbolic; + +import java.util.Map; + +import com.sun.org.apache.bcel.internal.Constants; +import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.InstructionFactory; +import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.MethodGen; +import com.sun.org.apache.bcel.internal.generic.ObjectType; +import com.sun.org.apache.bcel.internal.generic.Type; + +import symjava.symbolic.Expr.TYPE; +import symjava.symbolic.arity.UnaryOp; +import symjava.symbolic.utils.Utils; + +public class Abs extends UnaryOp { + + public Abs(Expr arg) { + super(arg); + label = "|" + arg + "|"; + sortKey = label; + } + + @Override + public Expr simplify() { + return this; + } + + @Override + public boolean symEquals(Expr other) { + if(other instanceof Abs) { + Utils.symCompare(this.arg, ((Cos) other).arg); + } + return false; + } + + public static Expr simplifiedIns(Expr expr) { + return new Abs(expr); + } + + /** + * Recall that |f(x)| = sqrt(f(x)*f(x)), so + * |f(x)|' = f(x)*f'(x)/|f(x)| + */ + @Override + public Expr diff(Expr x) { + return arg.multiply(arg.diff(x)).divide(this); + } + + @Override + public InstructionHandle bytecodeGen(String clsName, MethodGen mg, + ConstantPoolGen cp, InstructionFactory factory, + InstructionList il, Map argsMap, int argsStartPos, + Map funcRefsMap) { + InstructionHandle startPos = arg.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + if(arg.getType() == TYPE.MATRIX || arg.getType() == TYPE.VECTOR) { + il.append(factory.createInvoke("symjava.symbolic.utils.BytecodeOpSupport", "abs", + new ObjectType("Jama.Matrix"), + new Type[] { new ObjectType("Jama.Matrix") }, + Constants.INVOKESTATIC)); + } else { + il.append(factory.createInvoke("java.lang.Math", "abs", + Type.DOUBLE, + new Type[] { Type.DOUBLE }, + Constants.INVOKESTATIC)); + } + return startPos; + } + + @Override + public void updateLabel() { + label = "|" + arg + "|"; + sortKey = label; + } +} diff --git a/src/symjava/symbolic/Add.java b/src/symjava/symbolic/Add.java index 8bcae49..a3c1bf5 100644 --- a/src/symjava/symbolic/Add.java +++ b/src/symjava/symbolic/Add.java @@ -1,15 +1,31 @@ package symjava.symbolic; +import static com.sun.org.apache.bcel.internal.generic.InstructionConstants.DADD; +import static com.sun.org.apache.bcel.internal.generic.InstructionConstants.FADD; +import static com.sun.org.apache.bcel.internal.generic.InstructionConstants.IADD; +import static com.sun.org.apache.bcel.internal.generic.InstructionConstants.LADD; + import java.util.List; +import java.util.Map; +import symjava.symbolic.Expr.TYPE; import symjava.symbolic.arity.BinaryOp; +import symjava.symbolic.utils.BytecodeUtils; import symjava.symbolic.utils.Utils; +import com.sun.org.apache.bcel.internal.Constants; +import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.InstructionFactory; +import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.MethodGen; +import com.sun.org.apache.bcel.internal.generic.ObjectType; +import com.sun.org.apache.bcel.internal.generic.Type; + public class Add extends BinaryOp { public Add(Expr l, Expr r) { super(l, r); - label = l + " + " + r; - sortKey = arg1.getSortKey()+arg2.getSortKey(); + updateLabel(); } public static Expr shallowSimplifiedIns(Expr l, Expr r) { @@ -112,8 +128,12 @@ public Expr simplify() { } public void flattenAdd(List outList) { - arg1.flattenAdd(outList); - arg2.flattenAdd(outList); + if(device != null) { + outList.add(this); + } else { + arg1.flattenAdd(outList); + arg2.flattenAdd(outList); + } } @Override @@ -125,4 +145,52 @@ public boolean symEquals(Expr other) { //return Utils.flattenSortAndCompare(this, other); return Utils.flattenSortAndCompare(this.simplify(), other.simplify()); } + + @Override + public InstructionHandle bytecodeGen(String clsName, MethodGen mg, + ConstantPoolGen cp, InstructionFactory factory, + InstructionList il, Map argsMap, int argsStartPos, + Map funcRefsMap) { + InstructionHandle startPos = arg1.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + if(arg1.getType() == TYPE.MATRIX && arg2.getType() == TYPE.MATRIX) { + arg2.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + il.append(factory.createInvoke("Jama.Matrix", "plus", + new ObjectType("Jama.Matrix"), new Type[] { new ObjectType("Jama.Matrix") }, + Constants.INVOKEVIRTUAL)); + return startPos; + } else if(arg1.getType() == TYPE.VECTOR && arg2.getType() == TYPE.VECTOR) { + arg2.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + il.append(factory.createInvoke("Jama.Matrix", "plus", + new ObjectType("Jama.Matrix"), new Type[] { new ObjectType("Jama.Matrix") }, + Constants.INVOKEVIRTUAL)); + return startPos; + } + + TYPE ty = Utils.getConvertedType(arg1.getType(), arg2.getType()); + BytecodeUtils.typeCast(il, arg1.getType(), ty); + arg2.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + BytecodeUtils.typeCast(il, arg2.getType(), ty); + if(ty == TYPE.DOUBLE) + il.append(DADD); + else if(ty == TYPE.INT) + il.append(IADD); + else if(ty == TYPE.LONG) + il.append(LADD); + else if(ty == TYPE.FLOAT) + il.append(FADD); + else + il.append(IADD); + return startPos; + } + + @Override + public void updateLabel() { + label = arg1 + " + " + arg2; + sortKey = arg1.getSortKey()+arg2.getSortKey(); + } + + @Override + public TypeInfo getTypeInfo() { + return arg1.getTypeInfo(); + } } diff --git a/src/symjava/symbolic/Concat.java b/src/symjava/symbolic/Concat.java new file mode 100644 index 0000000..5c5b9e9 --- /dev/null +++ b/src/symjava/symbolic/Concat.java @@ -0,0 +1,83 @@ +package symjava.symbolic; + +import java.util.Map; + +import symjava.symbolic.arity.NaryOp; +import symjava.symbolic.utils.Utils; + +import com.sun.org.apache.bcel.internal.Constants; +import com.sun.org.apache.bcel.internal.generic.AASTORE; +import com.sun.org.apache.bcel.internal.generic.ANEWARRAY; +import com.sun.org.apache.bcel.internal.generic.ArrayType; +import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.InstructionConstants; +import com.sun.org.apache.bcel.internal.generic.InstructionFactory; +import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.MethodGen; +import com.sun.org.apache.bcel.internal.generic.ObjectType; +import com.sun.org.apache.bcel.internal.generic.PUSH; +import com.sun.org.apache.bcel.internal.generic.Type; + +/** + * Concatenate symbol matrices or vectors with the same dimension(s) + * + */ +public class Concat extends NaryOp { + + public Concat(Expr ...args) { + super(args); + updateLabel(); + } + + @Override + public Expr simplify() { + return this; + } + + @Override + public boolean symEquals(Expr other) { + return false; + } + + @Override + public Expr diff(Expr x) { + return null; + } + + @Override + public void updateLabel() { + this.label = "["+Utils.joinLabels(args, ", ")+"]"; + this.sortKey = this.label; + } + + @Override + public InstructionHandle bytecodeGen(String clsName, MethodGen mg, + ConstantPoolGen cp, InstructionFactory factory, + InstructionList il, Map argsMap, int argsStartPos, + Map funcRefsMap) { + InstructionHandle startPos = null; + //if(arg1.getType() == TYPE.MATRIX && arg2.getType() == TYPE.MATRIX) { + il.append(new PUSH(cp, args.length)); + il.append(new ANEWARRAY(cp.addClass("Jama.Matrix"))); + for(int i=0; i argsMap, int argsStartPos, + Map funcRefsMap) { + InstructionHandle startPos = arg.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + if(arg.getType() == TYPE.MATRIX || arg.getType() == TYPE.VECTOR) { + il.append(factory.createInvoke("symjava.symbolic.utils.BytecodeOpSupport", "cos", + new ObjectType("Jama.Matrix"), + new Type[] { new ObjectType("Jama.Matrix") }, + Constants.INVOKESTATIC)); + } else { + il.append(factory.createInvoke("java.lang.Math", "cos", + Type.DOUBLE, + new Type[] { Type.DOUBLE }, + Constants.INVOKESTATIC)); + } + + return startPos; + } + @Override + public void updateLabel() { + label = "cos(" + arg + ")"; + sortKey = label; + } } diff --git a/src/symjava/symbolic/Divide.java b/src/symjava/symbolic/Divide.java index 38426c7..83b3336 100644 --- a/src/symjava/symbolic/Divide.java +++ b/src/symjava/symbolic/Divide.java @@ -2,10 +2,19 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; import symjava.symbolic.arity.BinaryOp; +import symjava.symbolic.utils.BytecodeUtils; import symjava.symbolic.utils.Utils; +import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.InstructionConstants; +import com.sun.org.apache.bcel.internal.generic.InstructionFactory; +import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.MethodGen; + /** * * @author yuemingl @@ -14,10 +23,7 @@ public class Divide extends BinaryOp { public Divide(Expr numerator, Expr denominator) { super(numerator, denominator); - label = SymPrinting.addParenthsesIfNeeded(arg1, this) - + "/" + - SymPrinting.addParenthsesIfNeeded2(arg2, this); - sortKey = arg1.getSortKey()+arg2.getSortKey(); + updateLabel(); } public static Expr shallowSimplifiedIns(Expr numerator, Expr denominator) { @@ -101,5 +107,34 @@ public boolean symEquals(Expr other) { //return Utils.flattenSortAndCompare(this, other); return Utils.flattenSortAndCompare(this.simplify(), other.simplify()); } + @Override + public InstructionHandle bytecodeGen(String clsName, MethodGen mg, + ConstantPoolGen cp, InstructionFactory factory, + InstructionList il, Map argsMap, int argsStartPos, + Map funcRefsMap) { + InstructionHandle startPos = arg1.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + TYPE ty = Utils.getConvertedType(arg1.getType(), arg2.getType()); + BytecodeUtils.typeCast(il, arg1.getType(), ty); + arg2.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + BytecodeUtils.typeCast(il, arg2.getType(), ty); + if(ty == TYPE.DOUBLE) + il.append(InstructionConstants.DDIV); + else if(ty == TYPE.INT) + il.append(InstructionConstants.IDIV); + else if(ty == TYPE.LONG) + il.append(InstructionConstants.LDIV); + else if(ty == TYPE.FLOAT) + il.append(InstructionConstants.FDIV); + else + il.append(InstructionConstants.IDIV); + return startPos; + } + @Override + public void updateLabel() { + label = SymPrinting.addParenthsesIfNeeded(arg1, this) + + "/" + + SymPrinting.addParenthsesIfNeeded2(arg2, this); + sortKey = arg1.getSortKey()+arg2.getSortKey(); + } } diff --git a/src/symjava/symbolic/Exp.java b/src/symjava/symbolic/Exp.java index 6927dbd..7954d96 100644 --- a/src/symjava/symbolic/Exp.java +++ b/src/symjava/symbolic/Exp.java @@ -6,7 +6,8 @@ public class Exp extends Pow { public Exp(Expr arg) { super(SymMath.E, arg); - String displayExp = String.format("{%s}", this.arg2); + //String displayExp = String.format("{%s}", this.arg2); + String displayExp = String.format("%s", this.arg2); if(arg instanceof SymReal) { SymReal realExp = (SymReal)arg; if(realExp.isInteger()) { @@ -15,9 +16,14 @@ public Exp(Expr arg) { //if(realExp.isNegative()) // displayExp = "{"+displayExp+"}"; } - label = "e^" + displayExp + ""; + //label = "e^" + displayExp + ""; + label = "pow(e," + displayExp + ")"; sortKey = "epower"+String.valueOf(displayExp); } + + public String toString() { + return label; + } public static Expr simplifiedIns(Expr expr) { return new Exp(expr); diff --git a/src/symjava/symbolic/Expr.java b/src/symjava/symbolic/Expr.java index 8aec5c4..3115e48 100644 --- a/src/symjava/symbolic/Expr.java +++ b/src/symjava/symbolic/Expr.java @@ -1,24 +1,30 @@ package symjava.symbolic; -import java.math.BigInteger; import java.util.List; +import java.util.Map; +import lambdacloud.core.lang.LCAssign; +import lambdacloud.core.lang.LCDevice; import symjava.logic.And; import symjava.logic.Not; import symjava.logic.Or; import symjava.logic.Xor; -import symjava.relational.Ge; -import symjava.relational.Relation; import symjava.symbolic.utils.Utils; +import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.InstructionFactory; +import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.MethodGen; + abstract public class Expr implements Cloneable { /** - * Label(or name) of an expression(Symbol, Func,...) + * Label(or name) of an expression */ protected String label = null; /** - * A string used to sort terms in an expression + * A string used to sort the terms in an expression */ protected String sortKey = null; @@ -26,25 +32,37 @@ abstract public class Expr implements Cloneable { * Number of operations for simplifying an expression */ public int simplifyOpNum = 0; - + + /** + * Return true if simplify() is called + */ public boolean isSimplified = false; + /** + * Simplify the expression + * @return + */ public abstract Expr simplify(); + /** + * Return true if two expressions are equal in the sense of mathematics + * @param other + * @return + */ public abstract boolean symEquals(Expr other); /** - * Return the arguments of the expr + * Return the arguments of the expression * @return */ - public Expr[] args() { return new Expr[0]; } + public abstract Expr[] args();// { return new Expr[0]; } /** - * Derivative of expr - * @param expr + * Derivative of the expression with respect to x + * @param x * @return */ - public abstract Expr diff(Expr expr); + public abstract Expr diff(Expr x); /** * Functional derivative of f with respect to df @@ -93,12 +111,20 @@ public boolean isAbstract() { } /** - * Return the string expression + * Return the string representation of the expression */ public String toString() { return label; } + /** + * Return the LaTex representation of the expression + * @return + */ + public String toLaTex() { + return label; + } + /** * Set the label(or name) of the expression * @param label @@ -118,7 +144,7 @@ public String getLabel() { } /** - * Set a string key for arranging terms in an expression + * Set a string key for sorting the terms in the expression * @param sortKey * @return */ @@ -128,7 +154,7 @@ public Expr setSortKey(String sortKey) { } /** - * Get the string key used to arrange terms in an expression + * Get the string key used to sort the terms in the expression * @param sortKey * @return */ @@ -161,7 +187,7 @@ public Expr setAsSimplified() { } /** - * Operator overload support: + * Operator overloading support: * Expr a = 5; * * @param v @@ -180,7 +206,7 @@ public static Expr valueOf(double v) { return new SymDouble(v); } /** - * Operator overload support: + * Operator overloading support: * a+b * @param other * @return @@ -212,9 +238,29 @@ public Expr add(double other) { public Expr addRev(double other) { return Add.simplifiedIns(new SymDouble(other), this); } - /** - * Operator overload support: + * Operator overload support for Groovy: + * a+b + * @param other + * @return + */ + public Expr plus(Expr other) { + return Add.simplifiedIns(this, other); + } + public Expr plus(int other) { + return Add.simplifiedIns(this, new SymInteger(other)); + } + public Expr plus(long other) { + return Add.simplifiedIns(this, new SymLong(other)); + } + public Expr plus(float other) { + return Add.simplifiedIns(this, new SymFloat(other)); + } + public Expr plus(double other) { + return Add.simplifiedIns(this, new SymDouble(other)); + } + /** + * Operator overloading support: * a-b * @param other * @return @@ -246,9 +292,29 @@ public Expr subtract(double other) { public Expr subtractRev(double other) { return Subtract.simplifiedIns(new SymDouble(other), this); } - /** - * Operator overload support: + * Operator overload support for Groovy: + * a-b + * @param other + * @return + */ + public Expr minus(Expr other) { + return Subtract.simplifiedIns(this, other); + } + public Expr minus(int other) { + return Subtract.simplifiedIns(this, new SymInteger(other)); + } + public Expr minus(long other) { + return Subtract.simplifiedIns(this, new SymLong(other)); + } + public Expr minus(float other) { + return Subtract.simplifiedIns(this, new SymFloat(other)); + } + public Expr minus(double other) { + return Subtract.simplifiedIns(this, new SymDouble(other)); + } + /** + * Operator overloading support: * a*b * @param other * @return @@ -282,7 +348,7 @@ public Expr multiplyRev(double other) { } /** - * Operator overload support: + * Operator overloading support: * a/b * @param other * @return @@ -314,9 +380,29 @@ public Expr divide(double other) { public Expr divideRev(double other) { return Divide.simplifiedIns(new SymDouble(other), this); } - /** - * Operator overload support: + * Operator overload support for Groovy: + * a/b + * @param other + * @return + */ + public Expr div(Expr other) { + return Divide.simplifiedIns(this, other); + } + public Expr divi(int other) { + return Divide.simplifiedIns(this, new SymInteger(other)); + } + public Expr div(long other) { + return Divide.simplifiedIns(this, new SymLong(other)); + } + public Expr div(float other) { + return Divide.simplifiedIns(this, new SymFloat(other)); + } + public Expr div(double other) { + return Divide.simplifiedIns(this, new SymDouble(other)); + } + /** + * Operator overloading support: * -a * */ @@ -374,7 +460,7 @@ public Expr xor(Expr other) { } // /** -// * TODO We cannot use the comparison operator overload in java-oo for our use case +// * TODO We cannot use the comparison Operator overloading in java-oo for our use case // * @param other // * @return // */ @@ -414,7 +500,7 @@ public Expr subs(Expr from, double to) { return subs(from, new SymDouble(to)); } - protected Expr clone() { + public Expr clone() { try { return (Expr) super.clone(); } catch (CloneNotSupportedException e) { @@ -436,4 +522,124 @@ public int hashCode() { public boolean equals(Object obj) { return this.label.equals(((Expr)obj).label); } + +//////////////////////////////////////////////////////////////////////////// +// /** +// * Assign the result of evaluating an expression to a local variable +// * when compiling. The local variable must be a symbol which is declared +// * as a local variable. +// *

+// * The call of this function can be understand as +// * Symbol symLocal; //Declared somewhere +// * symLocal = this; +// * +// *

+// * Note: The name of a symbol is a global name. Make sure you don't have +// * two symbols with the same name, otherwise they are treated as the same +// * symbol or local variable in compiled code. +// * +// * @param symLocal A symbol declared as a local variable +// * @return An instance of operator OPAsign +// */ +// public Expr assignTo(Symbol symLocal) { +// return new OPAsign(symLocal, this); +// } + + public InstructionHandle bytecodeGen(String clsName, MethodGen mg, + ConstantPoolGen cp, InstructionFactory factory, + InstructionList il, Map argsMap, int argsStartPos, + Map funcRefsMap) { + throw new UnsupportedOperationException();//il.append(InstructionConstants.NOP); + } + + + /** + * Reset the compile flags for an expression. + * + * For example, a matrix is defined and stored to new a local variable when it is referenced + * at the first time. The following references of the matrix just load the local variable. + * By calling this function, the state is reset to define a new local variable. + */ + public void bytecodeGenReset() { + + } + + public enum TYPE {INT, LONG, FLOAT, DOUBLE, BOOLEAN, BYTE, CHAR, SHORT, VOID, + MATRIX, VECTOR, TENSOR}; + + public abstract TypeInfo getTypeInfo(); + + public TYPE getType() { + return getTypeInfo().type; + } + + public Expr assign(Expr expr) { + return new LCAssign(this, expr); + } + + public Expr assign(double val) { + return new LCAssign(this, Expr.valueOf(val)); + } + + public Expr assign(int val) { + return new LCAssign(this, Expr.valueOf(val)); + } +///////////////////////////////////////////////////////////////////////// + + protected LCDevice device = null; + public Expr runOn(LCDevice dev) { + device = dev; + return this; + } + + public LCDevice getDevice() { + return device; + } + + /** + * Set the argument of the current expression + * Depends on the specific implementation + * + * @param index The position of the argument + * @param arg The expression of the argument + * @return + */ + public Expr setArg(int index, Expr arg) { + throw new UnsupportedOperationException(); + } + + abstract public void updateLabel(); + + /** + * Parent expression, for example: a sub-matrix or sub-vector has a parent + */ + public Expr getParent() { + throw new UnsupportedOperationException(); + } + + /** + * Return the dimension of a vector + * @return + */ + public int dim() { + throw new UnsupportedOperationException(); + } + + /** + * return the dimension of a matrix or tensor + * @return + */ + public int[] dims() { + throw new UnsupportedOperationException(); + } + + /** + * return the element at index + * @param index + * @return + */ + public Expr get(int index) { + throw new UnsupportedOperationException(); + } } + diff --git a/src/symjava/symbolic/Func.java b/src/symjava/symbolic/Func.java index 442fe47..3e7eabf 100644 --- a/src/symjava/symbolic/Func.java +++ b/src/symjava/symbolic/Func.java @@ -16,6 +16,11 @@ public class Func extends NaryOp { /** * Construct an abstract function + * Note: For an abstract function with only one argument, define it by + * passing an array for the second parameter + * + * Func f = new Func("F", new Expr[]{Symbol.x}); // F(x) + * * @param name * @param args */ @@ -26,6 +31,13 @@ public Func(String name, Expr ...args) { this.sortKey = label; } + /** + * Construct a function with expression expr + * For example: + * Func f = new Func("F", Symbol.x); // F(x)=x + * @param name + * @param expr + */ public Func(String name, Expr expr) { super(new Expr[] {expr}); //Extract free variables from expr @@ -146,6 +158,11 @@ public Expr simplify() { public boolean symEquals(Expr other) { if(other instanceof Func) { Func o = (Func)other; + //TODO support map(expr, [e1,e2,e3]) + if(this.label.equals("_") && other.label.equals("_")) + return true; + if(this.label.equals("__") && other.label.equals("__")) + return true; Boolean rlt = Utils.symCompareNull(this.expr, o.expr); if(rlt != null && rlt == false) return false; @@ -178,4 +195,15 @@ public void flattenMultiply(List outList) { outList.add(this); } + @Override + public TypeInfo getTypeInfo() { + return expr.getTypeInfo(); + } + + @Override + public void updateLabel() { + // TODO Auto-generated method stub + + } + } diff --git a/src/symjava/symbolic/Infinity.java b/src/symjava/symbolic/Infinity.java index 26f2c90..353fe21 100644 --- a/src/symjava/symbolic/Infinity.java +++ b/src/symjava/symbolic/Infinity.java @@ -1,14 +1,17 @@ package symjava.symbolic; +/** + * A symbol represents infinity + * + */ public class Infinity extends Expr { public Infinity() { - this.label = "oo"; - this.sortKey = label; + updateLabel(); } @Override public Expr diff(Expr expr) { - return null; + throw new UnsupportedOperationException(); } @Override @@ -20,4 +23,21 @@ public Expr simplify() { public boolean symEquals(Expr other) { return false; } + + @Override + public Expr[] args() { + return null; + } + + @Override + public TypeInfo getTypeInfo() { + //TODO + return null; + } + + @Override + public void updateLabel() { + this.label = "oo"; + this.sortKey = label; + } } diff --git a/src/symjava/symbolic/Integrate.java b/src/symjava/symbolic/Integrate.java index c00f333..b13cbdb 100644 --- a/src/symjava/symbolic/Integrate.java +++ b/src/symjava/symbolic/Integrate.java @@ -17,17 +17,20 @@ public class Integrate extends Expr { public Expr integrand = null; public Domain domain = null; + /** + * \int_{domain}{integrand} + * + * @param integrand + * @param domain + */ public Integrate(Expr integrand, Domain domain) { this.integrand = integrand; this.domain = domain; - String postfix = "d" + Utils.joinLabels(domain.getCoordVars(),"d"); - if(domain instanceof Interval) { - Interval o = (Interval)domain; - this.label = "\\int_{"+o.getStart()+"}^{"+o.getEnd()+"}{"+integrand+"}" + postfix; - } - else - this.label = "\\int_{"+domain+"}{"+integrand+"}" + postfix; - this.sortKey = integrand.toString()+domain.toString(); + updateLabel(); + } + + public String toString() { + return "integrate("+integrand+","+domain+")"; } public static Expr apply(Expr integrand, Domain domain) { @@ -63,6 +66,14 @@ public Integrate changeOfVars(Transformation trans) { this.domain.transform(this.domain.getLabel()+"T", trans)); } + /** + * Change of Variables for the integration + * + * @param subsList + * @param jac + * @param target + * @return + */ public Integrate changeOfVars(List subsList, Expr jac, Domain target) { Expr tmp = this.integrand; for(ExprPair p : subsList) { @@ -99,4 +110,27 @@ public boolean isMultipleIntegral() { return this.domain.getConstraint() == null; } + @Override + public Expr[] args() { + //DOTO + return integrand.args(); + } + + @Override + public TypeInfo getTypeInfo() { + return null; + } + + @Override + public void updateLabel() { + String postfix = "d" + Utils.joinLabels(domain.getCoordVars(),"d"); + if(domain instanceof Interval) { + Interval o = (Interval)domain; + this.label = "\\int_{"+o.getStart()+"}^{"+o.getEnd()+"}{"+integrand+"}" + postfix; + } + else + this.label = "\\int_{"+domain+"}{"+integrand+"}" + postfix; + this.sortKey = integrand.toString()+domain.toString(); + } + } diff --git a/src/symjava/symbolic/Limit.java b/src/symjava/symbolic/Limit.java index 150bd70..b924000 100644 --- a/src/symjava/symbolic/Limit.java +++ b/src/symjava/symbolic/Limit.java @@ -1,5 +1,46 @@ package symjava.symbolic; -public class Limit { +/** + * TODO + * + * + */ +public class Limit extends Expr { + + @Override + public Expr simplify() { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean symEquals(Expr other) { + // TODO Auto-generated method stub + return false; + } + + @Override + public Expr diff(Expr expr) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Expr[] args() { + // TODO Auto-generated method stub + return null; + } + + @Override + public TypeInfo getTypeInfo() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void updateLabel() { + // TODO Auto-generated method stub + + } } diff --git a/src/symjava/symbolic/Log.java b/src/symjava/symbolic/Log.java index 96ad21f..e3e4014 100644 --- a/src/symjava/symbolic/Log.java +++ b/src/symjava/symbolic/Log.java @@ -1,9 +1,26 @@ package symjava.symbolic; +import java.util.Map; + +import com.sun.org.apache.bcel.internal.Constants; +import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.InstructionFactory; +import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.MethodGen; +import com.sun.org.apache.bcel.internal.generic.ObjectType; +import com.sun.org.apache.bcel.internal.generic.Type; + import symjava.math.SymMath; import symjava.symbolic.arity.BinaryOp; import symjava.symbolic.utils.Utils; +/** + * logarithm + * + * log(A): if A is a matrix do element wise log + * + */ public class Log extends BinaryOp { /** @@ -12,8 +29,8 @@ public class Log extends BinaryOp { */ public Log(Expr expr) { super(SymMath.E, expr); - label = "log(" + expr + ")"; - sortKey = label; + updateLabel(); + } /** @@ -27,6 +44,13 @@ public Log(Expr base, Expr expr) { sortKey = label; } + public String toString() { + if(!arg1.symEquals(SymMath.E)) + return "log(" + arg1 + "," + arg2 + ")"; + else + return label; + } + public static Expr simplifiedIns(Expr base, Expr expr) { if(base instanceof SymReal && expr instanceof SymReal) { return new SymDouble( @@ -61,9 +85,47 @@ public Expr simplify() { return this; } + @Override + public Expr subs(Expr from, Expr to) { + if(Utils.symCompare(this, from)) + return to; + Expr sl = arg1.subs(from, to); + Expr sr = arg2.subs(from, to); + if(sl == arg1 && sr == arg2) + return this; + return new Log(sl, sr); + } + @Override public boolean symEquals(Expr other) { return false; } + + public InstructionHandle bytecodeGen(String clsName, MethodGen mg, + ConstantPoolGen cp, InstructionFactory factory, + InstructionList il, Map argsMap, int argsStartPos, + Map funcRefsMap) { + InstructionHandle startPos = arg1.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + arg2.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + if(arg2.getType() == TYPE.MATRIX || arg2.getType() == TYPE.VECTOR) { + il.append(factory.createInvoke("symjava.symbolic.utils.BytecodeOpSupport", "log", + new ObjectType("Jama.Matrix"), + new Type[] { Type.DOUBLE, new ObjectType("Jama.Matrix") }, + Constants.INVOKESTATIC)); + } else { + il.append(factory.createInvoke("symjava.symbolic.utils.BytecodeSupport", "log", + Type.DOUBLE, new Type[] { Type.DOUBLE, Type.DOUBLE }, Constants.INVOKESTATIC)); + } + + return startPos; + } + @Override + public void updateLabel() { + if(arg1.symEquals(SymMath.E)) + label = "log(" + arg2 + ")"; + else + label = "log_{"+arg1+"}(" + arg2 + ")"; + sortKey = label; + } } diff --git a/src/symjava/symbolic/Log10.java b/src/symjava/symbolic/Log10.java index cb99c1a..1b4b99f 100644 --- a/src/symjava/symbolic/Log10.java +++ b/src/symjava/symbolic/Log10.java @@ -1,14 +1,21 @@ package symjava.symbolic; + public class Log10 extends Log { public Log10(Expr expr) { super(Expr.valueOf(10), expr); - label = "log10(" + expr + ")"; - sortKey = label; + updateLabel(); } public static Expr simplifiedIns(Expr expr) { return new Log10(expr); } + + @Override + public void updateLabel() { + label = "log10(" + arg2 + ")"; + sortKey = label; + } + } diff --git a/src/symjava/symbolic/Log2.java b/src/symjava/symbolic/Log2.java index e297b2e..d057f9f 100644 --- a/src/symjava/symbolic/Log2.java +++ b/src/symjava/symbolic/Log2.java @@ -4,11 +4,16 @@ public class Log2 extends Log { public Log2(Expr expr) { super(Expr.valueOf(2), expr); - label = "log2(" + expr + ")"; - sortKey = label; + updateLabel(); } - + public static Expr simplifiedIns(Expr expr) { return new Log2(expr); } + + @Override + public void updateLabel() { + label = "log2(" + arg2 + ")"; + sortKey = label; + } } diff --git a/src/symjava/symbolic/Matrix.java b/src/symjava/symbolic/Matrix.java new file mode 100644 index 0000000..d041f9b --- /dev/null +++ b/src/symjava/symbolic/Matrix.java @@ -0,0 +1,158 @@ +package symjava.symbolic; + +import java.util.Map; + +import com.sun.org.apache.bcel.internal.Constants; +import com.sun.org.apache.bcel.internal.generic.ALOAD; +import com.sun.org.apache.bcel.internal.generic.ASTORE; +import com.sun.org.apache.bcel.internal.generic.ArrayType; +import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.DSTORE; +import com.sun.org.apache.bcel.internal.generic.InstructionConstants; +import com.sun.org.apache.bcel.internal.generic.InstructionFactory; +import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.LocalVariableGen; +import com.sun.org.apache.bcel.internal.generic.MethodGen; +import com.sun.org.apache.bcel.internal.generic.NEW; +import com.sun.org.apache.bcel.internal.generic.ObjectType; +import com.sun.org.apache.bcel.internal.generic.PUSH; +import com.sun.org.apache.bcel.internal.generic.Type; + +import symjava.matrix.ExprMatrix; +import symjava.symbolic.Expr.TYPE; + +public class Matrix extends Tensor { + public int nRowStart; + public int nColStart; + public int nRow; + public int nCol; + public Matrix parent; + + protected int indexLVT = -1; + public Matrix(String name, int nRow, int nCol) { + super(name); + nRowStart = 0; + nColStart = 0; + this.nRow = nRow; + this.nCol = nCol; + } + + public Matrix(Matrix parent, int nRowStart, int nColStart, int nRow, int nCol) { + super(parent.label+"_"+nRowStart+"_"+nColStart+"_"+nRow+"_"+nCol); + this.nRowStart = nRowStart; + this.nColStart = nColStart; + this.nRow = nRow; + this.nCol = nCol; + this.parent = parent; + } + + public Matrix(Matrix parent, String name, int nRowStart, int nColStart, int nRow, int nCol) { + super(name); + this.nRowStart = nRowStart; + this.nColStart = nColStart; + this.nRow = nRow; + this.nCol = nCol; + this.parent = parent; + } + + + public ExprMatrix split(int nRowBlock, int nColBlock) { + int m = nRow/nRowBlock; + if(nRow%nRowBlock > 0) + m = (nRow+(nRowBlock-nRow%nRowBlock))/nRowBlock; + int n = nCol/nColBlock; + if(nCol%nColBlock > 0) + n = (nCol+(nColBlock-nCol%nColBlock))/nColBlock; + int last_m = nRow%m==0?m:nRow%m; + int last_n = nCol%n==0?n:nCol%n; +/* System.out.println(m); + System.out.println(n); + System.out.println(last_m); + System.out.println(last_n); +*/ Expr[][] items = new Expr[nRowBlock][nColBlock]; + for(int i=0; i argsMap, int argsStartPos, + Map funcRefsMap) { + // Create an instance of Jama.Matrix and store it to local variable index with this.indexLVT + if(indexLVT == -1) { + //jama.Matrix l_m = null; + LocalVariableGen lg = mg.addLocalVariable("l_"+getLabel(), + new ObjectType("Jama.Matrix"), null, null); + indexLVT = lg.getIndex(); +// il.append(InstructionConstants.ACONST_NULL); +// lg.setStart(il.append(new DSTORE(idx))); + + // First time touch the matrix, declare a local reference of Java.Matrix + il.append(new NEW(cp.addClass("Jama.Matrix"))); + il.append(InstructionConstants.DUP); + + //prepare argument: double[] vals + //il.append(new ALOAD(argsStartPos)); + //il.append(new PUSH(cp, argsMap.get(this.label))); + //il.append(InstructionConstants.DALOAD); //Load double from array + //////////////il.append(new ALOAD(argsMap.get(this.label))); //Load reference from local variable (from function arguments) + //il.append(new ALOAD(1)); //Load reference from local variable (from function arguments) + + il.append(new ALOAD(argsStartPos)); + il.append(new PUSH(cp, argsMap.get(this.label))); + il.append(InstructionConstants.AALOAD); //Load double from array + + //prepare argument: double m - number of rows + il.append(new PUSH(cp, nRow)); + il.append(factory.createInvoke("Jama.Matrix", "", + Type.VOID, new Type[] { new ArrayType(Type.DOUBLE, 1), Type.INT }, + Constants.INVOKESPECIAL)); + + //jama.Matrix l_m = new jama.Matrix(args[], nRow); + lg.setStart(il.append(new ASTORE(indexLVT))); + } + // Retrun the local reference of the matrix + return il.append(new ALOAD(indexLVT)); + + //For test purpose + //il.append(new ALOAD(indexLVT)); + //il.append(new PUSH(cp, 1.0)); + //return il.append(InstructionConstants.DRETURN); + } + + @Override + public TypeInfo getTypeInfo() { + TypeInfo ti = new TypeInfo(TYPE.MATRIX, new int[2]); + ti.dim[0] = this.nRow; + ti.dim[1] = this.nCol; + return ti; + } + + public void bytecodeGenReset() { + this.indexLVT = -1; + } + + @Override + public Expr getParent() { + return this.parent; + } + + public static void main(String[] args) { + Matrix m = new Matrix("A",6,8); + ExprMatrix sm = m.split(3, 2); + System.out.println(sm); + + } +} diff --git a/src/symjava/symbolic/Multiply.java b/src/symjava/symbolic/Multiply.java index 0cacfe8..acb1e38 100644 --- a/src/symjava/symbolic/Multiply.java +++ b/src/symjava/symbolic/Multiply.java @@ -2,10 +2,26 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; +import symjava.symbolic.Expr.TYPE; import symjava.symbolic.arity.BinaryOp; +import symjava.symbolic.utils.BytecodeUtils; import symjava.symbolic.utils.Utils; +import com.sun.org.apache.bcel.internal.Constants; +import com.sun.org.apache.bcel.internal.generic.ALOAD; +import com.sun.org.apache.bcel.internal.generic.ArrayType; +import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.InstructionConstants; +import com.sun.org.apache.bcel.internal.generic.InstructionFactory; +import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.MethodGen; +import com.sun.org.apache.bcel.internal.generic.ObjectType; +import com.sun.org.apache.bcel.internal.generic.PUSH; +import com.sun.org.apache.bcel.internal.generic.Type; + public class Multiply extends BinaryOp { public Multiply(Expr l, Expr r) { super(l, r); @@ -17,14 +33,7 @@ public Multiply(Expr l, Expr r) { arg1 = l; arg2 = r; } - label = SymPrinting.addParenthsesIfNeeded(arg1, this) - + "*" + - SymPrinting.addParenthsesIfNeeded(arg2, this); - if(this.isCoeffMulSymbol()) { - sortKey = this.getSymbolTerm().getSortKey();//+this.getCoeffTerm().getSortKey(); - } else { - sortKey = arg1.getSortKey()+arg2.getSortKey(); - } + updateLabel(); } public static Expr shallowSimplifiedIns(Expr l, Expr r) { @@ -69,19 +78,19 @@ else if(Symbol.C0.symEquals(l) || Symbol.C0.symEquals(r)) { Pow lp = (Pow)l; Pow rp = (Pow)r; if(Utils.symCompare(lp.arg1, rp.arg1)) { - return Pow.simplifiedIns( lp.arg1, lp.arg2+rp.arg2).setSimplifyOps(simOps).setAsSimplified(); + return Pow.simplifiedIns( lp.arg1, lp.arg2.add(rp.arg2)).setSimplifyOps(simOps).setAsSimplified(); } else if(lp.arg2 == rp.arg2) { return Pow.simplifiedIns( simplifiedIns(lp.arg1, rp.arg1), lp.arg2).setSimplifyOps(simOps).setAsSimplified(); } } else if(l instanceof Pow) { Pow lp = (Pow)l; if(Utils.symCompare(lp.arg1, r)) { - return new Pow(lp.arg1, lp.arg2 + 1).setSimplifyOps(simOps).setAsSimplified(); + return new Pow(lp.arg1, lp.arg2.add(1)).setSimplifyOps(simOps).setAsSimplified(); } } else if(r instanceof Pow) { Pow rp = (Pow)r; if(Utils.symCompare(rp.arg1, l)) { - return new Pow(rp.arg1, rp.arg2 + 1).setSimplifyOps(simOps).setAsSimplified(); + return new Pow(rp.arg1, rp.arg2.add(1)).setSimplifyOps(simOps).setAsSimplified(); } } if(Utils.symCompare(l, r)) { @@ -139,16 +148,20 @@ public Expr simplify() { @Override public void flattenAdd(List outList) { - List list1 = new ArrayList(); - List list2 = new ArrayList(); - arg1.flattenAdd(list1); - arg2.flattenAdd(list2); - if(list1.size()==1 && list2.size()==1) + if(device != null) { outList.add(this); - else { - for(Expr e1 : list1) { - for(Expr e2 : list2) { - outList.add( shallowSimplifiedIns(e1, e2) ); + } else { + List list1 = new ArrayList(); + List list2 = new ArrayList(); + arg1.flattenAdd(list1); + arg2.flattenAdd(list2); + if(list1.size()==1 && list2.size()==1) + outList.add(this); + else { + for(Expr e1 : list1) { + for(Expr e2 : list2) { + outList.add( shallowSimplifiedIns(e1, e2) ); + } } } } @@ -156,12 +169,104 @@ public void flattenAdd(List outList) { @Override public void flattenMultiply(List outList) { - arg1.flattenMultiply(outList); - arg2.flattenMultiply(outList); + if(device != null) { + outList.add(this); + } else { + arg1.flattenMultiply(outList); + arg2.flattenMultiply(outList); + } } public boolean symEquals(Expr other) { //return Utils.flattenSortAndCompare(this, other); return Utils.flattenSortAndCompare(this.simplify(), other.simplify()); } + + @Override + public InstructionHandle bytecodeGen(String clsName, MethodGen mg, + ConstantPoolGen cp, InstructionFactory factory, + InstructionList il, Map argsMap, int argsStartPos, + Map funcRefsMap) { + InstructionHandle startPos = arg1.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + if(arg1.getType() == TYPE.MATRIX) { + arg2.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + if(arg2.getType() == TYPE.VECTOR) { + il.append(factory.createInvoke("Jama.Matrix", "times", + new ObjectType("Jama.Matrix"), new Type[] { new ObjectType("Jama.Matrix") }, + //Type.getType(Jama.Matrix.class), new Type[] { Type.getType(Jama.Matrix.class) }, + Constants.INVOKEVIRTUAL)); +/* Move the return part out of here to class CompileUtil + //Copy results to outAry + il.append(factory.createInvoke("Jama.Matrix", "getColumnPackedCopy", + new ArrayType(Type.DOUBLE,1), new Type[] {}, + Constants.INVOKEVIRTUAL)); + il.append(new PUSH(cp, 0)); + il.append(InstructionConstants.ALOAD_1); //outAry (output buffer) + il.append(InstructionConstants.ILOAD_2); //outPos (start position of output buffer) + Vector x = (Vector)arg2; + il.append(new PUSH(cp, x.nDim)); + //Call System.arraycopy(src, srcPos, dest, destPos, length); + il.append(factory.createInvoke("java.lang.System", "arraycopy", + Type.VOID, new Type[] { Type.OBJECT, Type.INT, Type.OBJECT, Type.INT, Type.INT }, + Constants.INVOKESTATIC)); +*/ + //test only + //il.append(new ALOAD(indexLVT)); + //il.append(new PUSH(cp, 1.0)); + //return il.append(InstructionConstants.DRETURN); + + } else if(arg2.getType() == TYPE.DOUBLE) { + + } + + return startPos; + } + + TYPE ty = Utils.getConvertedType(arg1.getType(), arg2.getType()); + BytecodeUtils.typeCast(il, arg1.getType(), ty); + arg2.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + BytecodeUtils.typeCast(il, arg2.getType(), ty); + if(ty == TYPE.DOUBLE) + il.append(InstructionConstants.DMUL); + else if(ty == TYPE.INT) + il.append(InstructionConstants.IMUL); + else if(ty == TYPE.LONG) + il.append(InstructionConstants.LMUL); + else if(ty == TYPE.FLOAT) + il.append(InstructionConstants.FMUL); + else + il.append(InstructionConstants.IMUL); + return startPos; + } + + @Override + public void updateLabel() { + label = SymPrinting.addParenthsesIfNeeded(arg1, this) + + "*" + + SymPrinting.addParenthsesIfNeeded(arg2, this); + if(this.isCoeffMulSymbol()) { + sortKey = this.getSymbolTerm().getSortKey();//+this.getCoeffTerm().getSortKey(); + } else { + sortKey = arg1.getSortKey()+arg2.getSortKey(); + } + } + + @Override + public TypeInfo getTypeInfo() { + if(arg1.getType() == TYPE.MATRIX) { + if(arg2.getType() == TYPE.VECTOR) + return arg2.getTypeInfo(); + else if(arg2.getType() == TYPE.MATRIX) { + //A_mn * B_nl = C_ml + TypeInfo ti = new TypeInfo(TYPE.MATRIX, new int[2]); + ti.dim[0] = arg1.getTypeInfo().dim[0]; + ti.dim[1] = arg2.getTypeInfo().dim[1]; + return ti; + } else + return arg1.getTypeInfo(); //matrix * scalar? + } + TYPE ty = Utils.getConvertedType(arg1.getType(), arg2.getType()); + TypeInfo tyi = new TypeInfo(ty); + return tyi; + } } diff --git a/src/symjava/symbolic/Negate.java b/src/symjava/symbolic/Negate.java index d7bf7d7..4a2ab23 100644 --- a/src/symjava/symbolic/Negate.java +++ b/src/symjava/symbolic/Negate.java @@ -2,7 +2,19 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; +import com.sun.org.apache.bcel.internal.Constants; +import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.InstructionConstants; +import com.sun.org.apache.bcel.internal.generic.InstructionFactory; +import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.MethodGen; +import com.sun.org.apache.bcel.internal.generic.ObjectType; +import com.sun.org.apache.bcel.internal.generic.Type; + +import symjava.symbolic.Expr.TYPE; import symjava.symbolic.arity.UnaryOp; import symjava.symbolic.utils.Utils; @@ -10,8 +22,7 @@ public class Negate extends UnaryOp { public Negate(Expr expr) { super(expr); - label = "-" + SymPrinting.addParenthsesIfNeeded(expr, this); - sortKey = arg.getSortKey(); + updateLabel(); } @Override @@ -100,5 +111,28 @@ public void flattenMultiply(List outList) { } } } + + @Override + public InstructionHandle bytecodeGen(String clsName, MethodGen mg, + ConstantPoolGen cp, InstructionFactory factory, + InstructionList il, Map argsMap, int argsStartPos, + Map funcRefsMap) { + InstructionHandle startPos = arg.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + if(arg.getType() == TYPE.MATRIX || arg.getType() == TYPE.VECTOR) { + il.append(factory.createInvoke("symjava.symbolic.utils.BytecodeOpSupport", "negate", + new ObjectType("Jama.Matrix"), + new Type[] { new ObjectType("Jama.Matrix") }, + Constants.INVOKESTATIC)); + } else { + il.append(InstructionConstants.DNEG); + } + return startPos; + } + + @Override + public void updateLabel() { + label = "-" + SymPrinting.addParenthsesIfNeeded(arg, this); + sortKey = arg.getSortKey(); + } } diff --git a/src/symjava/symbolic/Pow.java b/src/symjava/symbolic/Pow.java index 2f011e2..7ce6608 100644 --- a/src/symjava/symbolic/Pow.java +++ b/src/symjava/symbolic/Pow.java @@ -1,31 +1,28 @@ package symjava.symbolic; import java.util.List; +import java.util.Map; import symjava.symbolic.arity.BinaryOp; import symjava.symbolic.utils.Utils; +import com.sun.org.apache.bcel.internal.Constants; +import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.InstructionFactory; +import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.MethodGen; +import com.sun.org.apache.bcel.internal.generic.Type; + public class Pow extends BinaryOp { public Pow(Expr base, Expr exponent) { super(base, exponent); - String displayExp = String.format("%s", this.arg2); - if(exponent instanceof SymReal) { - SymReal realExp = (SymReal)exponent; - if(realExp.isInteger()) { - displayExp = String.format("%d", realExp.getIntValue()); - } - if(realExp.isNegative()) - displayExp = "{"+displayExp+"}"; - } - if(base instanceof Symbol) { - label = base + "^" + displayExp + ""; - label = "pow(" + base + ","+displayExp+")"; - } else { - label = "("+base + ")^" + displayExp; - } - //TODO? x^3 + x^2 + x + 1 - sortKey = base.getSortKey()+"power"+String.valueOf(displayExp); + updateLabel(); + } + + public String toString() { + return "pow("+arg1+","+arg2+")"; } public static Expr simplifiedIns(Expr base, Expr exponent) { @@ -63,7 +60,7 @@ public Expr subs(Expr from, Expr to) { public Expr diff(Expr expr) { if(arg2 instanceof SymReal) { SymReal realExp = (SymReal)arg2; - return realExp.multiply(Pow.simplifiedIns(arg1, arg2 - 1)).multiply(arg1.diff(expr)); + return realExp.multiply(Pow.simplifiedIns(arg1, arg2.subtract(1))).multiply(arg1.diff(expr)); } else { Expr x = expr; Expr b = arg1; @@ -100,19 +97,66 @@ public void flattenAdd(List outList) { @Override public void flattenMultiply(List outList) { + if(device != null) { + outList.add(this); + } else { + if(arg2 instanceof SymReal) { + SymReal realExp = (SymReal)arg2; + if(realExp.isPositive()) { + double exp = realExp.getDoubleValue(); + for(int i=0; i<(int)exp; i++) + outList.add(arg1); + double remain = exp - Math.floor(exp); + if(remain > 0.0) { + outList.add(simplifiedIns(arg1, Expr.valueOf(remain))); + } + return; + } + } + outList.add(this); + } + } + @Override + public InstructionHandle bytecodeGen(String clsName, MethodGen mg, + ConstantPoolGen cp, InstructionFactory factory, + InstructionList il, Map argsMap, int argsStartPos, + Map funcRefsMap) { + InstructionHandle startPos = arg1.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + arg2.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); if(arg2 instanceof SymReal) { SymReal realExp = (SymReal)arg2; - if(realExp.isPositive()) { - double exp = realExp.getDoubleValue(); - for(int i=0; i<(int)exp; i++) - outList.add(arg1); - double remain = exp - Math.floor(exp); - if(remain > 0.0) { - outList.add(simplifiedIns(arg1, Expr.valueOf(remain))); - } - return; + if(realExp.isInteger()) { + il.append(factory.createInvoke("symjava.symbolic.utils.BytecodeSupport", "powi", + Type.DOUBLE, new Type[] { Type.DOUBLE, Type.INT }, Constants.INVOKESTATIC)); + return startPos; } } - outList.add(this); + il.append(factory.createInvoke("java.lang.Math", "pow", + Type.DOUBLE, new Type[] { Type.DOUBLE, Type.DOUBLE }, Constants.INVOKESTATIC)); + return startPos; } + + @Override + public void updateLabel() { + Expr base = arg1; + Expr exponent = arg2; +// String displayExp = exponent.toString(); +// if(exponent instanceof SymReal) { +// SymReal realExp = (SymReal)exponent; +// if(realExp.isInteger()) { +// displayExp = String.format("%d", realExp.getIntValue()); +// } +// if(realExp.isNegative()) +// displayExp = "{"+displayExp+"}"; +// } +// if(base instanceof Symbol) { +// label = base + "^" + displayExp + ""; +// } else { +// label = "("+base + ")^" + displayExp; +// } + //TODO? x^3 + x^2 + x + 1 + label = "pow(" + base + ","+exponent+")"; + sortKey = base.getSortKey()+"power"+exponent.getSortKey(); + + } } diff --git a/src/symjava/symbolic/Prod.java b/src/symjava/symbolic/Prod.java index aa032ef..0b00b80 100644 --- a/src/symjava/symbolic/Prod.java +++ b/src/symjava/symbolic/Prod.java @@ -1,5 +1,46 @@ package symjava.symbolic; -public class Prod { +/** + * TODO + * a*b*c*d... + * + */ +public class Prod extends Expr { + + @Override + public Expr simplify() { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean symEquals(Expr other) { + // TODO Auto-generated method stub + return false; + } + + @Override + public Expr diff(Expr expr) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Expr[] args() { + // TODO Auto-generated method stub + return null; + } + + @Override + public TypeInfo getTypeInfo() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void updateLabel() { + // TODO Auto-generated method stub + + } } diff --git a/src/symjava/symbolic/Reciprocal.java b/src/symjava/symbolic/Reciprocal.java index 322c51f..a652baf 100644 --- a/src/symjava/symbolic/Reciprocal.java +++ b/src/symjava/symbolic/Reciprocal.java @@ -1,14 +1,23 @@ package symjava.symbolic; +import java.util.Map; + import symjava.symbolic.arity.UnaryOp; +import symjava.symbolic.utils.BytecodeUtils; import symjava.symbolic.utils.Utils; +import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.InstructionConstants; +import com.sun.org.apache.bcel.internal.generic.InstructionFactory; +import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.MethodGen; + public class Reciprocal extends UnaryOp { public Reciprocal(Expr base) { super(base); - label = "1/" + SymPrinting.addParenthsesIfNeeded(base, this); - sortKey = base.getSortKey(); + updateLabel(); } @Override @@ -23,7 +32,7 @@ public Expr simplify() { if(arg instanceof Pow) { Pow p = (Pow)arg.simplify(); p.isSimplified = true; - Expr rlt = Pow.simplifiedIns(p.arg1, -p.arg2); + Expr rlt = Pow.simplifiedIns(p.arg1, p.arg2.negate()); rlt.isSimplified = true; return rlt; } @@ -59,5 +68,23 @@ public Expr subs(Expr from, Expr to) { return this; return Reciprocal.simplifiedIns(arg.subs(from, to)); } + + @Override + public InstructionHandle bytecodeGen(String clsName, MethodGen mg, + ConstantPoolGen cp, InstructionFactory factory, + InstructionList il, Map argsMap, int argsStartPos, + Map funcRefsMap) { + InstructionHandle startPos = il.append(InstructionConstants.DCONST_1); + arg.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + BytecodeUtils.typeCast(il, arg.getType(), TYPE.DOUBLE); + il.append(InstructionConstants.DDIV); + return startPos; + } + @Override + public void updateLabel() { + label = "1/" + SymPrinting.addParenthsesIfNeeded(arg, this); + sortKey = arg.getSortKey(); + } + } diff --git a/src/symjava/symbolic/Remainder.java b/src/symjava/symbolic/Remainder.java index ad80b6b..8e3cf8f 100644 --- a/src/symjava/symbolic/Remainder.java +++ b/src/symjava/symbolic/Remainder.java @@ -1,12 +1,30 @@ package symjava.symbolic; +import static com.sun.org.apache.bcel.internal.generic.InstructionConstants.DREM; +import static com.sun.org.apache.bcel.internal.generic.InstructionConstants.FREM; +import static com.sun.org.apache.bcel.internal.generic.InstructionConstants.IREM; +import static com.sun.org.apache.bcel.internal.generic.InstructionConstants.LREM; + +import java.util.Map; + import symjava.symbolic.arity.BinaryOp; +import symjava.symbolic.utils.BytecodeUtils; +import symjava.symbolic.utils.Utils; +import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.InstructionFactory; +import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.MethodGen; + +/** + * a % b + * + */ public class Remainder extends BinaryOp { public Remainder(Expr arg1, Expr arg2) { super(arg1, arg2); - this.label = arg1+"%"+arg2; - this.sortKey = this.label; + updateLabel(); } @Override @@ -16,12 +34,41 @@ public Expr simplify() { @Override public boolean symEquals(Expr other) { + //TODO return false; } @Override public Expr diff(Expr expr) { - //??? - return this; + throw new UnsupportedOperationException(); + } + + @Override + public InstructionHandle bytecodeGen(String clsName, MethodGen mg, + ConstantPoolGen cp, InstructionFactory factory, + InstructionList il, Map argsMap, int argsStartPos, + Map funcRefsMap) { + InstructionHandle startPos = arg1.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + TYPE ty = Utils.getConvertedType(arg1.getType(), arg2.getType()); + BytecodeUtils.typeCast(il, arg1.getType(), ty); + arg2.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + BytecodeUtils.typeCast(il, arg2.getType(), ty); + if(ty == TYPE.DOUBLE) + il.append(DREM); + else if(ty == TYPE.INT) + il.append(IREM); + else if(ty == TYPE.LONG) + il.append(LREM); + else if(ty == TYPE.FLOAT) + il.append(FREM); + else + il.append(IREM); + return startPos; + } + + @Override + public void updateLabel() { + this.label = arg1+"%"+arg2; + this.sortKey = this.label; } } diff --git a/src/symjava/symbolic/Select.java b/src/symjava/symbolic/Select.java new file mode 100644 index 0000000..f6439f9 --- /dev/null +++ b/src/symjava/symbolic/Select.java @@ -0,0 +1,63 @@ +package symjava.symbolic; + +public class Select extends Expr { + + public Select(Expr ...cols) { + + } + + public Select from(Expr ...tables) { + return this; + } + + public Select where() { + return this; + } + + public Select groupBy(Expr ...cols) { + return this; + } + + + public static void main(String[] args) { + // TODO Auto-generated method stub + + } + + @Override + public Expr simplify() { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean symEquals(Expr other) { + // TODO Auto-generated method stub + return false; + } + + @Override + public Expr[] args() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Expr diff(Expr x) { + // TODO Auto-generated method stub + return null; + } + + @Override + public TypeInfo getTypeInfo() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void updateLabel() { + // TODO Auto-generated method stub + + } + +} diff --git a/src/symjava/symbolic/Sin.java b/src/symjava/symbolic/Sin.java index 4dd7b52..d6803fd 100644 --- a/src/symjava/symbolic/Sin.java +++ b/src/symjava/symbolic/Sin.java @@ -1,5 +1,16 @@ package symjava.symbolic; +import java.util.Map; + +import com.sun.org.apache.bcel.internal.Constants; +import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.InstructionFactory; +import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.MethodGen; +import com.sun.org.apache.bcel.internal.generic.ObjectType; +import com.sun.org.apache.bcel.internal.generic.Type; + import symjava.symbolic.arity.UnaryOp; import symjava.symbolic.utils.Utils; @@ -7,8 +18,7 @@ public class Sin extends UnaryOp { public Sin(Expr arg) { super(arg); - label = "sin(" + arg + ")"; - sortKey = label; + updateLabel(); } @Override @@ -25,6 +35,16 @@ public Expr simplify() { return this; } + @Override + public Expr subs(Expr from, Expr to) { + if(Utils.symCompare(this, from)) + return to; + Expr sl = arg.subs(from, to); + if(sl == arg) + return this; + return new Sin(sl); + } + @Override public boolean symEquals(Expr other) { if(other instanceof Sin) { @@ -32,5 +52,30 @@ public boolean symEquals(Expr other) { } return false; } + + @Override + public InstructionHandle bytecodeGen(String clsName, MethodGen mg, + ConstantPoolGen cp, InstructionFactory factory, + InstructionList il, Map argsMap, int argsStartPos, + Map funcRefsMap) { + InstructionHandle startPos = arg.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + if(arg.getType() == TYPE.MATRIX || arg.getType() == TYPE.VECTOR) { + il.append(factory.createInvoke("symjava.symbolic.utils.BytecodeOpSupport", "sin", + new ObjectType("Jama.Matrix"), + new Type[] { new ObjectType("Jama.Matrix") }, + Constants.INVOKESTATIC)); + } else { + il.append(factory.createInvoke("java.lang.Math", "sin", + Type.DOUBLE, + new Type[] { Type.DOUBLE }, + Constants.INVOKESTATIC)); + } + return startPos; + } + @Override + public void updateLabel() { + label = "sin(" + arg + ")"; + sortKey = label; + } } diff --git a/src/symjava/symbolic/Sqrt.java b/src/symjava/symbolic/Sqrt.java index 836619d..e696e23 100644 --- a/src/symjava/symbolic/Sqrt.java +++ b/src/symjava/symbolic/Sqrt.java @@ -1,32 +1,33 @@ package symjava.symbolic; +import java.util.Map; + import symjava.symbolic.arity.BinaryOp; import symjava.symbolic.utils.Utils; +import com.sun.org.apache.bcel.internal.Constants; +import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.InstructionConstants; +import com.sun.org.apache.bcel.internal.generic.InstructionFactory; +import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.MethodGen; +import com.sun.org.apache.bcel.internal.generic.Type; + public class Sqrt extends BinaryOp { public Sqrt(Expr expr) { super(expr, Expr.valueOf(2)); - label = "\\sqrt{" + expr + "}"; - sortKey = expr.getSortKey()+"sqrt[2]"+String.valueOf(arg2); + updateLabel(); } public Sqrt(Expr expr, Expr root) { super(expr, root); - String displayRoot = String.format("%s", this.arg2); - if(root instanceof SymReal) { - SymReal realExp = (SymReal)root; - if(realExp.isInteger()) { - displayRoot = String.format("%d", realExp.getIntValue()); - } - } - label = "\\sqrt["+displayRoot+"]{" + expr + "}"; - //TODO - sortKey = expr.getSortKey()+"sqrt["+root+"]"+String.valueOf(root); + updateLabel(); } @Override public Expr diff(Expr expr) { - return Pow.simplifiedIns(arg1, 1.0/arg2).diff(expr); + return Pow.simplifiedIns(arg1, arg2.divideRev(1.0)).diff(expr); } public static Expr simplifiedIns(Expr expr, Expr root) { @@ -74,4 +75,40 @@ public Expr subs(Expr from, Expr to) { return to; return new Sqrt(arg1.subs(from, to), arg2.subs(from, to)); } + + @Override + public InstructionHandle bytecodeGen(String clsName, MethodGen mg, + ConstantPoolGen cp, InstructionFactory factory, + InstructionList il, Map argsMap, int argsStartPos, + Map funcRefsMap) { + InstructionHandle startPos = arg1.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + il.append(InstructionConstants.DCONST_1); + arg2.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + if(arg2 instanceof SymReal) { + SymReal realExp = (SymReal)arg2; + if(realExp.isInteger()) { + il.append(InstructionConstants.I2D); + } + } + il.append(InstructionConstants.DDIV); + il.append(factory.createInvoke("java.lang.Math", "pow", + Type.DOUBLE, + new Type[] { Type.DOUBLE, Type.DOUBLE }, + Constants.INVOKESTATIC)); + return startPos; + } + + @Override + public void updateLabel() { + if(arg2 instanceof SymReal) { + SymReal t = (SymReal)arg2; + if(t.isInteger() && t.getIntValue() == 2) { + label = "sqrt(" + arg1 + ")"; + sortKey = arg1.getSortKey()+"sqrt[2]"+arg2; + return; + } + } + label = "sqrtn(" + arg1 + "," + arg2 + ")"; + sortKey = arg1.getSortKey()+"sqrt"+arg2.getSortKey(); + } } diff --git a/src/symjava/symbolic/Subtract.java b/src/symjava/symbolic/Subtract.java index 5c24df9..90b403a 100644 --- a/src/symjava/symbolic/Subtract.java +++ b/src/symjava/symbolic/Subtract.java @@ -1,19 +1,28 @@ package symjava.symbolic; import java.util.List; +import java.util.Map; +import symjava.symbolic.Expr.TYPE; import symjava.symbolic.arity.BinaryOp; +import symjava.symbolic.utils.BytecodeUtils; import symjava.symbolic.utils.Utils; +import com.sun.org.apache.bcel.internal.Constants; +import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.InstructionConstants; +import com.sun.org.apache.bcel.internal.generic.InstructionFactory; +import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.MethodGen; +import com.sun.org.apache.bcel.internal.generic.ObjectType; +import com.sun.org.apache.bcel.internal.generic.Type; + public class Subtract extends BinaryOp { public Subtract(Expr l, Expr r) { super(l, r); - if(arg2 instanceof Add || arg2 instanceof Subtract) - label = arg1 + " - (" + arg2 + ")"; - else - label = arg1 + " - " + arg2; + updateLabel(); - sortKey = arg1.getSortKey()+arg2.getSortKey(); } @Override @@ -75,4 +84,51 @@ public boolean symEquals(Expr other) { //return Utils.flattenSortAndCompare(this, other); return Utils.flattenSortAndCompare(this.simplify(), other.simplify()); } + + @Override + public InstructionHandle bytecodeGen(String clsName, MethodGen mg, + ConstantPoolGen cp, InstructionFactory factory, + InstructionList il, Map argsMap, int argsStartPos, + Map funcRefsMap) { + InstructionHandle startPos = arg1.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + if(arg1.getType() == TYPE.MATRIX && arg2.getType() == TYPE.MATRIX) { + arg2.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + il.append(factory.createInvoke("Jama.Matrix", "minus", + new ObjectType("Jama.Matrix"), new Type[] { new ObjectType("Jama.Matrix") }, + Constants.INVOKEVIRTUAL)); + return startPos; + } else if(arg1.getType() == TYPE.VECTOR && arg2.getType() == TYPE.VECTOR) { + arg2.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + il.append(factory.createInvoke("Jama.Matrix", "minus", + new ObjectType("Jama.Matrix"), new Type[] { new ObjectType("Jama.Matrix") }, + Constants.INVOKEVIRTUAL)); + return startPos; + } + + TYPE ty = Utils.getConvertedType(arg1.getType(), arg2.getType()); + BytecodeUtils.typeCast(il, arg1.getType(), ty); + arg2.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + BytecodeUtils.typeCast(il, arg2.getType(), ty); + if(ty == TYPE.DOUBLE) + il.append(InstructionConstants.DSUB); + else if(ty == TYPE.INT) + il.append(InstructionConstants.ISUB); + else if(ty == TYPE.LONG) + il.append(InstructionConstants.LSUB); + else if(ty == TYPE.FLOAT) + il.append(InstructionConstants.FSUB); + else + il.append(InstructionConstants.ISUB); + return startPos; + } + + @Override + public void updateLabel() { + if(arg2 instanceof Add || arg2 instanceof Subtract) + label = arg1 + " - (" + arg2 + ")"; + else + label = arg1 + " - " + arg2; + + sortKey = arg1.getSortKey()+arg2.getSortKey(); + } } diff --git a/src/symjava/symbolic/Sum.java b/src/symjava/symbolic/Sum.java index 3eba735..5278fac 100644 --- a/src/symjava/symbolic/Sum.java +++ b/src/symjava/symbolic/Sum.java @@ -7,6 +7,9 @@ import symjava.symbolic.utils.AddList; import symjava.symbolic.utils.Utils; +/** + * a+b+c+d+... + */ public class Sum extends Expr { public Expr summandTemplate; public Expr indexExpr; @@ -14,6 +17,14 @@ public class Sum extends Expr { public int end; HashMap cache = new HashMap(); + /** + * \Sigma_{i=start}^{end}{x_i} + * + * @param summandTemplate + * @param indexExpr + * @param start + * @param end + */ public Sum(Expr summandTemplate, Expr indexExpr, int start, int end) { this.summandTemplate = summandTemplate; this.indexExpr = indexExpr; @@ -117,4 +128,22 @@ public void flattenMultiply(List outList) { outList.add(this); } + @Override + public Expr[] args() { + // TODO Auto-generated method stub + return null; + } + + @Override + public TypeInfo getTypeInfo() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void updateLabel() { + // TODO Auto-generated method stub + + } + } diff --git a/src/symjava/symbolic/SymComplex.java b/src/symjava/symbolic/SymComplex.java index 934ed2f..6385495 100644 --- a/src/symjava/symbolic/SymComplex.java +++ b/src/symjava/symbolic/SymComplex.java @@ -1,9 +1,11 @@ package symjava.symbolic; -import java.util.List; - import symjava.symbolic.utils.Utils; +/** + * TODO + * + */ public class SymComplex extends Expr { Expr real; Expr imaginary; @@ -44,4 +46,20 @@ public boolean symEquals(Expr other) { return false; } + @Override + public TypeInfo getTypeInfo() { + // TODO Auto-generated method stub + return null; + } + @Override + public Expr[] args() { + return new Expr[] {real, imaginary}; + } + + @Override + public void updateLabel() { + // TODO Auto-generated method stub + + } + } diff --git a/src/symjava/symbolic/SymConst.java b/src/symjava/symbolic/SymConst.java index 8457ec6..6f8f5e7 100644 --- a/src/symjava/symbolic/SymConst.java +++ b/src/symjava/symbolic/SymConst.java @@ -1,5 +1,14 @@ package symjava.symbolic; +import java.util.Map; + +import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.InstructionFactory; +import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.MethodGen; +import com.sun.org.apache.bcel.internal.generic.PUSH; + /** * An object of SymConst represent a mathematical constant such as PI, E. * The constant is displayed as its label but used as a double number @@ -33,4 +42,27 @@ public Expr simplify() { public boolean symEquals(Expr other) { return this.label.equals(other.label); } + + @Override + public InstructionHandle bytecodeGen(String clsName, MethodGen mg, + ConstantPoolGen cp, InstructionFactory factory, + InstructionList il, Map argsMap, int argsStartPos, + Map funcRefsMap) { + return il.append(new PUSH(cp, value)); + } + + @Override + public Expr[] args() { + return new Expr[0]; + } + + @Override + public TypeInfo getTypeInfo() { + return TypeInfo.tiDouble; + } + + @Override + public void updateLabel() { + //Do nothing + } } diff --git a/src/symjava/symbolic/SymDouble.java b/src/symjava/symbolic/SymDouble.java index 34253e6..c64438d 100644 --- a/src/symjava/symbolic/SymDouble.java +++ b/src/symjava/symbolic/SymDouble.java @@ -1,5 +1,6 @@ package symjava.symbolic; + public class SymDouble extends SymReal { public SymDouble(double val) { super(val); diff --git a/src/symjava/symbolic/SymFloat.java b/src/symjava/symbolic/SymFloat.java index fdd1db6..63a840f 100644 --- a/src/symjava/symbolic/SymFloat.java +++ b/src/symjava/symbolic/SymFloat.java @@ -1,5 +1,6 @@ package symjava.symbolic; + public class SymFloat extends SymReal { public SymFloat(float val) { super(val); diff --git a/src/symjava/symbolic/SymInteger.java b/src/symjava/symbolic/SymInteger.java index fc6b742..ec601ea 100644 --- a/src/symjava/symbolic/SymInteger.java +++ b/src/symjava/symbolic/SymInteger.java @@ -1,5 +1,6 @@ package symjava.symbolic; + public class SymInteger extends SymReal { public SymInteger(int val) { super(val); diff --git a/src/symjava/symbolic/SymLong.java b/src/symjava/symbolic/SymLong.java index 4a216d8..3f98acc 100644 --- a/src/symjava/symbolic/SymLong.java +++ b/src/symjava/symbolic/SymLong.java @@ -1,5 +1,6 @@ package symjava.symbolic; + public class SymLong extends SymReal { public SymLong(long val) { super(val); diff --git a/src/symjava/symbolic/SymRandom.java b/src/symjava/symbolic/SymRandom.java new file mode 100644 index 0000000..63feddb --- /dev/null +++ b/src/symjava/symbolic/SymRandom.java @@ -0,0 +1,59 @@ +package symjava.symbolic; + +import java.util.Map; + +import com.sun.org.apache.bcel.internal.Constants; +import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.InstructionFactory; +import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.MethodGen; +import com.sun.org.apache.bcel.internal.generic.Type; + +/** + * Represents a random number in the range [0.0, 1.0] + * + */ +public class SymRandom extends Expr { + public SymRandom() { + this.label = "random()"; + this.sortKey = label; + } + + @Override + public Expr diff(Expr expr) { + return null; + } + + @Override + public Expr simplify() { + return this; + } + + @Override + public boolean symEquals(Expr other) { + return false; + } + + @Override + public TypeInfo getTypeInfo() { + return TypeInfo.tiDouble; + } + + @Override + public Expr[] args() { + return new Expr[0]; + } + + public InstructionHandle bytecodeGen(String clsName, MethodGen mg, + ConstantPoolGen cp, InstructionFactory factory, + InstructionList il, Map argsMap, int argsStartPos, + Map funcRefsMap) { + return il.append(factory.createInvoke("java.lang.Math", "random", + Type.DOUBLE, new Type[] { }, Constants.INVOKESTATIC)); + } + + @Override + public void updateLabel() { + } +} diff --git a/src/symjava/symbolic/SymReal.java b/src/symjava/symbolic/SymReal.java index d39665b..993dfa3 100644 --- a/src/symjava/symbolic/SymReal.java +++ b/src/symjava/symbolic/SymReal.java @@ -1,15 +1,28 @@ package symjava.symbolic; +import java.util.Map; + +import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.InstructionFactory; +import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.MethodGen; +import com.sun.org.apache.bcel.internal.generic.PUSH; + import symjava.symbolic.utils.Utils; +/** + * A SymReal object is a symbolic representation of a real number + * + * @param + */ public class SymReal extends Expr { protected T value; public SymReal(T val) { this.value = val; - label = String.valueOf(val); - sortKey = label; isSimplified = true; + updateLabel(); } public T getValue() { @@ -105,5 +118,38 @@ else if(other instanceof SymReal) { } return false; } + + @Override + public InstructionHandle bytecodeGen(String clsName, MethodGen mg, + ConstantPoolGen cp, InstructionFactory factory, + InstructionList il, Map argsMap, int argsStartPos, + Map funcRefsMap) { + return il.append(new PUSH(cp, value)); + } + + @Override + public TypeInfo getTypeInfo() { + if(value instanceof Double) + return TypeInfo.tiDouble; + else if(value instanceof Integer) + return TypeInfo.tiInt; + else if(value instanceof Long) + return TypeInfo.tiLong; + else if(value instanceof Float) + return TypeInfo.tiFloat; + else + throw new RuntimeException(); + } + + @Override + public Expr[] args() { + return new Expr[0]; + } + + @Override + public void updateLabel() { + label = String.valueOf(value); + sortKey = label; + } } diff --git a/src/symjava/symbolic/Symbol.java b/src/symjava/symbolic/Symbol.java index 418633b..eb74440 100644 --- a/src/symjava/symbolic/Symbol.java +++ b/src/symjava/symbolic/Symbol.java @@ -1,11 +1,25 @@ package symjava.symbolic; +import java.util.Map; + import symjava.symbolic.utils.Utils; +import com.sun.org.apache.bcel.internal.generic.ALOAD; +import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.InstructionConstants; +import com.sun.org.apache.bcel.internal.generic.InstructionFactory; +import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.MethodGen; +import com.sun.org.apache.bcel.internal.generic.PUSH; + /** - * An object of Symbol has a string name which is its unique id. - * Two objects of Symbol with the same name are the same thing in SymJava. - * see method symEquals() + * An object of Symbol has a string name which is its unique id, + * just like the name of a variable in Java. + * + * Two Symbol objects with the same name are treated as the same thing. + * + * @see symEquals() * */ public class Symbol extends Expr { @@ -46,7 +60,6 @@ public class Symbol extends Expr { public static Infinity oo = new Infinity(); - public Symbol(String name) { this.label = name; sortKey = label; @@ -84,6 +97,9 @@ public boolean symEquals(Expr other) { } public String getPrefix() { + //TODO Fixit suport reduce + if(this.toString().equals("_")||this.toString().equals("__")) + return this.toString(); String[] ss = this.toString().split("_"); return ss[0]; } @@ -103,4 +119,53 @@ public int getSubIndex() { } throw new IllegalArgumentException(this.getLabel()+" contains no sub index."); } + +// /** +// * Declare the symbol as a local variable when compiling an expression which +// * contains this symbol. By default, a symbol is one of the arguments of +// * an instance of SymFunc. The declaration changes this default behavior of +// * the symbol. +// * +// * If a symbol is declared as a local variable it will be defined as +// * a local variable in the compiled function. The result of evaluation of the +// * associated expression is stored in this local variable. +// * +// * @return +// */ +// public Expr declareAsLocal(Class clazz) { +// this.isDeclaredAsLocal = true; +// return this; +// } + + @Override + public InstructionHandle bytecodeGen(String clsName, MethodGen mg, + ConstantPoolGen cp, InstructionFactory factory, + InstructionList il, Map argsMap, int argsStartPos, + Map funcRefsMap) { +//Note: local variable implementation has been moved to LCVar +// if(this.isDeclaredAsLocal) { +// // Load from a local variable +// return il.append(new DLOAD(indexLVT)); +// } else { + // Load from an array (argument or local array) + il.append(new ALOAD(argsStartPos)); + il.append(new PUSH(cp, argsMap.get(this.label))); + return il.append(InstructionConstants.DALOAD); +// } + } + + @Override + public TypeInfo getTypeInfo() { + return TypeInfo.tiDouble; + } + + @Override + public Expr[] args() { + return new Expr[0]; + } + + @Override + public void updateLabel() { + } + } diff --git a/src/symjava/symbolic/Symbols.java b/src/symjava/symbolic/Symbols.java index 1e2efcd..ea30f89 100644 --- a/src/symjava/symbolic/Symbols.java +++ b/src/symjava/symbolic/Symbols.java @@ -31,8 +31,7 @@ public class Symbols extends Expr { public Symbols(String namePrefix) { this.namePrefix = new Symbol(namePrefix); this.indexExpr = new Symbol("i"); - this.label = namePrefix + "_" +indexExpr; - sortKey = label; + updateLabel(); } /** @@ -46,11 +45,7 @@ public Symbols(String namePrefix) { public Symbols(String namePrefix, Expr indexExpr) { this.namePrefix = new Symbol(namePrefix); this.indexExpr = indexExpr; - if(indexExpr instanceof Symbol) - this.label = namePrefix + "_" + indexExpr; - else - this.label = namePrefix + "_{" + indexExpr+"}"; - sortKey = label; + updateLabel(); } public Symbol get(int index) { @@ -152,4 +147,25 @@ public boolean symEquals(Expr other) { return false; } + @Override + public Expr[] args() { + // TODO Auto-generated method stub + return null; + } + + @Override + public TypeInfo getTypeInfo() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void updateLabel() { + if(indexExpr instanceof Symbol) + this.label = namePrefix + "_" + indexExpr; + else + this.label = namePrefix + "_{" + indexExpr+"}"; + sortKey = label; + } + } diff --git a/src/symjava/symbolic/Table.java b/src/symjava/symbolic/Table.java new file mode 100644 index 0000000..a0ba3b9 --- /dev/null +++ b/src/symjava/symbolic/Table.java @@ -0,0 +1,52 @@ +package symjava.symbolic; + +import symjava.symbolic.arity.NaryOp; + +/** + * An expressions table is similar to the table of a relational database (RDBMS). + * The expressions table itself is nothing but an array of expressions. + * + * It will return an array of CloudSD when evaluating the expressions table. + * Each element of the returned CloudSD corresponds to a column of a RDBMS table. + * + * The main purpose of an expression table is to 'bind' the values of expressions + * together into a table. The length of values must be the same for each expression + * in the expressions table. + * + */ +public class Table extends NaryOp { + + public Table(Expr... args) { + super(args); + } + + public Expr get(int i) { + return this.args[i]; + } + + @Override + public Expr simplify() { + return this; + } + + @Override + public boolean symEquals(Expr other) { + return false; + } + + @Override + public Expr diff(Expr x) { + return null; + } + + @Override + public TypeInfo getTypeInfo() { + return null; + } + + @Override + public void updateLabel() { + + } + +} diff --git a/src/symjava/symbolic/Tan.java b/src/symjava/symbolic/Tan.java index 1db6d42..cab9597 100644 --- a/src/symjava/symbolic/Tan.java +++ b/src/symjava/symbolic/Tan.java @@ -1,5 +1,15 @@ package symjava.symbolic; +import java.util.Map; + +import com.sun.org.apache.bcel.internal.Constants; +import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.InstructionFactory; +import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.MethodGen; +import com.sun.org.apache.bcel.internal.generic.Type; + import symjava.symbolic.arity.UnaryOp; import symjava.symbolic.utils.Utils; @@ -7,12 +17,12 @@ public class Tan extends UnaryOp { public Tan(Expr arg) { super(arg); - label = "tan(" + arg + ")"; - sortKey = label; + updateLabel(); } @Override public Expr diff(Expr expr) { + //1 + tan^2(x) return arg.diff(expr).multiply(new Pow(this, Expr.valueOf(2)).add(1)); } @@ -24,7 +34,17 @@ public static Expr simplifiedIns(Expr expr) { public Expr simplify() { return this; } - + + @Override + public Expr subs(Expr from, Expr to) { + if(Utils.symCompare(this, from)) + return to; + Expr sl = arg.subs(from, to); + if(sl == arg) + return this; + return new Tan(sl); + } + @Override public boolean symEquals(Expr other) { if(other instanceof Tan) { @@ -32,4 +52,24 @@ public boolean symEquals(Expr other) { } return false; } + + @Override + public InstructionHandle bytecodeGen(String clsName, MethodGen mg, + ConstantPoolGen cp, InstructionFactory factory, + InstructionList il, Map argsMap, int argsStartPos, + Map funcRefsMap) { + InstructionHandle startPos = arg.bytecodeGen(clsName, mg, cp, factory, il, argsMap, argsStartPos, funcRefsMap); + il.append(factory.createInvoke("java.lang.Math", "tan", + Type.DOUBLE, + new Type[] { Type.DOUBLE }, + Constants.INVOKESTATIC)); + return startPos; + } + + @Override + public void updateLabel() { + label = "tan(" + arg + ")"; + sortKey = label; + + } } diff --git a/src/symjava/symbolic/Tensor.java b/src/symjava/symbolic/Tensor.java new file mode 100644 index 0000000..e29556f --- /dev/null +++ b/src/symjava/symbolic/Tensor.java @@ -0,0 +1,10 @@ +package symjava.symbolic; + +public class Tensor extends Symbol { + + public Tensor(String name) { + super(name); + // TODO Auto-generated constructor stub + } + +} diff --git a/src/symjava/symbolic/TypeInfo.java b/src/symjava/symbolic/TypeInfo.java new file mode 100644 index 0000000..bf37648 --- /dev/null +++ b/src/symjava/symbolic/TypeInfo.java @@ -0,0 +1,32 @@ +package symjava.symbolic; + +import symjava.symbolic.Expr.TYPE; + +/** + * Provide type information of a symbol + * type: see enum TYPE + * dim: dimension of the type (for tensor, matrix and vector) + * + */ +public class TypeInfo { + public TYPE type; + public int[] dim; + + public static TypeInfo tiBoolean = new TypeInfo(TYPE.BOOLEAN); + public static TypeInfo tiByte = new TypeInfo(TYPE.BYTE); + public static TypeInfo tiChar = new TypeInfo(TYPE.CHAR); + public static TypeInfo tiShort = new TypeInfo(TYPE.SHORT); + public static TypeInfo tiInt = new TypeInfo(TYPE.INT); + public static TypeInfo tiLong = new TypeInfo(TYPE.LONG); + public static TypeInfo tiFloat = new TypeInfo(TYPE.FLOAT); + public static TypeInfo tiDouble = new TypeInfo(TYPE.DOUBLE); + + public TypeInfo(TYPE type) { + this.type = type; + dim = new int[0]; + } + public TypeInfo(TYPE type, int[] dim) { + this.type = type; + this.dim = dim; + } +} diff --git a/src/symjava/symbolic/Vector.java b/src/symjava/symbolic/Vector.java new file mode 100644 index 0000000..afca875 --- /dev/null +++ b/src/symjava/symbolic/Vector.java @@ -0,0 +1,126 @@ +package symjava.symbolic; + +import java.util.Map; + +import com.sun.org.apache.bcel.internal.Constants; +import com.sun.org.apache.bcel.internal.generic.ALOAD; +import com.sun.org.apache.bcel.internal.generic.ASTORE; +import com.sun.org.apache.bcel.internal.generic.ArrayType; +import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.InstructionConstants; +import com.sun.org.apache.bcel.internal.generic.InstructionFactory; +import com.sun.org.apache.bcel.internal.generic.InstructionHandle; +import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.LocalVariableGen; +import com.sun.org.apache.bcel.internal.generic.MethodGen; +import com.sun.org.apache.bcel.internal.generic.NEW; +import com.sun.org.apache.bcel.internal.generic.ObjectType; +import com.sun.org.apache.bcel.internal.generic.PUSH; +import com.sun.org.apache.bcel.internal.generic.Type; + +import symjava.matrix.ExprVector; + +public class Vector extends Tensor { + public int nStart; + public int nDim; + public Vector parent; + protected int indexLVT = -1; + + public Vector(String name, int nDim) { + super(name); + this.nStart = 0; + this.nDim = nDim; + } + + public Vector(Vector parent, int nStart, int nDim) { + super(parent.label+"_"+nStart+"_"+nDim); + this.nStart = nStart; + this.nDim = nDim; + this.parent = parent; + } + + public Vector(Vector parent, String name, int nStart, int nDim) { + super(name); + this.nStart = nStart; + this.nDim = nDim; + this.parent = parent; + } + + public ExprVector split(int nBlock) { + int n = nDim/nBlock; + if(nDim%nBlock > 0) + n = (nDim+(nBlock-nDim%nBlock))/nBlock; + int last_n = nDim%n==0?n:nDim%n; + //System.out.println(n); + //System.out.println(last_n); + Expr[] items = new Expr[nBlock]; + for(int j=0; j argsMap, int argsStartPos, + Map funcRefsMap) { + if(indexLVT == -1) { + //jama.Matrix l_m = null; + LocalVariableGen lg = mg.addLocalVariable("l_"+getLabel(), + new ObjectType("Jama.Matrix"), null, null); + indexLVT = lg.getIndex(); +// il.append(InstructionConstants.ACONST_NULL); +// lg.setStart(il.append(new DSTORE(idx))); + + // First time touch the matrix, declare a local reference of Java.Matrix + il.append(new NEW(cp.addClass("Jama.Matrix"))); + il.append(InstructionConstants.DUP); + + //prepare argument: double[] vals + il.append(new ALOAD(argsStartPos)); + il.append(new PUSH(cp, argsMap.get(this.label))); + il.append(InstructionConstants.AALOAD); //Load double from array + + //prepare argument: double m - number of rows + il.append(new PUSH(cp, nDim)); + il.append(factory.createInvoke("Jama.Matrix", "", + Type.VOID, new Type[] { new ArrayType(Type.DOUBLE, 1), Type.INT }, + Constants.INVOKESPECIAL)); + + //jama.Matrix l_m = new jama.Matrix(args[], nRow); + lg.setStart(il.append(new ASTORE(indexLVT))); + } + return il.append(new ALOAD(indexLVT)); + //il.append(new ALOAD(indexLVT)); + //il.append(new PUSH(cp, 1.0)); + //return il.append(InstructionConstants.DRETURN); + } + + @Override + public TypeInfo getTypeInfo() { + TypeInfo ti = new TypeInfo(TYPE.VECTOR, new int[1]); + ti.dim[0] = nDim; + return ti; + } + + public void bytecodeGenReset() { + this.indexLVT = -1; + } + + @Override + public Expr getParent() { + return this.parent; + } + + public int dim() { + return this.nDim; + } + + public static void main(String[] args) { + Vector v = new Vector("A",8); + ExprVector sv = v.split(3); + System.out.println(sv); + } +} diff --git a/src/symjava/symbolic/arity/BinaryOp.java b/src/symjava/symbolic/arity/BinaryOp.java index 429c3dd..c0eb05a 100644 --- a/src/symjava/symbolic/arity/BinaryOp.java +++ b/src/symjava/symbolic/arity/BinaryOp.java @@ -1,6 +1,8 @@ package symjava.symbolic.arity; import symjava.symbolic.Expr; +import symjava.symbolic.TypeInfo; +import symjava.symbolic.utils.Utils; public abstract class BinaryOp extends Expr { public Expr arg1; @@ -26,5 +28,19 @@ public Expr lhs() { public Expr rhs() { return arg2; - } + } + + @Override + public TypeInfo getTypeInfo() { + //TODO make it support matrix, vector and tensor? + TYPE ty = Utils.getConvertedType(arg1.getType(), arg2.getType()); + return new TypeInfo(ty); + } + + public Expr setArg(int index, Expr arg) { + if(index == 0) arg1 = arg; + else if(index == 1) arg2 = arg; + updateLabel(); + return this; + } } diff --git a/src/symjava/symbolic/arity/NaryOp.java b/src/symjava/symbolic/arity/NaryOp.java index cbeb28b..f4624a6 100644 --- a/src/symjava/symbolic/arity/NaryOp.java +++ b/src/symjava/symbolic/arity/NaryOp.java @@ -13,4 +13,10 @@ public NaryOp(Expr[] args) { public Expr[] args() { return args; } + + public Expr setArg(int index, Expr arg) { + args[index] = arg; + updateLabel(); + return this; + } } diff --git a/src/symjava/symbolic/arity/TernaryOp.java b/src/symjava/symbolic/arity/TernaryOp.java index 088ddae..e9bf7a1 100644 --- a/src/symjava/symbolic/arity/TernaryOp.java +++ b/src/symjava/symbolic/arity/TernaryOp.java @@ -22,4 +22,11 @@ public TernaryOp(Expr arg1, Expr arg2, Expr arg3) { public Expr[] args() { return new Expr[] { arg1, arg2, arg3 }; } + public Expr setArg(int index, Expr arg) { + if(index == 0) arg1 = arg; + else if(index == 1) arg2 = arg; + else if(index == 2) arg3 = arg; + updateLabel(); + return this; + } } diff --git a/src/symjava/symbolic/arity/UnaryOp.java b/src/symjava/symbolic/arity/UnaryOp.java index 8f48983..009ffd0 100644 --- a/src/symjava/symbolic/arity/UnaryOp.java +++ b/src/symjava/symbolic/arity/UnaryOp.java @@ -1,6 +1,7 @@ package symjava.symbolic.arity; import symjava.symbolic.Expr; +import symjava.symbolic.TypeInfo; public abstract class UnaryOp extends Expr { public Expr arg; @@ -16,4 +17,16 @@ public UnaryOp(Expr arg) { public Expr[] args() { return new Expr[] { arg }; } + + @Override + public TypeInfo getTypeInfo() { + return arg.getTypeInfo(); + } + + public Expr setArg(int index, Expr arg) { + this.arg = arg; + updateLabel(); + return this; + } + } diff --git a/src/symjava/symbolic/utils/BytecodeOpSupport.java b/src/symjava/symbolic/utils/BytecodeOpSupport.java new file mode 100644 index 0000000..83cdac9 --- /dev/null +++ b/src/symjava/symbolic/utils/BytecodeOpSupport.java @@ -0,0 +1,95 @@ +package symjava.symbolic.utils; + +import Jama.Matrix; + +public class BytecodeOpSupport { + public static Jama.Matrix concat(Jama.Matrix[] args) { + int len = 0; + for(int i=0; i outList) { Expr[] args = e.args(); for(int i=0; i argsMap = new HashMap(); @@ -258,12 +285,12 @@ public static ClassGen genClassBytecodeFunc(Func fun, boolean writeClassFile, bo return cg; } - public static ClassGen genClassBytecodeVecFunc(String className, List exprs, List outPos, Expr[] args, + public static ClassGen genClassBytecodeBatchFunc(String className, List exprs, List outPos, Expr[] args, boolean writeClassFile, boolean staticMethod) { String packageName = "symjava.bytecode"; String fullClsName = packageName+"."+className; ClassGen cg = new ClassGen(fullClsName, "java.lang.Object", - "", ACC_PUBLIC | ACC_SUPER, new String[]{"symjava.bytecode.BytecodeVecFunc"}); + "", ACC_PUBLIC | ACC_SUPER, new String[]{"symjava.bytecode.BytecodeBatchFunc"}); ConstantPoolGen cp = cg.getConstantPool(); // cg creates constant pool InstructionList il = new InstructionList(); InstructionFactory factory = new InstructionFactory(cg); @@ -295,10 +322,12 @@ public static ClassGen genClassBytecodeVecFunc(String className, List expr // il.append(new PUSH(cp, exprs.length)); // il.append(new NEWARRAY(Type.DOUBLE)); // il.append(new ASTORE(retArray)); + System.out.println("JIT compiling: class="+fullClsName); for(int i=0; i", ACC_PUBLIC | ACC_SUPER, new String[]{"symjava.bytecode.BytecodeBatchFunc"}); + "", ACC_PUBLIC | ACC_SUPER, new String[]{"symjava.bytecode.BytecodeVecFunc"}); ConstantPoolGen cp = cg.getConstantPool(); // cg creates constant pool InstructionList il = new InstructionList(); InstructionFactory factory = new InstructionFactory(cg); @@ -385,7 +417,10 @@ public static ClassGen genClassBytecodeBatchFunc(String className, Expr expr, Ex //Loop body: InstructionHandle loopStart = il.append(new ALOAD(1)); - il.append(new ILOAD(idxI)); //outAry[i] + //outAry[i+outPos] + il.append(new ILOAD(idxI)); + il.append(new ILOAD(2)); + il.append(InstructionConstants.IADD); //Traverse the expression tree List insList = new ArrayList(); @@ -538,6 +573,9 @@ public static void addOthers(MethodGen mg, ConstantPoolGen cp, InstructionFactor il.append(factory.createInvoke("symjava.symbolic.utils.BytecodeSupport", "log", Type.DOUBLE, new Type[] { Type.DOUBLE, Type.DOUBLE }, Constants.INVOKESTATIC)); // } + } else if(ins instanceof SymRandom) { + il.append(factory.createInvoke("java.lang.Math", "random", + Type.DOUBLE, new Type[] { }, Constants.INVOKESTATIC)); } else if(ins instanceof Reciprocal) { il.append(new DDIV()); } else if(ins instanceof Negate) { @@ -751,7 +789,7 @@ public static void addToInstructionList(MethodGen mg, ConstantPoolGen cp, Instru List insList = new ArrayList(); post_order(expr, insList); if(insList.size() == 0) { - throw new RuntimeException("Expressionis empty. Nothing to generate!"); + throw new RuntimeException("Expression is empty. Nothing to generate!"); } for(int insIndex=0; insIndex extends ClassLoader { + public FuncClassLoader() { + //super(Thread.currentThread().getContextClassLoader()); + //https://blogs.oracle.com/sundararajan/understanding-java-class-loading + //super(java.lang.ClassLoader.getSystemClassLoader()); + super(BytecodeFunc.class.getClassLoader()); + } +// +// public FuncClassLoader(ClassLoader parent) { +// super(parent); +// } + /** * Return an instance from a ClassGen object * diff --git a/src/symjava/symbolic/utils/JIT.java b/src/symjava/symbolic/utils/JIT.java index 870b55e..d3340b1 100644 --- a/src/symjava/symbolic/utils/JIT.java +++ b/src/symjava/symbolic/utils/JIT.java @@ -3,20 +3,23 @@ import java.util.ArrayList; import java.util.List; +import lambdacloud.core.CloudFunc.FUNC_TYPE; + import com.sun.org.apache.bcel.internal.generic.ClassGen; -import symjava.bytecode.BytecodeBatchFunc; -import symjava.bytecode.BytecodeFunc; import symjava.bytecode.BytecodeVecFunc; +import symjava.bytecode.BytecodeFunc; +import symjava.bytecode.BytecodeBatchFunc; +import symjava.bytecode.IR; import symjava.bytecode.VecFuncs; +import symjava.matrix.ExprMatrix; +import symjava.numeric.NumMatrix; import symjava.symbolic.Expr; import symjava.symbolic.Func; import symjava.symbolic.Symbol; public class JIT { - private JIT() {} - public static BytecodeFunc compile(Expr[] args, Expr expr) { if(expr instanceof Func) { Func func = (Func)expr; @@ -34,16 +37,20 @@ public static BytecodeFunc compile(Expr expr) { return func.toBytecodeFunc(); } else { Func func = new Func("JITFunc_"+java.util.UUID.randomUUID().toString().replaceAll("-", ""), expr); - return func.toBytecodeFunc(true, false); + return func.toBytecodeFunc(false, false); } } - public static BytecodeVecFunc compile(Expr[] args, Expr[] exprs) { + public static NumMatrix compile(Expr[] args, ExprMatrix m) { + return new NumMatrix(m, args); + } + + public static BytecodeBatchFunc compileBatchFunc(Expr[] args, Expr[] exprs) { boolean isWriteFile = true; boolean staticMethod = false; try { int NMaxExpr = 36; - FuncClassLoader fcl = new FuncClassLoader(); + FuncClassLoader fcl = new FuncClassLoader(); List nonZeroList = new ArrayList(); List nonZeroIdx = new ArrayList(); for(int i=0; i 0) { String className = "JITVecFunc_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX__"+(N-remain)+"___outof___"+exprs.length+"___XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"+java.util.UUID.randomUUID().toString().replaceAll("-", ""); - ClassGen genClass = BytecodeUtils.genClassBytecodeVecFunc(className, batchExprs, batchOutPos, args, + ClassGen genClass = BytecodeUtils.genClassBytecodeBatchFunc(className, batchExprs, batchOutPos, args, isWriteFile, staticMethod); - BytecodeVecFunc func = fcl.newInstance(genClass); + BytecodeBatchFunc func = fcl.newInstance(genClass); ret.addFunc(func, batchOutPos.get(0)); } return ret; } else { String className = "JITVecFunc_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX__"+exprs.length+"___XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"+java.util.UUID.randomUUID().toString().replaceAll("-", ""); - ClassGen genClass = BytecodeUtils.genClassBytecodeVecFunc(className, nonZeroList, nonZeroIdx, args, + ClassGen genClass = BytecodeUtils.genClassBytecodeBatchFunc(className, nonZeroList, nonZeroIdx, args, isWriteFile, staticMethod); return fcl.newInstance(genClass); } @@ -91,13 +98,25 @@ public static BytecodeVecFunc compile(Expr[] args, Expr[] exprs) { return null; } - public static BytecodeBatchFunc compileBatchFunc(Expr[] args, Expr expr) { + public static BytecodeVecFunc compileVecFunc(Expr[] args, Expr expr) { String className = "JITVecFunc_YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY"+java.util.UUID.randomUUID().toString().replaceAll("-", ""); - ClassGen genClass = BytecodeUtils.genClassBytecodeBatchFunc(className,expr, args, true, false); - FuncClassLoader fcl = new FuncClassLoader(); + ClassGen genClass = BytecodeUtils.genClassBytecodeVecFunc(className,expr, args, true, false); + FuncClassLoader fcl = new FuncClassLoader(); return fcl.newInstance(genClass); } + public static IR getIR(String name, Expr[] args, Expr expr) { + String className = name; + Func func = new Func(className, expr, args); + ClassGen genClass = BytecodeUtils.genClassBytecodeFunc(func, false, false); + IR ir = new IR(); + ir.type = FUNC_TYPE.SCALAR; + ir.name = genClass.getJavaClass().getClassName(); + ir.bytes = genClass.getJavaClass().getBytes(); + return ir; + + } + public static void main(String[] args) { // Expr[] exprs = new Expr[3]; // exprs[0] = Symbol.x; @@ -109,8 +128,8 @@ public static void main(String[] args) { // for(double d : outAry) // System.out.println(d); - Expr expr = Symbol.x + Symbol.y; - BytecodeBatchFunc vecFunc = compileBatchFunc(new Expr[]{Symbol.x, Symbol.y}, expr); + Expr expr = Symbol.x.add(Symbol.y); + BytecodeVecFunc vecFunc = JIT.compileVecFunc(new Expr[]{Symbol.x, Symbol.y}, expr); double[] outAry = new double[3]; double[][] params = { {1.0, 2.0, 3.0}, diff --git a/src/symjava/symbolic/utils/Utils.java b/src/symjava/symbolic/utils/Utils.java index 65e5ce1..a1cb667 100644 --- a/src/symjava/symbolic/utils/Utils.java +++ b/src/symjava/symbolic/utils/Utils.java @@ -8,9 +8,11 @@ import java.util.List; import java.util.Set; +import lambdacloud.core.CloudSD; import symjava.symbolic.Add; import symjava.symbolic.Divide; import symjava.symbolic.Expr; +import symjava.symbolic.Expr.TYPE; import symjava.symbolic.Func; import symjava.symbolic.Multiply; import symjava.symbolic.Negate; @@ -18,6 +20,7 @@ import symjava.symbolic.Subtract; import symjava.symbolic.Symbol; import symjava.symbolic.Symbols; +import symjava.symbolic.Tensor; public class Utils { @@ -55,7 +58,7 @@ public int compare(Expr o1, Expr o2) { }); return exprs; } - + public static List sortExprs(List list) { Collections.sort(list, new Comparator() { @Override @@ -150,10 +153,18 @@ public static List removeNegate(List list) { } public static Expr flattenSortAndSimplify(Expr expr) { +// //Don't simplify the expr if it is on a device +// if(expr.getDevice() != null) +// return expr; List addList = flattenAddAndSort(expr); List rlt = new ArrayList(); for(int i=0; i mulList = flattenMultiplyAndSort(e); if(mulList.size() == 1) rlt.addAll(mulList); @@ -294,13 +305,19 @@ public static Expr multiplyListToExpr(List list) { } } +// public static void extractSymbols(Expr expr, Set set) { +// for(Expr e : expr.args()) +// extractSymbols(e, set); +// set.add(expr); +// } + public static List extractSymbols(Expr ...exprs) { Set set = new HashSet(); List list = new ArrayList(); for(int i=0; i extractSymbols(Expr ...exprs) { return rlt; } + public static List extractCloudSDs(Expr ...exprs) { + Set set = new HashSet(); + List list = new ArrayList(); + for(int i=0; i rlt = new ArrayList(); + rlt.addAll(set); + sortExprs(rlt); + List rlt2 = new ArrayList(); + for(Expr e : rlt) { + rlt2.add((CloudSD)e); + } + return rlt2; + } + + public static double[][] getDataFromCloudSDs(CloudSD[] cloudSDs) { + double[][] rlt = new double[cloudSDs.length][]; + for(int i=0; i list = new ArrayList(); BytecodeUtils.post_order(expr, list); @@ -351,6 +398,22 @@ public static String joinLabels(Expr[] list, String deliminator) { sb.delete(sb.length()-deliminator.length(), sb.length()); return sb.toString(); } + + public static String joinLabels(String[] list, int startIdx, int endIdx, String deliminator) { + StringBuilder sb = new StringBuilder(); + if(list == null) return null; + for(int i=startIdx; i deliminator.length()) + sb.delete(sb.length()-deliminator.length(), sb.length()); + return sb.toString(); + } + + public static String joinLabels(String[] list, String deliminator) { + return joinLabels(list, 0, list.length, deliminator); + } public static String joinLabels(List list, String deliminator) { return joinLabels(list.toArray(new Expr[0]), deliminator); @@ -371,4 +434,24 @@ public static Expr[] joinArrays(Expr[] ...arys) { return rlt; } + public static TYPE getConvertedType(TYPE t1, TYPE t2) { + if(t1 == t2) return t1; + if(t1 == TYPE.BOOLEAN || t2 == TYPE.BOOLEAN) { + if(t1 != TYPE.BOOLEAN || t2 != TYPE.BOOLEAN) + throw new RuntimeException(); + } + if(t1 == TYPE.VOID || t2 == TYPE.VOID) { + if(t1 != TYPE.VOID || t2 != TYPE.VOID) + throw new RuntimeException(); + } + if(t1 == TYPE.DOUBLE || t2 == TYPE.DOUBLE) return TYPE.DOUBLE; + if(t1 == TYPE.FLOAT || t2 == TYPE.FLOAT) return TYPE.FLOAT; + if(t1 == TYPE.LONG || t2 == TYPE.LONG) return TYPE.LONG; + if(t1 == TYPE.INT || t2 == TYPE.INT) return TYPE.INT; + if(t1 == TYPE.SHORT || t2 == TYPE.SHORT) return TYPE.SHORT; + if(t1 == TYPE.CHAR || t2 == TYPE.CHAR) return TYPE.CHAR; + if(t1 != TYPE.BOOLEAN && t2 != TYPE.BYTE) + throw new RuntimeException(); + return t1; //TYPE.BYTE + } } diff --git a/src/symjava/test/TestSymbolic.java b/src/symjava/test/TestSymbolic.java index 5323b32..8187999 100644 --- a/src/symjava/test/TestSymbolic.java +++ b/src/symjava/test/TestSymbolic.java @@ -1,10 +1,23 @@ package symjava.test; -import static symjava.symbolic.Symbol.*; -import static symjava.math.SymMath.*; - -import java.math.BigInteger; - +import static symjava.math.SymMath.PI2; +import static symjava.math.SymMath.cos; +import static symjava.math.SymMath.exp; +import static symjava.math.SymMath.log; +import static symjava.math.SymMath.log10; +import static symjava.math.SymMath.log2; +import static symjava.math.SymMath.pow; +import static symjava.math.SymMath.sin; +import static symjava.math.SymMath.sqrt; +import static symjava.math.SymMath.tan; +import static symjava.symbolic.Symbol.e; +import static symjava.symbolic.Symbol.oo; +import static symjava.symbolic.Symbol.r; +import static symjava.symbolic.Symbol.s; +import static symjava.symbolic.Symbol.t; +import static symjava.symbolic.Symbol.x; +import static symjava.symbolic.Symbol.y; +import static symjava.symbolic.Symbol.z; import symjava.bytecode.BytecodeFunc; import symjava.domains.Domain; import symjava.domains.Domain2D; @@ -12,15 +25,26 @@ import symjava.math.Div; import symjava.math.Dot; import symjava.math.Grad; -import symjava.matrix.SymVector; +import symjava.matrix.ExprVector; import symjava.numeric.NumVector; -import symjava.relational.Eq; import symjava.relational.Ge; import symjava.relational.Gt; import symjava.relational.Le; import symjava.relational.Lt; import symjava.relational.Neq; -import symjava.symbolic.*; +import symjava.symbolic.Expr; +import symjava.symbolic.Func; +import symjava.symbolic.Integrate; +import symjava.symbolic.Reciprocal; +import symjava.symbolic.Sum; +import symjava.symbolic.SymDouble; +import symjava.symbolic.SymFloat; +import symjava.symbolic.SymInteger; +import symjava.symbolic.SymLong; +import symjava.symbolic.SymRandom; +import symjava.symbolic.SymReal; +import symjava.symbolic.Symbol; +import symjava.symbolic.Symbols; import symjava.symbolic.utils.JIT; @@ -308,7 +332,7 @@ public static void testAbstract() { checkResult("\\nabla{w(x,y,x)} \\cdot \\nabla{v(x,y,z)}", new Dot(gu, gv).fdiff(u,w)); Func f = new Func("F"); - SymVector grad = Grad.apply(f); + ExprVector grad = Grad.apply(f); Div div = new Div(grad); //checkResult("\\nabla \\cdot \\nabla{F}", div); checkResult("div(\\nabla{F})", div); @@ -442,7 +466,7 @@ public static void testLogic() { } public static void testJITVectorized() { - SymVector v = new SymVector(); + ExprVector v = new ExprVector(); for(int i=0; i<101; i++) v[i] = x*x + 1; NumVector nv = v.toNumVector(new Expr[]{x}); @@ -453,6 +477,30 @@ public static void testJITVectorized() { System.out.println(outAry[i]); } } + public static void testMatrixVector() { + + } + + public static void testSymRandom() { + BytecodeFunc f = JIT.compile(new SymRandom()); + System.out.println(f.apply()); + } + + + public static double eps = 1e-5; + public static void check(String info, double d1, double d2) { + if(Math.abs(d1-d2) < eps) { + System.out.println("pass"); + } else { + System.out.println("!!!FAIL!!! "+d1+"!="+d2+" "+info); + } + } + + public static void testMathematicalFunction() { + //TODO compile use bytecoeGen() + check(sqrt(x).toString(), JIT.compile(sqrt(x)).apply(0.1), Math.sqrt(0.1)); + } + public static void main(String[] args) { //eclipse不能编译的问题:cmd进到某个class目录后,该目录不允许删除, //导致eclipse不能删除该目录,所以不能编译 @@ -470,6 +518,8 @@ public static void main(String[] args) { // testLogic(); //set vm parameters: -XX:+PrintCompilation - testJITVectorized(); + //testJITVectorized(); + //testSymRandom(); + testMathematicalFunction(); } } diff --git a/src/symjava/test/TestValueOf.java b/src/symjava/test/TestValueOf.java new file mode 100644 index 0000000..45bf8a4 --- /dev/null +++ b/src/symjava/test/TestValueOf.java @@ -0,0 +1,32 @@ +package symjava.test; + +public class TestValueOf { + public static class Car { + public int id; + public Car(int id) { + this.id = id; + } + public Car add(Car c) { + return new Car(this.id+c.id); + } + } + public static class Jeep extends Car { + public Jeep(int id) { + super(id); + } + public static Jeep valueOf(Car c) { + return new Jeep(c.id); + } + } + public static void main(String[] args) { + Car c1 = new Car(1); + Car c2 = new Car(10); + Car c12 = c1 + c2; + //Jeep j = c12; //works + //Jeep j = Jeep.valueOf(c1 + c2); //works + Jeep j = c1 + c2; + System.out.println(j.id); + + } + +}