Declare std::math in KCL (BREAKING) (#6588)
Declare std::math in KCL Signed-off-by: Nick Cameron <nrc@ncameron.org>
This commit is contained in:
		@ -1307,7 +1307,7 @@ part001 = startSketchOn(XY)
 | 
			
		||||
  |> startProfile(at = [0, 0])
 | 
			
		||||
  |> line(end = [3, 4], tag = $seg01)
 | 
			
		||||
  |> line(end = [
 | 
			
		||||
  min([segLen(seg01), myVar]),
 | 
			
		||||
  math::min([segLen(seg01), myVar]),
 | 
			
		||||
  -legLen(hypotenuse = segLen(seg01), leg = myVar)
 | 
			
		||||
])
 | 
			
		||||
"#;
 | 
			
		||||
@ -1322,7 +1322,7 @@ part001 = startSketchOn(XY)
 | 
			
		||||
  |> startProfile(at = [0, 0])
 | 
			
		||||
  |> line(end = [3, 4], tag = $seg01)
 | 
			
		||||
  |> line(end = [
 | 
			
		||||
  min([segLen(seg01), myVar]),
 | 
			
		||||
  math::min([segLen(seg01), myVar]),
 | 
			
		||||
  legLen(hypotenuse = segLen(seg01), leg = myVar)
 | 
			
		||||
])
 | 
			
		||||
"#;
 | 
			
		||||
@ -1662,7 +1662,7 @@ shape = layer() |> patternTransform(instances = 10, transform = transform)
 | 
			
		||||
 | 
			
		||||
    #[tokio::test(flavor = "multi_thread")]
 | 
			
		||||
    async fn test_math_execute_with_functions() {
 | 
			
		||||
        let ast = r#"myVar = 2 + min([100, -1 + legLen(hypotenuse = 5, leg = 3)])"#;
 | 
			
		||||
        let ast = r#"myVar = 2 + math::min([100, -1 + legLen(hypotenuse = 5, leg = 3)])"#;
 | 
			
		||||
        let result = parse_execute(ast).await.unwrap();
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            5.0,
 | 
			
		||||
 | 
			
		||||
@ -669,8 +669,9 @@ impl NumericType {
 | 
			
		||||
                meta: meta.clone(),
 | 
			
		||||
            }),
 | 
			
		||||
 | 
			
		||||
            // We don't actually need to coerce, since we just keep the partially-known type with the value.
 | 
			
		||||
            (Default { .. }, Default { .. }) => Ok(KclValue::Number {
 | 
			
		||||
            // If we're coercing to a default, we treat this as coercing to Any since leaving the numeric type unspecified in a coercion situation
 | 
			
		||||
            // means accept any number rather than force the current default.
 | 
			
		||||
            (_, Default { .. }) => Ok(KclValue::Number {
 | 
			
		||||
                value: *value,
 | 
			
		||||
                ty: ty.clone(),
 | 
			
		||||
                meta: meta.clone(),
 | 
			
		||||
@ -698,16 +699,13 @@ impl NumericType {
 | 
			
		||||
            (Known(_), Known(_)) => Err(val.into()),
 | 
			
		||||
 | 
			
		||||
            // Known and unknown => we assume the rhs, possibly with adjustment
 | 
			
		||||
            (Known(UnitType::Count), Default { .. }) | (Default { .. }, Known(UnitType::Count)) => {
 | 
			
		||||
                Ok(KclValue::Number {
 | 
			
		||||
                    value: *value,
 | 
			
		||||
                    ty: Known(UnitType::Count),
 | 
			
		||||
                    meta: meta.clone(),
 | 
			
		||||
                })
 | 
			
		||||
            }
 | 
			
		||||
            (Default { .. }, Known(UnitType::Count)) => Ok(KclValue::Number {
 | 
			
		||||
                value: *value,
 | 
			
		||||
                ty: Known(UnitType::Count),
 | 
			
		||||
                meta: meta.clone(),
 | 
			
		||||
            }),
 | 
			
		||||
 | 
			
		||||
            (Known(UnitType::Length(l1)), Default { len: l2, .. })
 | 
			
		||||
            | (Default { len: l1, .. }, Known(UnitType::Length(l2))) => {
 | 
			
		||||
            (Default { len: l1, .. }, Known(UnitType::Length(l2))) => {
 | 
			
		||||
                let (value, ty) = l1.adjust_to(*value, *l2);
 | 
			
		||||
                Ok(KclValue::Number {
 | 
			
		||||
                    value,
 | 
			
		||||
@ -716,8 +714,7 @@ impl NumericType {
 | 
			
		||||
                })
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            (Known(UnitType::Angle(a1)), Default { angle: a2, .. })
 | 
			
		||||
            | (Default { angle: a1, .. }, Known(UnitType::Angle(a2))) => {
 | 
			
		||||
            (Default { angle: a1, .. }, Known(UnitType::Angle(a2))) => {
 | 
			
		||||
                let (value, ty) = a1.adjust_to(*value, *a2);
 | 
			
		||||
                Ok(KclValue::Number {
 | 
			
		||||
                    value,
 | 
			
		||||
@ -775,7 +772,7 @@ pub enum UnitType {
 | 
			
		||||
impl std::fmt::Display for UnitType {
 | 
			
		||||
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 | 
			
		||||
        match self {
 | 
			
		||||
            UnitType::Count => write!(f, "_"),
 | 
			
		||||
            UnitType::Count => write!(f, "Count"),
 | 
			
		||||
            UnitType::Length(l) => l.fmt(f),
 | 
			
		||||
            UnitType::Angle(a) => a.fmt(f),
 | 
			
		||||
        }
 | 
			
		||||
@ -2034,7 +2031,7 @@ mod test {
 | 
			
		||||
                .as_f64()
 | 
			
		||||
                .unwrap()
 | 
			
		||||
                .round(),
 | 
			
		||||
            25.0
 | 
			
		||||
            1.0
 | 
			
		||||
        );
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            rads.coerce(&NumericType::default().into(), &mut exec_state)
 | 
			
		||||
@ -2042,7 +2039,7 @@ mod test {
 | 
			
		||||
                .as_f64()
 | 
			
		||||
                .unwrap()
 | 
			
		||||
                .round(),
 | 
			
		||||
            57.0
 | 
			
		||||
            1.0
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -2084,14 +2081,19 @@ o = 3mm / 3
 | 
			
		||||
p = 3_ / 4
 | 
			
		||||
q = 4inch / 2_
 | 
			
		||||
 | 
			
		||||
r = min([0, 3, 42])
 | 
			
		||||
s = min([0, 3mm, -42])
 | 
			
		||||
t = min([100, 3in, 142mm])
 | 
			
		||||
u = min([3rad, 4in])
 | 
			
		||||
r = math::min([0, 3, 42])
 | 
			
		||||
s = math::min([0, 3mm, -42])
 | 
			
		||||
t = math::min([100, 3in, 142mm])
 | 
			
		||||
u = math::min([3rad, 4in])
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
        let result = parse_execute(program).await.unwrap();
 | 
			
		||||
        assert_eq!(result.exec_state.errors().len(), 5);
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            result.exec_state.errors().len(),
 | 
			
		||||
            5,
 | 
			
		||||
            "errors: {:?}",
 | 
			
		||||
            result.exec_state.errors()
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        assert_value_and_type("a", &result, 9.0, NumericType::default());
 | 
			
		||||
        assert_value_and_type("b", &result, 3.0, NumericType::default());
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,6 @@
 | 
			
		||||
//! Functions related to mathematics.
 | 
			
		||||
 | 
			
		||||
use anyhow::Result;
 | 
			
		||||
use kcl_derive_docs::stdlib;
 | 
			
		||||
 | 
			
		||||
use crate::{
 | 
			
		||||
    errors::KclError,
 | 
			
		||||
@ -26,36 +25,11 @@ pub async fn rem(exec_state: &mut ExecState, args: Args) -> Result<KclValue, Kcl
 | 
			
		||||
            "Calling `rem` on numbers which have unknown or incompatible units.\n\nYou may need to add information about the type of the argument, for example:\n  using a numeric suffix: `42{ty}`\n  or using type ascription: `foo(): number({ty})`"
 | 
			
		||||
        ));
 | 
			
		||||
    }
 | 
			
		||||
    let remainder = inner_rem(n, d);
 | 
			
		||||
    let remainder = n % d;
 | 
			
		||||
 | 
			
		||||
    Ok(args.make_user_val_from_f64_with_type(TyF64::new(remainder, ty)))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Compute the remainder after dividing `num` by `div`.
 | 
			
		||||
/// If `num` is negative, the result will be too.
 | 
			
		||||
///
 | 
			
		||||
/// ```no_run
 | 
			
		||||
/// assert(rem( 7,    divisor =   4), isEqualTo =   3, error = "remainder is 3")
 | 
			
		||||
/// assert(rem(-7,    divisor =   4), isEqualTo =  -3, error = "remainder is -3")
 | 
			
		||||
/// assert(rem( 7,    divisor =  -4), isEqualTo =   3, error = "remainder is 3")
 | 
			
		||||
/// assert(rem( 6,    divisor = 2.5), isEqualTo =   1, error = "remainder is 1")
 | 
			
		||||
/// assert(rem( 6.5,  divisor = 2.5), isEqualTo = 1.5, error = "remainder is 1.5")
 | 
			
		||||
/// assert(rem( 6.5,  divisor =   2), isEqualTo = 0.5, error = "remainder is 0.5")
 | 
			
		||||
/// ```
 | 
			
		||||
#[stdlib {
 | 
			
		||||
    name = "rem",
 | 
			
		||||
    tags = ["math"],
 | 
			
		||||
    keywords = true,
 | 
			
		||||
    unlabeled_first = true,
 | 
			
		||||
    args = {
 | 
			
		||||
        num = {docs = "The number which will be divided by `divisor`."},
 | 
			
		||||
        divisor = {docs = "The number which will divide `num`."},
 | 
			
		||||
    }
 | 
			
		||||
}]
 | 
			
		||||
fn inner_rem(num: f64, divisor: f64) -> f64 {
 | 
			
		||||
    num % divisor
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Compute the cosine of a number (in radians).
 | 
			
		||||
pub async fn cos(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
 | 
			
		||||
    let num: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::angle(), exec_state)?;
 | 
			
		||||
@ -80,184 +54,48 @@ pub async fn tan(exec_state: &mut ExecState, args: Args) -> Result<KclValue, Kcl
 | 
			
		||||
/// Compute the square root of a number.
 | 
			
		||||
pub async fn sqrt(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
 | 
			
		||||
    let input: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::num_any(), exec_state)?;
 | 
			
		||||
    let result = inner_sqrt(input.n);
 | 
			
		||||
    let result = input.n.sqrt();
 | 
			
		||||
 | 
			
		||||
    Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, exec_state.current_default_units())))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Compute the square root of a number.
 | 
			
		||||
///
 | 
			
		||||
/// ```no_run
 | 
			
		||||
/// exampleSketch = startSketchOn("XZ")
 | 
			
		||||
///   |> startProfile(at = [0, 0])
 | 
			
		||||
///   |> angledLine(
 | 
			
		||||
///     angle = 50,
 | 
			
		||||
///     length = sqrt(2500),
 | 
			
		||||
///   )
 | 
			
		||||
///   |> yLine(endAbsolute = 0)
 | 
			
		||||
///   |> close()
 | 
			
		||||
///
 | 
			
		||||
/// example = extrude(exampleSketch, length = 5)
 | 
			
		||||
/// ```
 | 
			
		||||
#[stdlib {
 | 
			
		||||
    name = "sqrt",
 | 
			
		||||
    tags = ["math"],
 | 
			
		||||
    keywords = true,
 | 
			
		||||
    unlabeled_first = true,
 | 
			
		||||
    args = {
 | 
			
		||||
        input = {docs = "The number to compute the square root of."},
 | 
			
		||||
    }
 | 
			
		||||
}]
 | 
			
		||||
fn inner_sqrt(input: f64) -> f64 {
 | 
			
		||||
    input.sqrt()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Compute the absolute value of a number.
 | 
			
		||||
pub async fn abs(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
 | 
			
		||||
    let input: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::num_any(), exec_state)?;
 | 
			
		||||
    let result = inner_abs(input.n);
 | 
			
		||||
    let result = input.n.abs();
 | 
			
		||||
 | 
			
		||||
    Ok(args.make_user_val_from_f64_with_type(input.map_value(result)))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Compute the absolute value of a number.
 | 
			
		||||
///
 | 
			
		||||
/// ```no_run
 | 
			
		||||
/// myAngle = -120
 | 
			
		||||
///
 | 
			
		||||
/// sketch001 = startSketchOn('XZ')
 | 
			
		||||
///   |> startProfile(at = [0, 0])
 | 
			
		||||
///   |> line(end = [8, 0])
 | 
			
		||||
///   |> angledLine(
 | 
			
		||||
///     angle = abs(myAngle),
 | 
			
		||||
///     length = 5,
 | 
			
		||||
///   )
 | 
			
		||||
///   |> line(end = [-5, 0])
 | 
			
		||||
///   |> angledLine(
 | 
			
		||||
///     angle = myAngle,
 | 
			
		||||
///     length = 5,
 | 
			
		||||
///   )
 | 
			
		||||
///   |> close()
 | 
			
		||||
///
 | 
			
		||||
/// baseExtrusion = extrude(sketch001, length = 5)
 | 
			
		||||
/// ```
 | 
			
		||||
#[stdlib {
 | 
			
		||||
    name = "abs",
 | 
			
		||||
    tags = ["math"],
 | 
			
		||||
    keywords = true,
 | 
			
		||||
    unlabeled_first = true,
 | 
			
		||||
    args = {
 | 
			
		||||
        input = {docs = "The number to compute the absolute value of."},
 | 
			
		||||
    }
 | 
			
		||||
}]
 | 
			
		||||
fn inner_abs(input: f64) -> f64 {
 | 
			
		||||
    input.abs()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Round a number to the nearest integer.
 | 
			
		||||
pub async fn round(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
 | 
			
		||||
    let input: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::num_any(), exec_state)?;
 | 
			
		||||
    let result = inner_round(input.n);
 | 
			
		||||
    let result = input.n.round();
 | 
			
		||||
 | 
			
		||||
    Ok(args.make_user_val_from_f64_with_type(input.map_value(result)))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Round a number to the nearest integer.
 | 
			
		||||
///
 | 
			
		||||
/// ```no_run
 | 
			
		||||
/// sketch001 = startSketchOn('XZ')
 | 
			
		||||
///    |> startProfile(at = [0, 0])
 | 
			
		||||
///    |> line(endAbsolute = [12, 10])
 | 
			
		||||
///    |> line(end = [round(7.02986), 0])
 | 
			
		||||
///    |> yLine(endAbsolute = 0)
 | 
			
		||||
///    |> close()
 | 
			
		||||
///
 | 
			
		||||
/// extrude001 = extrude(sketch001, length = 5)
 | 
			
		||||
/// ```
 | 
			
		||||
#[stdlib {
 | 
			
		||||
    name = "round",
 | 
			
		||||
    tags = ["math"],
 | 
			
		||||
    keywords = true,
 | 
			
		||||
    unlabeled_first = true,
 | 
			
		||||
    args = {
 | 
			
		||||
        input = {docs = "The number to round."},
 | 
			
		||||
    }
 | 
			
		||||
}]
 | 
			
		||||
fn inner_round(input: f64) -> f64 {
 | 
			
		||||
    input.round()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Compute the largest integer less than or equal to a number.
 | 
			
		||||
pub async fn floor(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
 | 
			
		||||
    let input: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::num_any(), exec_state)?;
 | 
			
		||||
    let result = inner_floor(input.n);
 | 
			
		||||
    let result = input.n.floor();
 | 
			
		||||
 | 
			
		||||
    Ok(args.make_user_val_from_f64_with_type(input.map_value(result)))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Compute the largest integer less than or equal to a number.
 | 
			
		||||
///
 | 
			
		||||
/// ```no_run
 | 
			
		||||
/// sketch001 = startSketchOn('XZ')
 | 
			
		||||
///    |> startProfile(at = [0, 0])
 | 
			
		||||
///    |> line(endAbsolute = [12, 10])
 | 
			
		||||
///    |> line(end = [floor(7.02986), 0])
 | 
			
		||||
///    |> yLine(endAbsolute = 0)
 | 
			
		||||
///    |> close()
 | 
			
		||||
///
 | 
			
		||||
/// extrude001 = extrude(sketch001, length = 5)
 | 
			
		||||
/// ```
 | 
			
		||||
#[stdlib {
 | 
			
		||||
    name = "floor",
 | 
			
		||||
    tags = ["math"],
 | 
			
		||||
    keywords = true,
 | 
			
		||||
    unlabeled_first = true,
 | 
			
		||||
    args = {
 | 
			
		||||
        input = {docs = "The number to round."},
 | 
			
		||||
    }
 | 
			
		||||
}]
 | 
			
		||||
fn inner_floor(input: f64) -> f64 {
 | 
			
		||||
    input.floor()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Compute the smallest integer greater than or equal to a number.
 | 
			
		||||
pub async fn ceil(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
 | 
			
		||||
    let input: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::num_any(), exec_state)?;
 | 
			
		||||
    let result = inner_ceil(input.n);
 | 
			
		||||
    let result = input.n.ceil();
 | 
			
		||||
 | 
			
		||||
    Ok(args.make_user_val_from_f64_with_type(input.map_value(result)))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Compute the smallest integer greater than or equal to a number.
 | 
			
		||||
///
 | 
			
		||||
/// ```no_run
 | 
			
		||||
/// sketch001 = startSketchOn('XZ')
 | 
			
		||||
///   |> startProfile(at = [0, 0])
 | 
			
		||||
///   |> line(endAbsolute = [12, 10])
 | 
			
		||||
///   |> line(end = [ceil(7.02986), 0])
 | 
			
		||||
///   |> yLine(endAbsolute = 0)
 | 
			
		||||
///   |> close()
 | 
			
		||||
///
 | 
			
		||||
/// extrude001 = extrude(sketch001, length = 5)
 | 
			
		||||
/// ```
 | 
			
		||||
#[stdlib {
 | 
			
		||||
    name = "ceil",
 | 
			
		||||
    tags = ["math"],
 | 
			
		||||
    keywords = true,
 | 
			
		||||
    unlabeled_first = true,
 | 
			
		||||
    args = {
 | 
			
		||||
        input = {docs = "The number to round."},
 | 
			
		||||
    }
 | 
			
		||||
}]
 | 
			
		||||
fn inner_ceil(input: f64) -> f64 {
 | 
			
		||||
    input.ceil()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Compute the minimum of the given arguments.
 | 
			
		||||
pub async fn min(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
 | 
			
		||||
    let nums: Vec<TyF64> = args.get_unlabeled_kw_arg_typed(
 | 
			
		||||
        "input",
 | 
			
		||||
        &RuntimeType::Array(Box::new(RuntimeType::num_any()), ArrayLen::None),
 | 
			
		||||
        &RuntimeType::Array(Box::new(RuntimeType::num_any()), ArrayLen::NonEmpty),
 | 
			
		||||
        exec_state,
 | 
			
		||||
    )?;
 | 
			
		||||
    let (nums, ty) = NumericType::combine_eq_array(&nums);
 | 
			
		||||
@ -267,50 +105,22 @@ pub async fn min(exec_state: &mut ExecState, args: Args) -> Result<KclValue, Kcl
 | 
			
		||||
            "Calling `min` on numbers which have unknown or incompatible units.\n\nYou may need to add information about the type of the argument, for example:\n  using a numeric suffix: `42{ty}`\n  or using type ascription: `foo(): number({ty})`",
 | 
			
		||||
        ));
 | 
			
		||||
    }
 | 
			
		||||
    let result = inner_min(nums);
 | 
			
		||||
 | 
			
		||||
    Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, ty)))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Compute the minimum of the given arguments.
 | 
			
		||||
