feat: use Math namespace for pow function in formulas
This commit is contained in:
parent
88f55a1e32
commit
80d6c7d0df
2 changed files with 40 additions and 40 deletions
|
|
@ -17,7 +17,7 @@ Where:
|
||||||
{"name": "g", "unit": "meters per second"} // Gravitational acceleration
|
{"name": "g", "unit": "meters per second"} // Gravitational acceleration
|
||||||
],
|
],
|
||||||
"output": {"name": "h", "unit": "meter"}, // Height in meters
|
"output": {"name": "h", "unit": "meter"}, // Height in meters
|
||||||
"d4rtCode": "h = 0.5 * g * pow(t, 2);",
|
"d4rtCode": "h = 0.5 * g * Math.pow(t, 2);",
|
||||||
"tags": ["physics", "kinematics"]
|
"tags": ["physics", "kinematics"]
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -41,7 +41,7 @@ Where:
|
||||||
{"name": "r", "unit": "meter"} // Distance between masses
|
{"name": "r", "unit": "meter"} // Distance between masses
|
||||||
],
|
],
|
||||||
"output": {"name": "F", "unit": "newton"}, // Force in newtons
|
"output": {"name": "F", "unit": "newton"}, // Force in newtons
|
||||||
"d4rtCode": "F = (6.67430e-11 * m1 * m2) / pow(r, 2);",
|
"d4rtCode": "F = (6.67430e-11 * m1 * m2) / Math.pow(r, 2);",
|
||||||
"tags": ["physics", "astronomy", "gravity"]
|
"tags": ["physics", "astronomy", "gravity"]
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -63,7 +63,7 @@ Where:
|
||||||
{"name": "v", "unit": "meters per second"} // Velocity
|
{"name": "v", "unit": "meters per second"} // Velocity
|
||||||
],
|
],
|
||||||
"output": {"name": "KE", "unit": "joule"}, // Energy in joules
|
"output": {"name": "KE", "unit": "joule"}, // Energy in joules
|
||||||
"d4rtCode": "KE = 0.5 * m * pow(v, 2);",
|
"d4rtCode": "KE = 0.5 * m * Math.pow(v, 2);",
|
||||||
"tags": ["physics", "energy", "mechanics"]
|
"tags": ["physics", "energy", "mechanics"]
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -82,7 +82,7 @@ Where:
|
||||||
{"name": "θ", "unit": "degree"} // Launch angle
|
{"name": "θ", "unit": "degree"} // Launch angle
|
||||||
],
|
],
|
||||||
"output": {"name": "R", "unit": "meter"}, // Horizontal distance
|
"output": {"name": "R", "unit": "meter"}, // Horizontal distance
|
||||||
"d4rtCode": "R = (pow(v, 2) * sin(2 * radians(θ))) / 9.80665;",
|
"d4rtCode": "R = (Math.pow(v, 2) * sin(2 * radians(θ))) / 9.80665;",
|
||||||
"tags": ["physics", "kinematics", "projectile"]
|
"tags": ["physics", "kinematics", "projectile"]
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,13 @@
|
||||||
|
import 'dart:math' as Math;
|
||||||
|
|
||||||
import 'package:d4rt/d4rt.dart';
|
import 'package:d4rt/d4rt.dart';
|
||||||
import 'formula_models.dart';
|
import 'formula_models.dart';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// Exception thrown when formula evaluation fails
|
/// Exception thrown when formula evaluation fails
|
||||||
class FormulaEvaluationException implements Exception {
|
class FormulaEvaluationException implements Exception {
|
||||||
final String message;
|
final String message;
|
||||||
|
|
@ -14,34 +20,39 @@ class FormulaEvaluationException implements Exception {
|
||||||
'${cause != null ? ' (caused by: $cause)' : ''}';
|
'${cause != null ? ' (caused by: $cause)' : ''}';
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Evaluates formulas using the d4rt interpreter
|
class MyMath{
|
||||||
|
static Number log(Number x) => Math.log(x);
|
||||||
|
static Number pow(Number b, Number e) => Math.pow(b,e) as Number;
|
||||||
|
}
|
||||||
|
|
||||||
class FormulaEvaluator {
|
class FormulaEvaluator {
|
||||||
final D4rt _interpreter;
|
final D4rt _interpreter;
|
||||||
|
|
||||||
/// Creates a new formula evaluator with an optional d4rt interpreter instance.
|
FormulaEvaluator([D4rt? interpreter]) : _interpreter = interpreter ?? D4rt(){
|
||||||
/// If no interpreter is provided, a new one will be created.
|
prepareInterpreter(_interpreter);
|
||||||
FormulaEvaluator([D4rt? interpreter]) : _interpreter = interpreter ?? D4rt();
|
}
|
||||||
|
|
||||||
/// Evaluates a formula with the given input values.
|
Number getNumberValueOf(String s){
|
||||||
///
|
return double.parse(s);
|
||||||
/// The [formula] must have exactly one output variable (validated during construction).
|
}
|
||||||
/// The [inputValues] map must contain values for all input variables defined
|
|
||||||
/// in the formula.
|
void prepareInterpreter(D4rt interpreter){
|
||||||
///
|
final myMathDefinition = BridgedClass(
|
||||||
/// The formula's d4rt_code should define a main function that uses the input
|
nativeType: MyMath,
|
||||||
/// variable names directly. The evaluator will inject variable declarations
|
name: 'Math',
|
||||||
/// before the formula code. For example:
|
staticMethods: {
|
||||||
/// ```
|
'pow': (visitor, positionalArgs, namedArgs) {
|
||||||
/// main() {
|
final Number base = getNumberValueOf( positionalArgs[0].toString() );
|
||||||
/// return m * a; // Returns Force = mass * acceleration
|
final Number exp = getNumberValueOf( positionalArgs[1].toString() );
|
||||||
/// }
|
return MyMath.pow(base,exp);
|
||||||
/// ```
|
},
|
||||||
///
|
}
|
||||||
/// Returns the computed value of the single output variable.
|
);
|
||||||
///
|
|
||||||
/// Throws [FormulaEvaluationException] if:
|
interpreter.registerBridgedClass(myMathDefinition, 'package:myapp/my_math.dart');
|
||||||
/// - Required input variables are missing
|
}
|
||||||
/// - The d4rt code execution fails
|
|
||||||
|
|
||||||
dynamic evaluate(Formula formula, Map<String, dynamic> inputValues) {
|
dynamic evaluate(Formula formula, Map<String, dynamic> inputValues) {
|
||||||
_validateInputValues(formula, inputValues);
|
_validateInputValues(formula, inputValues);
|
||||||
|
|
||||||
|
|
@ -61,7 +72,6 @@ class FormulaEvaluator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Validates that all required input variables are provided
|
|
||||||
void _validateInputValues(Formula formula, Map<String, dynamic> inputValues) {
|
void _validateInputValues(Formula formula, Map<String, dynamic> inputValues) {
|
||||||
final missingVars = <String>[];
|
final missingVars = <String>[];
|
||||||
|
|
||||||
|
|
@ -79,47 +89,37 @@ class FormulaEvaluator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the name of the single output variable from the formula
|
|
||||||
String getOutputVariableName(Formula formula) {
|
String getOutputVariableName(Formula formula) {
|
||||||
return formula.output.name;
|
return formula.output.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the magnitude of the single output variable from the formula
|
|
||||||
String getOutputVariableMagnitude(Formula formula) {
|
String getOutputVariableMagnitude(Formula formula) {
|
||||||
// Formula construction already ensures exactly one output variable
|
|
||||||
return formula.output.unit;
|
return formula.output.unit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the ordered list of input variable names (alphabetically sorted)
|
|
||||||
List<String> getInputVariableOrder(Formula formula) {
|
List<String> getInputVariableOrder(Formula formula) {
|
||||||
return formula.inputVarNames()..sort();
|
return formula.inputVarNames()..sort();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds the complete d4rt source code by injecting variable declarations
|
|
||||||
/// before the formula's d4rt code
|
|
||||||
String _buildCompleteSource(Formula formula, Map<String, dynamic> inputValues) {
|
String _buildCompleteSource(Formula formula, Map<String, dynamic> inputValues) {
|
||||||
final buffer = StringBuffer();
|
final buffer = StringBuffer();
|
||||||
|
|
||||||
|
buffer.writeln("import 'package:myapp/my_math.dart';");
|
||||||
buffer.writeln("main(){");
|
buffer.writeln("main(){");
|
||||||
|
|
||||||
// Add variable declarations for all input variables
|
|
||||||
for (final entry in inputValues.entries) {
|
for (final entry in inputValues.entries) {
|
||||||
final varName = entry.key;
|
final varName = entry.key;
|
||||||
final value = entry.value;
|
final value = entry.value;
|
||||||
|
|
||||||
// Handle different value types appropriately for d4rt
|
|
||||||
if (value is String) {
|
if (value is String) {
|
||||||
// Escape quotes in string values
|
|
||||||
final escapedValue = value.replaceAll('"', '\\"');
|
final escapedValue = value.replaceAll('"', '\\"');
|
||||||
buffer.writeln('var $varName = "$escapedValue";');
|
buffer.writeln('var $varName = "$escapedValue";');
|
||||||
} else {
|
} else {
|
||||||
// For numbers and other types, use direct representation
|
|
||||||
buffer.writeln('var $varName = $value;');
|
buffer.writeln('var $varName = $value;');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buffer.writeln("late var ${getOutputVariableName(formula)};");
|
buffer.writeln("late var ${getOutputVariableName(formula)};");
|
||||||
|
|
||||||
// Add the formula's d4rt code
|
|
||||||
buffer.writeln(formula.d4rtCode);
|
buffer.writeln(formula.d4rtCode);
|
||||||
buffer.writeln("return ${getOutputVariableName(formula)};");
|
buffer.writeln("return ${getOutputVariableName(formula)};");
|
||||||
buffer.writeln("}");
|
buffer.writeln("}");
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue