Skip to content

Commit

Permalink
Feat: Add math funcs Log10, Log2, Log and Exp (#813)
Browse files Browse the repository at this point in the history
Implement Math.log and Math.pow
  • Loading branch information
jrmoulton committed Jan 7, 2022
1 parent 89df782 commit c5c139f
Show file tree
Hide file tree
Showing 8 changed files with 36 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -22,6 +22,7 @@ All notable changes to this project will be documented in this file.
- More special keyboard key codes are provided in the `FocusScope`, and
special keys are handled
- `start()`, `stop()`, `running()` and a default constructor for C++ `sixtyfps::Timer`
- Math functions `log`, and `pow`

### Fixed

Expand Down
8 changes: 8 additions & 0 deletions docs/langref.md
Expand Up @@ -977,6 +977,14 @@ The trigonometry function. Note that the should be typed with `deg` or `rad` uni

Square root

* **`pow(float, float) -> float`**

Return the value of the first value raised to the second

* **`log(float, float) -> float`**

Return the log of the first value with a base of the second value

### `Colors` namespace

These functions are available both in the global scope, and in the `Colors` namespace.
Expand Down
8 changes: 8 additions & 0 deletions sixtyfps_compiler/expression_tree.rs
Expand Up @@ -31,6 +31,8 @@ pub enum BuiltinFunction {
ACos,
ASin,
ATan,
Log,
Pow,
SetFocusItem,
ShowPopupWindow,
/// the "42".to_float()
Expand Down Expand Up @@ -83,6 +85,10 @@ impl BuiltinFunction {
BuiltinFunction::ACos | BuiltinFunction::ASin | BuiltinFunction::ATan => {
Type::Function { return_type: Box::new(Type::Angle), args: vec![Type::Float32] }
}
BuiltinFunction::Log | BuiltinFunction::Pow => Type::Function {
return_type: Box::new(Type::Float32),
args: vec![Type::Float32, Type::Float32],
},
BuiltinFunction::SetFocusItem => Type::Function {
return_type: Box::new(Type::Void),
args: vec![Type::ElementReference],
Expand Down Expand Up @@ -154,6 +160,8 @@ impl BuiltinFunction {
| BuiltinFunction::Tan
| BuiltinFunction::ACos
| BuiltinFunction::ASin
| BuiltinFunction::Log
| BuiltinFunction::Pow
| BuiltinFunction::ATan => true,
BuiltinFunction::SetFocusItem => false,
BuiltinFunction::ShowPopupWindow => false,
Expand Down
2 changes: 2 additions & 0 deletions sixtyfps_compiler/generator/cpp.rs
Expand Up @@ -1981,6 +1981,8 @@ fn compile_expression(
BuiltinFunction::Floor => "std::floor".into(),
BuiltinFunction::Sqrt => "std::sqrt".into(),
BuiltinFunction::Abs => "std::abs".into(),
BuiltinFunction::Log => "[](auto a1, auto a2){ return std::log(a1) / std::log(a2); }".into(),
BuiltinFunction::Pow => "[](auto a1, auto a2){return pow(a1, a2); }".into(),
BuiltinFunction::Sin => format!("[](float a){{ return std::sin(a * {}); }}", std::f32::consts::PI / 180.),
BuiltinFunction::Cos => format!("[](float a){{ return std::cos(a * {}); }}", std::f32::consts::PI / 180.),
BuiltinFunction::Tan => format!("[](float a){{ return std::tan(a * {}); }}", std::f32::consts::PI / 180.),
Expand Down
2 changes: 2 additions & 0 deletions sixtyfps_compiler/generator/rust.rs
Expand Up @@ -1634,6 +1634,8 @@ fn compile_expression(expr: &Expression, component: &Rc<Component>) -> TokenStre
BuiltinFunction::ASin => quote!((|a| (a as f64).asin().to_degrees())),
BuiltinFunction::ACos => quote!((|a| (a as f64).acos().to_degrees())),
BuiltinFunction::ATan => quote!((|a| (a as f64).atan().to_degrees())),
BuiltinFunction::Log => quote!((|a1, a2| (a1 as f64).log(a2 as f64))),
BuiltinFunction::Pow => quote!((|a1, a2| (a1 as f64).powf(a2 as f64))),
BuiltinFunction::SetFocusItem | BuiltinFunction::ShowPopupWindow | BuiltinFunction::ImplicitLayoutInfo(_) => {
panic!("internal error: should be handled directly in CallFunction")
}
Expand Down
2 changes: 2 additions & 0 deletions sixtyfps_compiler/lookup.rs
Expand Up @@ -537,6 +537,8 @@ impl LookupObject for MathFunctions {
.or_else(|| f("asin", BuiltinFunctionReference(BuiltinFunction::ASin, sl())))
.or_else(|| f("acos", BuiltinFunctionReference(BuiltinFunction::ACos, sl())))
.or_else(|| f("atan", BuiltinFunctionReference(BuiltinFunction::ATan, sl())))
.or_else(|| f("log", BuiltinFunctionReference(BuiltinFunction::Log, sl())))
.or_else(|| f("pow", BuiltinFunctionReference(BuiltinFunction::Pow, sl())))
}
}

Expand Down
10 changes: 10 additions & 0 deletions sixtyfps_runtime/interpreter/eval.rs
Expand Up @@ -256,6 +256,16 @@ pub fn eval_expression(expression: &Expression, local_context: &mut EvalLocalCon
let x: f64 = eval_expression(&arguments[0], local_context).try_into().unwrap();
Value::Number(x.atan().to_degrees())
}
Expression::BuiltinFunctionReference(BuiltinFunction::Log, _) => {
let x: f64 = eval_expression(&arguments[0], local_context).try_into().unwrap();
let y: f64 = eval_expression(&arguments[1], local_context).try_into().unwrap();
Value::Number(x.log(y))
}
Expression::BuiltinFunctionReference(BuiltinFunction::Pow, _) => {
let x: f64 = eval_expression(&arguments[0], local_context).try_into().unwrap();
let y: f64 = eval_expression(&arguments[1], local_context).try_into().unwrap();
Value::Number(x.powf(y))
}
Expression::BuiltinFunctionReference(BuiltinFunction::SetFocusItem, _) => {
if arguments.len() != 1 {
panic!("internal error: incorrect argument count to SetFocusItem")
Expand Down
4 changes: 3 additions & 1 deletion tests/cases/expr/math.60
Expand Up @@ -4,7 +4,9 @@
TestCase := Rectangle {
property <bool> test_sqrt: sqrt(100) == 10 && Math.sqrt(1) == 1 && sqrt(6.25) == 2.5;
property <bool> test_abs: abs(100.5) == 100.5 && Math.abs(-200.5) == 200.5 && abs(0) == 0;
property <bool> test: test_sqrt && test_abs;
property <bool> test_log: log(4,2) == 2 && Math.log(9,3) == 2 && log(64,4) == 3;
property <bool> test_pow: pow(4,2) == 16 && Math.pow(9,3) == 729 && pow(4,3) == 64;
property <bool> test: test_sqrt && test_abs && test_log && test_pow;
}
/*
```cpp
Expand Down

0 comments on commit c5c139f

Please sign in to comment.