From ae7143a94f4db6da47be27c4a9f6f32b95b86665 Mon Sep 17 00:00:00 2001 From: Jess Frazelle Date: Fri, 15 Sep 2023 15:54:49 -0700 Subject: [PATCH] add a bunch of math stdlib fns (#555) add a bunch of math stuff Signed-off-by: Jess Frazelle --- docs/kcl/std.json | 264 +++++++++++++++++++++++++++++++ docs/kcl/std.md | 190 ++++++++++++++++++++++ src/wasm-lib/kcl/src/std/math.rs | 194 ++++++++++++++++++++++- src/wasm-lib/kcl/src/std/mod.rs | 34 ++-- 4 files changed, 657 insertions(+), 25 deletions(-) diff --git a/docs/kcl/std.json b/docs/kcl/std.json index 734e5d9b3..be6c3458e 100644 --- a/docs/kcl/std.json +++ b/docs/kcl/std.json @@ -1,4 +1,60 @@ [ + { + "name": "abs", + "summary": "Computes the absolute value of a number.", + "description": "", + "tags": [], + "args": [ + { + "name": "num", + "type": "number", + "schema": { + "type": "number", + "format": "double" + }, + "required": true + } + ], + "returnValue": { + "name": "", + "type": "number", + "schema": { + "type": "number", + "format": "double" + }, + "required": true + }, + "unpublished": false, + "deprecated": false + }, + { + "name": "acos", + "summary": "Computes the arccosine of a number (in radians).", + "description": "", + "tags": [], + "args": [ + { + "name": "num", + "type": "number", + "schema": { + "type": "number", + "format": "double" + }, + "required": true + } + ], + "returnValue": { + "name": "", + "type": "number", + "schema": { + "type": "number", + "format": "double" + }, + "required": true + }, + "unpublished": false, + "deprecated": false + }, { "name": "angleToMatchLengthX", "summary": "Returns the angle to match the given length for x.", @@ -7473,6 +7529,62 @@ "unpublished": false, "deprecated": false }, + { + "name": "asin", + "summary": "Computes the arcsine of a number (in radians).", + "description": "", + "tags": [], + "args": [ + { + "name": "num", + "type": "number", + "schema": { + "type": "number", + "format": "double" + }, + "required": true + } + ], + "returnValue": { + "name": "", + "type": "number", + "schema": { + "type": "number", + "format": "double" + }, + "required": true + }, + "unpublished": false, + "deprecated": false + }, + { + "name": "atan", + "summary": "Computes the arctangent of a number (in radians).", + "description": "", + "tags": [], + "args": [ + { + "name": "num", + "type": "number", + "schema": { + "type": "number", + "format": "double" + }, + "required": true + } + ], + "returnValue": { + "name": "", + "type": "number", + "schema": { + "type": "number", + "format": "double" + }, + "required": true + }, + "unpublished": false, + "deprecated": false + }, { "name": "bezierCurve", "summary": "Draw a bezier curve.", @@ -8446,6 +8558,34 @@ "unpublished": false, "deprecated": false }, + { + "name": "ceil", + "summary": "Computes the smallest integer greater than or equal to a number.", + "description": "", + "tags": [], + "args": [ + { + "name": "num", + "type": "number", + "schema": { + "type": "number", + "format": "double" + }, + "required": true + } + ], + "returnValue": { + "name": "", + "type": "number", + "schema": { + "type": "number", + "format": "double" + }, + "required": true + }, + "unpublished": false, + "deprecated": false + }, { "name": "close", "summary": "Close the current sketch.", @@ -9944,6 +10084,34 @@ "unpublished": false, "deprecated": false }, + { + "name": "floor", + "summary": "Computes the largest integer less than or equal to a number.", + "description": "", + "tags": [], + "args": [ + { + "name": "num", + "type": "number", + "schema": { + "type": "number", + "format": "double" + }, + "required": true + } + ], + "returnValue": { + "name": "", + "type": "number", + "schema": { + "type": "number", + "format": "double" + }, + "required": true + }, + "unpublished": false, + "deprecated": false + }, { "name": "getExtrudeWallTransform", "summary": "Returns the extrude wall transform.", @@ -13015,6 +13183,37 @@ "unpublished": false, "deprecated": false }, + { + "name": "max", + "summary": "Returns the maximum of the given arguments.", + "description": "", + "tags": [], + "args": [ + { + "name": "args", + "type": "[number]", + "schema": { + "type": "array", + "items": { + "type": "number", + "format": "double" + } + }, + "required": true + } + ], + "returnValue": { + "name": "", + "type": "number", + "schema": { + "type": "number", + "format": "double" + }, + "required": true + }, + "unpublished": false, + "deprecated": false + }, { "name": "min", "summary": "Returns the minimum of the given arguments.", @@ -13064,6 +13263,43 @@ "unpublished": false, "deprecated": false }, + { + "name": "pow", + "summary": "Computes the number to a power.", + "description": "", + "tags": [], + "args": [ + { + "name": "num", + "type": "number", + "schema": { + "type": "number", + "format": "double" + }, + "required": true + }, + { + "name": "pow", + "type": "number", + "schema": { + "type": "number", + "format": "double" + }, + "required": true + } + ], + "returnValue": { + "name": "", + "type": "number", + "schema": { + "type": "number", + "format": "double" + }, + "required": true + }, + "unpublished": false, + "deprecated": false + }, { "name": "segAng", "summary": "Returns the angle of the segment.", @@ -15376,6 +15612,34 @@ "unpublished": false, "deprecated": false }, + { + "name": "sqrt", + "summary": "Computes the square root of a number.", + "description": "", + "tags": [], + "args": [ + { + "name": "num", + "type": "number", + "schema": { + "type": "number", + "format": "double" + }, + "required": true + } + ], + "returnValue": { + "name": "", + "type": "number", + "schema": { + "type": "number", + "format": "double" + }, + "required": true + }, + "unpublished": false, + "deprecated": false + }, { "name": "startSketchAt", "summary": "Start a sketch at a given point.", diff --git a/docs/kcl/std.md b/docs/kcl/std.md index d98366a73..f65e81084 100644 --- a/docs/kcl/std.md +++ b/docs/kcl/std.md @@ -5,6 +5,8 @@ ## Table of Contents * [Functions](#functions) + * [`abs`](#abs) + * [`acos`](#acos) * [`angleToMatchLengthX`](#angleToMatchLengthX) * [`angleToMatchLengthY`](#angleToMatchLengthY) * [`angledLine`](#angledLine) @@ -14,10 +16,14 @@ * [`angledLineToX`](#angledLineToX) * [`angledLineToY`](#angledLineToY) * [`arc`](#arc) + * [`asin`](#asin) + * [`atan`](#atan) * [`bezierCurve`](#bezierCurve) + * [`ceil`](#ceil) * [`close`](#close) * [`cos`](#cos) * [`extrude`](#extrude) + * [`floor`](#floor) * [`getExtrudeWallTransform`](#getExtrudeWallTransform) * [`lastSegX`](#lastSegX) * [`lastSegY`](#lastSegY) @@ -26,14 +32,17 @@ * [`legLen`](#legLen) * [`line`](#line) * [`lineTo`](#lineTo) + * [`max`](#max) * [`min`](#min) * [`pi`](#pi) + * [`pow`](#pow) * [`segAng`](#segAng) * [`segEndX`](#segEndX) * [`segEndY`](#segEndY) * [`segLen`](#segLen) * [`show`](#show) * [`sin`](#sin) + * [`sqrt`](#sqrt) * [`startSketchAt`](#startSketchAt) * [`tan`](#tan) * [`xLine`](#xLine) @@ -44,6 +53,46 @@ ## Functions +### abs + +Computes the absolute value of a number. + + + +``` +abs(num: number) -> number +``` + +#### Arguments + +* `num`: `number` + +#### Returns + +* `number` + + + +### acos + +Computes the arccosine of a number (in radians). + + + +``` +acos(num: number) -> number +``` + +#### Arguments + +* `num`: `number` + +#### Returns + +* `number` + + + ### angleToMatchLengthX Returns the angle to match the given length for x. @@ -1332,6 +1381,46 @@ arc(data: ArcData, sketch_group: SketchGroup) -> SketchGroup +### asin + +Computes the arcsine of a number (in radians). + + + +``` +asin(num: number) -> number +``` + +#### Arguments + +* `num`: `number` + +#### Returns + +* `number` + + + +### atan + +Computes the arctangent of a number (in radians). + + + +``` +atan(num: number) -> number +``` + +#### Arguments + +* `num`: `number` + +#### Returns + +* `number` + + + ### bezierCurve Draw a bezier curve. @@ -1497,6 +1586,26 @@ bezierCurve(data: BezierData, sketch_group: SketchGroup) -> SketchGroup +### ceil + +Computes the smallest integer greater than or equal to a number. + + + +``` +ceil(num: number) -> number +``` + +#### Arguments + +* `num`: `number` + +#### Returns + +* `number` + + + ### close Close the current sketch. @@ -1770,6 +1879,26 @@ extrude(length: number, sketch_group: SketchGroup) -> ExtrudeGroup +### floor + +Computes the largest integer less than or equal to a number. + + + +``` +floor(num: number) -> number +``` + +#### Arguments + +* `num`: `number` + +#### Returns + +* `number` + + + ### getExtrudeWallTransform Returns the extrude wall transform. @@ -2358,6 +2487,26 @@ lineTo(data: LineToData, sketch_group: SketchGroup) -> SketchGroup +### max + +Returns the maximum of the given arguments. + + + +``` +max(args: [number]) -> number +``` + +#### Arguments + +* `args`: `[number]` + +#### Returns + +* `number` + + + ### min Returns the minimum of the given arguments. @@ -2397,6 +2546,27 @@ pi() -> number +### pow + +Computes the number to a power. + + + +``` +pow(num: number, pow: number) -> number +``` + +#### Arguments + +* `num`: `number` +* `pow`: `number` + +#### Returns + +* `number` + + + ### segAng Returns the angle of the segment. @@ -2827,6 +2997,26 @@ sin(num: number) -> number +### sqrt + +Computes the square root of a number. + + + +``` +sqrt(num: number) -> number +``` + +#### Arguments + +* `num`: `number` + +#### Returns + +* `number` + + + ### startSketchAt Start a sketch at a given point. diff --git a/src/wasm-lib/kcl/src/std/math.rs b/src/wasm-lib/kcl/src/std/math.rs index bd4cc309f..f49abbd67 100644 --- a/src/wasm-lib/kcl/src/std/math.rs +++ b/src/wasm-lib/kcl/src/std/math.rs @@ -4,7 +4,11 @@ use anyhow::Result; use derive_docs::stdlib; use schemars::JsonSchema; -use crate::{errors::KclError, executor::MemoryItem, std::Args}; +use crate::{ + errors::{KclError, KclErrorDetails}, + executor::MemoryItem, + std::Args, +}; /// Computes the cosine of a number (in radians). pub fn cos(args: &mut Args) -> Result { @@ -68,3 +72,191 @@ pub fn pi(args: &mut Args) -> Result { fn inner_pi() -> Result { Ok(std::f64::consts::PI) } + +/// Computes the square root of a number. +pub fn sqrt(args: &mut Args) -> Result { + let num = args.get_number()?; + let result = inner_sqrt(num)?; + + args.make_user_val_from_f64(result) +} + +/// Computes the square root of a number. +#[stdlib { + name = "sqrt", +}] +fn inner_sqrt(num: f64) -> Result { + Ok(num.sqrt()) +} + +/// Computes the absolute value of a number. +pub fn abs(args: &mut Args) -> Result { + let num = args.get_number()?; + let result = inner_abs(num)?; + + args.make_user_val_from_f64(result) +} + +/// Computes the absolute value of a number. +#[stdlib { + name = "abs", +}] +fn inner_abs(num: f64) -> Result { + Ok(num.abs()) +} + +/// Computes the largest integer less than or equal to a number. +pub fn floor(args: &mut Args) -> Result { + let num = args.get_number()?; + let result = inner_floor(num)?; + + args.make_user_val_from_f64(result) +} + +/// Computes the largest integer less than or equal to a number. +#[stdlib { + name = "floor", +}] +fn inner_floor(num: f64) -> Result { + Ok(num.floor()) +} + +/// Computes the smallest integer greater than or equal to a number. +pub fn ceil(args: &mut Args) -> Result { + let num = args.get_number()?; + let result = inner_ceil(num)?; + + args.make_user_val_from_f64(result) +} + +/// Computes the smallest integer greater than or equal to a number. +#[stdlib { + name = "ceil", +}] +fn inner_ceil(num: f64) -> Result { + Ok(num.ceil()) +} + +/// Returns the minimum of the given arguments. +pub fn min(args: &mut Args) -> Result { + let nums = args.get_number_array()?; + let result = inner_min(nums); + + args.make_user_val_from_f64(result) +} + +/// Returns the minimum of the given arguments. +#[stdlib { + name = "min", +}] +fn inner_min(args: Vec) -> f64 { + let mut min = std::f64::MAX; + for arg in args.iter() { + if *arg < min { + min = *arg; + } + } + + min +} + +/// Returns the maximum of the given arguments. +pub fn max(args: &mut Args) -> Result { + let nums = args.get_number_array()?; + let result = inner_max(nums); + + args.make_user_val_from_f64(result) +} + +/// Returns the maximum of the given arguments. +#[stdlib { + name = "max", +}] +fn inner_max(args: Vec) -> f64 { + let mut max = std::f64::MAX; + for arg in args.iter() { + if *arg > max { + max = *arg; + } + } + + max +} + +/// Computes the number to a power. +pub fn pow(args: &mut Args) -> Result { + let nums = args.get_number_array()?; + if nums.len() > 2 { + return Err(KclError::Type(KclErrorDetails { + message: format!("expected 2 arguments, got {}", nums.len()), + source_ranges: vec![args.source_range], + })); + } + + if nums.len() <= 1 { + return Err(KclError::Type(KclErrorDetails { + message: format!("expected 2 arguments, got {}", nums.len()), + source_ranges: vec![args.source_range], + })); + } + + let result = inner_pow(nums[0], nums[1])?; + + args.make_user_val_from_f64(result) +} + +/// Computes the number to a power. +#[stdlib { + name = "pow", +}] +fn inner_pow(num: f64, pow: f64) -> Result { + Ok(num.powf(pow)) +} + +/// Computes the arccosine of a number (in radians). +pub fn acos(args: &mut Args) -> Result { + let num = args.get_number()?; + let result = inner_acos(num)?; + + args.make_user_val_from_f64(result) +} + +/// Computes the arccosine of a number (in radians). +#[stdlib { + name = "acos", +}] +fn inner_acos(num: f64) -> Result { + Ok(num.acos()) +} + +/// Computes the arcsine of a number (in radians). +pub fn asin(args: &mut Args) -> Result { + let num = args.get_number()?; + let result = inner_asin(num)?; + + args.make_user_val_from_f64(result) +} + +/// Computes the arcsine of a number (in radians). +#[stdlib { + name = "asin", +}] +fn inner_asin(num: f64) -> Result { + Ok(num.asin()) +} + +/// Computes the arctangent of a number (in radians). +pub fn atan(args: &mut Args) -> Result { + let num = args.get_number()?; + let result = inner_atan(num)?; + + args.make_user_val_from_f64(result) +} + +/// Computes the arctangent of a number (in radians). +#[stdlib { + name = "atan", +}] +fn inner_atan(num: f64) -> Result { + Ok(num.atan()) +} diff --git a/src/wasm-lib/kcl/src/std/mod.rs b/src/wasm-lib/kcl/src/std/mod.rs index b708c5816..06d9d9159 100644 --- a/src/wasm-lib/kcl/src/std/mod.rs +++ b/src/wasm-lib/kcl/src/std/mod.rs @@ -32,7 +32,6 @@ impl StdLib { pub fn new() -> Self { let internal_fns: Vec> = vec![ Box::new(Show), - Box::new(Min), Box::new(LegLen), Box::new(LegAngX), Box::new(LegAngY), @@ -65,7 +64,17 @@ impl StdLib { Box::new(crate::std::math::Cos), Box::new(crate::std::math::Sin), Box::new(crate::std::math::Tan), + Box::new(crate::std::math::Acos), + Box::new(crate::std::math::Asin), + Box::new(crate::std::math::Atan), Box::new(crate::std::math::Pi), + Box::new(crate::std::math::Sqrt), + Box::new(crate::std::math::Abs), + Box::new(crate::std::math::Floor), + Box::new(crate::std::math::Ceil), + Box::new(crate::std::math::Min), + Box::new(crate::std::math::Max), + Box::new(crate::std::math::Pow), ]; let mut fns = HashMap::new(); @@ -426,29 +435,6 @@ impl<'a> Args<'a> { } } -/// Returns the minimum of the given arguments. -pub fn min(args: &mut Args) -> Result { - let nums = args.get_number_array()?; - let result = inner_min(nums); - - args.make_user_val_from_f64(result) -} - -/// Returns the minimum of the given arguments. -#[stdlib { - name = "min", -}] -fn inner_min(args: Vec) -> f64 { - let mut min = std::f64::MAX; - for arg in args.iter() { - if *arg < min { - min = *arg; - } - } - - min -} - /// Render a model. // This never actually gets called so this is fine. pub fn show(args: &mut Args) -> Result {