///
 | 
			
		||||
/// ```no_run
 | 
			
		||||
/// exampleSketch = startSketchOn("XZ")
 | 
			
		||||
///   |> startProfile(at = [0, 0])
 | 
			
		||||
///   |> angledLine(
 | 
			
		||||
///     angle = 70,
 | 
			
		||||
///     length = min([15, 31, 4, 13, 22])
 | 
			
		||||
///   )
 | 
			
		||||
///   |> line(end = [20, 0])
 | 
			
		||||
///   |> close()
 | 
			
		||||
///
 | 
			
		||||
/// example = extrude(exampleSketch, length = 5)
 | 
			
		||||
/// ```
 | 
			
		||||
#[stdlib {
 | 
			
		||||
    name = "min",
 | 
			
		||||
    tags = ["math"],
 | 
			
		||||
    keywords = true,
 | 
			
		||||
    unlabeled_first = true,
 | 
			
		||||
    args = {
 | 
			
		||||
        input = {docs = "An array of numbers to compute the minimum of."},
 | 
			
		||||
    }
 | 
			
		||||
}]
 | 
			
		||||
fn inner_min(input: Vec<f64>) -> f64 {
 | 
			
		||||
    let mut min = f64::MAX;
 | 
			
		||||
    for num in input.iter() {
 | 
			
		||||
        if *num < min {
 | 
			
		||||
            min = *num;
 | 
			
		||||
    let mut result = f64::MAX;
 | 
			
		||||
    for num in nums {
 | 
			
		||||
        if num < result {
 | 
			
		||||
            result = num;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    min
 | 
			
		||||
    Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, ty)))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Compute the maximum of the given arguments.
 | 
			
		||||
pub async fn max(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
 | 
			
		||||
    let nums: Vec<TyF64> = args.get_unlabeled_kw_arg_typed(
 | 
			
		||||
        "input",
 | 
			
		||||
        &RuntimeType::Array(Box::new(RuntimeType::num_any()), ArrayLen::None),
 | 
			
		||||
        &RuntimeType::Array(Box::new(RuntimeType::num_any()), ArrayLen::NonEmpty),
 | 
			
		||||
        exec_state,
 | 
			
		||||
    )?;
 | 
			
		||||
    let (nums, ty) = NumericType::combine_eq_array(&nums);
 | 
			
		||||
@ -320,228 +130,60 @@ pub async fn max(exec_state: &mut ExecState, args: Args) -> Result<KclValue, Kcl
 | 
			
		||||
            "Calling `max` on numbers which have unknown or incompatible units.\n\nYou may need to add information about the type of the argument, for example:\n  using a numeric suffix: `42{ty}`\n  or using type ascription: `foo(): number({ty})`",
 | 
			
		||||
        ));
 | 
			
		||||
    }
 | 
			
		||||
    let result = inner_max(nums);
 | 
			
		||||
 | 
			
		||||
    Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, ty)))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Compute the maximum of the given arguments.
 | 
			
		||||
