From 5556010c91bc1d52b455f6c5b545182b45f38cdc Mon Sep 17 00:00:00 2001 From: Jordan Wages Date: Sat, 27 Jun 2026 19:41:26 -0500 Subject: [PATCH] Expanding Standard Library Expanding functions in the standard library. --- src/StandardLibrary/Functions/Lerp.cs | 50 ++++++++++++++++ src/StandardLibrary/Functions/Log.cs | 39 +++++++++++++ src/StandardLibrary/Functions/Map.cs | 58 +++++++++++++++++++ src/StandardLibrary/Functions/Natural Log.cs | 36 ++++++++++++ src/StandardLibrary/Functions/Normalize.cs | 50 ++++++++++++++++ .../NumberTheory/GreatedCommonDenomitator.cs | 2 +- src/StandardLibrary/Functions/Power.cs | 39 +++++++++++++ src/StandardLibrary/Functions/SmoothStep.cs | 46 +++++++++++++++ src/StandardLibrary/Functions/SquareRoot.cs | 36 ++++++++++++ src/StandardLibrary/Initializer.cs | 3 +- src/Tests/NumberTheoryFunctionsTests.cs | 2 +- src/Tests/StdlibFunctionsTests.cs | 8 +++ 12 files changed, 366 insertions(+), 3 deletions(-) create mode 100644 src/StandardLibrary/Functions/Lerp.cs create mode 100644 src/StandardLibrary/Functions/Log.cs create mode 100644 src/StandardLibrary/Functions/Map.cs create mode 100644 src/StandardLibrary/Functions/Natural Log.cs create mode 100644 src/StandardLibrary/Functions/Normalize.cs create mode 100644 src/StandardLibrary/Functions/Power.cs create mode 100644 src/StandardLibrary/Functions/SmoothStep.cs create mode 100644 src/StandardLibrary/Functions/SquareRoot.cs diff --git a/src/StandardLibrary/Functions/Lerp.cs b/src/StandardLibrary/Functions/Lerp.cs new file mode 100644 index 0000000..0993d86 --- /dev/null +++ b/src/StandardLibrary/Functions/Lerp.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CSMic.StandardLibrary.Functions +{ + public class Lerp: FunctionBase, ICodedFunction + { + public string Name + { + get + { + return "lerp"; + } + } + + public override IEnumerable ExpectedArguments + { + get + { + yield return new FunctionArgument("start", FunctionValue.NUMBER); + yield return new FunctionArgument("end", FunctionValue.NUMBER); + yield return new FunctionArgument("ammount", FunctionValue.NUMBER); + } + } + + public FunctionValue Execute(params FunctionArgument[] args) + { + return base.Execute(args, (_args) => + { + var input = _args[0].Value; + var input2 = _args[1].Value; + var input3 = _args[2].Value; + + decimal start = Convert.ToDecimal(input); + decimal end = Convert.ToDecimal(input2); + decimal ammount = Convert.ToDecimal(input3); + + if (start == end) + { + return new FunctionValue(FunctionValueType.Numeric, start); + } + + var lerp = start + (ammount * (end - start)); + + return new FunctionValue(FunctionValueType.Numeric, lerp); + }); + } + } +} diff --git a/src/StandardLibrary/Functions/Log.cs b/src/StandardLibrary/Functions/Log.cs new file mode 100644 index 0000000..efc2e8a --- /dev/null +++ b/src/StandardLibrary/Functions/Log.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CSMic.StandardLibrary.Functions +{ + public class Log: FunctionBase, ICodedFunction + { + public string Name + { + get + { + return "log"; + } + } + + public override IEnumerable ExpectedArguments + { + get + { + yield return new FunctionArgument("value", FunctionValue.NUMBER); + yield return new FunctionArgument("base", FunctionValue.NUMBER); + } + } + + public FunctionValue Execute(params FunctionArgument[] args) + { + return base.Execute(args, (_args) => + { + var input = _args[0].Value; + var input2 = _args[1].Value; + double number = Convert.ToDouble(input.Value); + double _baseNumber = Convert.ToDouble(input2.Value); + + return new FunctionValue(FunctionValueType.Numeric, Math.Log(number, _baseNumber)); + }); + } + } +} diff --git a/src/StandardLibrary/Functions/Map.cs b/src/StandardLibrary/Functions/Map.cs new file mode 100644 index 0000000..665b79f --- /dev/null +++ b/src/StandardLibrary/Functions/Map.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CSMic.StandardLibrary.Functions +{ + public class Map: FunctionBase, ICodedFunction + { + public string Name + { + get + { + return "map"; + } + } + + public override IEnumerable ExpectedArguments + { + get + { + yield return new FunctionArgument("value", FunctionValue.NUMBER); + yield return new FunctionArgument("oldMinimum", FunctionValue.NUMBER); + yield return new FunctionArgument("oldMaximum", FunctionValue.NUMBER); + yield return new FunctionArgument("newMinimum", FunctionValue.NUMBER); + yield return new FunctionArgument("newMaximum", FunctionValue.NUMBER); + } + } + + public FunctionValue Execute(params FunctionArgument[] args) + { + return base.Execute(args, (_args) => + { + var input = _args[0].Value; + var input2 = _args[1].Value; + var input3 = _args[2].Value; + var input4 = _args[3].Value; + var input5 = _args[4].Value; + + decimal number = Convert.ToDecimal(input); + decimal oldMinimum = Convert.ToDecimal(input2); + decimal oldMaximum = Convert.ToDecimal(input3); + decimal newMinimum = Convert.ToDecimal(input4); + decimal newMaximum = Convert.ToDecimal(input5); + + if (oldMinimum == oldMaximum) + { + return FunctionValue.ZERO; + } + + var oldRange = oldMaximum - oldMinimum; + var newRange = newMaximum - newMinimum; + var newNumber = newMinimum + ((number - oldMinimum) * (newRange / oldRange)); + + return new FunctionValue(FunctionValueType.Numeric, newNumber); + }); + } + } +} diff --git a/src/StandardLibrary/Functions/Natural Log.cs b/src/StandardLibrary/Functions/Natural Log.cs new file mode 100644 index 0000000..94252af --- /dev/null +++ b/src/StandardLibrary/Functions/Natural Log.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CSMic.StandardLibrary.Functions +{ + public class Natural_Log: FunctionBase, ICodedFunction + { + public string Name + { + get + { + return "ln"; + } + } + + public override IEnumerable ExpectedArguments + { + get + { + yield return new FunctionArgument("value", FunctionValue.NUMBER); + } + } + + public FunctionValue Execute(params FunctionArgument[] args) + { + return base.Execute(args, (_args) => + { + var input = _args[0].Value; + double number = Convert.ToDouble(input.Value); + + return new FunctionValue(FunctionValueType.Numeric, Math.Log(number)); + }); + } + } +} diff --git a/src/StandardLibrary/Functions/Normalize.cs b/src/StandardLibrary/Functions/Normalize.cs new file mode 100644 index 0000000..3a2fc74 --- /dev/null +++ b/src/StandardLibrary/Functions/Normalize.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CSMic.StandardLibrary.Functions +{ + public class Normalize : FunctionBase, ICodedFunction + { + public string Name + { + get + { + return "normalize"; + } + } + + public override IEnumerable ExpectedArguments + { + get + { + yield return new FunctionArgument("value", FunctionValue.NUMBER); + yield return new FunctionArgument("minimum", FunctionValue.NUMBER); + yield return new FunctionArgument("maximum", FunctionValue.NUMBER); + } + } + + public FunctionValue Execute(params FunctionArgument[] args) + { + return base.Execute(args, (_args) => + { + var input = _args[0].Value; + var input2 = _args[1].Value; + var input3 = _args[2].Value; + + decimal number = Convert.ToDecimal(input); + decimal minimum = Convert.ToDecimal(input2); + decimal maximum = Convert.ToDecimal(input3); + + if (minimum == maximum) + { + return FunctionValue.ZERO; + } + + var normalization = (number - minimum) / (maximum - minimum); + + return new FunctionValue(FunctionValueType.Numeric, normalization); + }); + } + } +} diff --git a/src/StandardLibrary/Functions/NumberTheory/GreatedCommonDenomitator.cs b/src/StandardLibrary/Functions/NumberTheory/GreatedCommonDenomitator.cs index 234022d..980da00 100644 --- a/src/StandardLibrary/Functions/NumberTheory/GreatedCommonDenomitator.cs +++ b/src/StandardLibrary/Functions/NumberTheory/GreatedCommonDenomitator.cs @@ -58,7 +58,7 @@ namespace CSMic.StandardLibrary.Functions.NumberTheory decimal first = Convert.ToDecimal(inputFirst.Value); decimal second = Convert.ToDecimal(inputSecond.Value); - if (first <= 0 || second <= 0) + if (first <= 0 && second <= 0) { return FunctionValue.ZERO; } diff --git a/src/StandardLibrary/Functions/Power.cs b/src/StandardLibrary/Functions/Power.cs new file mode 100644 index 0000000..a6dcd37 --- /dev/null +++ b/src/StandardLibrary/Functions/Power.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CSMic.StandardLibrary.Functions +{ + public class Power : FunctionBase, ICodedFunction + { + public string Name + { + get + { + return "pow"; + } + } + + public override IEnumerable ExpectedArguments + { + get + { + yield return new FunctionArgument("base", FunctionValue.NUMBER); + yield return new FunctionArgument("exponent", FunctionValue.NUMBER); + } + } + + public FunctionValue Execute(params FunctionArgument[] args) + { + return base.Execute(args, (_args) => + { + var input = _args[0].Value; + var input2 = _args[1].Value; + double _base = Convert.ToDouble(input.Value); + double exponent = Convert.ToDouble(input2.Value); + + return new FunctionValue(FunctionValueType.Numeric, Math.Pow(_base, exponent)); + }); + } + } +} diff --git a/src/StandardLibrary/Functions/SmoothStep.cs b/src/StandardLibrary/Functions/SmoothStep.cs new file mode 100644 index 0000000..b375d63 --- /dev/null +++ b/src/StandardLibrary/Functions/SmoothStep.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CSMic.StandardLibrary.Functions +{ + public class SmoothStep : FunctionBase, ICodedFunction + { + public string Name + { + get + { + return "lerp"; + } + } + + public override IEnumerable ExpectedArguments + { + get + { + yield return new FunctionArgument("startEdge", FunctionValue.NUMBER); + yield return new FunctionArgument("endEdge", FunctionValue.NUMBER); + yield return new FunctionArgument("value", FunctionValue.NUMBER); + } + } + + public FunctionValue Execute(params FunctionArgument[] args) + { + return base.Execute(args, (_args) => + { + var input = _args[0].Value; + var input2 = _args[1].Value; + var input3 = _args[2].Value; + + decimal startEdge = Convert.ToDecimal(input); + decimal endEdge = Convert.ToDecimal(input2); + decimal value = Convert.ToDecimal(input3); + + var normalization = Math.Clamp((value - startEdge) / (endEdge - startEdge), 0, 1); + var polynomialization = normalization * normalization * (3 - (2 * normalization)); + + return new FunctionValue(FunctionValueType.Numeric, polynomialization); + }); + } + } +} diff --git a/src/StandardLibrary/Functions/SquareRoot.cs b/src/StandardLibrary/Functions/SquareRoot.cs new file mode 100644 index 0000000..d6e25fd --- /dev/null +++ b/src/StandardLibrary/Functions/SquareRoot.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CSMic.StandardLibrary.Functions +{ + public class SquareRoot: FunctionBase, ICodedFunction + { + public string Name + { + get + { + return "sqrt"; + } + } + + public override IEnumerable ExpectedArguments + { + get + { + yield return new FunctionArgument("value", FunctionValue.NUMBER); + } + } + + public FunctionValue Execute(params FunctionArgument[] args) + { + return base.Execute(args, (_args) => + { + var input = _args[0].Value; + double number = Convert.ToDouble(input.Value); + + return new FunctionValue(FunctionValueType.Numeric, Math.Sqrt(number)); + }); + } + } +} diff --git a/src/StandardLibrary/Initializer.cs b/src/StandardLibrary/Initializer.cs index 02d0f7b..5cc5970 100644 --- a/src/StandardLibrary/Initializer.cs +++ b/src/StandardLibrary/Initializer.cs @@ -64,6 +64,7 @@ namespace CSMic.StandardLibrary inputInterpreter.RegisterFunction(new Sign()); inputInterpreter.RegisterFunction(new Min()); inputInterpreter.RegisterFunction(new Max()); + inputInterpreter.RegisterFunction(new SquareRoot()); } /// Initializes the angle-related functions. @@ -177,7 +178,7 @@ namespace CSMic.StandardLibrary inputInterpreter.Interpret("tau :: 6.2831853071795862"); inputInterpreter.Interpret("phi :: 1.6180339887498948"); inputInterpreter.Interpret("goldenratio :: 1.6180339887498948"); - inputInterpreter.Interpret("eurler :: 0.5772156649015329"); + inputInterpreter.Interpret("euler :: 0.5772156649015329"); inputInterpreter.Interpret("omega :: 0.5671432904097839"); } } diff --git a/src/Tests/NumberTheoryFunctionsTests.cs b/src/Tests/NumberTheoryFunctionsTests.cs index e4c09b4..dda332f 100644 --- a/src/Tests/NumberTheoryFunctionsTests.cs +++ b/src/Tests/NumberTheoryFunctionsTests.cs @@ -34,7 +34,7 @@ public class NumberTheoryFunctionsTests { AssertSuccess(_interp.Interpret("gcd(54, 24)"), 6m, _interp); AssertSuccess(_interp.Interpret("gcd(7, 3)"), 1m, _interp); - AssertSuccess(_interp.Interpret("gcd(0, 5)"), 0m, _interp); + AssertSuccess(_interp.Interpret("gcd(0, 5)"), 5m, _interp); AssertSuccess(_interp.Interpret("gcd(5.5, 2)"), 0m, _interp); } diff --git a/src/Tests/StdlibFunctionsTests.cs b/src/Tests/StdlibFunctionsTests.cs index 263795e..f921f68 100644 --- a/src/Tests/StdlibFunctionsTests.cs +++ b/src/Tests/StdlibFunctionsTests.cs @@ -90,6 +90,14 @@ public class StdlibFunctionsTests AssertSuccess(result, expected, _interp); } + [TestCase("sqrt(25)", 5)] + [TestCase("sqrt(1)", 1)] + public void Sqrt_Works(string expr, decimal expected) + { + var result = _interp.Interpret(expr); + AssertSuccess(result, expected, _interp); + } + [TestCase("pi", "3.1415926535897931")] [TestCase("e", "2.7182818284590451")] [TestCase("tau", "6.2831853071795862")]