2023-09-13 15:09:07 -07:00
|
|
|
|
//! Functions related to mathematics.
|
|
|
|
|
|
|
|
|
|
use anyhow::Result;
|
|
|
|
|
use derive_docs::stdlib;
|
|
|
|
|
use schemars::JsonSchema;
|
|
|
|
|
|
2023-09-15 15:54:49 -07:00
|
|
|
|
use crate::{
|
|
|
|
|
errors::{KclError, KclErrorDetails},
|
2024-09-16 15:10:33 -04:00
|
|
|
|
executor::{ExecState, KclValue},
|
2023-09-15 15:54:49 -07:00
|
|
|
|
std::Args,
|
|
|
|
|
};
|
2023-09-13 15:09:07 -07:00
|
|
|
|
|
2024-08-06 20:27:26 -04:00
|
|
|
|
/// Compute the cosine of a number (in radians).
|
2024-09-16 15:10:33 -04:00
|
|
|
|
pub async fn cos(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
2023-09-13 15:09:07 -07:00
|
|
|
|
let num = args.get_number()?;
|
|
|
|
|
let result = inner_cos(num)?;
|
|
|
|
|
|
|
|
|
|
args.make_user_val_from_f64(result)
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-06 20:27:26 -04:00
|
|
|
|
/// Compute the cosine of a number (in radians).
|
2024-03-13 12:56:46 -07:00
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
2024-05-22 09:15:38 -07:00
|
|
|
|
/// const exampleSketch = startSketchOn("XZ")
|
|
|
|
|
/// |> startProfileAt([0, 0], %)
|
|
|
|
|
/// |> angledLine({
|
|
|
|
|
/// angle: 30,
|
|
|
|
|
/// length: 3 / cos(toRadians(30)),
|
|
|
|
|
/// }, %)
|
|
|
|
|
/// |> yLineTo(0, %)
|
|
|
|
|
/// |> close(%)
|
|
|
|
|
///
|
|
|
|
|
/// const example = extrude(5, exampleSketch)
|
2024-03-13 12:56:46 -07:00
|
|
|
|
/// ```
|
2023-09-13 15:09:07 -07:00
|
|
|
|
#[stdlib {
|
|
|
|
|
name = "cos",
|
2024-03-26 21:28:50 -07:00
|
|
|
|
tags = ["math"],
|
2023-09-13 15:09:07 -07:00
|
|
|
|
}]
|
|
|
|
|
fn inner_cos(num: f64) -> Result<f64, KclError> {
|
|
|
|
|
Ok(num.cos())
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-06 20:27:26 -04:00
|
|
|
|
/// Compute the sine of a number (in radians).
|
2024-09-16 15:10:33 -04:00
|
|
|
|
pub async fn sin(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
2023-09-13 15:09:07 -07:00
|
|
|
|
let num = args.get_number()?;
|
|
|
|
|
let result = inner_sin(num)?;
|
|
|
|
|
|
|
|
|
|
args.make_user_val_from_f64(result)
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-06 20:27:26 -04:00
|
|
|
|
/// Compute the sine of a number (in radians).
|
2024-03-13 12:56:46 -07:00
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
2024-05-22 09:15:38 -07:00
|
|
|
|
/// const exampleSketch = startSketchOn("XZ")
|
|
|
|
|
/// |> startProfileAt([0, 0], %)
|
|
|
|
|
/// |> angledLine({
|
|
|
|
|
/// angle: 50,
|
|
|
|
|
/// length: 15 / sin(toDegrees(135)),
|
|
|
|
|
/// }, %)
|
|
|
|
|
/// |> yLineTo(0, %)
|
|
|
|
|
/// |> close(%)
|
|
|
|
|
///
|
|
|
|
|
/// const example = extrude(5, exampleSketch)
|
2024-03-13 12:56:46 -07:00
|
|
|
|
/// ```
|
2023-09-13 15:09:07 -07:00
|
|
|
|
#[stdlib {
|
|
|
|
|
name = "sin",
|
2024-03-26 21:28:50 -07:00
|
|
|
|
tags = ["math"],
|
2023-09-13 15:09:07 -07:00
|
|
|
|
}]
|
|
|
|
|
fn inner_sin(num: f64) -> Result<f64, KclError> {
|
|
|
|
|
Ok(num.sin())
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-06 20:27:26 -04:00
|
|
|
|
/// Compute the tangent of a number (in radians).
|
2024-09-16 15:10:33 -04:00
|
|
|
|
pub async fn tan(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
2023-09-13 15:09:07 -07:00
|
|
|
|
let num = args.get_number()?;
|
|
|
|
|
let result = inner_tan(num)?;
|
|
|
|
|
|
|
|
|
|
args.make_user_val_from_f64(result)
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-06 20:27:26 -04:00
|
|
|
|
/// Compute the tangent of a number (in radians).
|
2024-03-13 12:56:46 -07:00
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
2024-05-22 09:15:38 -07:00
|
|
|
|
/// const exampleSketch = startSketchOn("XZ")
|
|
|
|
|
/// |> startProfileAt([0, 0], %)
|
|
|
|
|
/// |> angledLine({
|
|
|
|
|
/// angle: 50,
|
|
|
|
|
/// length: 50 * tan(1/2),
|
|
|
|
|
/// }, %)
|
|
|
|
|
/// |> yLineTo(0, %)
|
|
|
|
|
/// |> close(%)
|
|
|
|
|
///
|
|
|
|
|
/// const example = extrude(5, exampleSketch)
|
2024-03-13 12:56:46 -07:00
|
|
|
|
/// ```
|
2023-09-13 15:09:07 -07:00
|
|
|
|
#[stdlib {
|
|
|
|
|
name = "tan",
|
2024-03-26 21:28:50 -07:00
|
|
|
|
tags = ["math"],
|
2023-09-13 15:09:07 -07:00
|
|
|
|
}]
|
|
|
|
|
fn inner_tan(num: f64) -> Result<f64, KclError> {
|
|
|
|
|
Ok(num.tan())
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-15 17:40:57 -07:00
|
|
|
|
/// Return the value of `pi`. Archimedes’ constant (π).
|
2024-09-16 15:10:33 -04:00
|
|
|
|
pub async fn pi(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
2023-09-13 15:09:07 -07:00
|
|
|
|
let result = inner_pi()?;
|
|
|
|
|
|
|
|
|
|
args.make_user_val_from_f64(result)
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-15 17:40:57 -07:00
|
|
|
|
/// Return the value of `pi`. Archimedes’ constant (π).
|
2024-03-13 12:56:46 -07:00
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
2024-05-22 09:15:38 -07:00
|
|
|
|
/// const circumference = 70
|
|
|
|
|
///
|
|
|
|
|
/// const exampleSketch = startSketchOn("XZ")
|
2024-09-23 22:42:51 +10:00
|
|
|
|
/// |> circle({ center: [0, 0], radius: circumference/ (2 * pi()) }, %)
|
2024-05-22 09:15:38 -07:00
|
|
|
|
///
|
|
|
|
|
/// const example = extrude(5, exampleSketch)
|
2024-03-13 12:56:46 -07:00
|
|
|
|
/// ```
|
2023-09-13 15:09:07 -07:00
|
|
|
|
#[stdlib {
|
|
|
|
|
name = "pi",
|
2024-03-26 21:28:50 -07:00
|
|
|
|
tags = ["math"],
|
2023-09-13 15:09:07 -07:00
|
|
|
|
}]
|
|
|
|
|
fn inner_pi() -> Result<f64, KclError> {
|
|
|
|
|
Ok(std::f64::consts::PI)
|
|
|
|
|
}
|
2023-09-15 15:54:49 -07:00
|
|
|
|
|
2024-08-06 20:27:26 -04:00
|
|
|
|
/// Compute the square root of a number.
|
2024-09-16 15:10:33 -04:00
|
|
|
|
pub async fn sqrt(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
2023-09-15 15:54:49 -07:00
|
|
|
|
let num = args.get_number()?;
|
|
|
|
|
let result = inner_sqrt(num)?;
|
|
|
|
|
|
|
|
|
|
args.make_user_val_from_f64(result)
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-06 20:27:26 -04:00
|
|
|
|
/// Compute the square root of a number.
|
2024-03-13 12:56:46 -07:00
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
2024-05-22 09:15:38 -07:00
|
|
|
|
/// const exampleSketch = startSketchOn("XZ")
|
|
|
|
|
/// |> startProfileAt([0, 0], %)
|
|
|
|
|
/// |> angledLine({
|
|
|
|
|
/// angle: 50,
|
|
|
|
|
/// length: sqrt(2500),
|
|
|
|
|
/// }, %)
|
|
|
|
|
/// |> yLineTo(0, %)
|
|
|
|
|
/// |> close(%)
|
|
|
|
|
///
|
|
|
|
|
/// const example = extrude(5, exampleSketch)
|
2024-03-13 12:56:46 -07:00
|
|
|
|
/// ```
|
2023-09-15 15:54:49 -07:00
|
|
|
|
#[stdlib {
|
|
|
|
|
name = "sqrt",
|
2024-03-26 21:28:50 -07:00
|
|
|
|
tags = ["math"],
|
2023-09-15 15:54:49 -07:00
|
|
|
|
}]
|
|
|
|
|
fn inner_sqrt(num: f64) -> Result<f64, KclError> {
|
|
|
|
|
Ok(num.sqrt())
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-06 20:27:26 -04:00
|
|
|
|
/// Compute the absolute value of a number.
|
2024-09-16 15:10:33 -04:00
|
|
|
|
pub async fn abs(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
2023-09-15 15:54:49 -07:00
|
|
|
|
let num = args.get_number()?;
|
|
|
|
|
let result = inner_abs(num)?;
|
|
|
|
|
|
|
|
|
|
args.make_user_val_from_f64(result)
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-06 20:27:26 -04:00
|
|
|
|
/// Compute the absolute value of a number.
|
2024-03-13 12:56:46 -07:00
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
2024-05-14 17:10:47 -07:00
|
|
|
|
/// const myAngle = -120
|
|
|
|
|
///
|
2024-05-22 09:15:38 -07:00
|
|
|
|
/// const sketch001 = startSketchOn('XZ')
|
2024-05-14 17:10:47 -07:00
|
|
|
|
/// |> startProfileAt([0, 0], %)
|
|
|
|
|
/// |> line([8, 0], %)
|
|
|
|
|
/// |> angledLine({
|
|
|
|
|
/// angle: abs(myAngle),
|
|
|
|
|
/// length: 5,
|
|
|
|
|
/// }, %)
|
|
|
|
|
/// |> line([-5, 0], %)
|
|
|
|
|
/// |> angledLine({
|
|
|
|
|
/// angle: myAngle,
|
|
|
|
|
/// length: 5,
|
|
|
|
|
/// }, %)
|
|
|
|
|
/// |> close(%)
|
|
|
|
|
///
|
|
|
|
|
/// const baseExtrusion = extrude(5, sketch001)
|
2024-03-13 12:56:46 -07:00
|
|
|
|
/// ```
|
2023-09-15 15:54:49 -07:00
|
|
|
|
#[stdlib {
|
|
|
|
|
name = "abs",
|
2024-03-26 21:28:50 -07:00
|
|
|
|
tags = ["math"],
|
2023-09-15 15:54:49 -07:00
|
|
|
|
}]
|
|
|
|
|
fn inner_abs(num: f64) -> Result<f64, KclError> {
|
|
|
|
|
Ok(num.abs())
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-06 20:27:26 -04:00
|
|
|
|
/// Compute the largest integer less than or equal to a number.
|
2024-09-16 15:10:33 -04:00
|
|
|
|
pub async fn floor(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
2023-09-15 15:54:49 -07:00
|
|
|
|
let num = args.get_number()?;
|
|
|
|
|
let result = inner_floor(num)?;
|
|
|
|
|
|
|
|
|
|
args.make_user_val_from_f64(result)
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-06 20:27:26 -04:00
|
|
|
|
/// Compute the largest integer less than or equal to a number.
|
2024-03-13 12:56:46 -07:00
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
2024-05-22 09:15:38 -07:00
|
|
|
|
/// const sketch001 = startSketchOn('XZ')
|
|
|
|
|
/// |> startProfileAt([0, 0], %)
|
|
|
|
|
/// |> lineTo([12, 10], %)
|
|
|
|
|
/// |> line([floor(7.02986), 0], %)
|
|
|
|
|
/// |> yLineTo(0, %)
|
|
|
|
|
/// |> close(%)
|
|
|
|
|
///
|
|
|
|
|
/// const extrude001 = extrude(5, sketch001)
|
2024-03-13 12:56:46 -07:00
|
|
|
|
/// ```
|
2023-09-15 15:54:49 -07:00
|
|
|
|
#[stdlib {
|
|
|
|
|
name = "floor",
|
2024-03-26 21:28:50 -07:00
|
|
|
|
tags = ["math"],
|
2023-09-15 15:54:49 -07:00
|
|
|
|
}]
|
|
|
|
|
fn inner_floor(num: f64) -> Result<f64, KclError> {
|
|
|
|
|
Ok(num.floor())
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-06 20:27:26 -04:00
|
|
|
|
/// Compute the smallest integer greater than or equal to a number.
|
2024-09-16 15:10:33 -04:00
|
|
|
|
pub async fn ceil(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
2023-09-15 15:54:49 -07:00
|
|
|
|
let num = args.get_number()?;
|
|
|
|
|
let result = inner_ceil(num)?;
|
|
|
|
|
|
|
|
|
|
args.make_user_val_from_f64(result)
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-06 20:27:26 -04:00
|
|
|
|
/// Compute the smallest integer greater than or equal to a number.
|
2024-03-13 12:56:46 -07:00
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
2024-05-22 09:15:38 -07:00
|
|
|
|
/// const sketch001 = startSketchOn('XZ')
|
|
|
|
|
/// |> startProfileAt([0, 0], %)
|
|
|
|
|
/// |> lineTo([12, 10], %)
|
|
|
|
|
/// |> line([ceil(7.02986), 0], %)
|
|
|
|
|
/// |> yLineTo(0, %)
|
|
|
|
|
/// |> close(%)
|
|
|
|
|
///
|
|
|
|
|
/// const extrude001 = extrude(5, sketch001)
|
2024-03-13 12:56:46 -07:00
|
|
|
|
/// ```
|
2023-09-15 15:54:49 -07:00
|
|
|
|
#[stdlib {
|
|
|
|
|
name = "ceil",
|
2024-03-26 21:28:50 -07:00
|
|
|
|
tags = ["math"],
|
2023-09-15 15:54:49 -07:00
|
|
|
|
}]
|
|
|
|
|
fn inner_ceil(num: f64) -> Result<f64, KclError> {
|
|
|
|
|
Ok(num.ceil())
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-06 20:27:26 -04:00
|
|
|
|
/// Compute the minimum of the given arguments.
|
2024-09-16 15:10:33 -04:00
|
|
|
|
pub async fn min(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
2023-09-15 15:54:49 -07:00
|
|
|
|
let nums = args.get_number_array()?;
|
|
|
|
|
let result = inner_min(nums);
|
|
|
|
|
|
|
|
|
|
args.make_user_val_from_f64(result)
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-06 20:27:26 -04:00
|
|
|
|
/// Compute the minimum of the given arguments.
|
2024-03-13 12:56:46 -07:00
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
2024-05-22 09:15:38 -07:00
|
|
|
|
/// const exampleSketch = startSketchOn("XZ")
|
|
|
|
|
/// |> startProfileAt([0, 0], %)
|
|
|
|
|
/// |> angledLine({
|
|
|
|
|
/// angle: 70,
|
|
|
|
|
/// length: min(15, 31, 4, 13, 22)
|
|
|
|
|
/// }, %)
|
|
|
|
|
/// |> line([20, 0], %)
|
|
|
|
|
/// |> close(%)
|
|
|
|
|
///
|
|
|
|
|
/// const example = extrude(5, exampleSketch)
|
2024-03-13 12:56:46 -07:00
|
|
|
|
/// ```
|
2023-09-15 15:54:49 -07:00
|
|
|
|
#[stdlib {
|
|
|
|
|
name = "min",
|
2024-03-26 21:28:50 -07:00
|
|
|
|
tags = ["math"],
|
2023-09-15 15:54:49 -07:00
|
|
|
|
}]
|
|
|
|
|
fn inner_min(args: Vec<f64>) -> f64 {
|
2024-06-13 14:42:21 -05:00
|
|
|
|
let mut min = f64::MAX;
|
2023-09-15 15:54:49 -07:00
|
|
|
|
for arg in args.iter() {
|
|
|
|
|
if *arg < min {
|
|
|
|
|
min = *arg;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
min
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-06 20:27:26 -04:00
|
|
|
|
/// Compute the maximum of the given arguments.
|
2024-09-16 15:10:33 -04:00
|
|
|
|
pub async fn max(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
2023-09-15 15:54:49 -07:00
|
|
|
|
let nums = args.get_number_array()?;
|
|
|
|
|
let result = inner_max(nums);
|
|
|
|
|
|
|
|
|
|
args.make_user_val_from_f64(result)
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-06 20:27:26 -04:00
|
|
|
|
/// Compute the maximum of the given arguments.
|
2024-03-13 12:56:46 -07:00
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
2024-05-22 09:15:38 -07:00
|
|
|
|
/// const exampleSketch = startSketchOn("XZ")
|
|
|
|
|
/// |> startProfileAt([0, 0], %)
|
|
|
|
|
/// |> angledLine({
|
|
|
|
|
/// angle: 70,
|
|
|
|
|
/// length: max(15, 31, 4, 13, 22)
|
|
|
|
|
/// }, %)
|
|
|
|
|
/// |> line([20, 0], %)
|
|
|
|
|
/// |> close(%)
|
|
|
|
|
///
|
|
|
|
|
/// const example = extrude(5, exampleSketch)
|
2024-03-13 12:56:46 -07:00
|
|
|
|
/// ```
|
2023-09-15 15:54:49 -07:00
|
|
|
|
#[stdlib {
|
|
|
|
|
name = "max",
|
2024-03-26 21:28:50 -07:00
|
|
|
|
tags = ["math"],
|
2023-09-15 15:54:49 -07:00
|
|
|
|
}]
|
|
|
|
|
fn inner_max(args: Vec<f64>) -> f64 {
|
2024-06-13 14:42:21 -05:00
|
|
|
|
let mut max = f64::MIN;
|
2023-09-15 15:54:49 -07:00
|
|
|
|
for arg in args.iter() {
|
|
|
|
|
if *arg > max {
|
|
|
|
|
max = *arg;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
max
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-06 20:27:26 -04:00
|
|
|
|
/// Compute the number to a power.
|
2024-09-16 15:10:33 -04:00
|
|
|
|
pub async fn pow(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
2023-09-15 15:54:49 -07:00
|
|
|
|
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)
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-06 20:27:26 -04:00
|
|
|
|
/// Compute the number to a power.
|
2024-03-13 12:56:46 -07:00
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
2024-05-22 09:15:38 -07:00
|
|
|
|
/// const exampleSketch = startSketchOn("XZ")
|
|
|
|
|
/// |> startProfileAt([0, 0], %)
|
|
|
|
|
/// |> angledLine({
|
|
|
|
|
/// angle: 50,
|
|
|
|
|
/// length: pow(5, 2),
|
|
|
|
|
/// }, %)
|
|
|
|
|
/// |> yLineTo(0, %)
|
|
|
|
|
/// |> close(%)
|
|
|
|
|
///
|
|
|
|
|
/// const example = extrude(5, exampleSketch)
|
2024-03-13 12:56:46 -07:00
|
|
|
|
/// ```
|
2023-09-15 15:54:49 -07:00
|
|
|
|
#[stdlib {
|
|
|
|
|
name = "pow",
|
2024-03-26 21:28:50 -07:00
|
|
|
|
tags = ["math"],
|
2023-09-15 15:54:49 -07:00
|
|
|
|
}]
|
|
|
|
|
fn inner_pow(num: f64, pow: f64) -> Result<f64, KclError> {
|
|
|
|
|
Ok(num.powf(pow))
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-06 20:27:26 -04:00
|
|
|
|
/// Compute the arccosine of a number (in radians).
|
2024-09-16 15:10:33 -04:00
|
|
|
|
pub async fn acos(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
2023-09-15 15:54:49 -07:00
|
|
|
|
let num = args.get_number()?;
|
|
|
|
|
let result = inner_acos(num)?;
|
|
|
|
|
|
|
|
|
|
args.make_user_val_from_f64(result)
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-06 20:27:26 -04:00
|
|
|
|
/// Compute the arccosine of a number (in radians).
|
2024-03-13 12:56:46 -07:00
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
2024-05-22 09:15:38 -07:00
|
|
|
|
/// const sketch001 = startSketchOn('XZ')
|
|
|
|
|
/// |> startProfileAt([0, 0], %)
|
|
|
|
|
/// |> angledLine({
|
|
|
|
|
/// angle: toDegrees(acos(0.5)),
|
|
|
|
|
/// length: 10,
|
|
|
|
|
/// }, %)
|
|
|
|
|
/// |> line([5, 0], %)
|
|
|
|
|
/// |> lineTo([12, 0], %)
|
|
|
|
|
/// |> close(%)
|
|
|
|
|
///
|
|
|
|
|
/// const extrude001 = extrude(5, sketch001)
|
2024-03-13 12:56:46 -07:00
|
|
|
|
/// ```
|
2023-09-15 15:54:49 -07:00
|
|
|
|
#[stdlib {
|
|
|
|
|
name = "acos",
|
2024-03-26 21:28:50 -07:00
|
|
|
|
tags = ["math"],
|
2023-09-15 15:54:49 -07:00
|
|
|
|
}]
|
|
|
|
|
fn inner_acos(num: f64) -> Result<f64, KclError> {
|
|
|
|
|
Ok(num.acos())
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-06 20:27:26 -04:00
|
|
|
|
/// Compute the arcsine of a number (in radians).
|
2024-09-16 15:10:33 -04:00
|
|
|
|
pub async fn asin(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
2023-09-15 15:54:49 -07:00
|
|
|
|
let num = args.get_number()?;
|
|
|
|
|
let result = inner_asin(num)?;
|
|
|
|
|
|
|
|
|
|
args.make_user_val_from_f64(result)
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-06 20:27:26 -04:00
|
|
|
|
/// Compute the arcsine of a number (in radians).
|
2024-03-13 12:56:46 -07:00
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
2024-05-22 09:15:38 -07:00
|
|
|
|
/// const sketch001 = startSketchOn('XZ')
|
|
|
|
|
/// |> startProfileAt([0, 0], %)
|
|
|
|
|
/// |> angledLine({
|
|
|
|
|
/// angle: toDegrees(asin(0.5)),
|
|
|
|
|
/// length: 20,
|
|
|
|
|
/// }, %)
|
|
|
|
|
/// |> yLineTo(0, %)
|
|
|
|
|
/// |> close(%)
|
|
|
|
|
///
|
|
|
|
|
/// const extrude001 = extrude(5, sketch001)
|
2024-03-13 12:56:46 -07:00
|
|
|
|
/// ```
|
2023-09-15 15:54:49 -07:00
|
|
|
|
#[stdlib {
|
|
|
|
|
name = "asin",
|
2024-03-26 21:28:50 -07:00
|
|
|
|
tags = ["math"],
|
2023-09-15 15:54:49 -07:00
|
|
|
|
}]
|
|
|
|
|
fn inner_asin(num: f64) -> Result<f64, KclError> {
|
|
|
|
|
Ok(num.asin())
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-06 20:27:26 -04:00
|
|
|
|
/// Compute the arctangent of a number (in radians).
|
2024-09-16 15:10:33 -04:00
|
|
|
|
pub async fn atan(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
2023-09-15 15:54:49 -07:00
|
|
|
|
let num = args.get_number()?;
|
|
|
|
|
let result = inner_atan(num)?;
|
|
|
|
|
|
|
|
|
|
args.make_user_val_from_f64(result)
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-06 20:27:26 -04:00
|
|
|
|
/// Compute the arctangent of a number (in radians).
|
2024-03-13 12:56:46 -07:00
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
2024-05-22 09:15:38 -07:00
|
|
|
|
/// const sketch001 = startSketchOn('XZ')
|
|
|
|
|
/// |> startProfileAt([0, 0], %)
|
|
|
|
|
/// |> angledLine({
|
|
|
|
|
/// angle: toDegrees(atan(1.25)),
|
|
|
|
|
/// length: 20,
|
|
|
|
|
/// }, %)
|
|
|
|
|
/// |> yLineTo(0, %)
|
|
|
|
|
/// |> close(%)
|
|
|
|
|
///
|
|
|
|
|
/// const extrude001 = extrude(5, sketch001)
|
2024-03-13 12:56:46 -07:00
|
|
|
|
/// ```
|
2023-09-15 15:54:49 -07:00
|
|
|
|
#[stdlib {
|
|
|
|
|
name = "atan",
|
2024-03-26 21:28:50 -07:00
|
|
|
|
tags = ["math"],
|
2023-09-15 15:54:49 -07:00
|
|
|
|
}]
|
|
|
|
|
fn inner_atan(num: f64) -> Result<f64, KclError> {
|
|
|
|
|
Ok(num.atan())
|
|
|
|
|
}
|
2023-09-15 17:40:57 -07:00
|
|
|
|
|
2024-08-06 20:27:26 -04:00
|
|
|
|
/// Compute the logarithm of the number with respect to an arbitrary base.
|
2023-09-15 17:40:57 -07:00
|
|
|
|
///
|
|
|
|
|
/// 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.
|
2024-09-16 15:10:33 -04:00
|
|
|
|
pub async fn log(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
2023-09-15 17:40:57 -07:00
|
|
|
|
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_log(nums[0], nums[1])?;
|
|
|
|
|
|
|
|
|
|
args.make_user_val_from_f64(result)
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-06 20:27:26 -04:00
|
|
|
|
/// Compute the logarithm of the number with respect to an arbitrary base.
|
2023-09-15 17:40:57 -07:00
|
|
|
|
///
|
|
|
|
|
/// 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.
|
2024-03-13 12:56:46 -07:00
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
2024-05-22 09:15:38 -07:00
|
|
|
|
/// const exampleSketch = startSketchOn("XZ")
|
|
|
|
|
/// |> startProfileAt([0, 0], %)
|
|
|
|
|
/// |> line([log(100, 5), 0], %)
|
|
|
|
|
/// |> line([5, 8], %)
|
|
|
|
|
/// |> line([-10, 0], %)
|
|
|
|
|
/// |> close(%)
|
|
|
|
|
///
|
|
|
|
|
/// const example = extrude(5, exampleSketch)
|
2024-03-13 12:56:46 -07:00
|
|
|
|
/// ```
|
2023-09-15 17:40:57 -07:00
|
|
|
|
#[stdlib {
|
|
|
|
|
name = "log",
|
2024-03-26 21:28:50 -07:00
|
|
|
|
tags = ["math"],
|
2023-09-15 17:40:57 -07:00
|
|
|
|
}]
|
|
|
|
|
fn inner_log(num: f64, base: f64) -> Result<f64, KclError> {
|
|
|
|
|
Ok(num.log(base))
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-06 20:27:26 -04:00
|
|
|
|
/// Compute the base 2 logarithm of the number.
|
2024-09-16 15:10:33 -04:00
|
|
|
|
pub async fn log2(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
2023-09-15 17:40:57 -07:00
|
|
|
|
let num = args.get_number()?;
|
|
|
|
|
let result = inner_log2(num)?;
|
|
|
|
|
|
|
|
|
|
args.make_user_val_from_f64(result)
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-06 20:27:26 -04:00
|
|
|
|
/// Compute the base 2 logarithm of the number.
|
2024-03-13 12:56:46 -07:00
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
2024-05-22 09:15:38 -07:00
|
|
|
|
/// const exampleSketch = startSketchOn("XZ")
|
|
|
|
|
/// |> startProfileAt([0, 0], %)
|
|
|
|
|
/// |> line([log2(100), 0], %)
|
|
|
|
|
/// |> line([5, 8], %)
|
|
|
|
|
/// |> line([-10, 0], %)
|
|
|
|
|
/// |> close(%)
|
|
|
|
|
///
|
|
|
|
|
/// const example = extrude(5, exampleSketch)
|
2024-03-13 12:56:46 -07:00
|
|
|
|
/// ```
|
2023-09-15 17:40:57 -07:00
|
|
|
|
#[stdlib {
|
|
|
|
|
name = "log2",
|
2024-03-26 21:28:50 -07:00
|
|
|
|
tags = ["math"],
|
2023-09-15 17:40:57 -07:00
|
|
|
|
}]
|
|
|
|
|
fn inner_log2(num: f64) -> Result<f64, KclError> {
|
|
|
|
|
Ok(num.log2())
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-06 20:27:26 -04:00
|
|
|
|
/// Compute the base 10 logarithm of the number.
|
2024-09-16 15:10:33 -04:00
|
|
|
|
pub async fn log10(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
2023-09-15 17:40:57 -07:00
|
|
|
|
let num = args.get_number()?;
|
|
|
|
|
let result = inner_log10(num)?;
|
|
|
|
|
|
|
|
|
|
args.make_user_val_from_f64(result)
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-06 20:27:26 -04:00
|
|
|
|
/// Compute the base 10 logarithm of the number.
|
2024-03-13 12:56:46 -07:00
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
2024-05-22 09:15:38 -07:00
|
|
|
|
/// const exampleSketch = startSketchOn("XZ")
|
|
|
|
|
/// |> startProfileAt([0, 0], %)
|
|
|
|
|
/// |> line([log10(100), 0], %)
|
|
|
|
|
/// |> line([5, 8], %)
|
|
|
|
|
/// |> line([-10, 0], %)
|
|
|
|
|
/// |> close(%)
|
|
|
|
|
///
|
|
|
|
|
/// const example = extrude(5, exampleSketch)
|
2024-03-13 12:56:46 -07:00
|
|
|
|
/// ```
|
2023-09-15 17:40:57 -07:00
|
|
|
|
#[stdlib {
|
|
|
|
|
name = "log10",
|
2024-03-26 21:28:50 -07:00
|
|
|
|
tags = ["math"],
|
2023-09-15 17:40:57 -07:00
|
|
|
|
}]
|
|
|
|
|
fn inner_log10(num: f64) -> Result<f64, KclError> {
|
|
|
|
|
Ok(num.log10())
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-06 20:27:26 -04:00
|
|
|
|
/// Compute the natural logarithm of the number.
|
2024-09-16 15:10:33 -04:00
|
|
|
|
pub async fn ln(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
2023-09-15 17:40:57 -07:00
|
|
|
|
let num = args.get_number()?;
|
|
|
|
|
let result = inner_ln(num)?;
|
|
|
|
|
|
|
|
|
|
args.make_user_val_from_f64(result)
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-06 20:27:26 -04:00
|
|
|
|
/// Compute the natural logarithm of the number.
|
2024-03-13 12:56:46 -07:00
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
2024-05-22 09:15:38 -07:00
|
|
|
|
/// const exampleSketch = startSketchOn("XZ")
|
|
|
|
|
/// |> startProfileAt([0, 0], %)
|
|
|
|
|
/// |> line([ln(100), 15], %)
|
|
|
|
|
/// |> line([5, -6], %)
|
|
|
|
|
/// |> line([-10, -10], %)
|
|
|
|
|
/// |> close(%)
|
|
|
|
|
///
|
|
|
|
|
/// const example = extrude(5, exampleSketch)
|
2024-03-13 12:56:46 -07:00
|
|
|
|
/// ```
|
2023-09-15 17:40:57 -07:00
|
|
|
|
#[stdlib {
|
|
|
|
|
name = "ln",
|
2024-03-26 21:28:50 -07:00
|
|
|
|
tags = ["math"],
|
2023-09-15 17:40:57 -07:00
|
|
|
|
}]
|
|
|
|
|
fn inner_ln(num: f64) -> Result<f64, KclError> {
|
|
|
|
|
Ok(num.ln())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Return the value of Euler’s number `e`.
|
2024-09-16 15:10:33 -04:00
|
|
|
|
pub async fn e(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
2023-09-15 17:40:57 -07:00
|
|
|
|
let result = inner_e()?;
|
|
|
|
|
|
|
|
|
|
args.make_user_val_from_f64(result)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Return the value of Euler’s number `e`.
|
2024-03-13 12:56:46 -07:00
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
2024-05-22 09:15:38 -07:00
|
|
|
|
/// const exampleSketch = startSketchOn("XZ")
|
|
|
|
|
/// |> startProfileAt([0, 0], %)
|
|
|
|
|
/// |> angledLine({
|
|
|
|
|
/// angle: 30,
|
|
|
|
|
/// length: 2 * e() ^ 2,
|
|
|
|
|
/// }, %)
|
|
|
|
|
/// |> yLineTo(0, %)
|
|
|
|
|
/// |> close(%)
|
|
|
|
|
///
|
|
|
|
|
/// const example = extrude(10, exampleSketch)
|
2024-03-13 12:56:46 -07:00
|
|
|
|
/// ```
|
2023-09-15 17:40:57 -07:00
|
|
|
|
#[stdlib {
|
|
|
|
|
name = "e",
|
2024-03-26 21:28:50 -07:00
|
|
|
|
tags = ["math"],
|
2023-09-15 17:40:57 -07:00
|
|
|
|
}]
|
|
|
|
|
fn inner_e() -> Result<f64, KclError> {
|
|
|
|
|
Ok(std::f64::consts::E)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Return the value of `tau`. The full circle constant (τ). Equal to 2π.
|
2024-09-16 15:10:33 -04:00
|
|
|
|
pub async fn tau(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
2023-09-15 17:40:57 -07:00
|
|
|
|
let result = inner_tau()?;
|
|
|
|
|
|
|
|
|
|
args.make_user_val_from_f64(result)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Return the value of `tau`. The full circle constant (τ). Equal to 2π.
|
2024-03-13 12:56:46 -07:00
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
2024-05-22 09:15:38 -07:00
|
|
|
|
/// const exampleSketch = startSketchOn("XZ")
|
|
|
|
|
/// |> startProfileAt([0, 0], %)
|
|
|
|
|
/// |> angledLine({
|
|
|
|
|
/// angle: 50,
|
|
|
|
|
/// length: 10 * tau(),
|
|
|
|
|
/// }, %)
|
|
|
|
|
/// |> yLineTo(0, %)
|
|
|
|
|
/// |> close(%)
|
|
|
|
|
///
|
|
|
|
|
/// const example = extrude(5, exampleSketch)
|
2024-03-13 12:56:46 -07:00
|
|
|
|
/// ```
|
2023-09-15 17:40:57 -07:00
|
|
|
|
#[stdlib {
|
|
|
|
|
name = "tau",
|
2024-03-26 21:28:50 -07:00
|
|
|
|
tags = ["math"],
|
2023-09-15 17:40:57 -07:00
|
|
|
|
}]
|
|
|
|
|
fn inner_tau() -> Result<f64, KclError> {
|
|
|
|
|
Ok(std::f64::consts::TAU)
|
|
|
|
|
}
|
2024-03-13 00:33:50 -07:00
|
|
|
|
|
|
|
|
|
/// Converts a number from degrees to radians.
|
2024-09-16 15:10:33 -04:00
|
|
|
|
pub async fn to_radians(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
2024-03-13 00:33:50 -07:00
|
|
|
|
let num = args.get_number()?;
|
2024-03-13 12:56:46 -07:00
|
|
|
|
let result = inner_to_radians(num)?;
|
2024-03-13 00:33:50 -07:00
|
|
|
|
|
|
|
|
|
args.make_user_val_from_f64(result)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Converts a number from degrees to radians.
|
2024-03-13 12:56:46 -07:00
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
2024-05-22 09:15:38 -07:00
|
|
|
|
/// const exampleSketch = startSketchOn("XZ")
|
|
|
|
|
/// |> startProfileAt([0, 0], %)
|
|
|
|
|
/// |> angledLine({
|
|
|
|
|
/// angle: 50,
|
|
|
|
|
/// length: 70 * cos(toRadians(45)),
|
|
|
|
|
/// }, %)
|
|
|
|
|
/// |> yLineTo(0, %)
|
|
|
|
|
/// |> close(%)
|
|
|
|
|
///
|
|
|
|
|
/// const example = extrude(5, exampleSketch)
|
2024-03-13 12:56:46 -07:00
|
|
|
|
/// ```
|
2024-03-13 00:33:50 -07:00
|
|
|
|
#[stdlib {
|
2024-03-13 12:56:46 -07:00
|
|
|
|
name = "toRadians",
|
2024-03-26 21:28:50 -07:00
|
|
|
|
tags = ["math"],
|
2024-03-13 00:33:50 -07:00
|
|
|
|
}]
|
2024-03-13 12:56:46 -07:00
|
|
|
|
fn inner_to_radians(num: f64) -> Result<f64, KclError> {
|
2024-03-13 00:33:50 -07:00
|
|
|
|
Ok(num.to_radians())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Converts a number from radians to degrees.
|
2024-09-16 15:10:33 -04:00
|
|
|
|
pub async fn to_degrees(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
2024-03-13 00:33:50 -07:00
|
|
|
|
let num = args.get_number()?;
|
2024-03-13 12:56:46 -07:00
|
|
|
|
let result = inner_to_degrees(num)?;
|
2024-03-13 00:33:50 -07:00
|
|
|
|
|
|
|
|
|
args.make_user_val_from_f64(result)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Converts a number from radians to degrees.
|
2024-03-13 12:56:46 -07:00
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
2024-05-22 09:15:38 -07:00
|
|
|
|
/// const exampleSketch = startSketchOn("XZ")
|
|
|
|
|
/// |> startProfileAt([0, 0], %)
|
|
|
|
|
/// |> angledLine({
|
|
|
|
|
/// angle: 50,
|
|
|
|
|
/// length: 70 * cos(toDegrees(pi()/4)),
|
|
|
|
|
/// }, %)
|
|
|
|
|
/// |> yLineTo(0, %)
|
|
|
|
|
/// |> close(%)
|
|
|
|
|
///
|
|
|
|
|
/// const example = extrude(5, exampleSketch)
|
2024-03-13 12:56:46 -07:00
|
|
|
|
/// ```
|
2024-03-13 00:33:50 -07:00
|
|
|
|
#[stdlib {
|
2024-03-13 12:56:46 -07:00
|
|
|
|
name = "toDegrees",
|
2024-03-26 21:28:50 -07:00
|
|
|
|
tags = ["math"],
|
2024-03-13 00:33:50 -07:00
|
|
|
|
}]
|
2024-03-13 12:56:46 -07:00
|
|
|
|
fn inner_to_degrees(num: f64) -> Result<f64, KclError> {
|
2024-03-13 00:33:50 -07:00
|
|
|
|
Ok(num.to_degrees())
|
|
|
|
|
}
|
2024-05-20 21:14:00 -07:00
|
|
|
|
|
|
|
|
|
#[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);
|
|
|
|
|
}
|
|
|
|
|
}
|