///
 | 
			
		||||
/// ```no_run
 | 
			
		||||
/// exampleSketch = startSketchOn("XZ")
 | 
			
		||||
///   |> startProfile(at = [0, 0])
 | 
			
		||||
///   |> angledLine(
 | 
			
		||||
///     angle = 70,
 | 
			
		||||
///     length = max([15, 31, 4, 13, 22])
 | 
			
		||||
///   )
 | 
			
		||||
///   |> line(end = [20, 0])
 | 
			
		||||
///   |> close()
 | 
			
		||||
///
 | 
			
		||||
/// example = extrude(exampleSketch, length = 5)
 | 
			
		||||
/// ```
 | 
			
		||||
#[stdlib {
 | 
			
		||||
    name = "max",
 | 
			
		||||
    tags = ["math"],
 | 
			
		||||
    keywords = true,
 | 
			
		||||
    unlabeled_first = true,
 | 
			
		||||
    args = {
 | 
			
		||||
        input = {docs = "An array of numbers to compute the maximum of."},
 | 
			
		||||
    }
 | 
			
		||||
}]
 | 
			
		||||
fn inner_max(input: Vec<f64>) -> f64 {
 | 
			
		||||
    let mut max = f64::MIN;
 | 
			
		||||
    for num in input.iter() {
 | 
			
		||||
        if *num > max {
 | 
			
		||||
            max = *num;
 | 
			
		||||
    let mut result = f64::MIN;
 | 
			
		||||
    for num in nums {
 | 
			
		||||
        if num > result {
 | 
			
		||||
            result = num;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    max
 | 
			
		||||
    Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, ty)))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Compute the number to a power.
 | 
			
		||||
pub async fn pow(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
 | 
			
		||||
    let input: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::num_any(), exec_state)?;
 | 
			
		||||
    let exp: TyF64 = args.get_kw_arg_typed("exp", &RuntimeType::count(), exec_state)?;
 | 
			
		||||
    let result = inner_pow(input.n, exp.n);
 | 
			
		||||
    let result = input.n.powf(exp.n);
 | 
			
		||||
 | 
			
		||||
    Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, exec_state.current_default_units())))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Compute the number to a power.
 | 
			
		||||
