Added arc versions of trigonometric functions

This commit is contained in:
Add00
2023-08-01 13:41:55 -04:00
parent b06b2d9485
commit f5ba1181c0
2 changed files with 211 additions and 0 deletions

View File

@@ -438,6 +438,175 @@ static int nativeTan(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
return 1; return 1;
} }
static int nativeAsin(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
if (arguments->count != 1) {
interpreter->errorOutput("Incorrect number of arguments to asin\n");
return -1;
}
//get the argument
Toy_Literal radiansLiteral = Toy_popLiteralArray(arguments);
//parse the argument (if it's an identifier)
Toy_Literal radiansLiteralIdn = radiansLiteral;
if (TOY_IS_IDENTIFIER(radiansLiteral) && Toy_parseIdentifierToValue(interpreter, &radiansLiteral)) {
Toy_freeLiteral(radiansLiteralIdn);
}
//check the argument type
if (!(TOY_IS_INTEGER(radiansLiteral) || TOY_IS_FLOAT(radiansLiteral))) {
interpreter->errorOutput("Incorrect argument type passed to asin\n");
Toy_freeLiteral(radiansLiteral);
return -1;
}
// cast ints to floats to handle all types of numbers
float radians = TOY_IS_INTEGER(radiansLiteral)? TOY_AS_INTEGER(radiansLiteral) : TOY_AS_FLOAT(radiansLiteral);
// calculate the result
float result = asinf(radians);
//return the result
Toy_Literal resultLiteral = TOY_TO_FLOAT_LITERAL(result);
Toy_pushLiteralArray(&interpreter->stack, resultLiteral);
//cleanup
Toy_freeLiteral(resultLiteral);
Toy_freeLiteral(radiansLiteral);
return 1;
}
static int nativeAcos(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
if (arguments->count != 1) {
interpreter->errorOutput("Incorrect number of arguments to acos\n");
return -1;
}
//get the argument
Toy_Literal radiansLiteral = Toy_popLiteralArray(arguments);
//parse the argument (if it's an identifier)
Toy_Literal radiansLiteralIdn = radiansLiteral;
if (TOY_IS_IDENTIFIER(radiansLiteral) && Toy_parseIdentifierToValue(interpreter, &radiansLiteral)) {
Toy_freeLiteral(radiansLiteralIdn);
}
//check the argument type
if (!(TOY_IS_INTEGER(radiansLiteral) || TOY_IS_FLOAT(radiansLiteral))) {
interpreter->errorOutput("Incorrect argument type passed to acos\n");
Toy_freeLiteral(radiansLiteral);
return -1;
}
// cast ints to floats to handle all types of numbers
float radians = TOY_IS_INTEGER(radiansLiteral)? TOY_AS_INTEGER(radiansLiteral) : TOY_AS_FLOAT(radiansLiteral);
// calculate the result
float result = acosf(radians);
//return the result
Toy_Literal resultLiteral = TOY_TO_FLOAT_LITERAL(result);
Toy_pushLiteralArray(&interpreter->stack, resultLiteral);
//cleanup
Toy_freeLiteral(resultLiteral);
Toy_freeLiteral(radiansLiteral);
return 1;
}
static int nativeAtan(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
if (arguments->count != 1) {
interpreter->errorOutput("Incorrect number of arguments to atan\n");
return -1;
}
//get the argument
Toy_Literal radiansLiteral = Toy_popLiteralArray(arguments);
//parse the argument (if it's an identifier)
Toy_Literal radiansLiteralIdn = radiansLiteral;
if (TOY_IS_IDENTIFIER(radiansLiteral) && Toy_parseIdentifierToValue(interpreter, &radiansLiteral)) {
Toy_freeLiteral(radiansLiteralIdn);
}
//check the argument type
if (!(TOY_IS_INTEGER(radiansLiteral) || TOY_IS_FLOAT(radiansLiteral))) {
interpreter->errorOutput("Incorrect argument type passed to atan\n");
Toy_freeLiteral(radiansLiteral);
return -1;
}
// cast ints to floats to handle all types of numbers
float radians = TOY_IS_INTEGER(radiansLiteral)? TOY_AS_INTEGER(radiansLiteral) : TOY_AS_FLOAT(radiansLiteral);
// calculate the result
float result = atanf(radians);
//return the result
Toy_Literal resultLiteral = TOY_TO_FLOAT_LITERAL(result);
Toy_pushLiteralArray(&interpreter->stack, resultLiteral);
//cleanup
Toy_freeLiteral(resultLiteral);
Toy_freeLiteral(radiansLiteral);
return 1;
}
static int nativeAtan2(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
if (arguments->count != 2) {
interpreter->errorOutput("Incorrect number of arguments to atan2\n");
return -1;
}
//get the argument
Toy_Literal yLiteral = Toy_popLiteralArray(arguments);
Toy_Literal xLiteral = Toy_popLiteralArray(arguments);
//parse the argument (if it's an identifier)
Toy_Literal xLiteralIdn = xLiteral;
if (TOY_IS_IDENTIFIER(xLiteral) && Toy_parseIdentifierToValue(interpreter, &xLiteral)) {
Toy_freeLiteral(xLiteralIdn);
}
Toy_Literal yLiteralIdn = yLiteral;
if (TOY_IS_IDENTIFIER(yLiteral) && Toy_parseIdentifierToValue(interpreter, &yLiteral)) {
Toy_freeLiteral(yLiteralIdn);
}
//check the argument type
if (!(TOY_IS_INTEGER(xLiteral) || TOY_IS_FLOAT(xLiteral))) {
interpreter->errorOutput("Incorrect argument type passed to atan2\n");
Toy_freeLiteral(xLiteral);
return -1;
}
if (!(TOY_IS_INTEGER(yLiteral) || TOY_IS_FLOAT(yLiteral))) {
interpreter->errorOutput("Incorrect argument type passed to atan2\n");
Toy_freeLiteral(yLiteral);
return -1;
}
// cast ints to floats to handle all types of numbers
float x = TOY_IS_INTEGER(xLiteral)? TOY_AS_INTEGER(xLiteral) : TOY_AS_FLOAT(xLiteral);
float y = TOY_IS_INTEGER(yLiteral)? TOY_AS_INTEGER(yLiteral) : TOY_AS_FLOAT(yLiteral);
// calculate the result
float result = atan2f(x, y);
//return the result
Toy_Literal resultLiteral = TOY_TO_FLOAT_LITERAL(result);
Toy_pushLiteralArray(&interpreter->stack, resultLiteral);
//cleanup
Toy_freeLiteral(resultLiteral);
Toy_freeLiteral(xLiteral);
return 1;
}
static int nativeIsnan(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { static int nativeIsnan(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
if (arguments->count != 1) { if (arguments->count != 1) {
interpreter->errorOutput("Incorrect number of arguments to tan\n"); interpreter->errorOutput("Incorrect number of arguments to tan\n");
@@ -554,6 +723,10 @@ int Toy_hookMath(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Liter
{"sin", nativeSin}, {"sin", nativeSin},
{"cos", nativeCos}, {"cos", nativeCos},
{"tan", nativeTan}, {"tan", nativeTan},
{"asin", nativeAsin},
{"acos", nativeAcos},
{"atan", nativeAtan},
{"atans", nativeAtan2},
// Comparison // Comparison
{"isnan", nativeIsnan}, {"isnan", nativeIsnan},

View File

@@ -71,6 +71,44 @@ import math;
assert floatCompare(cos(0), 1), "cos(0) failed"; assert floatCompare(cos(0), 1), "cos(0) failed";
} }
// test tan
{
assert floatCompare(tan(PI), 0), "tan(π) failed";
assert floatCompare(tan(PI / 4), 1), "tan(π/4) failed";
assert floatCompare(tan(0), 0), "tan(0) failed";
}
// test asin
{
assert floatCompare(asin(1), 1.570796), "asin(1) failed";
assert floatCompare(asin(-0.5), -0.523599), "asin(-0.5) failed";
assert floatCompare(asin(0), 0), "asin(0) failed";
}
// test acos
{
assert floatCompare(acos(1), 0), "acos(1) failed";
assert floatCompare(acos(0.5), 1.047198), "acos(0.5) failed";
assert floatCompare(acos(0), 1.570796), "acos(0) failed";
}
// test atan
{
assert floatCompare(atan(1), 0.785398), "acos(1) failed";
assert floatCompare(atan(INFINITY), 1.570796), "atan(INFINITY) failed";
assert floatCompare(atan(0), 0), "atan(0) failed";
}
// test atan2
{
assert floatCompare(atans(0, 0), 0), "atan2(0, 0) failed";
assert floatCompare(atans(7, 0), 1.570796), "atans(7, 0) failed";
}
// test isnan // test isnan
{ {