Skip to content

Commit 745a7ad

Browse files
committed
Add complete constant folding in kmath-ast by introducing TypedMst, some minor changes
1 parent ef747f6 commit 745a7ad

File tree

16 files changed

+611
-301
lines changed

16 files changed

+611
-301
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,12 @@ One can still use generic algebras though.
247247
> **Maturity**: PROTOTYPE
248248
<hr/>
249249
250+
* ### [kmath-tensorflow](kmath-tensorflow)
251+
>
252+
>
253+
> **Maturity**: PROTOTYPE
254+
<hr/>
255+
250256
* ### [kmath-tensors](kmath-tensors)
251257
>
252258
>

kmath-ast/README.md

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Module kmath-ast
22

3-
Performance and visualization extensions to MST API.
3+
Extensions to MST API: transformations, dynamic compilation and visualization.
44

55
- [expression-language](src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser
66
- [mst-jvm-codegen](src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt) : Dynamic MST to JVM bytecode compiler
@@ -35,55 +35,68 @@ dependencies {
3535
}
3636
```
3737

38+
## Parsing expressions
39+
40+
In this module there is a parser from human-readable strings like `"x^3-x+3"` (in the more specific [grammar](reference/ArithmeticsEvaluator.g4)) to MST instances.
41+
42+
Supported literals:
43+
1. Constants and variables (consist of latin letters, digits and underscores, can't start with digit): `x`, `_Abc2`.
44+
2. Numbers: `123`, `1.02`, `1e10`, `1e-10`, `1.0e+3`&mdash;all parsed either as `kotlin.Long` or `kotlin.Double`.
45+
46+
Supported binary operators (from the highest precedence to the lowest one):
47+
1. `^`
48+
2. `*`, `/`
49+
3. `+`, `-`
50+
51+
Supported unary operator:
52+
1. `-`, e.&nbsp;g. `-x`
53+
54+
Arbitrary unary and binary functions are also supported: names consist of latin letters, digits and underscores, can't start with digit. Examples:
55+
1. `sin(x)`
56+
2. `add(x, y)`
57+
3858
## Dynamic expression code generation
3959

4060
### On JVM
4161

4262
`kmath-ast` JVM module supports runtime code generation to eliminate overhead of tree traversal. Code generator builds a
4363
special implementation of `Expression<T>` with implemented `invoke` function.
4464

45-
For example, the following builder:
65+
For example, the following code:
4666

4767
```kotlin
48-
import space.kscience.kmath.expressions.Symbol.Companion.x
49-
import space.kscience.kmath.expressions.*
50-
import space.kscience.kmath.operations.*
51-
import space.kscience.kmath.asm.*
68+
import space.kscience.kmath.asm.compileToExpression
69+
import space.kscience.kmath.complex.ComplexField
5270

53-
MstField { x + 2 }.compileToExpression(DoubleField)
54-
```
71+
"x+2".parseMath().compileToExpression(ComplexField)
72+
```
5573

56-
... leads to generation of bytecode, which can be decompiled to the following Java class:
74+
&mldr; leads to generation of bytecode, which can be decompiled to the following Java class:
5775

5876
```java
59-
package space.kscience.kmath.asm.generated;
60-
6177
import java.util.Map;
62-
6378
import kotlin.jvm.functions.Function2;
6479
import space.kscience.kmath.asm.internal.MapIntrinsics;
80+
import space.kscience.kmath.complex.Complex;
6581
import space.kscience.kmath.expressions.Expression;
6682
import space.kscience.kmath.expressions.Symbol;
6783

68-
public final class AsmCompiledExpression_45045_0 implements Expression<Double> {
84+
public final class CompiledExpression_45045_0 implements Expression<Complex> {
6985
private final Object[] constants;
7086

71-
public final Double invoke(Map<Symbol, ? extends Double> arguments) {
72-
return (Double) ((Function2) this.constants[0]).invoke((Double) MapIntrinsics.getOrFail(arguments, "x"), 2);
73-
}
74-
75-
public AsmCompiledExpression_45045_0(Object[] constants) {
76-
this.constants = constants;
87+
public Complex invoke(Map<Symbol, ? extends Complex> arguments) {
88+
Complex var2 = (Complex)MapIntrinsics.getOrFail(arguments, "x");
89+
return (Complex)((Function2)this.constants[0]).invoke(var2, (Complex)this.constants[1]);
7790
}
7891
}
79-
8092
```
8193

82-
#### Known issues
94+
Setting JVM system property `space.kscience.kmath.ast.dump.generated.classes` to `1` makes the translator dump class files to program's working directory, so they can be reviewed manually.
95+
96+
#### Limitations
8397

84-
- The same classes may be generated and loaded twice, so it is recommended to cache compiled expressions to avoid class
85-
loading overhead.
86-
- This API is not supported by non-dynamic JVM implementations (like TeaVM and GraalVM) because of using class loaders.
98+
- The same classes may be generated and loaded twice, so it is recommended to cache compiled expressions to avoid class loading overhead.
99+
- This API is not supported by non-dynamic JVM implementations like TeaVM or GraalVM Native Image because they may not support class loaders.
87100

88101
### On JS
89102

@@ -129,7 +142,7 @@ An example of emitted Wasm IR in the form of WAT:
129142
)
130143
```
131144

132-
#### Known issues
145+
#### Limitations
133146

134147
- ESTree expression compilation uses `eval` which can be unavailable in several environments.
135148
- WebAssembly isn't supported by old versions of browsers (see https://webassembly.org/roadmap/).

kmath-ast/docs/README-TEMPLATE.md

Lines changed: 65 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,98 @@
11
# Module kmath-ast
22

3-
Performance and visualization extensions to MST API.
3+
Extensions to MST API: transformations, dynamic compilation and visualization.
44

55
${features}
66

77
${artifact}
88

9+
## Parsing expressions
10+
11+
In this module there is a parser from human-readable strings like `"x^3-x+3"` (in the more specific [grammar](reference/ArithmeticsEvaluator.g4)) to MST instances.
12+
13+
Supported literals:
14+
1. Constants and variables (consist of latin letters, digits and underscores, can't start with digit): `x`, `_Abc2`.
15+
2. Numbers: `123`, `1.02`, `1e10`, `1e-10`, `1.0e+3`&mdash;all parsed either as `kotlin.Long` or `kotlin.Double`.
16+
17+
Supported binary operators (from the highest precedence to the lowest one):
18+
1. `^`
19+
2. `*`, `/`
20+
3. `+`, `-`
21+
22+
Supported unary operator:
23+
1. `-`, e.&nbsp;g. `-x`
24+
25+
Arbitrary unary and binary functions are also supported: names consist of latin letters, digits and underscores, can't start with digit. Examples:
26+
1. `sin(x)`
27+
2. `add(x, y)`
28+
929
## Dynamic expression code generation
1030

1131
### On JVM
1232

1333
`kmath-ast` JVM module supports runtime code generation to eliminate overhead of tree traversal. Code generator builds a
1434
special implementation of `Expression<T>` with implemented `invoke` function.
1535

16-
For example, the following builder:
36+
For example, the following code:
1737

1838
```kotlin
19-
import space.kscience.kmath.expressions.Symbol.Companion.x
20-
import space.kscience.kmath.expressions.*
21-
import space.kscience.kmath.operations.*
22-
import space.kscience.kmath.asm.*
39+
import space.kscience.kmath.asm.compileToExpression
40+
import space.kscience.kmath.operations.DoubleField
2341