///
 | 
			
		||||
/// ```no_run
 | 
			
		||||
/// exampleSketch = startSketchOn("XZ")
 | 
			
		||||
///   |> startProfile(at = [0, 0])
 | 
			
		||||
///   |> angledLine(
 | 
			
		||||
///     angle = 50,
 | 
			
		||||
///     length = pow(5, exp = 2),
 | 
			
		||||
///   )
 | 
			
		||||
///   |> yLine(endAbsolute = 0)
 | 
			
		||||
///   |> close()
 | 
			
		||||
///
 | 
			
		||||
/// example = extrude(exampleSketch, length = 5)
 | 
			
		||||
/// ```
 | 
			
		||||
#[stdlib {
 | 
			
		||||
    name = "pow",
 | 
			
		||||
    tags = ["math"],
 | 
			
		||||
    keywords = true,
 | 
			
		||||
    unlabeled_first = true,
 | 
			
		||||
    args = {
 | 
			
		||||
        input = {docs = "The number to raise."},
 | 
			
		||||
        exp = {docs = "The power to raise to."},
 | 
			
		||||
    }
 | 
			
		||||
}]
 | 
			
		||||
fn inner_pow(input: f64, exp: f64) -> f64 {
 | 
			
		||||
    input.powf(exp)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Compute the arccosine of a number (in radians).
 | 
			
		||||
pub async fn acos(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
 | 
			
		||||
    let input: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::count(), exec_state)?;
 | 
			
		||||
    let result = inner_acos(input.n);
 | 
			
		||||
    let result = input.n.acos();
 | 
			
		||||
 | 
			
		||||
    Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, NumericType::radians())))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Compute the arccosine of a number (in radians).
 | 
			
		||||
