diff --git a/std/math/fct.spice b/std/math/fct.spice index bace0d6be..3b8e453fd 100644 --- a/std/math/fct.spice +++ b/std/math/fct.spice @@ -1,25 +1,11 @@ // Imports import "std/math/const"; -import "std/type/double"; +import "std/type/double" as doubleType; // Generic type defs type Numeric double|int|short|long; type WholeNumber int|short|long; -/** - * Calculate the factorial of the input - * - * @param input Input number - * @return Factorial of input - */ -public inline f factorial(WholeNumber input) { - Numeric fac = cast(1); - for (int i = 1; i <= input; i++) { - fac *= i; - } - return fac; -} - /** * Calculate absolute value of the input * @@ -52,6 +38,16 @@ public inline f min(Numeric input1, Numeric input2) { return input1 < input2 ? input1 : input2; } +/** + * Truncate the number to a whole number + * + * @param input Intput number + * @return Rounding result + */ +public inline f trunc(double input) { + return doubleType::toInt(input); +} + /** * Round the input number down * @@ -59,7 +55,9 @@ public inline f min(Numeric input1, Numeric input2) { * @return Rounding result */ public inline f floor(double input) { - return toInt(input); + const int truncated = trunc(input); + if input >= 0.0 { return truncated; } + return truncated == input ? truncated : truncated - 1; } /** @@ -69,11 +67,36 @@ public inline f floor(double input) { * @return Rounding result */ public inline f ceil(double input) { - int truncatedInt = toInt(input); - if truncatedInt != input { - truncatedInt++; + const int truncated = trunc(input); + if input <= 0.0 { return truncated; } + return truncated == input ? truncated : truncated + 1; +} + +/** + * Round the input number to a whole number + * Note: 0.499999 is rounded down to 0, 0.5 is rounded up to 1. + * + * @param input Input number + * @return Rounding result + */ +public inline f round(double input) { + return cast(input + (input >= 0.0 ? 0.5 : -0.5)); +} + +/** + * Round the input number to the given number of decimal places + * Note: For 2 places 0.444 is rounded down to 0.44, 0.445 is rounded up to 0.45. + * + * @param input Input number + * @param places Number of decimal places + * @param Rounding result + */ +public inline f round(double input, unsigned int places) { + double factor = 1.0; + for unsigned int i = 0u; i < places; i++ { + factor *= 10.0; } - return truncatedInt; + return cast(input * factor + (input >= 0.0 ? 0.5 : -0.5)) / factor; } /** @@ -142,4 +165,18 @@ public f cos(Numeric x) { term *= -xRad * xRad / k / (k - 1); } return res; -} \ No newline at end of file +} + +/** + * Calculate the factorial of the input + * + * @param input Input number + * @return Factorial of input + */ +public inline f factorial(WholeNumber input) { + Numeric fac = cast(1); + for (int i = 1; i <= input; i++) { + fac *= i; + } + return fac; +} diff --git a/test/test-files/std/math/fct-basic/source.spice b/test/test-files/std/math/fct-basic/source.spice index 647f8e76b..40a8fd6ba 100644 --- a/test/test-files/std/math/fct-basic/source.spice +++ b/test/test-files/std/math/fct-basic/source.spice @@ -5,11 +5,66 @@ f main() { printf("Abs (int): %d\n", fct::abs(-137)); printf("Abs (short): %d\n", fct::abs(56s)); printf("Abs (short): %d\n", fct::abs(-3s)); - printf("Abs (long): %d\n", fct::abs(1234567890l)); - printf("Abs (long): %d\n", fct::abs(-987654321l)); + printf("Abs (long): %lld\n", fct::abs(1234567890l)); + printf("Abs (long): %lld\n", fct::abs(-987654321l)); printf("Abs (double): %f\n", fct::abs(56.123)); printf("Abs (double): %f\n", fct::abs(-348.12)); + printf("Max (int, int): %d\n", max(1, 2)); + printf("Max (int, int): %d\n", max(-1, -2)); + printf("Max (short, short): %d\n", max(165s, 263s)); + printf("Max (short, short): %d\n", max(-165s, -263s)); + printf("Max (long, long): %lld\n", max(3495872345l, 239458723l)); + printf("Max (long, long): %lld\n", max(-3495872345l, -239458723l)); + printf("Max (double, double): %f\n", max(34.234971, 34.23497)); + printf("Max (double, double): %f\n", max(-34.234971, -34.23497)); + + printf("Min (int, int): %d\n", min(1, 2)); + printf("Min (int, int): %d\n", min(-1, -2)); + printf("Min (short, short): %d\n", min(165s, 263s)); + printf("Min (short, short): %d\n", min(-165s, -263s)); + printf("Min (long, long): %lld\n", min(3495872345l, 239458723l)); + printf("Min (long, long): %lld\n", min(-3495872345l, -239458723l)); + printf("Min (double, double): %f\n", min(34.234971, 34.23497)); + printf("Min (double, double): %f\n", min(-34.234971, -34.23497)); + + printf("Trunc (double): %d\n", trunc(1.499)); + printf("Trunc (double): %d\n", trunc(1.500)); + printf("Trunc (double): %d\n", trunc(-1.499)); + printf("Trunc (double): %d\n", trunc(-1.500)); + + printf("Floor (double): %d\n", floor(1.499)); + printf("Floor (double): %d\n", floor(1.500)); + printf("Floor (double): %d\n", floor(-1.499)); + printf("Floor (double): %d\n", floor(-1.500)); + + printf("Ceil (double): %d\n", ceil(1.499)); + printf("Ceil (double): %d\n", ceil(1.500)); + printf("Ceil (double): %d\n", ceil(-1.499)); + printf("Ceil (double): %d\n", ceil(-1.500)); + + printf("Round (double): %d\n", round(1.499)); + printf("Round (double): %d\n", round(1.500)); + printf("Round (double): %d\n", round(-1.499)); + printf("Round (double): %d\n", round(-1.500)); + + printf("Round to 0 places (double): %f\n", round(1.499, 0)); + printf("Round to 0 places (double): %f\n", round(1.500, 0)); + printf("Round to 0 places (double): %f\n", round(-1.499, 0)); + printf("Round to 0 places (double): %f\n", round(-1.500, 0)); + printf("Round to 1 place (double): %f\n", round(1.049, 1)); + printf("Round to 1 place (double): %f\n", round(1.050, 1)); + printf("Round to 1 place (double): %f\n", round(-1.049, 1)); + printf("Round to 1 place (double): %f\n", round(-1.050, 1)); + printf("Round to 3 place (double): %f\n", round(1.499, 3)); + printf("Round to 3 place (double): %f\n", round(1.500, 3)); + printf("Round to 3 place (double): %f\n", round(-1.499, 3)); + printf("Round to 3 place (double): %f\n", round(-1.500, 3)); + printf("Round to 4 place (double): %f\n", round(1.499, 4)); + printf("Round to 4 place (double): %f\n", round(1.500, 4)); + printf("Round to 4 place (double): %f\n", round(-1.499, 4)); + printf("Round to 4 place (double): %f\n", round(-1.500, 4)); + printf("Deg2Rad: %f\n", degToRad(420.0)); printf("Deg2Rad: %f\n", degToRad(42.678)); printf("Deg2Rad: %f\n", degToRad(321.453));