From f5ba1181c059ce7fb23a06c278726ea5204763a4 Mon Sep 17 00:00:00 2001 From: Add00 Date: Tue, 1 Aug 2023 13:41:55 -0400 Subject: [PATCH] Added arc versions of trigonometric functions --- repl/lib_math.c | 173 ++++++++++++++++++++++++++++++++++++++ test/scripts/lib/math.toy | 38 +++++++++ 2 files changed, 211 insertions(+) diff --git a/repl/lib_math.c b/repl/lib_math.c index d3eacb0..c9f4d17 100644 --- a/repl/lib_math.c +++ b/repl/lib_math.c @@ -438,6 +438,175 @@ static int nativeTan(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) 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) { if (arguments->count != 1) { 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}, {"cos", nativeCos}, {"tan", nativeTan}, + {"asin", nativeAsin}, + {"acos", nativeAcos}, + {"atan", nativeAtan}, + {"atans", nativeAtan2}, // Comparison {"isnan", nativeIsnan}, diff --git a/test/scripts/lib/math.toy b/test/scripts/lib/math.toy index 5639775..d7a24e3 100644 --- a/test/scripts/lib/math.toy +++ b/test/scripts/lib/math.toy @@ -71,6 +71,44 @@ import math; 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 {