///
 | 
			
		||||
/// ```no_run
 | 
			
		||||
/// sketch001 = startSketchOn('XZ')
 | 
			
		||||
///   |> startProfile(at = [0, 0])
 | 
			
		||||
///   |> angledLine(
 | 
			
		||||
///     angle = units::toDegrees(acos(0.5)),
 | 
			
		||||
///     length = 10,
 | 
			
		||||
///   )
 | 
			
		||||
///   |> line(end = [5, 0])
 | 
			
		||||
///   |> line(endAbsolute = [12, 0])
 | 
			
		||||
///   |> close()
 | 
			
		||||
///
 | 
			
		||||
/// extrude001 = extrude(sketch001, length = 5)
 | 
			
		||||
/// ```
 | 
			
		||||
#[stdlib {
 | 
			
		||||
    name = "acos",
 | 
			
		||||
    tags = ["math"],
 | 
			
		||||
    keywords = true,
 | 
			
		||||
    unlabeled_first = true,
 | 
			
		||||
    args = {
 | 
			
		||||
        input = {docs = "The number to compute arccosine of."},
 | 
			
		||||
    }
 | 
			
		||||
}]
 | 
			
		||||
fn inner_acos(input: f64) -> f64 {
 | 
			
		||||
    input.acos()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Compute the arcsine of a number (in radians).
 | 
			
		||||
pub async fn asin(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
 | 
			
		||||
    let input: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::count(), exec_state)?;
 | 
			
		||||
    let result = inner_asin(input.n);
 | 
			
		||||
    let result = input.n.asin();
 | 
			
		||||
 | 
			
		||||
    Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, NumericType::radians())))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Compute the arcsine of a number (in radians).
 | 
			
		||||
///
 | 
			
		||||
/// ```no_run
 | 
			
		||||
/// sketch001 = startSketchOn('XZ')
 | 
			
		||||
///   |> startProfile(at = [0, 0])
 | 
			
		||||
///   |> angledLine(
 | 
			
		||||
///     angle = units::toDegrees(asin(0.5)),
 | 
			
		||||
///     length = 20,
 | 
			
		||||
///   )
 | 
			
		||||
///   |> yLine(endAbsolute = 0)
 | 
			
		||||
///   |> close()
 | 
			
		||||
///
 | 
			
		||||
/// extrude001 = extrude(sketch001, length = 5)
 | 
			
		||||
/// ```
 | 
			
		||||
#[stdlib {
 | 
			
		||||
    name = "asin",
 | 
			
		||||
    tags = ["math"],
 | 
			
		||||
    keywords = true,
 | 
			
		||||
    unlabeled_first = true,
 | 
			
		||||
    args = {
 | 
			
		||||
        input = {docs = "The number to compute arcsine of."},
 | 
			
		||||
    }
 | 
			
		||||
}]
 | 
			
		||||
fn inner_asin(input: f64) -> f64 {
 | 
			
		||||
    input.asin()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Compute the arctangent of a number (in radians).
 | 
			
		||||
pub async fn atan(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
 | 
			
		||||
    let input: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::count(), exec_state)?;
 | 
			
		||||
    let result = inner_atan(input.n);
 | 
			
		||||
    let result = input.n.atan();
 | 
			
		||||
 | 
			
		||||
    Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, NumericType::radians())))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Compute the arctangent of a number (in radians).
 | 
			
		||||
///
 | 
			
		||||
/// Consider using `atan2()` instead for the true inverse of tangent.
 | 
			
		||||
///
 | 
			
		||||
/// ```no_run
 | 
			
		||||
