Skip to content

Commit

Permalink
Fix bugs in math rounding functions and improve performance
Browse files Browse the repository at this point in the history
  • Loading branch information
marcauberer committed Feb 15, 2025
1 parent 6ef07d2 commit a7ed53e
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 23 deletions.
79 changes: 58 additions & 21 deletions std/math/fct.spice
Original file line number Diff line number Diff line change
@@ -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<WholeNumber> factorial<WholeNumber>(WholeNumber input) {
Numeric fac = cast<Numeric>(1);
for (int i = 1; i <= input; i++) {
fac *= i;
}
return fac;
}

/**
* Calculate absolute value of the input
*
Expand Down Expand Up @@ -52,14 +38,26 @@ public inline f<Numeric> min<Numeric>(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<int> trunc(double input) {
return doubleType::toInt(input);
}

/**
* Round the input number down
*
* @param input Intput number
* @return Rounding result
*/
public inline f<int> floor(double input) {
return toInt(input);
const int truncated = trunc(input);
if input >= 0.0 { return truncated; }
return truncated == input ? truncated : truncated - 1;
}

/**
Expand All @@ -69,11 +67,36 @@ public inline f<int> floor(double input) {
* @return Rounding result
*/
public inline f<int> 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<int> round(double input) {
return cast<int>(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<double> 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<int>(input * factor + (input >= 0.0 ? 0.5 : -0.5)) / factor;
}

/**
Expand Down Expand Up @@ -142,4 +165,18 @@ public f<double> cos<Numeric>(Numeric x) {
term *= -xRad * xRad / k / (k - 1);
}
return res;
}
}

/**
* Calculate the factorial of the input
*
* @param input Input number
* @return Factorial of input
*/
public inline f<WholeNumber> factorial<WholeNumber>(WholeNumber input) {
Numeric fac = cast<Numeric>(1);
for (int i = 1; i <= input; i++) {
fac *= i;
}
return fac;
}
48 changes: 48 additions & 0 deletions test/test-files/std/math/fct-basic/cout.out
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,54 @@ Abs (long): 1234567890
Abs (long): 987654321
Abs (double): 56.123000
Abs (double): 348.120000
Max (int, int): 2
Max (int, int): -1
Max (short, short): 263
Max (short, short): -165
Max (long, long): 3495872345
Max (long, long): -239458723
Max (double, double): 34.234971
Max (double, double): -34.234970
Min (int, int): 1
Min (int, int): -2
Min (short, short): 165
Min (short, short): -263
Min (long, long): 239458723
Min (long, long): -3495872345
Min (double, double): 34.234970
Min (double, double): -34.234971
Trunc (double): 1
Trunc (double): 1
Trunc (double): -1
Trunc (double): -1
Floor (double): 1
Floor (double): 1
Floor (double): -2
Floor (double): -2
Ceil (double): 2
Ceil (double): 2
Ceil (double): -1
Ceil (double): -1
Round (double): 1
Round (double): 2
Round (double): -1
Round (double): -2
Round to 0 places (double): 1.000000
Round to 0 places (double): 2.000000
Round to 0 places (double): -1.000000
Round to 0 places (double): -2.000000
Round to 1 place (double): 1.000000
Round to 1 place (double): 1.100000
Round to 1 place (double): -1.000000
Round to 1 place (double): -1.100000
Round to 3 place (double): 1.499000
Round to 3 place (double): 1.500000
Round to 3 place (double): -1.499000
Round to 3 place (double): -1.500000
Round to 4 place (double): 1.499000
Round to 4 place (double): 1.500000
Round to 4 place (double): -1.499000
Round to 4 place (double): -1.500000
Deg2Rad: 7.330383
Deg2Rad: 0.744872
Deg2Rad: 5.610413
Expand Down
59 changes: 57 additions & 2 deletions test/test-files/std/math/fct-basic/source.spice
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,66 @@ f<int> 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));
Expand Down

0 comments on commit a7ed53e

Please sign in to comment.