Merge feature/formula-evaluation into master
Adds comprehensive formula evaluation capabilities using d4rt interpreter: - FormulaEvaluator class for executing mathematical formulas - Variable injection mechanism for d4rt compatibility - Single output variable constraint with validation - Comprehensive test suite with 15 test cases - Working examples demonstrating physics and financial calculations - Proper error handling for missing variables and invalid formulas This enables the execution of user-defined mathematical formulas with type-safe input validation and d4rt-based computation.
This commit is contained in:
commit
eb38cfcb0e
5 changed files with 639 additions and 1 deletions
190
example/formula_evaluation_example.dart
Normal file
190
example/formula_evaluation_example.dart
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
/// Example demonstrating formula evaluation using the d4rt interpreter.
|
||||
///
|
||||
/// This example shows how to:
|
||||
/// 1. Create formulas with input/output specifications
|
||||
/// 2. Evaluate formulas with different input values
|
||||
/// 3. Handle evaluation errors
|
||||
|
||||
import 'package:d4rt_formulas/d4rt_formulas.dart';
|
||||
|
||||
void main() {
|
||||
print('=== Formula Evaluation Example ===\n');
|
||||
|
||||
// Create a formula evaluator
|
||||
final evaluator = FormulaEvaluator();
|
||||
|
||||
// Example 1: Newton's Second Law (F = m * a)
|
||||
print('1. Newton\'s Second Law of Motion');
|
||||
final newtonFormula = Formula(
|
||||
name: "Newton's Second Law",
|
||||
input: {
|
||||
'm': VariableSpec(magnitude: 'mass'),
|
||||
'a': VariableSpec(magnitude: 'acceleration'),
|
||||
},
|
||||
output: {
|
||||
'F': VariableSpec(magnitude: 'force'),
|
||||
},
|
||||
d4rtCode: '''
|
||||
main() {
|
||||
return m * a;
|
||||
}
|
||||
''',
|
||||
);
|
||||
|
||||
try {
|
||||
final force = evaluator.evaluate(newtonFormula, {
|
||||
'm': 10.0, // 10 kg
|
||||
'a': 9.8, // 9.8 m/s²
|
||||
});
|
||||
|
||||
print(' Mass: 10.0 kg');
|
||||
print(' Acceleration: 9.8 m/s²');
|
||||
print(' Calculated Force: $force N');
|
||||
print(' Output variable: ${evaluator.getOutputVariableName(newtonFormula)}');
|
||||
print(' Output magnitude: ${evaluator.getOutputVariableMagnitude(newtonFormula)}');
|
||||
} catch (e) {
|
||||
print(' Error: $e');
|
||||
}
|
||||
|
||||
print('');
|
||||
|
||||
// Example 2: Quadratic Formula Discriminant
|
||||
print('2. Quadratic Formula Discriminant (Δ = b² - 4ac)');
|
||||
final discriminantFormula = Formula(
|
||||
name: 'Quadratic Discriminant',
|
||||
input: {
|
||||
'a': VariableSpec(magnitude: 'coefficient'),
|
||||
'b': VariableSpec(magnitude: 'coefficient'),
|
||||
'c': VariableSpec(magnitude: 'coefficient'),
|
||||
},
|
||||
output: {
|
||||
'discriminant': VariableSpec(magnitude: 'scalar'),
|
||||
},
|
||||
d4rtCode: '''
|
||||
main() {
|
||||
return b * b - 4 * a * c;
|
||||
}
|
||||
''',
|
||||
);
|
||||
|
||||
try {
|
||||
final discriminant = evaluator.evaluate(discriminantFormula, {
|
||||
'a': 1,
|
||||
'b': 5,
|
||||
'c': 6,
|
||||
});
|
||||
|
||||
print(' Equation: 1x² + 5x + 6 = 0');
|
||||
print(' a = 1, b = 5, c = 6');
|
||||
print(' Discriminant: $discriminant');
|
||||
|
||||
if (discriminant > 0) {
|
||||
print(' → Two real solutions');
|
||||
} else if (discriminant == 0) {
|
||||
print(' → One real solution');
|
||||
} else {
|
||||
print(' → No real solutions');
|
||||
}
|
||||
} catch (e) {
|
||||
print(' Error: $e');
|
||||
}
|
||||
|
||||
print('');
|
||||
|
||||
// Example 3: Circle Area
|
||||
print('3. Circle Area (A = π * r²)');
|
||||
final circleAreaFormula = Formula(
|
||||
name: 'Circle Area',
|
||||
input: {
|
||||
'r': VariableSpec(magnitude: 'length'),
|
||||
},
|
||||
output: {
|
||||
'A': VariableSpec(magnitude: 'area'),
|
||||
},
|
||||
d4rtCode: '''
|
||||
main() {
|
||||
var pi = 3.14159265359;
|
||||
return pi * r * r;
|
||||
}
|
||||
''',
|
||||
);
|
||||
|
||||
try {
|
||||
final area = evaluator.evaluate(circleAreaFormula, {
|
||||
'r': 5.0, // radius = 5 units
|
||||
});
|
||||
|
||||
print(' Radius: 5.0 units');
|
||||
print(' Calculated Area: $area square units');
|
||||
} catch (e) {
|
||||
print(' Error: $e');
|
||||
}
|
||||
|
||||
print('');
|
||||
|
||||
// Example 4: Error handling
|
||||
print('4. Error Handling Example');
|
||||
try {
|
||||
// Try to evaluate with missing input variable
|
||||
evaluator.evaluate(newtonFormula, {
|
||||
'm': 10.0,
|
||||
// Missing 'a' variable
|
||||
});
|
||||
} catch (e) {
|
||||
print(' Expected error when missing input variable:');
|
||||
print(' $e');
|
||||
}
|
||||
|
||||
print('');
|
||||
|
||||
// Example 5: Complex calculation
|
||||
print('5. Compound Interest Formula');
|
||||
final compoundInterestFormula = Formula(
|
||||
name: 'Compound Interest',
|
||||
input: {
|
||||
'P': VariableSpec(magnitude: 'currency'), // Principal
|
||||
'r': VariableSpec(magnitude: 'rate'), // Annual interest rate
|
||||
'n': VariableSpec(magnitude: 'count'), // Times compounded per year
|
||||
't': VariableSpec(magnitude: 'time'), // Time in years
|
||||
},
|
||||
output: {
|
||||
'A': VariableSpec(magnitude: 'currency'), // Final amount
|
||||
},
|
||||
d4rtCode: '''
|
||||
main() {
|
||||
// A = P * (1 + r/n)^(n*t)
|
||||
var rate_per_period = r / n;
|
||||
var base = 1 + rate_per_period;
|
||||
var exponent = n * t;
|
||||
|
||||
// Calculate base^exponent using repeated multiplication
|
||||
// (d4rt may not have built-in pow function)
|
||||
var result = P;
|
||||
for (var i = 0; i < exponent; i++) {
|
||||
result = result * base;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
''',
|
||||
);
|
||||
|
||||
try {
|
||||
final finalAmount = evaluator.evaluate(compoundInterestFormula, {
|
||||
'P': 1000.0, // \$1000 principal
|
||||
'r': 0.05, // 5% annual interest rate
|
||||
'n': 12, // Compounded monthly
|
||||
't': 2, // 2 years
|
||||
});
|
||||
|
||||
print(' Principal: \$1000');
|
||||
print(' Annual interest rate: 5%');
|
||||
print(' Compounded: 12 times per year (monthly)');
|
||||
print(' Time: 2 years');
|
||||
print(' Final amount: \$$finalAmount');
|
||||
} catch (e) {
|
||||
print(' Error: $e');
|
||||
}
|
||||
|
||||
print('\n=== Example Complete ===');
|
||||
}
|
||||
8
lib/d4rt_formulas.dart
Normal file
8
lib/d4rt_formulas.dart
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
/// A library for working with mathematical formulas using the d4rt interpreter.
|
||||
///
|
||||
/// This library provides data models for representing formulas and an evaluator
|
||||
/// for executing them using the d4rt Dart interpreter.
|
||||
library d4rt_formulas;
|
||||
|
||||
export 'formula_models.dart';
|
||||
export 'formula_evaluator.dart';
|
||||
148
lib/formula_evaluator.dart
Normal file
148
lib/formula_evaluator.dart
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
/// Formula evaluator that executes d4rt code with input variables and
|
||||
/// returns the value of the single output variable.
|
||||
///
|
||||
/// The evaluator assumes that:
|
||||
/// - A formula has exactly one output variable
|
||||
/// - The d4rt code defines a main function with parameters matching input variables
|
||||
/// - The d4rt code when executed returns the value of that output variable
|
||||
/// - Input variables are provided as a Map<String, dynamic>
|
||||
|
||||
import 'package:d4rt/d4rt.dart';
|
||||
import 'formula_models.dart';
|
||||
|
||||
/// Exception thrown when formula evaluation fails
|
||||
class FormulaEvaluationException implements Exception {
|
||||
final String message;
|
||||
final Object? cause;
|
||||
|
||||
const FormulaEvaluationException(this.message, [this.cause]);
|
||||
|
||||
@override
|
||||
String toString() => 'FormulaEvaluationException: $message'
|
||||
'${cause != null ? ' (caused by: $cause)' : ''}';
|
||||
}
|
||||
|
||||
/// Evaluates formulas using the d4rt interpreter
|
||||
class FormulaEvaluator {
|
||||
final D4rt _interpreter;
|
||||
|
||||
/// Creates a new formula evaluator with an optional d4rt interpreter instance.
|
||||
/// If no interpreter is provided, a new one will be created.
|
||||
FormulaEvaluator([D4rt? interpreter]) : _interpreter = interpreter ?? D4rt();
|
||||
|
||||
/// Evaluates a formula with the given input values.
|
||||
///
|
||||
/// The [formula] must have exactly one output variable.
|
||||
/// The [inputValues] map must contain values for all input variables defined
|
||||
/// in the formula.
|
||||
///
|
||||
/// The formula's d4rt_code should define a main function that uses the input
|
||||
/// variable names directly. The evaluator will inject variable declarations
|
||||
/// before the formula code. For example:
|
||||
/// ```
|
||||
/// main() {
|
||||
/// return m * a; // Returns Force = mass * acceleration
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Returns the computed value of the single output variable.
|
||||
///
|
||||
/// Throws [FormulaEvaluationException] if:
|
||||
/// - The formula has zero or more than one output variable
|
||||
/// - Required input variables are missing
|
||||
/// - The d4rt code execution fails
|
||||
dynamic evaluate(Formula formula, Map<String, dynamic> inputValues) {
|
||||
_validateFormula(formula);
|
||||
_validateInputValues(formula, inputValues);
|
||||
|
||||
try {
|
||||
// Build the complete d4rt source code with variable declarations
|
||||
final completeSource = _buildCompleteSource(formula, inputValues);
|
||||
|
||||
// Execute the code using d4rt (no args needed since variables are in source)
|
||||
final result = _interpreter.execute(source: completeSource);
|
||||
|
||||
return result;
|
||||
} catch (e) {
|
||||
throw FormulaEvaluationException(
|
||||
'Failed to execute formula "${formula.name}"',
|
||||
e,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Validates that the formula has exactly one output variable
|
||||
void _validateFormula(Formula formula) {
|
||||
if (formula.output.length != 1) {
|
||||
throw FormulaEvaluationException(
|
||||
'Formula "${formula.name}" must have exactly one output variable, '
|
||||
'but has ${formula.output.length}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Validates that all required input variables are provided
|
||||
void _validateInputValues(Formula formula, Map<String, dynamic> inputValues) {
|
||||
final missingVars = <String>[];
|
||||
|
||||
for (final inputVar in formula.input.keys) {
|
||||
if (!inputValues.containsKey(inputVar)) {
|
||||
missingVars.add(inputVar);
|
||||
}
|
||||
}
|
||||
|
||||
if (missingVars.isNotEmpty) {
|
||||
throw FormulaEvaluationException(
|
||||
'Missing required input variables for formula "${formula.name}": '
|
||||
'${missingVars.join(', ')}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the name of the single output variable from the formula
|
||||
String getOutputVariableName(Formula formula) {
|
||||
_validateFormula(formula);
|
||||
return formula.output.keys.first;
|
||||
}
|
||||
|
||||
/// Gets the magnitude of the single output variable from the formula
|
||||
String getOutputVariableMagnitude(Formula formula) {
|
||||
_validateFormula(formula);
|
||||
return formula.output.values.first.magnitude;
|
||||
}
|
||||
|
||||
/// Gets the ordered list of input variable names (alphabetically sorted)
|
||||
List<String> getInputVariableOrder(Formula formula) {
|
||||
return formula.input.keys.toList()..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) {
|
||||
final buffer = StringBuffer();
|
||||
|
||||
// Add variable declarations for all input variables
|
||||
for (final entry in inputValues.entries) {
|
||||
final varName = entry.key;
|
||||
final value = entry.value;
|
||||
|
||||
// Handle different value types appropriately for d4rt
|
||||
if (value is String) {
|
||||
// Escape quotes in string values
|
||||
final escapedValue = value.replaceAll('"', '\\"');
|
||||
buffer.writeln('var $varName = "$escapedValue";');
|
||||
} else {
|
||||
// For numbers and other types, use direct representation
|
||||
buffer.writeln('var $varName = $value;');
|
||||
}
|
||||
}
|
||||
|
||||
// Add a blank line for readability
|
||||
buffer.writeln();
|
||||
|
||||
// Add the formula's d4rt code
|
||||
buffer.write(formula.d4rtCode);
|
||||
|
||||
return buffer.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
import 'package:d4rt/d4rt.dart';
|
||||
293
test/formula_evaluator_test.dart
Normal file
293
test/formula_evaluator_test.dart
Normal file
|
|
@ -0,0 +1,293 @@
|
|||
import 'package:test/test.dart';
|
||||
import 'package:d4rt_formulas/formula_models.dart';
|
||||
import 'package:d4rt_formulas/formula_evaluator.dart';
|
||||
|
||||
void main() {
|
||||
group('FormulaEvaluator', () {
|
||||
late FormulaEvaluator evaluator;
|
||||
|
||||
setUp(() {
|
||||
evaluator = FormulaEvaluator();
|
||||
});
|
||||
|
||||
group('Basic evaluation', () {
|
||||
test('evaluates Newton\'s second law formula', () {
|
||||
final formula = Formula(
|
||||
name: "Newton's second law",
|
||||
input: {
|
||||
'm': VariableSpec(magnitude: 'mass'),
|
||||
'a': VariableSpec(magnitude: 'acceleration'),
|
||||
},
|
||||
output: {
|
||||
'F': VariableSpec(magnitude: 'force'),
|
||||
},
|
||||
d4rtCode: '''
|
||||
main() {
|
||||
return a * m;
|
||||
}
|
||||
''',
|
||||
);
|
||||
|
||||
final result = evaluator.evaluate(formula, {
|
||||
'm': 10.0, // 10 kg
|
||||
'a': 9.8, // 9.8 m/s²
|
||||
});
|
||||
|
||||
expect(result, 98.0); // F = m * a = 10 * 9.8 = 98 N
|
||||
});
|
||||
|
||||
test('evaluates simple arithmetic formula', () {
|
||||
final formula = Formula(
|
||||
name: 'Simple addition',
|
||||
input: {
|
||||
'x': VariableSpec(magnitude: 'scalar'),
|
||||
'y': VariableSpec(magnitude: 'scalar'),
|
||||
},
|
||||
output: {
|
||||
'result': VariableSpec(magnitude: 'scalar'),
|
||||
},
|
||||
d4rtCode: '''
|
||||
main() {
|
||||
return x + y;
|
||||
}
|
||||
''',
|
||||
);
|
||||
|
||||
final result = evaluator.evaluate(formula, {
|
||||
'x': 5,
|
||||
'y': 3,
|
||||
});
|
||||
|
||||
expect(result, 8);
|
||||
});
|
||||
|
||||
test('handles single input variable', () {
|
||||
final formula = Formula(
|
||||
name: 'Square function',
|
||||
input: {
|
||||
'n': VariableSpec(magnitude: 'scalar'),
|
||||
},
|
||||
output: {
|
||||
'result': VariableSpec(magnitude: 'scalar'),
|
||||
},
|
||||
d4rtCode: '''
|
||||
main() {
|
||||
return n * n;
|
||||
}
|
||||
''',
|
||||
);
|
||||
|
||||
final result = evaluator.evaluate(formula, {'n': 7});
|
||||
expect(result, 49);
|
||||
});
|
||||
|
||||
test('handles complex mathematical operations', () {
|
||||
final formula = Formula(
|
||||
name: 'Quadratic formula discriminant',
|
||||
input: {
|
||||
'a': VariableSpec(magnitude: 'scalar'),
|
||||
'b': VariableSpec(magnitude: 'scalar'),
|
||||
'c': VariableSpec(magnitude: 'scalar'),
|
||||
},
|
||||
output: {
|
||||
'discriminant': VariableSpec(magnitude: 'scalar'),
|
||||
},
|
||||
d4rtCode: '''
|
||||
main() {
|
||||
return b * b - 4 * a * c;
|
||||
}
|
||||
''',
|
||||
);
|
||||
|
||||
final result = evaluator.evaluate(formula, {
|
||||
'a': 1,
|
||||
'b': 5,
|
||||
'c': 6,
|
||||
});
|
||||
|
||||
expect(result, 1); // b² - 4ac = 25 - 24 = 1
|
||||
});
|
||||
});
|
||||
|
||||
group('Input variable order', () {
|
||||
test('maintains consistent alphabetical order for input variables', () {
|
||||
final formula = Formula(
|
||||
name: 'Test order',
|
||||
input: {
|
||||
'z': VariableSpec(magnitude: 'scalar'),
|
||||
'a': VariableSpec(magnitude: 'scalar'),
|
||||
'b': VariableSpec(magnitude: 'scalar'),
|
||||
},
|
||||
output: {
|
||||
'result': VariableSpec(magnitude: 'scalar'),
|
||||
},
|
||||
d4rtCode: 'main() { return a + b + z; }',
|
||||
);
|
||||
|
||||
final order = evaluator.getInputVariableOrder(formula);
|
||||
expect(order, ['a', 'b', 'z']);
|
||||
});
|
||||
|
||||
test('passes arguments in correct alphabetical order', () {
|
||||
final formula = Formula(
|
||||
name: 'Test argument order',
|
||||
input: {
|
||||
'z': VariableSpec(magnitude: 'scalar'),
|
||||
'a': VariableSpec(magnitude: 'scalar'),
|
||||
'y': VariableSpec(magnitude: 'scalar'),
|
||||
},
|
||||
output: {
|
||||
'result': VariableSpec(magnitude: 'scalar'),
|
||||
},
|
||||
d4rtCode: '''
|
||||
main() {
|
||||
// Variables: a=1, y=2, z=3
|
||||
return a * 100 + y * 10 + z;
|
||||
}
|
||||
''',
|
||||
);
|
||||
|
||||
final result = evaluator.evaluate(formula, {
|
||||
'z': 3,
|
||||
'a': 1,
|
||||
'y': 2,
|
||||
});
|
||||
|
||||
expect(result, 123); // 1*100 + 2*10 + 3 = 123
|
||||
});
|
||||
});
|
||||
|
||||
group('Error handling', () {
|
||||
test('throws exception for formula with no output variables', () {
|
||||
final formula = Formula(
|
||||
name: 'Invalid formula',
|
||||
input: {'x': VariableSpec(magnitude: 'scalar')},
|
||||
output: {}, // No output variables
|
||||
d4rtCode: 'main() { return x; }',
|
||||
);
|
||||
|
||||
expect(
|
||||
() => evaluator.evaluate(formula, {'x': 1}),
|
||||
throwsA(isA<FormulaEvaluationException>()),
|
||||
);
|
||||
});
|
||||
|
||||
test('throws exception for formula with multiple output variables', () {
|
||||
final formula = Formula(
|
||||
name: 'Invalid formula',
|
||||
input: {'x': VariableSpec(magnitude: 'scalar')},
|
||||
output: {
|
||||
'y': VariableSpec(magnitude: 'scalar'),
|
||||
'z': VariableSpec(magnitude: 'scalar'),
|
||||
},
|
||||
d4rtCode: 'main(x) { return x; }',
|
||||
);
|
||||
|
||||
expect(
|
||||
() => evaluator.evaluate(formula, {'x': 1}),
|
||||
throwsA(isA<FormulaEvaluationException>()),
|
||||
);
|
||||
});
|
||||
|
||||
test('throws exception for missing input variables', () {
|
||||
final formula = Formula(
|
||||
name: 'Test formula',
|
||||
input: {
|
||||
'x': VariableSpec(magnitude: 'scalar'),
|
||||
'y': VariableSpec(magnitude: 'scalar'),
|
||||
},
|
||||
output: {'result': VariableSpec(magnitude: 'scalar')},
|
||||
d4rtCode: 'main() { return x + y; }',
|
||||
);
|
||||
|
||||
expect(
|
||||
() => evaluator.evaluate(formula, {'x': 1}), // Missing 'y'
|
||||
throwsA(isA<FormulaEvaluationException>()),
|
||||
);
|
||||
});
|
||||
|
||||
test('throws exception for invalid d4rt code', () {
|
||||
final formula = Formula(
|
||||
name: 'Invalid code formula',
|
||||
input: {'x': VariableSpec(magnitude: 'scalar')},
|
||||
output: {'result': VariableSpec(magnitude: 'scalar')},
|
||||
d4rtCode: 'invalid dart code here!',
|
||||
);
|
||||
|
||||
expect(
|
||||
() => evaluator.evaluate(formula, {'x': 1}),
|
||||
throwsA(isA<FormulaEvaluationException>()),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
group('Utility methods', () {
|
||||
test('getOutputVariableName returns the single output variable name', () {
|
||||
final formula = Formula(
|
||||
name: 'Test',
|
||||
input: {'x': VariableSpec(magnitude: 'scalar')},
|
||||
output: {'force': VariableSpec(magnitude: 'Newton')},
|
||||
d4rtCode: 'main() { return x; }',
|
||||
);
|
||||
|
||||
expect(evaluator.getOutputVariableName(formula), 'force');
|
||||
});
|
||||
|
||||
test('getOutputVariableMagnitude returns the output variable magnitude', () {
|
||||
final formula = Formula(
|
||||
name: 'Test',
|
||||
input: {'x': VariableSpec(magnitude: 'scalar')},
|
||||
output: {'force': VariableSpec(magnitude: 'Newton')},
|
||||
d4rtCode: 'main() { return x; }',
|
||||
);
|
||||
|
||||
expect(evaluator.getOutputVariableMagnitude(formula), 'Newton');
|
||||
});
|
||||
|
||||
test('utility methods throw exception for invalid formulas', () {
|
||||
final invalidFormula = Formula(
|
||||
name: 'Invalid',
|
||||
input: {'x': VariableSpec(magnitude: 'scalar')},
|
||||
output: {}, // No output variables
|
||||
d4rtCode: 'main() { return x; }',
|
||||
);
|
||||
|
||||
expect(
|
||||
() => evaluator.getOutputVariableName(invalidFormula),
|
||||
throwsA(isA<FormulaEvaluationException>()),
|
||||
);
|
||||
|
||||
expect(
|
||||
() => evaluator.getOutputVariableMagnitude(invalidFormula),
|
||||
throwsA(isA<FormulaEvaluationException>()),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
group('Data types', () {
|
||||
test('handles integer values', () {
|
||||
final formula = Formula(
|
||||
name: 'Integer test',
|
||||
input: {'n': VariableSpec(magnitude: 'count')},
|
||||
output: {'result': VariableSpec(magnitude: 'count')},
|
||||
d4rtCode: 'main() { return n + 1; }',
|
||||
);
|
||||
|
||||
final result = evaluator.evaluate(formula, {'n': 42});
|
||||
expect(result, 43);
|
||||
});
|
||||
|
||||
test('handles double values', () {
|
||||
final formula = Formula(
|
||||
name: 'Double test',
|
||||
input: {'x': VariableSpec(magnitude: 'length')},
|
||||
output: {'result': VariableSpec(magnitude: 'area')},
|
||||
d4rtCode: 'main() { return x * x; }',
|
||||
);
|
||||
|
||||
final result = evaluator.evaluate(formula, {'x': 3.14});
|
||||
expect(result, closeTo(9.8596, 0.0001));
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
Loading…
Reference in a new issue