/// sketch001 = startSketchOn('XZ')
 | 
			
		||||
///   |> startProfile(at = [0, 0])
 | 
			
		||||
///   |> angledLine(
 | 
			
		||||
///     angle = units::toDegrees(atan(1.25)),
 | 
			
		||||
///     length = 20,
 | 
			
		||||
///   )
 | 
			
		||||
///   |> yLine(endAbsolute = 0)
 | 
			
		||||
///   |> close()
 | 
			
		||||
///
 | 
			
		||||
/// extrude001 = extrude(sketch001, length = 5)
 | 
			
		||||
/// ```
 | 
			
		||||
#[stdlib {
 | 
			
		||||
    name = "atan",
 | 
			
		||||
    tags = ["math"],
 | 
			
		||||
    keywords = true,
 | 
			
		||||
    unlabeled_first = true,
 | 
			
		||||
    args = {
 | 
			
		||||
        input = {docs = "The number to compute arctangent of."},
 | 
			
		||||
    }
 | 
			
		||||
}]
 | 
			
		||||
fn inner_atan(input: f64) -> f64 {
 | 
			
		||||
    input.atan()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Compute the four quadrant arctangent of Y and X (in radians).
 | 
			
		||||
pub async fn atan2(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
 | 
			
		||||
    let y = args.get_kw_arg_typed("y", &RuntimeType::length(), exec_state)?;
 | 
			
		||||
    let x = args.get_kw_arg_typed("x", &RuntimeType::length(), exec_state)?;
 | 
			
		||||
    let (y, x, _) = NumericType::combine_eq_coerce(y, x);
 | 
			
		||||
    let result = inner_atan2(y, x);
 | 
			
		||||
    let result = y.atan2(x);
 | 
			
		||||
 | 
			
		||||
    Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, NumericType::radians())))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Compute the four quadrant arctangent of Y and X (in radians).
 | 
			
		||||
///
 | 
			
		||||
/// ```no_run
 | 
			
		||||
/// sketch001 = startSketchOn(XZ)
 | 
			
		||||
///   |> startProfile(at = [0, 0])
 | 
			
		||||
///   |> angledLine(
 | 
			
		||||
///     angle = units::toDegrees(atan2(y = 1.25, x = 2)),
 | 
			
		||||
///     length = 20,
 | 
			
		||||
///   )
 | 
			
		||||
///   |> yLine(endAbsolute = 0)
 | 
			
		||||
///   |> close()
 | 
			
		||||
///
 | 
			
		||||
/// extrude001 = extrude(sketch001, length = 5)
 | 
			
		||||
/// ```
 | 
			
		||||
#[stdlib {
 | 
			
		||||
    name = "atan2",
 | 
			
		||||
    tags = ["math"],
 | 
			
		||||
    keywords = true,
 | 
			
		||||
    unlabeled_first = false,
 | 
			
		||||
    args = {
 | 
			
		||||
        y = { docs = "Y"},
 | 
			
		||||
        x = { docs = "X"},
 | 
			
		||||
    }
 | 
			
		||||
}]
 | 
			
		||||
fn inner_atan2(y: f64, x: f64) -> f64 {
 | 
			
		||||
    y.atan2(x)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Compute the logarithm of the number with respect to an arbitrary base.
 | 
			
		||||
///
 | 
			
		||||
/// The result might not be correctly rounded owing to implementation
 | 
			
		||||
@ -550,166 +192,31 @@ fn inner_atan2(y: f64, x: f64) -> f64 {
 | 
			
		||||
pub async fn log(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
 | 
			
		||||
    let input: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::num_any(), exec_state)?;
 | 
			
		||||
    let base: TyF64 = args.get_kw_arg_typed("base", &RuntimeType::count(), exec_state)?;
 | 
			
		||||
    let result = inner_log(input.n, base.n);
 | 
			
		||||
    let result = input.n.log(base.n);
 | 
			
		||||
 | 
			
		||||
    Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, exec_state.current_default_units())))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Compute the logarithm of the number with respect to an arbitrary base.
 | 
			
		||||
///
 | 
			
		||||
/// The result might not be correctly rounded owing to implementation
 | 
			
		||||
/// details; `log2()` can produce more accurate results for base 2,
 | 
			
		||||
/// and `log10()` can produce more accurate results for base 10.
 | 
			
		||||
///
 | 
			
		||||
/// ```no_run
 | 
			
		||||
/// exampleSketch = startSketchOn("XZ")
 | 
			
		||||
///   |> startProfile(at = [0, 0])
 | 
			
		||||
///   |> line(end = [log(100, base = 5), 0])
 | 
			
		||||
///   |> line(end = [5, 8])
 | 
			
		||||
///   |> line(end = [-10, 0])
 | 
			
		||||
///   |> close()
 | 
			
		||||
///
 | 
			
		||||
/// example = extrude(exampleSketch, length = 5)
 | 
			
		||||
/// ```
 | 
			
		||||
#[stdlib {
 | 
			
		||||
    name = "log",
 | 
			
		||||
    tags = ["math"],
 | 
			
		||||
    keywords = true,
 | 
			
		||||
    unlabeled_first = true,
 | 
			
		||||
    args = {
 | 
			
		||||
        input = {docs = "The number to compute the logarithm of."},
 | 
			
		||||
        base = {docs = "The base of the logarithm."},
 | 
			
		||||
    }
 | 
			
		||||
}]
 | 
			
		||||
fn inner_log(input: f64, base: f64) -> f64 {
 | 
			
		||||
    input.log(base)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Compute the base 2 logarithm of the number.
 | 
			
		||||
pub async fn log2(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
 | 
			
		||||
    let input: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::num_any(), exec_state)?;
 | 
			
		||||
    let result = inner_log2(input.n);
 | 
			
		||||
    let result = input.n.log2();
 | 
			
		||||
 | 
			
		||||
    Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, exec_state.current_default_units())))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Compute the base 2 logarithm of the number.
 | 
			
		||||
///
 | 
			
		||||
/// ```no_run
 | 
			
		||||
/// exampleSketch = startSketchOn("XZ")
 | 
			
		||||
///   |> startProfile(at = [0, 0])
 | 
			
		||||