24-
MstField { x + 2 }.compileToExpression(DoubleField)
25-
```
42+
"x^3-x+3".parseMath().compileToExpression(DoubleField)
43+
```
2644

27-
... leads to generation of bytecode, which can be decompiled to the following Java class:
45+
&mldr; leads to generation of bytecode, which can be decompiled to the following Java class:
2846

2947
```java
30-
package space.kscience.kmath.asm.generated;
48+
import java.util.*;
49+
import kotlin.jvm.functions.*;
50+
import space.kscience.kmath.asm.internal.*;
51+
import space.kscience.kmath.complex.*;
52+
import space.kscience.kmath.expressions.*;
53+
54+
public final class CompiledExpression_45045_0 implements Expression<Complex> {
55+
private final Object[] constants;
3156

32-
import java.util.Map;
57+
public Complex invoke(Map<Symbol, ? extends Complex> arguments) {
58+
Complex var2 = (Complex)MapIntrinsics.getOrFail(arguments, "x");
59+
return (Complex)((Function2)this.constants[0]).invoke(var2, (Complex)this.constants[1]);
60+
}
61+
}
62+
```
3363

34-
import kotlin.jvm.functions.Function2;
35-
import space.kscience.kmath.asm.internal.MapIntrinsics;
36-
import space.kscience.kmath.expressions.Expression;
37-
import space.kscience.kmath.expressions.Symbol;
64+
For `LongRing`, `IntRing`, and `DoubleField` specialization is supported for better performance:
3865

39-
public final class AsmCompiledExpression_45045_0 implements Expression<Double> {
40-
private final Object[] constants;
66+
```java
67+
import java.util.*;
68+
import space.kscience.kmath.asm.internal.*;
69+
import space.kscience.kmath.expressions.*;
4170

42-
public final Double invoke(Map<Symbol, ? extends Double> arguments) {
43-
return (Double) ((Function2) this.constants[0]).invoke((Double) MapIntrinsics.getOrFail(arguments, "x"), 2);
71+
public final class CompiledExpression_-386104628_0 implements DoubleExpression {
72+
private final SymbolIndexer indexer;
73+
74+
public SymbolIndexer getIndexer() {
75+
return this.indexer;
4476
}
4577

46-
public AsmCompiledExpression_45045_0(Object[] constants) {
47-
this.constants = constants;
78+
public double invoke(double[] arguments) {
79+
double var2 = arguments[0];
80+
return Math.pow(var2, 3.0D) - var2 + 3.0D;
4881
}
49-
}
5082

83+
public final Double invoke(Map<Symbol, ? extends Double> arguments) {
84+
double var2 = ((Double)MapIntrinsics.getOrFail(arguments, "x")).doubleValue();
85+
return Math.pow(var2, 3.0D) - var2 + 3.0D;
86+
}
87+
}
5188
```
5289

53-
#### Known issues
90+
Setting JVM system property `space.kscience.kmath.ast.dump.generated.classes` to `1` makes the translator dump class files to program's working directory, so they can be reviewed manually.
91+
92+
#### Limitations
5493

55-
- The same classes may be generated and loaded twice, so it is recommended to cache compiled expressions to avoid class
56-
loading overhead.
57-
- This API is not supported by non-dynamic JVM implementations (like TeaVM and GraalVM) because of using class loaders.
94+
- The same classes may be generated and loaded twice, so it is recommended to cache compiled expressions to avoid class loading overhead.
95+
- This API is not supported by non-dynamic JVM implementations like TeaVM or GraalVM Native Image because they may not support class loaders.
5896

5997
### On JS
6098

@@ -100,7 +138,7 @@ An example of emitted Wasm IR in the form of WAT:
100138
)
101139
```
102140

103-
#### Known issues
141+
#### Limitations
104142

105143
- ESTree expression compilation uses `eval` which can be unavailable in several environments.
106144
- WebAssembly isn't supported by old versions of browsers (see https://webassembly.org/roadmap/).

0 commit comments

Comments
 (0)