Added partial cos and sine implementations

This commit is contained in:
Add00
2023-07-31 19:02:55 -04:00
parent 027d093e21
commit 81fe278c96
2 changed files with 50 additions and 37 deletions

View File

@@ -7,8 +7,9 @@
#include <time.h> #include <time.h>
#include <ctype.h> #include <ctype.h>
#define STD_MATH_PI 3.14159265358979323846f #define STD_MATH_PI 3.14159265358979323846f
#define STD_MATH_E 2.71828182845904523536f #define STD_MATH_E 2.71828182845904523536f
#define STD_MATH_LIMIT 20
static int nativeClock(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { static int nativeClock(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//no arguments //no arguments
@@ -669,34 +670,40 @@ static int nativeSin(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
} }
//get the argument //get the argument
Toy_Literal valueLiteral = Toy_popLiteralArray(arguments); Toy_Literal radiansLiteral = Toy_popLiteralArray(arguments);
//parse the argument (if it's an identifier) //parse the argument (if it's an identifier)
Toy_Literal valueLiteralIdn = valueLiteral; Toy_Literal radiansLiteralIdn = radiansLiteral;
if (TOY_IS_IDENTIFIER(valueLiteral) && Toy_parseIdentifierToValue(interpreter, &valueLiteral)) { if (TOY_IS_IDENTIFIER(radiansLiteral) && Toy_parseIdentifierToValue(interpreter, &radiansLiteral)) {
Toy_freeLiteral(valueLiteralIdn); Toy_freeLiteral(radiansLiteralIdn);
} }
//check the argument type //check the argument type
if (!(TOY_IS_INTEGER(valueLiteral) || TOY_IS_FLOAT(valueLiteral))) { if (!(TOY_IS_INTEGER(radiansLiteral) || TOY_IS_FLOAT(radiansLiteral))) {
interpreter->errorOutput("Incorrect argument type passed to lerp\n"); interpreter->errorOutput("Incorrect argument type passed to sin\n");
Toy_freeLiteral(valueLiteral); Toy_freeLiteral(radiansLiteral);
return -1; return -1;
} }
// cast ints to floats to handle all types of numbers // cast ints to floats to handle all types of numbers
float value = TOY_IS_INTEGER(valueLiteral)? TOY_AS_INTEGER(valueLiteral) : TOY_AS_FLOAT(valueLiteral); float radians = TOY_IS_INTEGER(radiansLiteral)? TOY_AS_INTEGER(radiansLiteral) : TOY_AS_FLOAT(radiansLiteral);
// calculate the result // calculate the result
// using Taylor series approximation // using Taylor series approximation
float result = 0; float result = radians;
float power = value; float numerator = radians;
int sign = 1; float denominator = 1;
for (int n = 1; n <= 10; n += 2) { for (int i = 1; i <= STD_MATH_LIMIT; i++) {
result += sign * power / n; numerator *= radians * radians;
power = power * value * value; denominator *= (2 * i) * (2 * i + 1);
sign = -sign;
float value = numerator / denominator;
if (i & 0x01)
result -= value;
else
result += value;
} }
//return the result //return the result
@@ -705,7 +712,7 @@ static int nativeSin(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
//cleanup //cleanup
Toy_freeLiteral(resultLiteral); Toy_freeLiteral(resultLiteral);
Toy_freeLiteral(valueLiteral); Toy_freeLiteral(radiansLiteral);
return 1; return 1;
} }
@@ -717,43 +724,37 @@ static int nativeCos(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
} }
//get the argument //get the argument
Toy_Literal valueLiteral = Toy_popLiteralArray(arguments); Toy_Literal radiansLiteral = Toy_popLiteralArray(arguments);
//parse the argument (if it's an identifier) //parse the argument (if it's an identifier)
Toy_Literal valueLiteralIdn = valueLiteral; Toy_Literal radiansLiteralIdn = radiansLiteral;
if (TOY_IS_IDENTIFIER(valueLiteral) && Toy_parseIdentifierToValue(interpreter, &valueLiteral)) { if (TOY_IS_IDENTIFIER(radiansLiteral) && Toy_parseIdentifierToValue(interpreter, &radiansLiteral)) {
Toy_freeLiteral(valueLiteralIdn); Toy_freeLiteral(radiansLiteralIdn);
} }
//check the argument type //check the argument type
if (!(TOY_IS_INTEGER(valueLiteral) || TOY_IS_FLOAT(valueLiteral))) { if (!(TOY_IS_INTEGER(radiansLiteral) || TOY_IS_FLOAT(radiansLiteral))) {
interpreter->errorOutput("Incorrect argument type passed to lerp\n"); interpreter->errorOutput("Incorrect argument type passed to lerp\n");
Toy_freeLiteral(valueLiteral); Toy_freeLiteral(radiansLiteral);
return -1; return -1;
} }
// cast ints to floats to handle all types of numbers // cast ints to floats to handle all types of numbers
float value = TOY_IS_INTEGER(valueLiteral)? TOY_AS_INTEGER(valueLiteral) : TOY_AS_FLOAT(valueLiteral); float radians = TOY_IS_INTEGER(radiansLiteral)? TOY_AS_INTEGER(radiansLiteral) : TOY_AS_FLOAT(radiansLiteral);
// calculate the result // calculate the result
// using Taylor series approximation // using Taylor series approximation
float result = 0;
float power = value;
int sign = 1;
for (int n = 0; n <= 10; n += 2) {
result += sign * power;
power = power * value * value / ((n + 1) * (n + 2));
sign = -sign;
}
// TODO
float result = -1;
//return the result //return the result
Toy_Literal resultLiteral = TOY_TO_FLOAT_LITERAL(result); Toy_Literal resultLiteral = TOY_TO_FLOAT_LITERAL(result);
Toy_pushLiteralArray(&interpreter->stack, resultLiteral); Toy_pushLiteralArray(&interpreter->stack, resultLiteral);
//cleanup //cleanup
Toy_freeLiteral(resultLiteral); Toy_freeLiteral(resultLiteral);
Toy_freeLiteral(valueLiteral); Toy_freeLiteral(radiansLiteral);
return 1; return 1;
} }
@@ -2325,8 +2326,8 @@ int Toy_hookStandard(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_L
{"lerp", nativeLerp}, {"lerp", nativeLerp},
{"toRad", nativeToRad}, {"toRad", nativeToRad},
{"toDeg", nativeToDeg}, {"toDeg", nativeToDeg},
// {"sin", nativeSin}, {"sin", nativeSin},
// {"cos", nativeCos}, {"cos", nativeCos},
//compound utils //compound utils
{"concat", nativeConcat}, //array, dictionary, string {"concat", nativeConcat}, //array, dictionary, string

View File

@@ -157,6 +157,7 @@ import standard;
assert typeof lerp(0, 10, 0) == float, "typeof lerp result failed"; assert typeof lerp(0, 10, 0) == float, "typeof lerp result failed";
} }
// test toRad // test toRad
{ {
assert toRad(0) == 0, "toRad 0° failed"; assert toRad(0) == 0, "toRad 0° failed";
@@ -164,6 +165,7 @@ import standard;
assert toRad(360) == 2 * PI, "toRad 360° failed"; assert toRad(360) == 2 * PI, "toRad 360° failed";
} }
// test toDeg // test toDeg
{ {
assert toDeg(0) == 0, "toDeg 0 failed"; assert toDeg(0) == 0, "toDeg 0 failed";
@@ -171,6 +173,16 @@ import standard;
assert toDeg(2 * PI) == 360, "toDeg 2π failed"; assert toDeg(2 * PI) == 360, "toDeg 2π failed";
} }
// test sin
{
assert sin(PI) == 0, "sin π failed";
}
// test cos
{
assert cos(PI) == -1, "cos π failed";
}
//test concat //test concat
{ {