///   |> line(end = [log2(100), 0])
 | 
			
		||||
///   |> line(end = [5, 8])
 | 
			
		||||
///   |> line(end = [-10, 0])
 | 
			
		||||
///   |> close()
 | 
			
		||||
///
 | 
			
		||||
/// example = extrude(exampleSketch, length = 5)
 | 
			
		||||
/// ```
 | 
			
		||||
#[stdlib {
 | 
			
		||||
    name = "log2",
 | 
			
		||||
    tags = ["math"],
 | 
			
		||||
    keywords = true,
 | 
			
		||||
    unlabeled_first = true,
 | 
			
		||||
    args = {
 | 
			
		||||
        input = {docs = "The number to compute the logarithm of."},
 | 
			
		||||
    }
 | 
			
		||||
}]
 | 
			
		||||
fn inner_log2(input: f64) -> f64 {
 | 
			
		||||
    input.log2()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Compute the base 10 logarithm of the number.
 | 
			
		||||
pub async fn log10(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
 | 
			
		||||
    let input: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::num_any(), exec_state)?;
 | 
			
		||||
    let result = inner_log10(input.n);
 | 
			
		||||
    let result = input.n.log10();
 | 
			
		||||
 | 
			
		||||
    Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, exec_state.current_default_units())))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Compute the base 10 logarithm of the number.
 | 
			
		||||
///
 | 
			
		||||
/// ```no_run
 | 
			
		||||
/// exampleSketch = startSketchOn("XZ")
 | 
			
		||||
///   |> startProfile(at = [0, 0])
 | 
			
		||||
///   |> line(end = [log10(100), 0])
 | 
			
		||||
///   |> line(end = [5, 8])
 | 
			
		||||
///   |> line(end = [-10, 0])
 | 
			
		||||
///   |> close()
 | 
			
		||||
///
 | 
			
		||||
/// example = extrude(exampleSketch, length = 5)
 | 
			
		||||
/// ```
 | 
			
		||||
#[stdlib {
 | 
			
		||||
    name = "log10",
 | 
			
		||||
    tags = ["math"],
 | 
			
		||||
}]
 | 
			
		||||
fn inner_log10(num: f64) -> f64 {
 | 
			
		||||
    num.log10()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Compute the natural logarithm of the number.
 | 
			
		||||
pub async fn ln(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
 | 
			
		||||
    let input: TyF64 = args.get_unlabeled_kw_arg_typed("input", &RuntimeType::num_any(), exec_state)?;
 | 
			
		||||
    let result = inner_ln(input.n);
 | 
			
		||||
    let result = input.n.ln();
 | 
			
		||||
 | 
			
		||||
    Ok(args.make_user_val_from_f64_with_type(TyF64::new(result, exec_state.current_default_units())))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Compute the natural logarithm of the number.
 | 
			
		||||
///
 | 
			
		||||
/// ```no_run
 | 
			
		||||
/// exampleSketch = startSketchOn("XZ")
 | 
			
		||||
///   |> startProfile(at = [0, 0])
 | 
			
		||||
///   |> line(end = [ln(100), 15])
 | 
			
		||||
///   |> line(end = [5, -6])
 | 
			
		||||
///   |> line(end = [-10, -10])
 | 
			
		||||
///   |> close()
 | 
			
		||||
///
 | 
			
		||||
/// example = extrude(exampleSketch, length = 5)
 | 
			
		||||
/// ```
 | 
			
		||||
#[stdlib {
 | 
			
		||||
    name = "ln",
 | 
			
		||||
    tags = ["math"],
 | 
			
		||||
    keywords = true,
 | 
			
		||||
    unlabeled_first = true,
 | 
			
		||||
    args = {
 | 
			
		||||
        input = {docs = "The number to compute the logarithm of."},
 | 
			
		||||
    }
 | 
			
		||||
}]
 | 
			
		||||
fn inner_ln(input: f64) -> f64 {
 | 
			
		||||
    input.ln()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(test)]
 | 
			
		||||
mod tests {
 | 
			
		||||
    use pretty_assertions::assert_eq;
 | 
			
		||||
 | 
			
		||||
    use super::*;
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_inner_max() {
 | 
			
		||||
        let nums = vec![4.0, 5.0, 6.0];
 | 
			
		||||
        let result = inner_max(nums);
 | 
			
		||||
        assert_eq!(result, 6.0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_inner_max_with_neg() {
 | 
			
		||||
        let nums = vec![4.0, -5.0];
 | 
			
		||||
        let result = inner_max(nums);
 | 
			
		||||
        assert_eq!(result, 4.0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_inner_min() {
 | 
			
		||||
        let nums = vec![4.0, 5.0, 6.0];
 | 
			
		||||
        let result = inner_min(nums);
 | 
			
		||||
        assert_eq!(result, 4.0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_inner_min_with_neg() {
 | 
			
		||||
        let nums = vec![4.0, -5.0];
 | 
			
		||||
        let result = inner_min(nums);
 | 
			
		||||
        assert_eq!(result, -5.0);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -104,23 +104,6 @@ lazy_static! {
 | 
			
		||||
        Box::new(crate::std::edge::GetCommonEdge),
 | 
			
		||||
        Box::new(crate::std::sweep::Sweep),
 | 
			
		||||
        Box::new(crate::std::loft::Loft),
 | 
			
		||||
        Box::new(crate::std::math::Acos),
 | 
			
		||||
        Box::new(crate::std::math::Asin),
 | 
			
		||||
        Box::new(crate::std::math::Atan),
 | 
			
		||||
        Box::new(crate::std::math::Atan2),
 | 
			
		||||
        Box::new(crate::std::math::Sqrt),
 | 
			
		||||
        Box::new(crate::std::math::Abs),
 | 
			
		||||
        Box::new(crate::std::math::Rem),
 | 
			
		||||
        Box::new(crate::std::math::Round),
 | 
			
		||||
        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),
 | 
			
		||||
        Box::new(crate::std::math::Log),
 | 
			
		||||
        Box::new(crate::std::math::Log2),
 | 
			
		||||
        Box::new(crate::std::math::Log10),
 | 
			
		||||
        Box::new(crate::std::math::Ln),
 | 
			
		||||
        Box::new(crate::std::assert::Assert),
 | 
			
		||||
        Box::new(crate::std::assert::AssertIs),
 | 
			
		||||
        Box::new(crate::std::transform::Scale),
 | 
			
		||||
@ -176,6 +159,75 @@ pub(crate) fn std_fn(path: &str, fn_name: &str) -> (crate::std::StdFn, StdFnProp
 | 
			
		||||
            |e, a| Box::pin(crate::std::math::tan(e, a)),
 | 
			
		||||
            StdFnProps::default("std::math::tan"),
 | 
			
		||||
        ),
 | 
			
		||||
        ("math", "acos") => (
 | 
			
		||||
            |e, a| Box::pin(crate::std::math::acos(e, a)),
 | 
			
		||||
            StdFnProps::default("std::math::acos"),
 | 
			
		||||
        ),
 | 
			
		||||
        ("math", "asin") => (
 | 
			
		||||
            |e, a| Box::pin(crate::std::math::asin(e, a)),
 | 
			
		||||
            StdFnProps::default("std::math::asin"),
 | 
			
		||||
        ),
 | 
			
		||||
        ("math", "atan") => (
 | 
			
		||||
            |e, a| Box::pin(crate::std::math::atan(e, a)),
 | 
			
		||||
            StdFnProps::default("std::math::atan"),
 | 
			
		||||
        ),
 | 
			
		||||
        ("math", "atan2") => (
 | 
			
		||||
            |e, a| Box::pin(crate::std::math::atan2(e, a)),
 | 
			
		||||
            StdFnProps::default("std::math::atan2"),
 | 
			
		||||
        ),
 | 
			
		||||
        ("math", "sqrt") => (
 | 
			
		||||
            |e, a| Box::pin(crate::std::math::sqrt(e, a)),
 | 
			
		||||
            StdFnProps::default("std::math::sqrt"),
 | 
			
		||||
        ),
 | 
			
		||||
 | 
			
		||||
        ("math", "abs") => (
 | 
			
		||||
            |e, a| Box::pin(crate::std::math::abs(e, a)),
 | 
			
		||||
            StdFnProps::default("std::math::abs"),
 | 
			
		||||
        ),
 | 
			
		||||
        ("math", "rem") => (
 | 
			
		||||
            |e, a| Box::pin(crate::std::math::rem(e, a)),
 | 
			
		||||
            StdFnProps::default("std::math::rem"),
 | 
			
		||||
        ),
 | 
			
		||||
        ("math", "round") => (
 | 
			
		||||
            |e, a| Box::pin(crate::std::math::round(e, a)),
 | 
			
		||||
            StdFnProps::default("std::math::round"),
 | 
			
		||||
        ),
 | 
			
		||||
        ("math", "floor") => (
 | 
			
		||||
            |e, a| Box::pin(crate::std::math::floor(e, a)),
 | 
			
		||||
            StdFnProps::default("std::math::floor"),
 | 
			
		||||
        ),
 | 
			
		||||
        ("math", "ceil") => (
 | 
			
		||||
            |e, a| Box::pin(crate::std::math::ceil(e, a)),
 | 
			
		||||
            StdFnProps::default("std::math::ceil"),
 | 
			
		||||
        ),
 | 
			
		||||
        ("math", "min") => (
 | 
			
		||||
            |e, a| Box::pin(crate::std::math::min(e, a)),
 | 
			
		||||
            StdFnProps::default("std::math::min"),
 | 
			
		||||
        ),
 | 
			
		||||
        ("math", "max") => (
 | 
			
		||||
            |e, a| Box::pin(crate::std::math::max(e, a)),
 | 
			
		||||
            StdFnProps::default("std::math::max"),
 | 
			
		||||
        ),
 | 
			
		||||
        ("math", "pow") => (
 | 
			
		||||
            |e, a| Box::pin(crate::std::math::pow(e, a)),
 | 
			
		||||
            StdFnProps::default("std::math::pow"),
 | 
			
		||||
        ),
 | 
			
		||||
        ("math", "log") => (
 | 
			
		||||
            |e, a| Box::pin(crate::std::math::log(e, a)),
 | 
			
		||||
            StdFnProps::default("std::math::log"),
 | 
			
		||||
        ),
 | 
			
		||||
        ("math", "log2") => (
 | 
			
		||||
            |e, a| Box::pin(crate::std::math::log2(e, a)),
 | 
			
		||||
            StdFnProps::default("std::math::log2"),
 | 
			
		||||
        ),
 | 
			
		||||
        ("math", "log10") => (
 | 
			
		||||
            |e, a| Box::pin(crate::std::math::log10(e, a)),
 | 
			
		||||
            StdFnProps::default("std::math::log10"),
 | 
			
		||||
        ),
 | 
			
		||||
        ("math", "ln") => (
 | 
			
		||||
            |e, a| Box::pin(crate::std::math::ln(e, a)),
 | 
			
		||||
            StdFnProps::default("std::math::ln"),
 | 
			
		||||
        ),
 | 
			
		||||
        ("sketch", "circle") => (
 | 
			
		||||
            |e, a| Box::pin(crate::std::shapes::circle(e, a)),
 | 
			
		||||
            StdFnProps::default("std::sketch::circle"),
 | 
			
		||||
 | 
			
		||||
@ -202,7 +202,7 @@ pub async fn pattern_transform_2d(exec_state: &mut ExecState, args: Args) -> Res
 | 
			
		||||
/// // Defines how to modify each layer of the vase.
 | 
			
		||||
/// // Each replica is shifted up the Z axis, and has a smoothly-varying radius
 | 
			
		||||
/// fn transform(replicaId) {
 | 
			
		||||
///   scale = r * abs(1 - (t * replicaId)) * (5 + math::cos((replicaId / 8): number(rad)))
 | 
			
		||||
///   scale = r * math::abs(1 - (t * replicaId)) * (5 + math::cos((replicaId / 8): number(rad)))
 | 
			
		||||
///   return {
 | 
			
		||||
///     translate = [0, 0, replicaId * 10],
 | 
			
		||||
///     scale = [scale, scale, 0],
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user