From c36984b8a5313039757bd85ea23c2f242182ca46 Mon Sep 17 00:00:00 2001 From: adazem009 <68537469+adazem009@users.noreply.github.com> Date: Tue, 5 Nov 2024 10:38:49 +0100 Subject: [PATCH 01/20] Optimize value_mod() --- src/scratch/value_functions.cpp | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/scratch/value_functions.cpp b/src/scratch/value_functions.cpp index b35092d0..710facd5 100644 --- a/src/scratch/value_functions.cpp +++ b/src/scratch/value_functions.cpp @@ -354,17 +354,9 @@ extern "C" /*! Calculates the modulo the given values and writes the result to dst. */ void value_mod(const libscratchcpp::ValueData *v1, const libscratchcpp::ValueData *v2, ValueData *dst) { - double a = value_toDouble(v1); - double b = value_toDouble(v2); - - if ((b == 0) || std::isinf(a)) - value_assign_double(dst, std::numeric_limits::quiet_NaN()); - else if (std::isinf(b)) - value_assign_double(dst, value_toDouble(v1)); - else if (value_isNegative(v1) || value_isNegative(v2)) - value_assign_double(dst, fmod(value_toDouble(v2) + fmod(value_toDouble(v1), -value_toDouble(v2)), value_toDouble(v2))); - else - value_assign_double(dst, fmod(value_toDouble(v1), value_toDouble(v2))); + const double a = value_toDouble(v1); + const double b = value_toDouble(v2); + value_assign_double(dst, fmod(a, b) / b < 0.0 ? fmod(a, b) + b : fmod(a, b)); } /* comparison */ From 6b1c7642154c2304acaa7c7161c6b11f8ae22b83 Mon Sep 17 00:00:00 2001 From: adazem009 <68537469+adazem009@users.noreply.github.com> Date: Tue, 5 Nov 2024 10:40:48 +0100 Subject: [PATCH 02/20] Use results from Value in LLVMCodeBuilder test --- test/dev/llvm/llvmcodebuilder_test.cpp | 150 ++++++++++++------------- 1 file changed, 75 insertions(+), 75 deletions(-) diff --git a/test/dev/llvm/llvmcodebuilder_test.cpp b/test/dev/llvm/llvmcodebuilder_test.cpp index 6715cc0e..14df8254 100644 --- a/test/dev/llvm/llvmcodebuilder_test.cpp +++ b/test/dev/llvm/llvmcodebuilder_test.cpp @@ -226,7 +226,7 @@ TEST_F(LLVMCodeBuilderTest, Add) { std::string expected; - auto addOpTest = [this, &expected](Value v1, Value v2, double expectedResult) { + auto addOpTest = [this, &expected](Value v1, Value v2) { createBuilder(true); m_builder->addConstValue(v1); @@ -241,7 +241,7 @@ TEST_F(LLVMCodeBuilderTest, Add) m_builder->createAdd(); m_builder->addFunctionCall("test_print_string", Compiler::StaticType::Void, { Compiler::StaticType::String }); - std::string str = Value(expectedResult).toString() + '\n'; + std::string str = (v1 + v2).toString() + '\n'; std::string expected = str + str; auto code = m_builder->finalize(); @@ -254,25 +254,25 @@ TEST_F(LLVMCodeBuilderTest, Add) ASSERT_THAT(testing::internal::GetCapturedStdout(), Eq(expected)) << quotes1 << v1.toString() << quotes1 << " " << quotes2 << v2.toString() << quotes2; }; - addOpTest(50, 25, 75); - addOpTest(-500, 25, -475); - addOpTest(-500, -25, -525); - addOpTest("2.54", "6.28", 8.82); - addOpTest(2.54, "-6.28", -3.74); - addOpTest(true, true, 2); - addOpTest("Infinity", "Infinity", std::numeric_limits::infinity()); - addOpTest("Infinity", "-Infinity", std::numeric_limits::quiet_NaN()); - addOpTest("-Infinity", "Infinity", std::numeric_limits::quiet_NaN()); - addOpTest("-Infinity", "-Infinity", -std::numeric_limits::infinity()); - addOpTest(1, "NaN", 1); - addOpTest("NaN", 1, 1); + addOpTest(50, 25); + addOpTest(-500, 25); + addOpTest(-500, -25); + addOpTest("2.54", "6.28"); + addOpTest(2.54, "-6.28"); + addOpTest(true, true); + addOpTest("Infinity", "Infinity"); + addOpTest("Infinity", "-Infinity"); + addOpTest("-Infinity", "Infinity"); + addOpTest("-Infinity", "-Infinity"); + addOpTest(1, "NaN"); + addOpTest("NaN", 1); } TEST_F(LLVMCodeBuilderTest, Subtract) { std::string expected; - auto addOpTest = [this, &expected](Value v1, Value v2, double expectedResult) { + auto addOpTest = [this, &expected](Value v1, Value v2) { createBuilder(true); m_builder->addConstValue(v1); @@ -287,7 +287,7 @@ TEST_F(LLVMCodeBuilderTest, Subtract) m_builder->createSub(); m_builder->addFunctionCall("test_print_string", Compiler::StaticType::Void, { Compiler::StaticType::String }); - std::string str = Value(expectedResult).toString() + '\n'; + std::string str = (v1 - v2).toString() + '\n'; std::string expected = str + str; auto code = m_builder->finalize(); @@ -300,25 +300,25 @@ TEST_F(LLVMCodeBuilderTest, Subtract) ASSERT_THAT(testing::internal::GetCapturedStdout(), Eq(expected)) << quotes1 << v1.toString() << quotes1 << " " << quotes2 << v2.toString() << quotes2; }; - addOpTest(50, 25, 25); - addOpTest(-500, 25, -525); - addOpTest(-500, -25, -475); - addOpTest("2.54", "6.28", -3.74); - addOpTest(2.54, "-6.28", 8.82); - addOpTest(true, true, 0); - addOpTest("Infinity", "Infinity", std::numeric_limits::quiet_NaN()); - addOpTest("Infinity", "-Infinity", std::numeric_limits::infinity()); - addOpTest("-Infinity", "Infinity", -std::numeric_limits::infinity()); - addOpTest("-Infinity", "-Infinity", std::numeric_limits::quiet_NaN()); - addOpTest(1, "NaN", 1); - addOpTest("NaN", 1, -1); + addOpTest(50, 25); + addOpTest(-500, 25); + addOpTest(-500, -25); + addOpTest("2.54", "6.28"); + addOpTest(2.54, "-6.28"); + addOpTest(true, true); + addOpTest("Infinity", "Infinity"); + addOpTest("Infinity", "-Infinity"); + addOpTest("-Infinity", "Infinity"); + addOpTest("-Infinity", "-Infinity"); + addOpTest(1, "NaN"); + addOpTest("NaN", 1); } TEST_F(LLVMCodeBuilderTest, Multiply) { std::string expected; - auto addOpTest = [this, &expected](Value v1, Value v2, double expectedResult) { + auto addOpTest = [this, &expected](Value v1, Value v2) { createBuilder(true); m_builder->addConstValue(v1); @@ -333,7 +333,7 @@ TEST_F(LLVMCodeBuilderTest, Multiply) m_builder->createMul(); m_builder->addFunctionCall("test_print_string", Compiler::StaticType::Void, { Compiler::StaticType::String }); - std::string str = Value(expectedResult).toString() + '\n'; + std::string str = (v1 * v2).toString() + '\n'; std::string expected = str + str; auto code = m_builder->finalize(); @@ -346,30 +346,30 @@ TEST_F(LLVMCodeBuilderTest, Multiply) ASSERT_THAT(testing::internal::GetCapturedStdout(), Eq(expected)) << quotes1 << v1.toString() << quotes1 << " " << quotes2 << v2.toString() << quotes2; }; - addOpTest(50, 2, 100); - addOpTest(-500, 25, -12500); - addOpTest("-500", -25, 12500); - addOpTest("2.54", "6.28", 15.9512); - addOpTest(true, true, 1); - addOpTest("Infinity", "Infinity", std::numeric_limits::infinity()); - addOpTest("Infinity", 0, std::numeric_limits::quiet_NaN()); - addOpTest("Infinity", 2, std::numeric_limits::infinity()); - addOpTest("Infinity", -2, -std::numeric_limits::infinity()); - addOpTest("Infinity", "-Infinity", -std::numeric_limits::infinity()); - addOpTest("-Infinity", "Infinity", -std::numeric_limits::infinity()); - addOpTest("-Infinity", 0, std::numeric_limits::quiet_NaN()); - addOpTest("-Infinity", 2, -std::numeric_limits::infinity()); - addOpTest("-Infinity", -2, std::numeric_limits::infinity()); - addOpTest("-Infinity", "-Infinity", std::numeric_limits::infinity()); - addOpTest(1, "NaN", 0); - addOpTest("NaN", 1, 0); + addOpTest(50, 2); + addOpTest(-500, 25); + addOpTest("-500", -25); + addOpTest("2.54", "6.28"); + addOpTest(true, true); + addOpTest("Infinity", "Infinity"); + addOpTest("Infinity", 0); + addOpTest("Infinity", 2); + addOpTest("Infinity", -2); + addOpTest("Infinity", "-Infinity"); + addOpTest("-Infinity", "Infinity"); + addOpTest("-Infinity", 0); + addOpTest("-Infinity", 2); + addOpTest("-Infinity", -2); + addOpTest("-Infinity", "-Infinity"); + addOpTest(1, "NaN"); + addOpTest("NaN", 1); } TEST_F(LLVMCodeBuilderTest, Divide) { std::string expected; - auto addOpTest = [this, &expected](Value v1, Value v2, double expectedResult) { + auto addOpTest = [this, &expected](Value v1, Value v2) { createBuilder(true); m_builder->addConstValue(v1); @@ -384,7 +384,7 @@ TEST_F(LLVMCodeBuilderTest, Divide) m_builder->createDiv(); m_builder->addFunctionCall("test_print_string", Compiler::StaticType::Void, { Compiler::StaticType::String }); - std::string str = Value(expectedResult).toString() + '\n'; + std::string str = (v1 / v2).toString() + '\n'; std::string expected = str + str; auto code = m_builder->finalize(); @@ -397,32 +397,32 @@ TEST_F(LLVMCodeBuilderTest, Divide) ASSERT_THAT(testing::internal::GetCapturedStdout(), Eq(expected)) << quotes1 << v1.toString() << quotes1 << " " << quotes2 << v2.toString() << quotes2; }; - addOpTest(50, 2, 25); - addOpTest(-500, 25, -20); - addOpTest("-500", -25, 20); - addOpTest("3.5", "2.5", 1.4); - addOpTest(true, true, 1); - addOpTest("Infinity", "Infinity", std::numeric_limits::quiet_NaN()); - addOpTest("Infinity", 0, std::numeric_limits::infinity()); - addOpTest("Infinity", 2, std::numeric_limits::infinity()); - addOpTest("Infinity", -2, -std::numeric_limits::infinity()); - addOpTest("Infinity", "-Infinity", std::numeric_limits::quiet_NaN()); - addOpTest("-Infinity", "Infinity", std::numeric_limits::quiet_NaN()); - addOpTest("-Infinity", 0, -std::numeric_limits::infinity()); - addOpTest("-Infinity", 2, -std::numeric_limits::infinity()); - addOpTest("-Infinity", -2, std::numeric_limits::infinity()); - addOpTest("-Infinity", "-Infinity", std::numeric_limits::quiet_NaN()); - addOpTest(0, "Infinity", 0); - addOpTest(2, "Infinity", 0); - addOpTest(-2, "Infinity", 0); - addOpTest(0, "-Infinity", 0); - addOpTest(2, "-Infinity", 0); - addOpTest(-2, "-Infinity", 0); - addOpTest(1, "NaN", std::numeric_limits::infinity()); - addOpTest("NaN", 1, 0); - addOpTest(5, 0, std::numeric_limits::infinity()); - addOpTest(-5, 0, -std::numeric_limits::infinity()); - addOpTest(0, 0, std::numeric_limits::quiet_NaN()); + addOpTest(50, 2); + addOpTest(-500, 25); + addOpTest("-500", -25); + addOpTest("3.5", "2.5"); + addOpTest(true, true); + addOpTest("Infinity", "Infinity"); + addOpTest("Infinity", 0); + addOpTest("Infinity", 2); + addOpTest("Infinity", -2); + addOpTest("Infinity", "-Infinity"); + addOpTest("-Infinity", "Infinity"); + addOpTest("-Infinity", 0); + addOpTest("-Infinity", 2); + addOpTest("-Infinity", -2); + addOpTest("-Infinity", "-Infinity"); + addOpTest(0, "Infinity"); + addOpTest(2, "Infinity"); + addOpTest(-2, "Infinity"); + addOpTest(0, "-Infinity"); + addOpTest(2, "-Infinity"); + addOpTest(-2, "-Infinity"); + addOpTest(1, "NaN"); + addOpTest("NaN", 1); + addOpTest(5, 0); + addOpTest(-5, 0); + addOpTest(0, 0); } TEST_F(LLVMCodeBuilderTest, EqualComparison) From 25bc8fce1ad855a5d10bd11d6050242e76a6b1a2 Mon Sep 17 00:00:00 2001 From: adazem009 <68537469+adazem009@users.noreply.github.com> Date: Tue, 5 Nov 2024 10:42:08 +0100 Subject: [PATCH 03/20] LLVMCodeBuilder: Implement mod operator --- src/dev/engine/internal/icodebuilder.h | 2 + src/dev/engine/internal/llvmcodebuilder.cpp | 19 +++++++ src/dev/engine/internal/llvmcodebuilder.h | 3 + test/dev/llvm/llvmcodebuilder_test.cpp | 61 +++++++++++++++++++++ test/mocks/codebuildermock.h | 2 + 5 files changed, 87 insertions(+) diff --git a/src/dev/engine/internal/icodebuilder.h b/src/dev/engine/internal/icodebuilder.h index f5852098..0d22c7e2 100644 --- a/src/dev/engine/internal/icodebuilder.h +++ b/src/dev/engine/internal/icodebuilder.h @@ -37,6 +37,8 @@ class ICodeBuilder virtual void createOr() = 0; virtual void createNot() = 0; + virtual void createMod() = 0; + virtual void beginIfStatement() = 0; virtual void beginElseBranch() = 0; virtual void endIf() = 0; diff --git a/src/dev/engine/internal/llvmcodebuilder.cpp b/src/dev/engine/internal/llvmcodebuilder.cpp index 22f3d552..9dd2411f 100644 --- a/src/dev/engine/internal/llvmcodebuilder.cpp +++ b/src/dev/engine/internal/llvmcodebuilder.cpp @@ -180,6 +180,20 @@ std::shared_ptr LLVMCodeBuilder::finalize() break; } + case Step::Type::Mod: { + assert(step.args.size() == 2); + const auto &arg1 = step.args[0]; + const auto &arg2 = step.args[1]; + // rem(a, b) / b < 0.0 ? rem(a, b) + b : rem(a, b) + llvm::Constant *zero = llvm::ConstantFP::get(m_ctx, llvm::APFloat(0.0)); + llvm::Value *num1 = removeNaN(castValue(arg1.second, arg1.first)); + llvm::Value *num2 = removeNaN(castValue(arg2.second, arg2.first)); + llvm::Value *value = m_builder.CreateFRem(num1, num2); // rem(a, b) + llvm::Value *cond = m_builder.CreateFCmpOLT(m_builder.CreateFDiv(value, num2), zero); // rem(a, b) / b < 0.0 // rem(a, b) + step.functionReturnReg->value = m_builder.CreateSelect(cond, m_builder.CreateFAdd(value, num2), value); + break; + } + case Step::Type::Yield: if (!m_warp) { freeHeap(); @@ -548,6 +562,11 @@ void LLVMCodeBuilder::createNot() createOp(Step::Type::Not, Compiler::StaticType::Bool, Compiler::StaticType::Bool, 1); } +void LLVMCodeBuilder::createMod() +{ + createOp(Step::Type::Mod, Compiler::StaticType::Number, Compiler::StaticType::Number, 2); +} + void LLVMCodeBuilder::beginIfStatement() { Step step(Step::Type::BeginIf); diff --git a/src/dev/engine/internal/llvmcodebuilder.h b/src/dev/engine/internal/llvmcodebuilder.h index 5fb17df5..184acf90 100644 --- a/src/dev/engine/internal/llvmcodebuilder.h +++ b/src/dev/engine/internal/llvmcodebuilder.h @@ -39,6 +39,8 @@ class LLVMCodeBuilder : public ICodeBuilder void createOr() override; void createNot() override; + void createMod() override; + void beginIfStatement() override; void beginElseBranch() override; void endIf() override; @@ -81,6 +83,7 @@ class LLVMCodeBuilder : public ICodeBuilder And, Or, Not, + Mod, Yield, BeginIf, BeginElse, diff --git a/test/dev/llvm/llvmcodebuilder_test.cpp b/test/dev/llvm/llvmcodebuilder_test.cpp index 14df8254..426f056c 100644 --- a/test/dev/llvm/llvmcodebuilder_test.cpp +++ b/test/dev/llvm/llvmcodebuilder_test.cpp @@ -1024,6 +1024,67 @@ TEST_F(LLVMCodeBuilderTest, Not) addOpTest("nan"); } +TEST_F(LLVMCodeBuilderTest, Mod) +{ + std::string expected; + + auto addOpTest = [this, &expected](Value v1, Value v2) { + createBuilder(true); + + m_builder->addConstValue(v1); + m_builder->addConstValue(v2); + m_builder->createMod(); + m_builder->addFunctionCall("test_print_string", Compiler::StaticType::Void, { Compiler::StaticType::String }); + + m_builder->addConstValue(v1); + m_builder->addFunctionCall("test_const_number", Compiler::StaticType::Number, { Compiler::StaticType::Number }); + m_builder->addConstValue(v2); + m_builder->addFunctionCall("test_const_number", Compiler::StaticType::Number, { Compiler::StaticType::Number }); + m_builder->createMod(); + m_builder->addFunctionCall("test_print_string", Compiler::StaticType::Void, { Compiler::StaticType::String }); + + std::string str = (v1 % v2).toString() + '\n'; + std::string expected = str + str; + + auto code = m_builder->finalize(); + auto ctx = code->createExecutionContext(&m_target); + + testing::internal::CaptureStdout(); + code->run(ctx.get()); + const std::string quotes1 = v1.isString() ? "\"" : ""; + const std::string quotes2 = v2.isString() ? "\"" : ""; + ASSERT_THAT(testing::internal::GetCapturedStdout(), Eq(expected)) << quotes1 << v1.toString() << quotes1 << " " << quotes2 << v2.toString() << quotes2; + }; + + addOpTest(4, 3); + addOpTest(3, 3); + addOpTest(2, 3); + addOpTest(1, 3); + addOpTest(0, 3); + addOpTest(-1, 3); + addOpTest(-2, 3); + addOpTest(-3, 3); + addOpTest(-4, 3); + addOpTest(4.75, 2); + addOpTest(-4.75, 2); + addOpTest(-4.75, -2); + addOpTest(4.75, -2); + addOpTest(5, 0); + addOpTest(-5, 0); + addOpTest(-2.5, "Infinity"); + addOpTest(-1.2, "-Infinity"); + addOpTest(2.5, "Infinity"); + addOpTest(1.2, "-Infinity"); + addOpTest("Infinity", 2); + addOpTest("-Infinity", 2); + addOpTest("Infinity", -2); + addOpTest("-Infinity", -2); + addOpTest(3, "NaN"); + addOpTest(-3, "NaN"); + addOpTest("NaN", 5); + addOpTest("NaN", -5); +} + TEST_F(LLVMCodeBuilderTest, Yield) { auto build = [this]() { diff --git a/test/mocks/codebuildermock.h b/test/mocks/codebuildermock.h index 3271451d..92e5f3b6 100644 --- a/test/mocks/codebuildermock.h +++ b/test/mocks/codebuildermock.h @@ -27,6 +27,8 @@ class CodeBuilderMock : public ICodeBuilder MOCK_METHOD(void, createOr, (), (override)); MOCK_METHOD(void, createNot, (), (override)); + MOCK_METHOD(void, createMod, (), (override)); + MOCK_METHOD(void, beginIfStatement, (), (override)); MOCK_METHOD(void, beginElseBranch, (), (override)); MOCK_METHOD(void, endIf, (), (override)); From 5e1e3b62ae2e5198da2ca8f7d32890abbdf75b91 Mon Sep 17 00:00:00 2001 From: adazem009 <68537469+adazem009@users.noreply.github.com> Date: Tue, 5 Nov 2024 21:56:05 +0100 Subject: [PATCH 04/20] Fix negative zero string conversion --- src/scratch/value_functions_p.h | 4 ++-- test/scratch_classes/value_test.cpp | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/scratch/value_functions_p.h b/src/scratch/value_functions_p.h index ca497e99..01958ab5 100644 --- a/src/scratch/value_functions_p.h +++ b/src/scratch/value_functions_p.h @@ -50,7 +50,7 @@ extern "C" return v < 0 && std::isinf(v); } - inline long value_convert_int_str(const char *str, int n, bool *ok) + inline double value_convert_int_str(const char *str, int n, bool *ok) { if (ok) *ok = false; @@ -80,7 +80,7 @@ extern "C" *ok = true; if (isNegative) - return -ret; + return -static_cast(ret); // for negative zero else return ret; } diff --git a/test/scratch_classes/value_test.cpp b/test/scratch_classes/value_test.cpp index 359bc946..04cce470 100644 --- a/test/scratch_classes/value_test.cpp +++ b/test/scratch_classes/value_test.cpp @@ -938,6 +938,15 @@ TEST(ValueTest, ToDouble) v = "-0.15"; ASSERT_EQ(v.toDouble(), -0.15); + v = "0"; + ASSERT_EQ(v.toDouble(), 0.0); + v = "-0"; + ASSERT_EQ(v.toDouble(), -0.0); + v = "0.0"; + ASSERT_EQ(v.toDouble(), 0.0); + v = "-0.0"; + ASSERT_EQ(v.toDouble(), -0.0); + v = "+.15"; ASSERT_EQ(v.toDouble(), 0.15); v = ".15"; @@ -2879,6 +2888,11 @@ TEST(ValueTest, StringToDouble) ASSERT_EQ(value_stringToDouble("0.15"), 0.15); ASSERT_EQ(value_stringToDouble("-0.15"), -0.15); + ASSERT_EQ(value_stringToDouble("0"), 0.0); + ASSERT_EQ(value_stringToDouble("-0"), -0.0); + ASSERT_EQ(value_stringToDouble("0.0"), 0.0); + ASSERT_EQ(value_stringToDouble("-0.0"), -0.0); + ASSERT_EQ(value_stringToDouble("+.15"), 0.15); ASSERT_EQ(value_stringToDouble(".15"), 0.15); ASSERT_EQ(value_stringToDouble("-.15"), -0.15); From ba6a97bc42acb7074fc292b06b83a591b71f32ec Mon Sep 17 00:00:00 2001 From: adazem009 <68537469+adazem009@users.noreply.github.com> Date: Tue, 5 Nov 2024 21:56:43 +0100 Subject: [PATCH 05/20] LLVMCodeBuilder: Implement round operator --- src/dev/engine/internal/icodebuilder.h | 1 + src/dev/engine/internal/llvmcodebuilder.cpp | 22 ++++++++++ src/dev/engine/internal/llvmcodebuilder.h | 2 + test/dev/llvm/llvmcodebuilder_test.cpp | 48 +++++++++++++++++++++ test/mocks/codebuildermock.h | 1 + 5 files changed, 74 insertions(+) diff --git a/src/dev/engine/internal/icodebuilder.h b/src/dev/engine/internal/icodebuilder.h index 0d22c7e2..5389c159 100644 --- a/src/dev/engine/internal/icodebuilder.h +++ b/src/dev/engine/internal/icodebuilder.h @@ -38,6 +38,7 @@ class ICodeBuilder virtual void createNot() = 0; virtual void createMod() = 0; + virtual void createRound() = 0; virtual void beginIfStatement() = 0; virtual void beginElseBranch() = 0; diff --git a/src/dev/engine/internal/llvmcodebuilder.cpp b/src/dev/engine/internal/llvmcodebuilder.cpp index 9dd2411f..126c865f 100644 --- a/src/dev/engine/internal/llvmcodebuilder.cpp +++ b/src/dev/engine/internal/llvmcodebuilder.cpp @@ -194,6 +194,23 @@ std::shared_ptr LLVMCodeBuilder::finalize() break; } + case Step::Type::Round: { + assert(step.args.size() == 1); + const auto &arg = step.args[0]; + // x >= 0.0 ? round(x) : (x >= -0.5 ? -0.0 : floor(x + 0.5)) + llvm::Constant *zero = llvm::ConstantFP::get(m_ctx, llvm::APFloat(0.0)); + llvm::Constant *negativeZero = llvm::ConstantFP::get(m_ctx, llvm::APFloat(-0.0)); + llvm::Function *roundFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::round, m_builder.getDoubleTy()); + llvm::Function *floorFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::floor, m_builder.getDoubleTy()); + llvm::Value *num = removeNaN(castValue(arg.second, arg.first)); + llvm::Value *notNegative = m_builder.CreateFCmpOGE(num, zero); // num >= 0.0 + llvm::Value *roundNum = m_builder.CreateCall(roundFunc, num); // round(num) + llvm::Value *negativeCond = m_builder.CreateFCmpOGE(num, llvm::ConstantFP::get(m_ctx, llvm::APFloat(-0.5))); // num >= -0.5 + llvm::Value *negativeRound = m_builder.CreateCall(floorFunc, m_builder.CreateFAdd(num, llvm::ConstantFP::get(m_ctx, llvm::APFloat(0.5)))); // floor(x + 0.5) + step.functionReturnReg->value = m_builder.CreateSelect(notNegative, roundNum, m_builder.CreateSelect(negativeCond, negativeZero, negativeRound)); + break; + } + case Step::Type::Yield: if (!m_warp) { freeHeap(); @@ -567,6 +584,11 @@ void LLVMCodeBuilder::createMod() createOp(Step::Type::Mod, Compiler::StaticType::Number, Compiler::StaticType::Number, 2); } +void LLVMCodeBuilder::createRound() +{ + createOp(Step::Type::Round, Compiler::StaticType::Number, Compiler::StaticType::Number, 1); +} + void LLVMCodeBuilder::beginIfStatement() { Step step(Step::Type::BeginIf); diff --git a/src/dev/engine/internal/llvmcodebuilder.h b/src/dev/engine/internal/llvmcodebuilder.h index 184acf90..4a8c067b 100644 --- a/src/dev/engine/internal/llvmcodebuilder.h +++ b/src/dev/engine/internal/llvmcodebuilder.h @@ -40,6 +40,7 @@ class LLVMCodeBuilder : public ICodeBuilder void createNot() override; void createMod() override; + void createRound() override; void beginIfStatement() override; void beginElseBranch() override; @@ -84,6 +85,7 @@ class LLVMCodeBuilder : public ICodeBuilder Or, Not, Mod, + Round, Yield, BeginIf, BeginElse, diff --git a/test/dev/llvm/llvmcodebuilder_test.cpp b/test/dev/llvm/llvmcodebuilder_test.cpp index 426f056c..cb787991 100644 --- a/test/dev/llvm/llvmcodebuilder_test.cpp +++ b/test/dev/llvm/llvmcodebuilder_test.cpp @@ -1085,6 +1085,54 @@ TEST_F(LLVMCodeBuilderTest, Mod) addOpTest("NaN", -5); } +TEST_F(LLVMCodeBuilderTest, Round) +{ + std::string expected; + + auto addOpTest = [this, &expected](Value v1, double expectedResult) { + createBuilder(true); + + m_builder->addConstValue(v1); + m_builder->createRound(); + m_builder->addFunctionCall("test_print_number", Compiler::StaticType::Void, { Compiler::StaticType::Number }); + + m_builder->addConstValue(v1); + m_builder->addFunctionCall("test_const_number", Compiler::StaticType::Number, { Compiler::StaticType::Number }); + m_builder->createRound(); + m_builder->addFunctionCall("test_print_number", Compiler::StaticType::Void, { Compiler::StaticType::Number }); + + std::stringstream stream; + stream << expectedResult; + std::string str = stream.str() + '\n'; + std::string expected = str + str; + + auto code = m_builder->finalize(); + auto ctx = code->createExecutionContext(&m_target); + + testing::internal::CaptureStdout(); + code->run(ctx.get()); + const std::string quotes1 = v1.isString() ? "\"" : ""; + ASSERT_THAT(testing::internal::GetCapturedStdout(), Eq(expected)) << quotes1 << v1.toString() << quotes1; + }; + + static const double inf = std::numeric_limits::infinity(); + static const double nan = std::numeric_limits::quiet_NaN(); + + addOpTest(4.0, 4.0); + addOpTest(3.2, 3.0); + addOpTest(3.5, 4.0); + addOpTest(3.6, 4.0); + addOpTest(-2.4, -2.0); + addOpTest(-2.5, -2.0); + addOpTest(-2.6, -3.0); + addOpTest(-0.4, -0.0); + addOpTest(-0.5, -0.0); + addOpTest(-0.51, -1.0); + addOpTest(inf, inf); + addOpTest(-inf, -inf); + addOpTest(nan, 0); +} + TEST_F(LLVMCodeBuilderTest, Yield) { auto build = [this]() { diff --git a/test/mocks/codebuildermock.h b/test/mocks/codebuildermock.h index 92e5f3b6..00a6adac 100644 --- a/test/mocks/codebuildermock.h +++ b/test/mocks/codebuildermock.h @@ -28,6 +28,7 @@ class CodeBuilderMock : public ICodeBuilder MOCK_METHOD(void, createNot, (), (override)); MOCK_METHOD(void, createMod, (), (override)); + MOCK_METHOD(void, createRound, (), (override)); MOCK_METHOD(void, beginIfStatement, (), (override)); MOCK_METHOD(void, beginElseBranch, (), (override)); From 7e7f7da99fcf2b9296bf4015d04e700b64cf6d98 Mon Sep 17 00:00:00 2001 From: adazem009 <68537469+adazem009@users.noreply.github.com> Date: Wed, 6 Nov 2024 09:00:48 +0100 Subject: [PATCH 06/20] LLVMCodeBuilder: Implement abs operator --- src/dev/engine/internal/icodebuilder.h | 1 + src/dev/engine/internal/llvmcodebuilder.cpp | 14 +++++++ src/dev/engine/internal/llvmcodebuilder.h | 2 + test/dev/llvm/llvmcodebuilder_test.cpp | 45 +++++++++++++++++++++ test/mocks/codebuildermock.h | 1 + 5 files changed, 63 insertions(+) diff --git a/src/dev/engine/internal/icodebuilder.h b/src/dev/engine/internal/icodebuilder.h index 5389c159..1e7cb522 100644 --- a/src/dev/engine/internal/icodebuilder.h +++ b/src/dev/engine/internal/icodebuilder.h @@ -39,6 +39,7 @@ class ICodeBuilder virtual void createMod() = 0; virtual void createRound() = 0; + virtual void createAbs() = 0; virtual void beginIfStatement() = 0; virtual void beginElseBranch() = 0; diff --git a/src/dev/engine/internal/llvmcodebuilder.cpp b/src/dev/engine/internal/llvmcodebuilder.cpp index 126c865f..c6d43201 100644 --- a/src/dev/engine/internal/llvmcodebuilder.cpp +++ b/src/dev/engine/internal/llvmcodebuilder.cpp @@ -211,6 +211,15 @@ std::shared_ptr LLVMCodeBuilder::finalize() break; } + case Step::Type::Abs: { + assert(step.args.size() == 1); + const auto &arg = step.args[0]; + llvm::Function *absFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::fabs, m_builder.getDoubleTy()); + llvm::Value *num = removeNaN(castValue(arg.second, arg.first)); + step.functionReturnReg->value = m_builder.CreateCall(absFunc, num); + break; + } + case Step::Type::Yield: if (!m_warp) { freeHeap(); @@ -589,6 +598,11 @@ void LLVMCodeBuilder::createRound() createOp(Step::Type::Round, Compiler::StaticType::Number, Compiler::StaticType::Number, 1); } +void LLVMCodeBuilder::createAbs() +{ + createOp(Step::Type::Abs, Compiler::StaticType::Number, Compiler::StaticType::Number, 1); +} + void LLVMCodeBuilder::beginIfStatement() { Step step(Step::Type::BeginIf); diff --git a/src/dev/engine/internal/llvmcodebuilder.h b/src/dev/engine/internal/llvmcodebuilder.h index 4a8c067b..b9d4cf6f 100644 --- a/src/dev/engine/internal/llvmcodebuilder.h +++ b/src/dev/engine/internal/llvmcodebuilder.h @@ -41,6 +41,7 @@ class LLVMCodeBuilder : public ICodeBuilder void createMod() override; void createRound() override; + void createAbs() override; void beginIfStatement() override; void beginElseBranch() override; @@ -86,6 +87,7 @@ class LLVMCodeBuilder : public ICodeBuilder Not, Mod, Round, + Abs, Yield, BeginIf, BeginElse, diff --git a/test/dev/llvm/llvmcodebuilder_test.cpp b/test/dev/llvm/llvmcodebuilder_test.cpp index cb787991..952a8c13 100644 --- a/test/dev/llvm/llvmcodebuilder_test.cpp +++ b/test/dev/llvm/llvmcodebuilder_test.cpp @@ -1133,6 +1133,51 @@ TEST_F(LLVMCodeBuilderTest, Round) addOpTest(nan, 0); } +TEST_F(LLVMCodeBuilderTest, Abs) +{ + std::string expected; + + auto addOpTest = [this, &expected](Value v1, double expectedResult) { + createBuilder(true); + + m_builder->addConstValue(v1); + m_builder->createAbs(); + m_builder->addFunctionCall("test_print_number", Compiler::StaticType::Void, { Compiler::StaticType::Number }); + + m_builder->addConstValue(v1); + m_builder->addFunctionCall("test_const_number", Compiler::StaticType::Number, { Compiler::StaticType::Number }); + m_builder->createAbs(); + m_builder->addFunctionCall("test_print_number", Compiler::StaticType::Void, { Compiler::StaticType::Number }); + + std::stringstream stream; + stream << expectedResult; + std::string str = stream.str() + '\n'; + std::string expected = str + str; + + auto code = m_builder->finalize(); + auto ctx = code->createExecutionContext(&m_target); + + testing::internal::CaptureStdout(); + code->run(ctx.get()); + const std::string quotes1 = v1.isString() ? "\"" : ""; + ASSERT_THAT(testing::internal::GetCapturedStdout(), Eq(expected)) << quotes1 << v1.toString() << quotes1; + }; + + static const double inf = std::numeric_limits::infinity(); + static const double nan = std::numeric_limits::quiet_NaN(); + + addOpTest(4.0, 4.0); + addOpTest(3.2, 3.2); + addOpTest(-2.0, 2.0); + addOpTest(-2.5, 2.5); + addOpTest(-2.6, 2.6); + addOpTest(0.0, 0.0); + addOpTest(-0.0, 0.0); + addOpTest(inf, inf); + addOpTest(-inf, inf); + addOpTest(nan, 0); +} + TEST_F(LLVMCodeBuilderTest, Yield) { auto build = [this]() { diff --git a/test/mocks/codebuildermock.h b/test/mocks/codebuildermock.h index 00a6adac..a9a9394a 100644 --- a/test/mocks/codebuildermock.h +++ b/test/mocks/codebuildermock.h @@ -29,6 +29,7 @@ class CodeBuilderMock : public ICodeBuilder MOCK_METHOD(void, createMod, (), (override)); MOCK_METHOD(void, createRound, (), (override)); + MOCK_METHOD(void, createAbs, (), (override)); MOCK_METHOD(void, beginIfStatement, (), (override)); MOCK_METHOD(void, beginElseBranch, (), (override)); From 6e66240843223dfd9360f10d62a891b991c82ca2 Mon Sep 17 00:00:00 2001 From: adazem009 <68537469+adazem009@users.noreply.github.com> Date: Wed, 6 Nov 2024 14:19:27 +0100 Subject: [PATCH 07/20] LLVMCodeBuilder: Implement floor operator --- src/dev/engine/internal/icodebuilder.h | 1 + src/dev/engine/internal/llvmcodebuilder.cpp | 14 ++++++ src/dev/engine/internal/llvmcodebuilder.h | 2 + test/dev/llvm/llvmcodebuilder_test.cpp | 50 +++++++++++++++++++++ test/mocks/codebuildermock.h | 1 + 5 files changed, 68 insertions(+) diff --git a/src/dev/engine/internal/icodebuilder.h b/src/dev/engine/internal/icodebuilder.h index 1e7cb522..4256e497 100644 --- a/src/dev/engine/internal/icodebuilder.h +++ b/src/dev/engine/internal/icodebuilder.h @@ -40,6 +40,7 @@ class ICodeBuilder virtual void createMod() = 0; virtual void createRound() = 0; virtual void createAbs() = 0; + virtual void createFloor() = 0; virtual void beginIfStatement() = 0; virtual void beginElseBranch() = 0; diff --git a/src/dev/engine/internal/llvmcodebuilder.cpp b/src/dev/engine/internal/llvmcodebuilder.cpp index c6d43201..51bc46c2 100644 --- a/src/dev/engine/internal/llvmcodebuilder.cpp +++ b/src/dev/engine/internal/llvmcodebuilder.cpp @@ -220,6 +220,15 @@ std::shared_ptr LLVMCodeBuilder::finalize() break; } + case Step::Type::Floor: { + assert(step.args.size() == 1); + const auto &arg = step.args[0]; + llvm::Function *floorFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::floor, m_builder.getDoubleTy()); + llvm::Value *num = removeNaN(castValue(arg.second, arg.first)); + step.functionReturnReg->value = m_builder.CreateCall(floorFunc, num); + break; + } + case Step::Type::Yield: if (!m_warp) { freeHeap(); @@ -603,6 +612,11 @@ void LLVMCodeBuilder::createAbs() createOp(Step::Type::Abs, Compiler::StaticType::Number, Compiler::StaticType::Number, 1); } +void LLVMCodeBuilder::createFloor() +{ + createOp(Step::Type::Floor, Compiler::StaticType::Number, Compiler::StaticType::Number, 1); +} + void LLVMCodeBuilder::beginIfStatement() { Step step(Step::Type::BeginIf); diff --git a/src/dev/engine/internal/llvmcodebuilder.h b/src/dev/engine/internal/llvmcodebuilder.h index b9d4cf6f..0db9c8e5 100644 --- a/src/dev/engine/internal/llvmcodebuilder.h +++ b/src/dev/engine/internal/llvmcodebuilder.h @@ -42,6 +42,7 @@ class LLVMCodeBuilder : public ICodeBuilder void createMod() override; void createRound() override; void createAbs() override; + void createFloor() override; void beginIfStatement() override; void beginElseBranch() override; @@ -88,6 +89,7 @@ class LLVMCodeBuilder : public ICodeBuilder Mod, Round, Abs, + Floor, Yield, BeginIf, BeginElse, diff --git a/test/dev/llvm/llvmcodebuilder_test.cpp b/test/dev/llvm/llvmcodebuilder_test.cpp index 952a8c13..c69c8da4 100644 --- a/test/dev/llvm/llvmcodebuilder_test.cpp +++ b/test/dev/llvm/llvmcodebuilder_test.cpp @@ -1178,6 +1178,56 @@ TEST_F(LLVMCodeBuilderTest, Abs) addOpTest(nan, 0); } +TEST_F(LLVMCodeBuilderTest, Floor) +{ + std::string expected; + + auto addOpTest = [this, &expected](Value v1, double expectedResult) { + createBuilder(true); + + m_builder->addConstValue(v1); + m_builder->createFloor(); + m_builder->addFunctionCall("test_print_number", Compiler::StaticType::Void, { Compiler::StaticType::Number }); + + m_builder->addConstValue(v1); + m_builder->addFunctionCall("test_const_number", Compiler::StaticType::Number, { Compiler::StaticType::Number }); + m_builder->createFloor(); + m_builder->addFunctionCall("test_print_number", Compiler::StaticType::Void, { Compiler::StaticType::Number }); + + std::stringstream stream; + stream << expectedResult; + std::string str = stream.str() + '\n'; + std::string expected = str + str; + + auto code = m_builder->finalize(); + auto ctx = code->createExecutionContext(&m_target); + + testing::internal::CaptureStdout(); + code->run(ctx.get()); + const std::string quotes1 = v1.isString() ? "\"" : ""; + ASSERT_THAT(testing::internal::GetCapturedStdout(), Eq(expected)) << quotes1 << v1.toString() << quotes1; + }; + + static const double inf = std::numeric_limits::infinity(); + static const double nan = std::numeric_limits::quiet_NaN(); + + addOpTest(4.0, 4.0); + addOpTest(3.2, 3.0); + addOpTest(3.5, 3.0); + addOpTest(3.6, 3.0); + addOpTest(0.0, 0.0); + addOpTest(-0.0, -0.0); + addOpTest(-2.4, -3.0); + addOpTest(-2.5, -3.0); + addOpTest(-2.6, -3.0); + addOpTest(-0.4, -1.0); + addOpTest(-0.5, -1.0); + addOpTest(-0.51, -1.0); + addOpTest(inf, inf); + addOpTest(-inf, -inf); + addOpTest(nan, 0); +} + TEST_F(LLVMCodeBuilderTest, Yield) { auto build = [this]() { diff --git a/test/mocks/codebuildermock.h b/test/mocks/codebuildermock.h index a9a9394a..64c8e99b 100644 --- a/test/mocks/codebuildermock.h +++ b/test/mocks/codebuildermock.h @@ -30,6 +30,7 @@ class CodeBuilderMock : public ICodeBuilder MOCK_METHOD(void, createMod, (), (override)); MOCK_METHOD(void, createRound, (), (override)); MOCK_METHOD(void, createAbs, (), (override)); + MOCK_METHOD(void, createFloor, (), (override)); MOCK_METHOD(void, beginIfStatement, (), (override)); MOCK_METHOD(void, beginElseBranch, (), (override)); From e01d6fff5b0b332dc9bbcb823fa6c66e8e5a50aa Mon Sep 17 00:00:00 2001 From: adazem009 <68537469+adazem009@users.noreply.github.com> Date: Wed, 6 Nov 2024 14:43:19 +0100 Subject: [PATCH 08/20] LLVMCodeBuilder: Implement ceil operator --- src/dev/engine/internal/icodebuilder.h | 1 + src/dev/engine/internal/llvmcodebuilder.cpp | 14 ++++++ src/dev/engine/internal/llvmcodebuilder.h | 2 + test/dev/llvm/llvmcodebuilder_test.cpp | 51 +++++++++++++++++++++ test/mocks/codebuildermock.h | 1 + 5 files changed, 69 insertions(+) diff --git a/src/dev/engine/internal/icodebuilder.h b/src/dev/engine/internal/icodebuilder.h index 4256e497..eb16e382 100644 --- a/src/dev/engine/internal/icodebuilder.h +++ b/src/dev/engine/internal/icodebuilder.h @@ -41,6 +41,7 @@ class ICodeBuilder virtual void createRound() = 0; virtual void createAbs() = 0; virtual void createFloor() = 0; + virtual void createCeil() = 0; virtual void beginIfStatement() = 0; virtual void beginElseBranch() = 0; diff --git a/src/dev/engine/internal/llvmcodebuilder.cpp b/src/dev/engine/internal/llvmcodebuilder.cpp index 51bc46c2..3ce2c386 100644 --- a/src/dev/engine/internal/llvmcodebuilder.cpp +++ b/src/dev/engine/internal/llvmcodebuilder.cpp @@ -229,6 +229,15 @@ std::shared_ptr LLVMCodeBuilder::finalize() break; } + case Step::Type::Ceil: { + assert(step.args.size() == 1); + const auto &arg = step.args[0]; + llvm::Function *ceilFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::ceil, m_builder.getDoubleTy()); + llvm::Value *num = removeNaN(castValue(arg.second, arg.first)); + step.functionReturnReg->value = m_builder.CreateCall(ceilFunc, num); + break; + } + case Step::Type::Yield: if (!m_warp) { freeHeap(); @@ -617,6 +626,11 @@ void LLVMCodeBuilder::createFloor() createOp(Step::Type::Floor, Compiler::StaticType::Number, Compiler::StaticType::Number, 1); } +void LLVMCodeBuilder::createCeil() +{ + createOp(Step::Type::Ceil, Compiler::StaticType::Number, Compiler::StaticType::Number, 1); +} + void LLVMCodeBuilder::beginIfStatement() { Step step(Step::Type::BeginIf); diff --git a/src/dev/engine/internal/llvmcodebuilder.h b/src/dev/engine/internal/llvmcodebuilder.h index 0db9c8e5..71519b58 100644 --- a/src/dev/engine/internal/llvmcodebuilder.h +++ b/src/dev/engine/internal/llvmcodebuilder.h @@ -43,6 +43,7 @@ class LLVMCodeBuilder : public ICodeBuilder void createRound() override; void createAbs() override; void createFloor() override; + void createCeil() override; void beginIfStatement() override; void beginElseBranch() override; @@ -90,6 +91,7 @@ class LLVMCodeBuilder : public ICodeBuilder Round, Abs, Floor, + Ceil, Yield, BeginIf, BeginElse, diff --git a/test/dev/llvm/llvmcodebuilder_test.cpp b/test/dev/llvm/llvmcodebuilder_test.cpp index c69c8da4..212a29a1 100644 --- a/test/dev/llvm/llvmcodebuilder_test.cpp +++ b/test/dev/llvm/llvmcodebuilder_test.cpp @@ -1228,6 +1228,57 @@ TEST_F(LLVMCodeBuilderTest, Floor) addOpTest(nan, 0); } +TEST_F(LLVMCodeBuilderTest, Ceil) +{ + std::string expected; + + auto addOpTest = [this, &expected](Value v1, double expectedResult) { + createBuilder(true); + + m_builder->addConstValue(v1); + m_builder->createCeil(); + m_builder->addFunctionCall("test_print_number", Compiler::StaticType::Void, { Compiler::StaticType::Number }); + + m_builder->addConstValue(v1); + m_builder->addFunctionCall("test_const_number", Compiler::StaticType::Number, { Compiler::StaticType::Number }); + m_builder->createCeil(); + m_builder->addFunctionCall("test_print_number", Compiler::StaticType::Void, { Compiler::StaticType::Number }); + + std::stringstream stream; + stream << expectedResult; + std::string str = stream.str() + '\n'; + std::string expected = str + str; + + auto code = m_builder->finalize(); + auto ctx = code->createExecutionContext(&m_target); + + testing::internal::CaptureStdout(); + code->run(ctx.get()); + const std::string quotes1 = v1.isString() ? "\"" : ""; + ASSERT_THAT(testing::internal::GetCapturedStdout(), Eq(expected)) << quotes1 << v1.toString() << quotes1; + }; + + static const double inf = std::numeric_limits::infinity(); + static const double nan = std::numeric_limits::quiet_NaN(); + + addOpTest(8.0, 8.0); + addOpTest(3.2, 4.0); + addOpTest(3.5, 4.0); + addOpTest(3.6, 4.0); + addOpTest(0.4, 1.0); + addOpTest(0.0, 0.0); + addOpTest(-0.0, -0.0); + addOpTest(-2.4, -2.0); + addOpTest(-2.5, -2.0); + addOpTest(-2.6, -2.0); + addOpTest(-0.4, -0.0); + addOpTest(-0.5, -0.0); + addOpTest(-0.51, -0.0); + addOpTest(inf, inf); + addOpTest(-inf, -inf); + addOpTest(nan, 0); +} + TEST_F(LLVMCodeBuilderTest, Yield) { auto build = [this]() { diff --git a/test/mocks/codebuildermock.h b/test/mocks/codebuildermock.h index 64c8e99b..e5599b8d 100644 --- a/test/mocks/codebuildermock.h +++ b/test/mocks/codebuildermock.h @@ -31,6 +31,7 @@ class CodeBuilderMock : public ICodeBuilder MOCK_METHOD(void, createRound, (), (override)); MOCK_METHOD(void, createAbs, (), (override)); MOCK_METHOD(void, createFloor, (), (override)); + MOCK_METHOD(void, createCeil, (), (override)); MOCK_METHOD(void, beginIfStatement, (), (override)); MOCK_METHOD(void, beginElseBranch, (), (override)); From 34d5c4268a79cfc4f6a69eb86e301e17820ac048 Mon Sep 17 00:00:00 2001 From: adazem009 <68537469+adazem009@users.noreply.github.com> Date: Wed, 6 Nov 2024 15:04:13 +0100 Subject: [PATCH 09/20] LLVMCodeBuilder: Implement sqrt operator --- src/dev/engine/internal/icodebuilder.h | 1 + src/dev/engine/internal/llvmcodebuilder.cpp | 17 ++++++++ src/dev/engine/internal/llvmcodebuilder.h | 2 + test/dev/llvm/llvmcodebuilder_test.cpp | 43 +++++++++++++++++++++ test/mocks/codebuildermock.h | 1 + 5 files changed, 64 insertions(+) diff --git a/src/dev/engine/internal/icodebuilder.h b/src/dev/engine/internal/icodebuilder.h index eb16e382..7f3cd34e 100644 --- a/src/dev/engine/internal/icodebuilder.h +++ b/src/dev/engine/internal/icodebuilder.h @@ -42,6 +42,7 @@ class ICodeBuilder virtual void createAbs() = 0; virtual void createFloor() = 0; virtual void createCeil() = 0; + virtual void createSqrt() = 0; virtual void beginIfStatement() = 0; virtual void beginElseBranch() = 0; diff --git a/src/dev/engine/internal/llvmcodebuilder.cpp b/src/dev/engine/internal/llvmcodebuilder.cpp index 3ce2c386..ccf39e31 100644 --- a/src/dev/engine/internal/llvmcodebuilder.cpp +++ b/src/dev/engine/internal/llvmcodebuilder.cpp @@ -238,6 +238,18 @@ std::shared_ptr LLVMCodeBuilder::finalize() break; } + case Step::Type::Sqrt: { + assert(step.args.size() == 1); + const auto &arg = step.args[0]; + // sqrt(x) + 0.0 + // This avoids negative zero + llvm::Constant *zero = llvm::ConstantFP::get(m_ctx, llvm::APFloat(0.0)); + llvm::Function *sqrtFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::sqrt, m_builder.getDoubleTy()); + llvm::Value *num = removeNaN(castValue(arg.second, arg.first)); + step.functionReturnReg->value = m_builder.CreateFAdd(m_builder.CreateCall(sqrtFunc, num), zero); + break; + } + case Step::Type::Yield: if (!m_warp) { freeHeap(); @@ -631,6 +643,11 @@ void LLVMCodeBuilder::createCeil() createOp(Step::Type::Ceil, Compiler::StaticType::Number, Compiler::StaticType::Number, 1); } +void LLVMCodeBuilder::createSqrt() +{ + createOp(Step::Type::Sqrt, Compiler::StaticType::Number, Compiler::StaticType::Number, 1); +} + void LLVMCodeBuilder::beginIfStatement() { Step step(Step::Type::BeginIf); diff --git a/src/dev/engine/internal/llvmcodebuilder.h b/src/dev/engine/internal/llvmcodebuilder.h index 71519b58..7d668aa1 100644 --- a/src/dev/engine/internal/llvmcodebuilder.h +++ b/src/dev/engine/internal/llvmcodebuilder.h @@ -44,6 +44,7 @@ class LLVMCodeBuilder : public ICodeBuilder void createAbs() override; void createFloor() override; void createCeil() override; + void createSqrt() override; void beginIfStatement() override; void beginElseBranch() override; @@ -92,6 +93,7 @@ class LLVMCodeBuilder : public ICodeBuilder Abs, Floor, Ceil, + Sqrt, Yield, BeginIf, BeginElse, diff --git a/test/dev/llvm/llvmcodebuilder_test.cpp b/test/dev/llvm/llvmcodebuilder_test.cpp index 212a29a1..bc8f91f6 100644 --- a/test/dev/llvm/llvmcodebuilder_test.cpp +++ b/test/dev/llvm/llvmcodebuilder_test.cpp @@ -1279,6 +1279,49 @@ TEST_F(LLVMCodeBuilderTest, Ceil) addOpTest(nan, 0); } +TEST_F(LLVMCodeBuilderTest, Sqrt) +{ + std::string expected; + + auto addOpTest = [this, &expected](Value v1, double expectedResult) { + createBuilder(true); + + m_builder->addConstValue(v1); + m_builder->createSqrt(); + m_builder->addFunctionCall("test_print_number", Compiler::StaticType::Void, { Compiler::StaticType::Number }); + + m_builder->addConstValue(v1); + m_builder->addFunctionCall("test_const_number", Compiler::StaticType::Number, { Compiler::StaticType::Number }); + m_builder->createSqrt(); + m_builder->addFunctionCall("test_print_number", Compiler::StaticType::Void, { Compiler::StaticType::Number }); + + std::stringstream stream; + stream << expectedResult; + std::string str = stream.str() + '\n'; + std::string expected = str + str; + + auto code = m_builder->finalize(); + auto ctx = code->createExecutionContext(&m_target); + + testing::internal::CaptureStdout(); + code->run(ctx.get()); + const std::string quotes1 = v1.isString() ? "\"" : ""; + ASSERT_THAT(testing::internal::GetCapturedStdout(), Eq(expected)) << quotes1 << v1.toString() << quotes1; + }; + + static const double inf = std::numeric_limits::infinity(); + static const double nan = std::numeric_limits::quiet_NaN(); + + addOpTest(16.0, 4.0); + addOpTest(0.04, 0.2); + addOpTest(0.0, 0.0); + addOpTest(-0.0, 0.0); + addOpTest(-4.0, -nan); // negative NaN shouldn't be a problem + addOpTest(inf, inf); + addOpTest(-inf, -nan); + addOpTest(nan, 0); +} + TEST_F(LLVMCodeBuilderTest, Yield) { auto build = [this]() { diff --git a/test/mocks/codebuildermock.h b/test/mocks/codebuildermock.h index e5599b8d..5f7594de 100644 --- a/test/mocks/codebuildermock.h +++ b/test/mocks/codebuildermock.h @@ -32,6 +32,7 @@ class CodeBuilderMock : public ICodeBuilder MOCK_METHOD(void, createAbs, (), (override)); MOCK_METHOD(void, createFloor, (), (override)); MOCK_METHOD(void, createCeil, (), (override)); + MOCK_METHOD(void, createSqrt, (), (override)); MOCK_METHOD(void, beginIfStatement, (), (override)); MOCK_METHOD(void, beginElseBranch, (), (override)); From a042b64c0726a9f49174522d6422e49182746301 Mon Sep 17 00:00:00 2001 From: adazem009 <68537469+adazem009@users.noreply.github.com> Date: Wed, 6 Nov 2024 16:59:25 +0100 Subject: [PATCH 10/20] LLVMCodeBuilder: Implement sin operator --- src/dev/engine/internal/icodebuilder.h | 1 + src/dev/engine/internal/llvmcodebuilder.cpp | 23 ++++++++++ src/dev/engine/internal/llvmcodebuilder.h | 2 + test/dev/llvm/llvmcodebuilder_test.cpp | 47 +++++++++++++++++++++ test/mocks/codebuildermock.h | 1 + 5 files changed, 74 insertions(+) diff --git a/src/dev/engine/internal/icodebuilder.h b/src/dev/engine/internal/icodebuilder.h index 7f3cd34e..ad9769af 100644 --- a/src/dev/engine/internal/icodebuilder.h +++ b/src/dev/engine/internal/icodebuilder.h @@ -43,6 +43,7 @@ class ICodeBuilder virtual void createFloor() = 0; virtual void createCeil() = 0; virtual void createSqrt() = 0; + virtual void createSin() = 0; virtual void beginIfStatement() = 0; virtual void beginElseBranch() = 0; diff --git a/src/dev/engine/internal/llvmcodebuilder.cpp b/src/dev/engine/internal/llvmcodebuilder.cpp index ccf39e31..ec448824 100644 --- a/src/dev/engine/internal/llvmcodebuilder.cpp +++ b/src/dev/engine/internal/llvmcodebuilder.cpp @@ -250,6 +250,24 @@ std::shared_ptr LLVMCodeBuilder::finalize() break; } + case Step::Type::Sin: { + assert(step.args.size() == 1); + const auto &arg = step.args[0]; + // round(sin(x * pi / 180.0) * 1e10) / 1e10 + 0.0 + // +0.0 to avoid -0.0 + llvm::Constant *zero = llvm::ConstantFP::get(m_ctx, llvm::APFloat(0.0)); + llvm::Constant *pi = llvm::ConstantFP::get(m_ctx, llvm::APFloat(std::acos(-1.0))); + llvm::Constant *piDeg = llvm::ConstantFP::get(m_ctx, llvm::APFloat(180.0)); + llvm::Constant *factor = llvm::ConstantFP::get(m_ctx, llvm::APFloat(1e10)); + llvm::Function *sinFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::sin, m_builder.getDoubleTy()); + llvm::Function *roundFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::round, m_builder.getDoubleTy()); + llvm::Value *num = removeNaN(castValue(arg.second, arg.first)); + llvm::Value *sinResult = m_builder.CreateCall(sinFunc, m_builder.CreateFDiv(m_builder.CreateFMul(num, pi), piDeg)); // sin(x * pi / 180) + llvm::Value *rounded = m_builder.CreateCall(roundFunc, m_builder.CreateFMul(sinResult, factor)); // round(sin(x * 180) * 1e10) + step.functionReturnReg->value = m_builder.CreateFAdd(m_builder.CreateFDiv(rounded, factor), zero); + break; + } + case Step::Type::Yield: if (!m_warp) { freeHeap(); @@ -648,6 +666,11 @@ void LLVMCodeBuilder::createSqrt() createOp(Step::Type::Sqrt, Compiler::StaticType::Number, Compiler::StaticType::Number, 1); } +void LLVMCodeBuilder::createSin() +{ + createOp(Step::Type::Sin, Compiler::StaticType::Number, Compiler::StaticType::Number, 1); +} + void LLVMCodeBuilder::beginIfStatement() { Step step(Step::Type::BeginIf); diff --git a/src/dev/engine/internal/llvmcodebuilder.h b/src/dev/engine/internal/llvmcodebuilder.h index 7d668aa1..2001a321 100644 --- a/src/dev/engine/internal/llvmcodebuilder.h +++ b/src/dev/engine/internal/llvmcodebuilder.h @@ -45,6 +45,7 @@ class LLVMCodeBuilder : public ICodeBuilder void createFloor() override; void createCeil() override; void createSqrt() override; + void createSin() override; void beginIfStatement() override; void beginElseBranch() override; @@ -94,6 +95,7 @@ class LLVMCodeBuilder : public ICodeBuilder Floor, Ceil, Sqrt, + Sin, Yield, BeginIf, BeginElse, diff --git a/test/dev/llvm/llvmcodebuilder_test.cpp b/test/dev/llvm/llvmcodebuilder_test.cpp index bc8f91f6..7816db8e 100644 --- a/test/dev/llvm/llvmcodebuilder_test.cpp +++ b/test/dev/llvm/llvmcodebuilder_test.cpp @@ -1322,6 +1322,53 @@ TEST_F(LLVMCodeBuilderTest, Sqrt) addOpTest(nan, 0); } +TEST_F(LLVMCodeBuilderTest, Sin) +{ + std::string expected; + + auto addOpTest = [this, &expected](Value v1, double expectedResult) { + createBuilder(true); + + m_builder->addConstValue(v1); + m_builder->createSin(); + m_builder->addFunctionCall("test_print_number", Compiler::StaticType::Void, { Compiler::StaticType::Number }); + + m_builder->addConstValue(v1); + m_builder->addFunctionCall("test_const_number", Compiler::StaticType::Number, { Compiler::StaticType::Number }); + m_builder->createSin(); + m_builder->addFunctionCall("test_print_number", Compiler::StaticType::Void, { Compiler::StaticType::Number }); + + std::stringstream stream; + stream << expectedResult; + std::string str = stream.str() + '\n'; + std::string expected = str + str; + + auto code = m_builder->finalize(); + auto ctx = code->createExecutionContext(&m_target); + + testing::internal::CaptureStdout(); + code->run(ctx.get()); + const std::string quotes1 = v1.isString() ? "\"" : ""; + ASSERT_THAT(testing::internal::GetCapturedStdout(), Eq(expected)) << quotes1 << v1.toString() << quotes1; + }; + + static const double inf = std::numeric_limits::infinity(); + static const double nan = std::numeric_limits::quiet_NaN(); + + addOpTest(30.0, 0.5); + addOpTest(90.0, 1.0); + addOpTest(2.8e-9, 0.0); + addOpTest(2.9e-9, 1e-10); + addOpTest(570.0, -0.5); + addOpTest(-30.0, -0.5); + addOpTest(-90.0, -1.0); + addOpTest(0.0, 0.0); + addOpTest(-0.0, 0.0); + addOpTest(inf, -nan); // negative NaN shouldn't be a problem + addOpTest(-inf, -nan); + addOpTest(nan, 0); +} + TEST_F(LLVMCodeBuilderTest, Yield) { auto build = [this]() { diff --git a/test/mocks/codebuildermock.h b/test/mocks/codebuildermock.h index 5f7594de..a3202d3c 100644 --- a/test/mocks/codebuildermock.h +++ b/test/mocks/codebuildermock.h @@ -33,6 +33,7 @@ class CodeBuilderMock : public ICodeBuilder MOCK_METHOD(void, createFloor, (), (override)); MOCK_METHOD(void, createCeil, (), (override)); MOCK_METHOD(void, createSqrt, (), (override)); + MOCK_METHOD(void, createSin, (), (override)); MOCK_METHOD(void, beginIfStatement, (), (override)); MOCK_METHOD(void, beginElseBranch, (), (override)); From 2c3c62c6a429000dd4eedbee4f307afb9b769d34 Mon Sep 17 00:00:00 2001 From: adazem009 <68537469+adazem009@users.noreply.github.com> Date: Wed, 6 Nov 2024 17:11:26 +0100 Subject: [PATCH 11/20] LLVMCodeBuilder: Implement cos operator --- src/dev/engine/internal/icodebuilder.h | 1 + src/dev/engine/internal/llvmcodebuilder.cpp | 21 +++++++++ src/dev/engine/internal/llvmcodebuilder.h | 2 + test/dev/llvm/llvmcodebuilder_test.cpp | 47 +++++++++++++++++++++ test/mocks/codebuildermock.h | 1 + 5 files changed, 72 insertions(+) diff --git a/src/dev/engine/internal/icodebuilder.h b/src/dev/engine/internal/icodebuilder.h index ad9769af..e98b8095 100644 --- a/src/dev/engine/internal/icodebuilder.h +++ b/src/dev/engine/internal/icodebuilder.h @@ -44,6 +44,7 @@ class ICodeBuilder virtual void createCeil() = 0; virtual void createSqrt() = 0; virtual void createSin() = 0; + virtual void createCos() = 0; virtual void beginIfStatement() = 0; virtual void beginElseBranch() = 0; diff --git a/src/dev/engine/internal/llvmcodebuilder.cpp b/src/dev/engine/internal/llvmcodebuilder.cpp index ec448824..5e7bc88c 100644 --- a/src/dev/engine/internal/llvmcodebuilder.cpp +++ b/src/dev/engine/internal/llvmcodebuilder.cpp @@ -268,6 +268,22 @@ std::shared_ptr LLVMCodeBuilder::finalize() break; } + case Step::Type::Cos: { + assert(step.args.size() == 1); + const auto &arg = step.args[0]; + // round(cos(x * pi / 180.0) * 1e10) / 1e10 + llvm::Constant *pi = llvm::ConstantFP::get(m_ctx, llvm::APFloat(std::acos(-1.0))); + llvm::Constant *piDeg = llvm::ConstantFP::get(m_ctx, llvm::APFloat(180.0)); + llvm::Constant *factor = llvm::ConstantFP::get(m_ctx, llvm::APFloat(1e10)); + llvm::Function *cosFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::cos, m_builder.getDoubleTy()); + llvm::Function *roundFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::round, m_builder.getDoubleTy()); + llvm::Value *num = removeNaN(castValue(arg.second, arg.first)); + llvm::Value *cosResult = m_builder.CreateCall(cosFunc, m_builder.CreateFDiv(m_builder.CreateFMul(num, pi), piDeg)); // cos(x * pi / 180) + llvm::Value *rounded = m_builder.CreateCall(roundFunc, m_builder.CreateFMul(cosResult, factor)); // round(cos(x * 180) * 1e10) + step.functionReturnReg->value = m_builder.CreateFDiv(rounded, factor); + break; + } + case Step::Type::Yield: if (!m_warp) { freeHeap(); @@ -671,6 +687,11 @@ void LLVMCodeBuilder::createSin() createOp(Step::Type::Sin, Compiler::StaticType::Number, Compiler::StaticType::Number, 1); } +void LLVMCodeBuilder::createCos() +{ + createOp(Step::Type::Cos, Compiler::StaticType::Number, Compiler::StaticType::Number, 1); +} + void LLVMCodeBuilder::beginIfStatement() { Step step(Step::Type::BeginIf); diff --git a/src/dev/engine/internal/llvmcodebuilder.h b/src/dev/engine/internal/llvmcodebuilder.h index 2001a321..33e79606 100644 --- a/src/dev/engine/internal/llvmcodebuilder.h +++ b/src/dev/engine/internal/llvmcodebuilder.h @@ -46,6 +46,7 @@ class LLVMCodeBuilder : public ICodeBuilder void createCeil() override; void createSqrt() override; void createSin() override; + void createCos() override; void beginIfStatement() override; void beginElseBranch() override; @@ -96,6 +97,7 @@ class LLVMCodeBuilder : public ICodeBuilder Ceil, Sqrt, Sin, + Cos, Yield, BeginIf, BeginElse, diff --git a/test/dev/llvm/llvmcodebuilder_test.cpp b/test/dev/llvm/llvmcodebuilder_test.cpp index 7816db8e..6a0c82c3 100644 --- a/test/dev/llvm/llvmcodebuilder_test.cpp +++ b/test/dev/llvm/llvmcodebuilder_test.cpp @@ -1369,6 +1369,53 @@ TEST_F(LLVMCodeBuilderTest, Sin) addOpTest(nan, 0); } +TEST_F(LLVMCodeBuilderTest, Cos) +{ + std::string expected; + + auto addOpTest = [this, &expected](Value v1, double expectedResult) { + createBuilder(true); + + m_builder->addConstValue(v1); + m_builder->createCos(); + m_builder->addFunctionCall("test_print_number", Compiler::StaticType::Void, { Compiler::StaticType::Number }); + + m_builder->addConstValue(v1); + m_builder->addFunctionCall("test_const_number", Compiler::StaticType::Number, { Compiler::StaticType::Number }); + m_builder->createCos(); + m_builder->addFunctionCall("test_print_number", Compiler::StaticType::Void, { Compiler::StaticType::Number }); + + std::stringstream stream; + stream << expectedResult; + std::string str = stream.str() + '\n'; + std::string expected = str + str; + + auto code = m_builder->finalize(); + auto ctx = code->createExecutionContext(&m_target); + + testing::internal::CaptureStdout(); + code->run(ctx.get()); + const std::string quotes1 = v1.isString() ? "\"" : ""; + ASSERT_THAT(testing::internal::GetCapturedStdout(), Eq(expected)) << quotes1 << v1.toString() << quotes1; + }; + + static const double inf = std::numeric_limits::infinity(); + static const double nan = std::numeric_limits::quiet_NaN(); + + addOpTest(60.0, 0.5); + addOpTest(90.0, 0.0); + addOpTest(600.0, -0.5); + addOpTest(89.9999999971352, 1e-10); + addOpTest(89.999999999, 0.0); + addOpTest(-60.0, 0.5); + addOpTest(-90.0, 0.0); + addOpTest(0.0, 1.0); + addOpTest(-0.0, 1.0); + addOpTest(inf, -nan); // negative NaN shouldn't be a problem + addOpTest(-inf, -nan); + addOpTest(nan, 1.0); +} + TEST_F(LLVMCodeBuilderTest, Yield) { auto build = [this]() { diff --git a/test/mocks/codebuildermock.h b/test/mocks/codebuildermock.h index a3202d3c..624f25e9 100644 --- a/test/mocks/codebuildermock.h +++ b/test/mocks/codebuildermock.h @@ -34,6 +34,7 @@ class CodeBuilderMock : public ICodeBuilder MOCK_METHOD(void, createCeil, (), (override)); MOCK_METHOD(void, createSqrt, (), (override)); MOCK_METHOD(void, createSin, (), (override)); + MOCK_METHOD(void, createCos, (), (override)); MOCK_METHOD(void, beginIfStatement, (), (override)); MOCK_METHOD(void, beginElseBranch, (), (override)); From f0c6eb5876cfa07b2c16a01aa159160e1a630572 Mon Sep 17 00:00:00 2001 From: adazem009 <68537469+adazem009@users.noreply.github.com> Date: Wed, 6 Nov 2024 18:41:25 +0100 Subject: [PATCH 12/20] LLVMCodeBuilder: Implement tan operator --- src/dev/engine/internal/icodebuilder.h | 1 + src/dev/engine/internal/llvmcodebuilder.cpp | 37 +++++++++++++++ src/dev/engine/internal/llvmcodebuilder.h | 2 + test/dev/llvm/llvmcodebuilder_test.cpp | 51 +++++++++++++++++++++ test/mocks/codebuildermock.h | 1 + 5 files changed, 92 insertions(+) diff --git a/src/dev/engine/internal/icodebuilder.h b/src/dev/engine/internal/icodebuilder.h index e98b8095..a7dc10fa 100644 --- a/src/dev/engine/internal/icodebuilder.h +++ b/src/dev/engine/internal/icodebuilder.h @@ -45,6 +45,7 @@ class ICodeBuilder virtual void createSqrt() = 0; virtual void createSin() = 0; virtual void createCos() = 0; + virtual void createTan() = 0; virtual void beginIfStatement() = 0; virtual void beginElseBranch() = 0; diff --git a/src/dev/engine/internal/llvmcodebuilder.cpp b/src/dev/engine/internal/llvmcodebuilder.cpp index 5e7bc88c..bdeec57f 100644 --- a/src/dev/engine/internal/llvmcodebuilder.cpp +++ b/src/dev/engine/internal/llvmcodebuilder.cpp @@ -284,6 +284,38 @@ std::shared_ptr LLVMCodeBuilder::finalize() break; } + case Step::Type::Tan: { + assert(step.args.size() == 1); + const auto &arg = step.args[0]; + // ((mod = rem(x, 360.0)) == -270.0 || mod == 90.0) ? inf : ((mod == -90.0 || mod == 270.0) ? -inf : round(tan(x * pi / 180.0) * 1e10) / 1e10 + 0.0) + // +0.0 to avoid -0.0 + llvm::Constant *zero = llvm::ConstantFP::get(m_ctx, llvm::APFloat(0.0)); + llvm::Constant *full = llvm::ConstantFP::get(m_ctx, llvm::APFloat(360.0)); + llvm::Constant *posInf = llvm::ConstantFP::getInfinity(m_builder.getDoubleTy(), false); + llvm::Constant *negInf = llvm::ConstantFP::getInfinity(m_builder.getDoubleTy(), true); + llvm::Constant *undefined1 = llvm::ConstantFP::get(m_ctx, llvm::APFloat(-270.0)); + llvm::Constant *undefined2 = llvm::ConstantFP::get(m_ctx, llvm::APFloat(90.0)); + llvm::Constant *undefined3 = llvm::ConstantFP::get(m_ctx, llvm::APFloat(-90.0)); + llvm::Constant *undefined4 = llvm::ConstantFP::get(m_ctx, llvm::APFloat(270.0)); + llvm::Constant *pi = llvm::ConstantFP::get(m_ctx, llvm::APFloat(std::acos(-1.0))); + llvm::Constant *piDeg = llvm::ConstantFP::get(m_ctx, llvm::APFloat(180.0)); + llvm::Constant *factor = llvm::ConstantFP::get(m_ctx, llvm::APFloat(1e10)); + llvm::Function *tanFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::tan, m_builder.getDoubleTy()); + llvm::Function *roundFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::round, m_builder.getDoubleTy()); + llvm::Value *num = removeNaN(castValue(arg.second, arg.first)); + llvm::Value *mod = m_builder.CreateFRem(num, full); + llvm::Value *isUndefined1 = m_builder.CreateFCmpOEQ(mod, undefined1); // rem(x, 360.0) == -270.0 + llvm::Value *isUndefined2 = m_builder.CreateFCmpOEQ(mod, undefined2); // rem(x, 360.0) == 90.0 + llvm::Value *isUndefined3 = m_builder.CreateFCmpOEQ(mod, undefined3); // rem(x, 360.0) == -90.0 + llvm::Value *isUndefined4 = m_builder.CreateFCmpOEQ(mod, undefined4); // rem(x, 360.0) == 270.0 + llvm::Value *tanResult = m_builder.CreateCall(tanFunc, m_builder.CreateFDiv(m_builder.CreateFMul(num, pi), piDeg)); // tan(x * pi / 180) + llvm::Value *rounded = m_builder.CreateCall(roundFunc, m_builder.CreateFMul(tanResult, factor)); // round(tan(x * 180) * 1e10) + llvm::Value *result = m_builder.CreateFAdd(m_builder.CreateFDiv(rounded, factor), zero); // round(tan(x * pi / 180.0) * 1e10) / 1e10 + 0.0 + llvm::Value *inner = m_builder.CreateSelect(m_builder.CreateOr(isUndefined3, isUndefined4), negInf, result); + step.functionReturnReg->value = m_builder.CreateSelect(m_builder.CreateOr(isUndefined1, isUndefined2), posInf, inner); + break; + } + case Step::Type::Yield: if (!m_warp) { freeHeap(); @@ -692,6 +724,11 @@ void LLVMCodeBuilder::createCos() createOp(Step::Type::Cos, Compiler::StaticType::Number, Compiler::StaticType::Number, 1); } +void LLVMCodeBuilder::createTan() +{ + createOp(Step::Type::Tan, Compiler::StaticType::Number, Compiler::StaticType::Number, 1); +} + void LLVMCodeBuilder::beginIfStatement() { Step step(Step::Type::BeginIf); diff --git a/src/dev/engine/internal/llvmcodebuilder.h b/src/dev/engine/internal/llvmcodebuilder.h index 33e79606..6b3cf82e 100644 --- a/src/dev/engine/internal/llvmcodebuilder.h +++ b/src/dev/engine/internal/llvmcodebuilder.h @@ -47,6 +47,7 @@ class LLVMCodeBuilder : public ICodeBuilder void createSqrt() override; void createSin() override; void createCos() override; + void createTan() override; void beginIfStatement() override; void beginElseBranch() override; @@ -98,6 +99,7 @@ class LLVMCodeBuilder : public ICodeBuilder Sqrt, Sin, Cos, + Tan, Yield, BeginIf, BeginElse, diff --git a/test/dev/llvm/llvmcodebuilder_test.cpp b/test/dev/llvm/llvmcodebuilder_test.cpp index 6a0c82c3..9895640f 100644 --- a/test/dev/llvm/llvmcodebuilder_test.cpp +++ b/test/dev/llvm/llvmcodebuilder_test.cpp @@ -1416,6 +1416,57 @@ TEST_F(LLVMCodeBuilderTest, Cos) addOpTest(nan, 1.0); } +TEST_F(LLVMCodeBuilderTest, Tan) +{ + std::string expected; + + auto addOpTest = [this, &expected](Value v1, double expectedResult) { + createBuilder(true); + + m_builder->addConstValue(v1); + m_builder->createTan(); + m_builder->addFunctionCall("test_print_number", Compiler::StaticType::Void, { Compiler::StaticType::Number }); + + m_builder->addConstValue(v1); + m_builder->addFunctionCall("test_const_number", Compiler::StaticType::Number, { Compiler::StaticType::Number }); + m_builder->createTan(); + m_builder->addFunctionCall("test_print_number", Compiler::StaticType::Void, { Compiler::StaticType::Number }); + + std::stringstream stream; + stream << expectedResult; + std::string str = stream.str() + '\n'; + std::string expected = str + str; + + auto code = m_builder->finalize(); + auto ctx = code->createExecutionContext(&m_target); + + testing::internal::CaptureStdout(); + code->run(ctx.get()); + const std::string quotes1 = v1.isString() ? "\"" : ""; + ASSERT_THAT(testing::internal::GetCapturedStdout(), Eq(expected)) << quotes1 << v1.toString() << quotes1; + }; + + static const double inf = std::numeric_limits::infinity(); + static const double nan = std::numeric_limits::quiet_NaN(); + + addOpTest(45.0, 1.0); + addOpTest(90.0, inf); + addOpTest(270.0, -inf); + addOpTest(450.0, inf); + addOpTest(-90.0, -inf); + addOpTest(-270.0, inf); + addOpTest(-450.0, -inf); + addOpTest(180.0, 0.0); + addOpTest(-180.0, 0.0); + addOpTest(2.87e-9, 1e-10); + addOpTest(2.8647e-9, 0.0); + addOpTest(0.0, 0.0); + addOpTest(-0.0, 0.0); + addOpTest(inf, -nan); // negative NaN shouldn't be a problem + addOpTest(-inf, -nan); + addOpTest(nan, 0.0); +} + TEST_F(LLVMCodeBuilderTest, Yield) { auto build = [this]() { diff --git a/test/mocks/codebuildermock.h b/test/mocks/codebuildermock.h index 624f25e9..ca33814a 100644 --- a/test/mocks/codebuildermock.h +++ b/test/mocks/codebuildermock.h @@ -35,6 +35,7 @@ class CodeBuilderMock : public ICodeBuilder MOCK_METHOD(void, createSqrt, (), (override)); MOCK_METHOD(void, createSin, (), (override)); MOCK_METHOD(void, createCos, (), (override)); + MOCK_METHOD(void, createTan, (), (override)); MOCK_METHOD(void, beginIfStatement, (), (override)); MOCK_METHOD(void, beginElseBranch, (), (override)); From e80226dc316206a080131ecef50969347ec48e1e Mon Sep 17 00:00:00 2001 From: adazem009 <68537469+adazem009@users.noreply.github.com> Date: Thu, 7 Nov 2024 14:12:21 +0100 Subject: [PATCH 13/20] LLVMCodeBuilder: Implement asin operator --- src/dev/engine/internal/icodebuilder.h | 1 + src/dev/engine/internal/llvmcodebuilder.cpp | 19 +++++++++ src/dev/engine/internal/llvmcodebuilder.h | 2 + test/dev/llvm/llvmcodebuilder_test.cpp | 46 +++++++++++++++++++++ test/mocks/codebuildermock.h | 1 + 5 files changed, 69 insertions(+) diff --git a/src/dev/engine/internal/icodebuilder.h b/src/dev/engine/internal/icodebuilder.h index a7dc10fa..735fed2f 100644 --- a/src/dev/engine/internal/icodebuilder.h +++ b/src/dev/engine/internal/icodebuilder.h @@ -46,6 +46,7 @@ class ICodeBuilder virtual void createSin() = 0; virtual void createCos() = 0; virtual void createTan() = 0; + virtual void createAsin() = 0; virtual void beginIfStatement() = 0; virtual void beginElseBranch() = 0; diff --git a/src/dev/engine/internal/llvmcodebuilder.cpp b/src/dev/engine/internal/llvmcodebuilder.cpp index bdeec57f..8a3df394 100644 --- a/src/dev/engine/internal/llvmcodebuilder.cpp +++ b/src/dev/engine/internal/llvmcodebuilder.cpp @@ -316,6 +316,20 @@ std::shared_ptr LLVMCodeBuilder::finalize() break; } + case Step::Type::Asin: { + assert(step.args.size() == 1); + const auto &arg = step.args[0]; + // asin(x) * 180.0 / pi + 0.0 + // +0.0 to avoid -0.0 + llvm::Constant *zero = llvm::ConstantFP::get(m_ctx, llvm::APFloat(0.0)); + llvm::Constant *pi = llvm::ConstantFP::get(m_ctx, llvm::APFloat(std::acos(-1.0))); + llvm::Constant *piDeg = llvm::ConstantFP::get(m_ctx, llvm::APFloat(180.0)); + llvm::Function *asinFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::asin, m_builder.getDoubleTy()); + llvm::Value *num = removeNaN(castValue(arg.second, arg.first)); + step.functionReturnReg->value = m_builder.CreateFAdd(m_builder.CreateFDiv(m_builder.CreateFMul(m_builder.CreateCall(asinFunc, num), piDeg), pi), zero); + break; + } + case Step::Type::Yield: if (!m_warp) { freeHeap(); @@ -729,6 +743,11 @@ void LLVMCodeBuilder::createTan() createOp(Step::Type::Tan, Compiler::StaticType::Number, Compiler::StaticType::Number, 1); } +void LLVMCodeBuilder::createAsin() +{ + createOp(Step::Type::Asin, Compiler::StaticType::Number, Compiler::StaticType::Number, 1); +} + void LLVMCodeBuilder::beginIfStatement() { Step step(Step::Type::BeginIf); diff --git a/src/dev/engine/internal/llvmcodebuilder.h b/src/dev/engine/internal/llvmcodebuilder.h index 6b3cf82e..01d5785e 100644 --- a/src/dev/engine/internal/llvmcodebuilder.h +++ b/src/dev/engine/internal/llvmcodebuilder.h @@ -48,6 +48,7 @@ class LLVMCodeBuilder : public ICodeBuilder void createSin() override; void createCos() override; void createTan() override; + void createAsin() override; void beginIfStatement() override; void beginElseBranch() override; @@ -100,6 +101,7 @@ class LLVMCodeBuilder : public ICodeBuilder Sin, Cos, Tan, + Asin, Yield, BeginIf, BeginElse, diff --git a/test/dev/llvm/llvmcodebuilder_test.cpp b/test/dev/llvm/llvmcodebuilder_test.cpp index 9895640f..18f83954 100644 --- a/test/dev/llvm/llvmcodebuilder_test.cpp +++ b/test/dev/llvm/llvmcodebuilder_test.cpp @@ -1467,6 +1467,52 @@ TEST_F(LLVMCodeBuilderTest, Tan) addOpTest(nan, 0.0); } +TEST_F(LLVMCodeBuilderTest, Asin) +{ + std::string expected; + + auto addOpTest = [this, &expected](Value v1, double expectedResult) { + createBuilder(true); + + m_builder->addConstValue(v1); + m_builder->createAsin(); + m_builder->addFunctionCall("test_print_number", Compiler::StaticType::Void, { Compiler::StaticType::Number }); + + m_builder->addConstValue(v1); + m_builder->addFunctionCall("test_const_number", Compiler::StaticType::Number, { Compiler::StaticType::Number }); + m_builder->createAsin(); + m_builder->addFunctionCall("test_print_number", Compiler::StaticType::Void, { Compiler::StaticType::Number }); + + std::stringstream stream; + stream << expectedResult; + std::string str = stream.str() + '\n'; + std::string expected = str + str; + + auto code = m_builder->finalize(); + auto ctx = code->createExecutionContext(&m_target); + + testing::internal::CaptureStdout(); + code->run(ctx.get()); + const std::string quotes1 = v1.isString() ? "\"" : ""; + ASSERT_THAT(testing::internal::GetCapturedStdout(), Eq(expected)) << quotes1 << v1.toString() << quotes1; + }; + + static const double inf = std::numeric_limits::infinity(); + static const double nan = std::numeric_limits::quiet_NaN(); + + addOpTest(1.0, 90.0); + addOpTest(0.5, 30.0); + addOpTest(0.0, 0.0); + addOpTest(-0.0, 0.0); + addOpTest(-0.5, -30.0); + addOpTest(-1.0, -90.0); + addOpTest(1.1, nan); + addOpTest(-1.2, nan); + addOpTest(inf, nan); + addOpTest(-inf, nan); + addOpTest(nan, 0.0); +} + TEST_F(LLVMCodeBuilderTest, Yield) { auto build = [this]() { diff --git a/test/mocks/codebuildermock.h b/test/mocks/codebuildermock.h index ca33814a..fe1eb403 100644 --- a/test/mocks/codebuildermock.h +++ b/test/mocks/codebuildermock.h @@ -36,6 +36,7 @@ class CodeBuilderMock : public ICodeBuilder MOCK_METHOD(void, createSin, (), (override)); MOCK_METHOD(void, createCos, (), (override)); MOCK_METHOD(void, createTan, (), (override)); + MOCK_METHOD(void, createAsin, (), (override)); MOCK_METHOD(void, beginIfStatement, (), (override)); MOCK_METHOD(void, beginElseBranch, (), (override)); From 30017662f19a6f1750068306f958b7c324b705ce Mon Sep 17 00:00:00 2001 From: adazem009 <68537469+adazem009@users.noreply.github.com> Date: Thu, 7 Nov 2024 14:29:38 +0100 Subject: [PATCH 14/20] LLVMCodeBuilder: Implement acos operator --- src/dev/engine/internal/icodebuilder.h | 1 + src/dev/engine/internal/llvmcodebuilder.cpp | 17 ++++++++ src/dev/engine/internal/llvmcodebuilder.h | 2 + test/dev/llvm/llvmcodebuilder_test.cpp | 46 +++++++++++++++++++++ test/mocks/codebuildermock.h | 1 + 5 files changed, 67 insertions(+) diff --git a/src/dev/engine/internal/icodebuilder.h b/src/dev/engine/internal/icodebuilder.h index 735fed2f..da062b6c 100644 --- a/src/dev/engine/internal/icodebuilder.h +++ b/src/dev/engine/internal/icodebuilder.h @@ -47,6 +47,7 @@ class ICodeBuilder virtual void createCos() = 0; virtual void createTan() = 0; virtual void createAsin() = 0; + virtual void createAcos() = 0; virtual void beginIfStatement() = 0; virtual void beginElseBranch() = 0; diff --git a/src/dev/engine/internal/llvmcodebuilder.cpp b/src/dev/engine/internal/llvmcodebuilder.cpp index 8a3df394..821e5d71 100644 --- a/src/dev/engine/internal/llvmcodebuilder.cpp +++ b/src/dev/engine/internal/llvmcodebuilder.cpp @@ -330,6 +330,18 @@ std::shared_ptr LLVMCodeBuilder::finalize() break; } + case Step::Type::Acos: { + assert(step.args.size() == 1); + const auto &arg = step.args[0]; + // acos(x) * 180.0 / pi + llvm::Constant *pi = llvm::ConstantFP::get(m_ctx, llvm::APFloat(std::acos(-1.0))); + llvm::Constant *piDeg = llvm::ConstantFP::get(m_ctx, llvm::APFloat(180.0)); + llvm::Function *acosFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::acos, m_builder.getDoubleTy()); + llvm::Value *num = removeNaN(castValue(arg.second, arg.first)); + step.functionReturnReg->value = m_builder.CreateFDiv(m_builder.CreateFMul(m_builder.CreateCall(acosFunc, num), piDeg), pi); + break; + } + case Step::Type::Yield: if (!m_warp) { freeHeap(); @@ -748,6 +760,11 @@ void LLVMCodeBuilder::createAsin() createOp(Step::Type::Asin, Compiler::StaticType::Number, Compiler::StaticType::Number, 1); } +void LLVMCodeBuilder::createAcos() +{ + createOp(Step::Type::Acos, Compiler::StaticType::Number, Compiler::StaticType::Number, 1); +} + void LLVMCodeBuilder::beginIfStatement() { Step step(Step::Type::BeginIf); diff --git a/src/dev/engine/internal/llvmcodebuilder.h b/src/dev/engine/internal/llvmcodebuilder.h index 01d5785e..ec66a0be 100644 --- a/src/dev/engine/internal/llvmcodebuilder.h +++ b/src/dev/engine/internal/llvmcodebuilder.h @@ -49,6 +49,7 @@ class LLVMCodeBuilder : public ICodeBuilder void createCos() override; void createTan() override; void createAsin() override; + void createAcos() override; void beginIfStatement() override; void beginElseBranch() override; @@ -102,6 +103,7 @@ class LLVMCodeBuilder : public ICodeBuilder Cos, Tan, Asin, + Acos, Yield, BeginIf, BeginElse, diff --git a/test/dev/llvm/llvmcodebuilder_test.cpp b/test/dev/llvm/llvmcodebuilder_test.cpp index 18f83954..9e1b2ccb 100644 --- a/test/dev/llvm/llvmcodebuilder_test.cpp +++ b/test/dev/llvm/llvmcodebuilder_test.cpp @@ -1513,6 +1513,52 @@ TEST_F(LLVMCodeBuilderTest, Asin) addOpTest(nan, 0.0); } +TEST_F(LLVMCodeBuilderTest, Acos) +{ + std::string expected; + + auto addOpTest = [this, &expected](Value v1, double expectedResult) { + createBuilder(true); + + m_builder->addConstValue(v1); + m_builder->createAcos(); + m_builder->addFunctionCall("test_print_number", Compiler::StaticType::Void, { Compiler::StaticType::Number }); + + m_builder->addConstValue(v1); + m_builder->addFunctionCall("test_const_number", Compiler::StaticType::Number, { Compiler::StaticType::Number }); + m_builder->createAcos(); + m_builder->addFunctionCall("test_print_number", Compiler::StaticType::Void, { Compiler::StaticType::Number }); + + std::stringstream stream; + stream << expectedResult; + std::string str = stream.str() + '\n'; + std::string expected = str + str; + + auto code = m_builder->finalize(); + auto ctx = code->createExecutionContext(&m_target); + + testing::internal::CaptureStdout(); + code->run(ctx.get()); + const std::string quotes1 = v1.isString() ? "\"" : ""; + ASSERT_THAT(testing::internal::GetCapturedStdout(), Eq(expected)) << quotes1 << v1.toString() << quotes1; + }; + + static const double inf = std::numeric_limits::infinity(); + static const double nan = std::numeric_limits::quiet_NaN(); + + addOpTest(1.0, 0.0); + addOpTest(0.5, 60.0); + addOpTest(0.0, 90.0); + addOpTest(-0.0, 90.0); + addOpTest(-0.5, 120.0); + addOpTest(-1.0, 180.0); + addOpTest(1.1, nan); + addOpTest(-1.2, nan); + addOpTest(inf, nan); + addOpTest(-inf, nan); + addOpTest(nan, 90.0); +} + TEST_F(LLVMCodeBuilderTest, Yield) { auto build = [this]() { diff --git a/test/mocks/codebuildermock.h b/test/mocks/codebuildermock.h index fe1eb403..67bbe38d 100644 --- a/test/mocks/codebuildermock.h +++ b/test/mocks/codebuildermock.h @@ -37,6 +37,7 @@ class CodeBuilderMock : public ICodeBuilder MOCK_METHOD(void, createCos, (), (override)); MOCK_METHOD(void, createTan, (), (override)); MOCK_METHOD(void, createAsin, (), (override)); + MOCK_METHOD(void, createAcos, (), (override)); MOCK_METHOD(void, beginIfStatement, (), (override)); MOCK_METHOD(void, beginElseBranch, (), (override)); From 923ec2328e26c8bd1de163b50330f30a66c9c0af Mon Sep 17 00:00:00 2001 From: adazem009 <68537469+adazem009@users.noreply.github.com> Date: Thu, 7 Nov 2024 16:38:58 +0100 Subject: [PATCH 15/20] LLVMCodeBuilder: Implement atan operator --- src/dev/engine/internal/icodebuilder.h | 1 + src/dev/engine/internal/llvmcodebuilder.cpp | 17 +++++++++ src/dev/engine/internal/llvmcodebuilder.h | 2 + test/dev/llvm/llvmcodebuilder_test.cpp | 42 +++++++++++++++++++++ test/mocks/codebuildermock.h | 1 + 5 files changed, 63 insertions(+) diff --git a/src/dev/engine/internal/icodebuilder.h b/src/dev/engine/internal/icodebuilder.h index da062b6c..db9adc31 100644 --- a/src/dev/engine/internal/icodebuilder.h +++ b/src/dev/engine/internal/icodebuilder.h @@ -48,6 +48,7 @@ class ICodeBuilder virtual void createTan() = 0; virtual void createAsin() = 0; virtual void createAcos() = 0; + virtual void createAtan() = 0; virtual void beginIfStatement() = 0; virtual void beginElseBranch() = 0; diff --git a/src/dev/engine/internal/llvmcodebuilder.cpp b/src/dev/engine/internal/llvmcodebuilder.cpp index 821e5d71..473c3a4b 100644 --- a/src/dev/engine/internal/llvmcodebuilder.cpp +++ b/src/dev/engine/internal/llvmcodebuilder.cpp @@ -342,6 +342,18 @@ std::shared_ptr LLVMCodeBuilder::finalize() break; } + case Step::Type::Atan: { + assert(step.args.size() == 1); + const auto &arg = step.args[0]; + // atan(x) * 180.0 / pi + llvm::Constant *pi = llvm::ConstantFP::get(m_ctx, llvm::APFloat(std::acos(-1.0))); + llvm::Constant *piDeg = llvm::ConstantFP::get(m_ctx, llvm::APFloat(180.0)); + llvm::Function *atanFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::atan, m_builder.getDoubleTy()); + llvm::Value *num = removeNaN(castValue(arg.second, arg.first)); + step.functionReturnReg->value = m_builder.CreateFDiv(m_builder.CreateFMul(m_builder.CreateCall(atanFunc, num), piDeg), pi); + break; + } + case Step::Type::Yield: if (!m_warp) { freeHeap(); @@ -765,6 +777,11 @@ void LLVMCodeBuilder::createAcos() createOp(Step::Type::Acos, Compiler::StaticType::Number, Compiler::StaticType::Number, 1); } +void LLVMCodeBuilder::createAtan() +{ + createOp(Step::Type::Atan, Compiler::StaticType::Number, Compiler::StaticType::Number, 1); +} + void LLVMCodeBuilder::beginIfStatement() { Step step(Step::Type::BeginIf); diff --git a/src/dev/engine/internal/llvmcodebuilder.h b/src/dev/engine/internal/llvmcodebuilder.h index ec66a0be..7b180406 100644 --- a/src/dev/engine/internal/llvmcodebuilder.h +++ b/src/dev/engine/internal/llvmcodebuilder.h @@ -50,6 +50,7 @@ class LLVMCodeBuilder : public ICodeBuilder void createTan() override; void createAsin() override; void createAcos() override; + void createAtan() override; void beginIfStatement() override; void beginElseBranch() override; @@ -104,6 +105,7 @@ class LLVMCodeBuilder : public ICodeBuilder Tan, Asin, Acos, + Atan, Yield, BeginIf, BeginElse, diff --git a/test/dev/llvm/llvmcodebuilder_test.cpp b/test/dev/llvm/llvmcodebuilder_test.cpp index 9e1b2ccb..02deb187 100644 --- a/test/dev/llvm/llvmcodebuilder_test.cpp +++ b/test/dev/llvm/llvmcodebuilder_test.cpp @@ -1559,6 +1559,48 @@ TEST_F(LLVMCodeBuilderTest, Acos) addOpTest(nan, 90.0); } +TEST_F(LLVMCodeBuilderTest, Atan) +{ + std::string expected; + + auto addOpTest = [this, &expected](Value v1, double expectedResult) { + createBuilder(true); + + m_builder->addConstValue(v1); + m_builder->createAtan(); + m_builder->addFunctionCall("test_print_number", Compiler::StaticType::Void, { Compiler::StaticType::Number }); + + m_builder->addConstValue(v1); + m_builder->addFunctionCall("test_const_number", Compiler::StaticType::Number, { Compiler::StaticType::Number }); + m_builder->createAtan(); + m_builder->addFunctionCall("test_print_number", Compiler::StaticType::Void, { Compiler::StaticType::Number }); + + std::stringstream stream; + stream << expectedResult; + std::string str = stream.str() + '\n'; + std::string expected = str + str; + + auto code = m_builder->finalize(); + auto ctx = code->createExecutionContext(&m_target); + + testing::internal::CaptureStdout(); + code->run(ctx.get()); + const std::string quotes1 = v1.isString() ? "\"" : ""; + ASSERT_THAT(testing::internal::GetCapturedStdout(), Eq(expected)) << quotes1 << v1.toString() << quotes1; + }; + + static const double inf = std::numeric_limits::infinity(); + static const double nan = std::numeric_limits::quiet_NaN(); + + addOpTest(1.0, 45.0); + addOpTest(0.0, 0.0); + addOpTest(-0.0, -0.0); + addOpTest(-1.0, -45.0); + addOpTest(inf, 90.0); + addOpTest(-inf, -90.0); + addOpTest(nan, 0.0); +} + TEST_F(LLVMCodeBuilderTest, Yield) { auto build = [this]() { diff --git a/test/mocks/codebuildermock.h b/test/mocks/codebuildermock.h index 67bbe38d..e405f2b0 100644 --- a/test/mocks/codebuildermock.h +++ b/test/mocks/codebuildermock.h @@ -38,6 +38,7 @@ class CodeBuilderMock : public ICodeBuilder MOCK_METHOD(void, createTan, (), (override)); MOCK_METHOD(void, createAsin, (), (override)); MOCK_METHOD(void, createAcos, (), (override)); + MOCK_METHOD(void, createAtan, (), (override)); MOCK_METHOD(void, beginIfStatement, (), (override)); MOCK_METHOD(void, beginElseBranch, (), (override)); From e80c54f3e18e60d1315184c92578d553e8e5c2ab Mon Sep 17 00:00:00 2001 From: adazem009 <68537469+adazem009@users.noreply.github.com> Date: Thu, 7 Nov 2024 17:09:09 +0100 Subject: [PATCH 16/20] LLVMCodeBuilder: Implement ln operator --- src/dev/engine/internal/icodebuilder.h | 1 + src/dev/engine/internal/llvmcodebuilder.cpp | 15 +++++++ src/dev/engine/internal/llvmcodebuilder.h | 2 + test/dev/llvm/llvmcodebuilder_test.cpp | 45 +++++++++++++++++++++ test/mocks/codebuildermock.h | 1 + 5 files changed, 64 insertions(+) diff --git a/src/dev/engine/internal/icodebuilder.h b/src/dev/engine/internal/icodebuilder.h index db9adc31..ce96d642 100644 --- a/src/dev/engine/internal/icodebuilder.h +++ b/src/dev/engine/internal/icodebuilder.h @@ -49,6 +49,7 @@ class ICodeBuilder virtual void createAsin() = 0; virtual void createAcos() = 0; virtual void createAtan() = 0; + virtual void createLn() = 0; virtual void beginIfStatement() = 0; virtual void beginElseBranch() = 0; diff --git a/src/dev/engine/internal/llvmcodebuilder.cpp b/src/dev/engine/internal/llvmcodebuilder.cpp index 473c3a4b..8977e83e 100644 --- a/src/dev/engine/internal/llvmcodebuilder.cpp +++ b/src/dev/engine/internal/llvmcodebuilder.cpp @@ -354,6 +354,16 @@ std::shared_ptr LLVMCodeBuilder::finalize() break; } + case Step::Type::Ln: { + assert(step.args.size() == 1); + const auto &arg = step.args[0]; + // log(x) + llvm::Function *logFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::log, m_builder.getDoubleTy()); + llvm::Value *num = removeNaN(castValue(arg.second, arg.first)); + step.functionReturnReg->value = m_builder.CreateCall(logFunc, num); + break; + } + case Step::Type::Yield: if (!m_warp) { freeHeap(); @@ -782,6 +792,11 @@ void LLVMCodeBuilder::createAtan() createOp(Step::Type::Atan, Compiler::StaticType::Number, Compiler::StaticType::Number, 1); } +void LLVMCodeBuilder::createLn() +{ + createOp(Step::Type::Ln, Compiler::StaticType::Number, Compiler::StaticType::Number, 1); +} + void LLVMCodeBuilder::beginIfStatement() { Step step(Step::Type::BeginIf); diff --git a/src/dev/engine/internal/llvmcodebuilder.h b/src/dev/engine/internal/llvmcodebuilder.h index 7b180406..f98a313f 100644 --- a/src/dev/engine/internal/llvmcodebuilder.h +++ b/src/dev/engine/internal/llvmcodebuilder.h @@ -51,6 +51,7 @@ class LLVMCodeBuilder : public ICodeBuilder void createAsin() override; void createAcos() override; void createAtan() override; + void createLn() override; void beginIfStatement() override; void beginElseBranch() override; @@ -106,6 +107,7 @@ class LLVMCodeBuilder : public ICodeBuilder Asin, Acos, Atan, + Ln, Yield, BeginIf, BeginElse, diff --git a/test/dev/llvm/llvmcodebuilder_test.cpp b/test/dev/llvm/llvmcodebuilder_test.cpp index 02deb187..0de1ae1e 100644 --- a/test/dev/llvm/llvmcodebuilder_test.cpp +++ b/test/dev/llvm/llvmcodebuilder_test.cpp @@ -1601,6 +1601,51 @@ TEST_F(LLVMCodeBuilderTest, Atan) addOpTest(nan, 0.0); } +TEST_F(LLVMCodeBuilderTest, Ln) +{ + std::string expected; + + auto addOpTest = [this, &expected](Value v1, double expectedResult) { + createBuilder(true); + + m_builder->addConstValue(v1); + m_builder->createLn(); + m_builder->addFunctionCall("test_print_number", Compiler::StaticType::Void, { Compiler::StaticType::Number }); + + m_builder->addConstValue(v1); + m_builder->addFunctionCall("test_const_number", Compiler::StaticType::Number, { Compiler::StaticType::Number }); + m_builder->createLn(); + m_builder->addFunctionCall("test_print_number", Compiler::StaticType::Void, { Compiler::StaticType::Number }); + + std::stringstream stream; + stream << expectedResult; + std::string str = stream.str() + '\n'; + std::string expected = str + str; + + auto code = m_builder->finalize(); + auto ctx = code->createExecutionContext(&m_target); + + testing::internal::CaptureStdout(); + code->run(ctx.get()); + const std::string quotes1 = v1.isString() ? "\"" : ""; + ASSERT_THAT(testing::internal::GetCapturedStdout(), Eq(expected)) << quotes1 << v1.toString() << quotes1; + }; + + static const double inf = std::numeric_limits::infinity(); + static const double nan = std::numeric_limits::quiet_NaN(); + + addOpTest(std::exp(1.0), 1.0); + addOpTest(std::exp(2.0), 2.0); + addOpTest(std::exp(0.3), 0.3); + addOpTest(1.0, 0.0); + addOpTest(0.0, -inf); + addOpTest(-0.0, -inf); + addOpTest(-0.7, -nan); // negative NaN shouldn't be a problem + addOpTest(inf, inf); + addOpTest(-inf, -nan); + addOpTest(nan, -inf); +} + TEST_F(LLVMCodeBuilderTest, Yield) { auto build = [this]() { diff --git a/test/mocks/codebuildermock.h b/test/mocks/codebuildermock.h index e405f2b0..7b5a10f2 100644 --- a/test/mocks/codebuildermock.h +++ b/test/mocks/codebuildermock.h @@ -39,6 +39,7 @@ class CodeBuilderMock : public ICodeBuilder MOCK_METHOD(void, createAsin, (), (override)); MOCK_METHOD(void, createAcos, (), (override)); MOCK_METHOD(void, createAtan, (), (override)); + MOCK_METHOD(void, createLn, (), (override)); MOCK_METHOD(void, beginIfStatement, (), (override)); MOCK_METHOD(void, beginElseBranch, (), (override)); From 2096b40ca6819307bd415edb35da6e356dafb5e4 Mon Sep 17 00:00:00 2001 From: adazem009 <68537469+adazem009@users.noreply.github.com> Date: Thu, 7 Nov 2024 18:20:19 +0100 Subject: [PATCH 17/20] LLVMCodeBuilder: Implement log10 operator --- src/dev/engine/internal/icodebuilder.h | 1 + src/dev/engine/internal/llvmcodebuilder.cpp | 15 +++++++ src/dev/engine/internal/llvmcodebuilder.h | 2 + test/dev/llvm/llvmcodebuilder_test.cpp | 44 +++++++++++++++++++++ test/mocks/codebuildermock.h | 1 + 5 files changed, 63 insertions(+) diff --git a/src/dev/engine/internal/icodebuilder.h b/src/dev/engine/internal/icodebuilder.h index ce96d642..205885bf 100644 --- a/src/dev/engine/internal/icodebuilder.h +++ b/src/dev/engine/internal/icodebuilder.h @@ -50,6 +50,7 @@ class ICodeBuilder virtual void createAcos() = 0; virtual void createAtan() = 0; virtual void createLn() = 0; + virtual void createLog10() = 0; virtual void beginIfStatement() = 0; virtual void beginElseBranch() = 0; diff --git a/src/dev/engine/internal/llvmcodebuilder.cpp b/src/dev/engine/internal/llvmcodebuilder.cpp index 8977e83e..d92ed612 100644 --- a/src/dev/engine/internal/llvmcodebuilder.cpp +++ b/src/dev/engine/internal/llvmcodebuilder.cpp @@ -364,6 +364,16 @@ std::shared_ptr LLVMCodeBuilder::finalize() break; } + case Step::Type::Log10: { + assert(step.args.size() == 1); + const auto &arg = step.args[0]; + // log10(x) + llvm::Function *log10Func = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::log10, m_builder.getDoubleTy()); + llvm::Value *num = removeNaN(castValue(arg.second, arg.first)); + step.functionReturnReg->value = m_builder.CreateCall(log10Func, num); + break; + } + case Step::Type::Yield: if (!m_warp) { freeHeap(); @@ -797,6 +807,11 @@ void LLVMCodeBuilder::createLn() createOp(Step::Type::Ln, Compiler::StaticType::Number, Compiler::StaticType::Number, 1); } +void LLVMCodeBuilder::createLog10() +{ + createOp(Step::Type::Log10, Compiler::StaticType::Number, Compiler::StaticType::Number, 1); +} + void LLVMCodeBuilder::beginIfStatement() { Step step(Step::Type::BeginIf); diff --git a/src/dev/engine/internal/llvmcodebuilder.h b/src/dev/engine/internal/llvmcodebuilder.h index f98a313f..85c0fa39 100644 --- a/src/dev/engine/internal/llvmcodebuilder.h +++ b/src/dev/engine/internal/llvmcodebuilder.h @@ -52,6 +52,7 @@ class LLVMCodeBuilder : public ICodeBuilder void createAcos() override; void createAtan() override; void createLn() override; + void createLog10() override; void beginIfStatement() override; void beginElseBranch() override; @@ -108,6 +109,7 @@ class LLVMCodeBuilder : public ICodeBuilder Acos, Atan, Ln, + Log10, Yield, BeginIf, BeginElse, diff --git a/test/dev/llvm/llvmcodebuilder_test.cpp b/test/dev/llvm/llvmcodebuilder_test.cpp index 0de1ae1e..c872a154 100644 --- a/test/dev/llvm/llvmcodebuilder_test.cpp +++ b/test/dev/llvm/llvmcodebuilder_test.cpp @@ -1646,6 +1646,50 @@ TEST_F(LLVMCodeBuilderTest, Ln) addOpTest(nan, -inf); } +TEST_F(LLVMCodeBuilderTest, Log10) +{ + std::string expected; + + auto addOpTest = [this, &expected](Value v1, double expectedResult) { + createBuilder(true); + + m_builder->addConstValue(v1); + m_builder->createLog10(); + m_builder->addFunctionCall("test_print_number", Compiler::StaticType::Void, { Compiler::StaticType::Number }); + + m_builder->addConstValue(v1); + m_builder->addFunctionCall("test_const_number", Compiler::StaticType::Number, { Compiler::StaticType::Number }); + m_builder->createLog10(); + m_builder->addFunctionCall("test_print_number", Compiler::StaticType::Void, { Compiler::StaticType::Number }); + + std::stringstream stream; + stream << expectedResult; + std::string str = stream.str() + '\n'; + std::string expected = str + str; + + auto code = m_builder->finalize(); + auto ctx = code->createExecutionContext(&m_target); + + testing::internal::CaptureStdout(); + code->run(ctx.get()); + const std::string quotes1 = v1.isString() ? "\"" : ""; + ASSERT_THAT(testing::internal::GetCapturedStdout(), Eq(expected)) << quotes1 << v1.toString() << quotes1; + }; + + static const double inf = std::numeric_limits::infinity(); + static const double nan = std::numeric_limits::quiet_NaN(); + + addOpTest(10.0, 1.0); + addOpTest(1000.0, 3.0); + addOpTest(0.01, -2.0); + addOpTest(0.0, -inf); + addOpTest(-0.0, -inf); + addOpTest(-0.7, nan); + addOpTest(inf, inf); + addOpTest(-inf, nan); + addOpTest(nan, -inf); +} + TEST_F(LLVMCodeBuilderTest, Yield) { auto build = [this]() { diff --git a/test/mocks/codebuildermock.h b/test/mocks/codebuildermock.h index 7b5a10f2..cfaa6195 100644 --- a/test/mocks/codebuildermock.h +++ b/test/mocks/codebuildermock.h @@ -40,6 +40,7 @@ class CodeBuilderMock : public ICodeBuilder MOCK_METHOD(void, createAcos, (), (override)); MOCK_METHOD(void, createAtan, (), (override)); MOCK_METHOD(void, createLn, (), (override)); + MOCK_METHOD(void, createLog10, (), (override)); MOCK_METHOD(void, beginIfStatement, (), (override)); MOCK_METHOD(void, beginElseBranch, (), (override)); From 1994f20a0e6b450982bcd6c85e5618e7dac37bc7 Mon Sep 17 00:00:00 2001 From: adazem009 <68537469+adazem009@users.noreply.github.com> Date: Thu, 7 Nov 2024 18:48:57 +0100 Subject: [PATCH 18/20] LLVMCodeBuilder: Implement exp operator --- src/dev/engine/internal/icodebuilder.h | 1 + src/dev/engine/internal/llvmcodebuilder.cpp | 15 +++++++ src/dev/engine/internal/llvmcodebuilder.h | 2 + test/dev/llvm/llvmcodebuilder_test.cpp | 43 +++++++++++++++++++++ test/mocks/codebuildermock.h | 1 + 5 files changed, 62 insertions(+) diff --git a/src/dev/engine/internal/icodebuilder.h b/src/dev/engine/internal/icodebuilder.h index 205885bf..119cff7a 100644 --- a/src/dev/engine/internal/icodebuilder.h +++ b/src/dev/engine/internal/icodebuilder.h @@ -51,6 +51,7 @@ class ICodeBuilder virtual void createAtan() = 0; virtual void createLn() = 0; virtual void createLog10() = 0; + virtual void createExp() = 0; virtual void beginIfStatement() = 0; virtual void beginElseBranch() = 0; diff --git a/src/dev/engine/internal/llvmcodebuilder.cpp b/src/dev/engine/internal/llvmcodebuilder.cpp index d92ed612..afc2198f 100644 --- a/src/dev/engine/internal/llvmcodebuilder.cpp +++ b/src/dev/engine/internal/llvmcodebuilder.cpp @@ -374,6 +374,16 @@ std::shared_ptr LLVMCodeBuilder::finalize() break; } + case Step::Type::Exp: { + assert(step.args.size() == 1); + const auto &arg = step.args[0]; + // exp(x) + llvm::Function *expFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::exp, m_builder.getDoubleTy()); + llvm::Value *num = removeNaN(castValue(arg.second, arg.first)); + step.functionReturnReg->value = m_builder.CreateCall(expFunc, num); + break; + } + case Step::Type::Yield: if (!m_warp) { freeHeap(); @@ -812,6 +822,11 @@ void LLVMCodeBuilder::createLog10() createOp(Step::Type::Log10, Compiler::StaticType::Number, Compiler::StaticType::Number, 1); } +void LLVMCodeBuilder::createExp() +{ + createOp(Step::Type::Exp, Compiler::StaticType::Number, Compiler::StaticType::Number, 1); +} + void LLVMCodeBuilder::beginIfStatement() { Step step(Step::Type::BeginIf); diff --git a/src/dev/engine/internal/llvmcodebuilder.h b/src/dev/engine/internal/llvmcodebuilder.h index 85c0fa39..289bea61 100644 --- a/src/dev/engine/internal/llvmcodebuilder.h +++ b/src/dev/engine/internal/llvmcodebuilder.h @@ -53,6 +53,7 @@ class LLVMCodeBuilder : public ICodeBuilder void createAtan() override; void createLn() override; void createLog10() override; + void createExp() override; void beginIfStatement() override; void beginElseBranch() override; @@ -110,6 +111,7 @@ class LLVMCodeBuilder : public ICodeBuilder Atan, Ln, Log10, + Exp, Yield, BeginIf, BeginElse, diff --git a/test/dev/llvm/llvmcodebuilder_test.cpp b/test/dev/llvm/llvmcodebuilder_test.cpp index c872a154..b4b47ae6 100644 --- a/test/dev/llvm/llvmcodebuilder_test.cpp +++ b/test/dev/llvm/llvmcodebuilder_test.cpp @@ -1690,6 +1690,49 @@ TEST_F(LLVMCodeBuilderTest, Log10) addOpTest(nan, -inf); } +TEST_F(LLVMCodeBuilderTest, Exp) +{ + std::string expected; + + auto addOpTest = [this, &expected](Value v1, double expectedResult) { + createBuilder(true); + + m_builder->addConstValue(v1); + m_builder->createExp(); + m_builder->addFunctionCall("test_print_number", Compiler::StaticType::Void, { Compiler::StaticType::Number }); + + m_builder->addConstValue(v1); + m_builder->addFunctionCall("test_const_number", Compiler::StaticType::Number, { Compiler::StaticType::Number }); + m_builder->createExp(); + m_builder->addFunctionCall("test_print_number", Compiler::StaticType::Void, { Compiler::StaticType::Number }); + + std::stringstream stream; + stream << expectedResult; + std::string str = stream.str() + '\n'; + std::string expected = str + str; + + auto code = m_builder->finalize(); + auto ctx = code->createExecutionContext(&m_target); + + testing::internal::CaptureStdout(); + code->run(ctx.get()); + const std::string quotes1 = v1.isString() ? "\"" : ""; + ASSERT_THAT(testing::internal::GetCapturedStdout(), Eq(expected)) << quotes1 << v1.toString() << quotes1; + }; + + static const double inf = std::numeric_limits::infinity(); + static const double nan = std::numeric_limits::quiet_NaN(); + + addOpTest(1.0, std::exp(1.0)); + addOpTest(0.5, std::exp(0.5)); + addOpTest(0.0, 1.0); + addOpTest(-0.0, 1.0); + addOpTest(-0.7, std::exp(-0.7)); + addOpTest(inf, inf); + addOpTest(-inf, 0.0); + addOpTest(nan, 1.0); +} + TEST_F(LLVMCodeBuilderTest, Yield) { auto build = [this]() { diff --git a/test/mocks/codebuildermock.h b/test/mocks/codebuildermock.h index cfaa6195..3bdcd51b 100644 --- a/test/mocks/codebuildermock.h +++ b/test/mocks/codebuildermock.h @@ -41,6 +41,7 @@ class CodeBuilderMock : public ICodeBuilder MOCK_METHOD(void, createAtan, (), (override)); MOCK_METHOD(void, createLn, (), (override)); MOCK_METHOD(void, createLog10, (), (override)); + MOCK_METHOD(void, createExp, (), (override)); MOCK_METHOD(void, beginIfStatement, (), (override)); MOCK_METHOD(void, beginElseBranch, (), (override)); From 60b53c488e642088409460c6fa37963eb9799f8d Mon Sep 17 00:00:00 2001 From: adazem009 <68537469+adazem009@users.noreply.github.com> Date: Thu, 7 Nov 2024 19:00:16 +0100 Subject: [PATCH 19/20] LLVMCodeBuilder: Implement exp10 operator --- src/dev/engine/internal/icodebuilder.h | 1 + src/dev/engine/internal/llvmcodebuilder.cpp | 15 +++++++ src/dev/engine/internal/llvmcodebuilder.h | 2 + test/dev/llvm/llvmcodebuilder_test.cpp | 44 +++++++++++++++++++++ test/mocks/codebuildermock.h | 1 + 5 files changed, 63 insertions(+) diff --git a/src/dev/engine/internal/icodebuilder.h b/src/dev/engine/internal/icodebuilder.h index 119cff7a..824471bf 100644 --- a/src/dev/engine/internal/icodebuilder.h +++ b/src/dev/engine/internal/icodebuilder.h @@ -52,6 +52,7 @@ class ICodeBuilder virtual void createLn() = 0; virtual void createLog10() = 0; virtual void createExp() = 0; + virtual void createExp10() = 0; virtual void beginIfStatement() = 0; virtual void beginElseBranch() = 0; diff --git a/src/dev/engine/internal/llvmcodebuilder.cpp b/src/dev/engine/internal/llvmcodebuilder.cpp index afc2198f..6d1c5872 100644 --- a/src/dev/engine/internal/llvmcodebuilder.cpp +++ b/src/dev/engine/internal/llvmcodebuilder.cpp @@ -384,6 +384,16 @@ std::shared_ptr LLVMCodeBuilder::finalize() break; } + case Step::Type::Exp10: { + assert(step.args.size() == 1); + const auto &arg = step.args[0]; + // exp10(x) + llvm::Function *expFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::exp10, m_builder.getDoubleTy()); + llvm::Value *num = removeNaN(castValue(arg.second, arg.first)); + step.functionReturnReg->value = m_builder.CreateCall(expFunc, num); + break; + } + case Step::Type::Yield: if (!m_warp) { freeHeap(); @@ -827,6 +837,11 @@ void LLVMCodeBuilder::createExp() createOp(Step::Type::Exp, Compiler::StaticType::Number, Compiler::StaticType::Number, 1); } +void LLVMCodeBuilder::createExp10() +{ + createOp(Step::Type::Exp10, Compiler::StaticType::Number, Compiler::StaticType::Number, 1); +} + void LLVMCodeBuilder::beginIfStatement() { Step step(Step::Type::BeginIf); diff --git a/src/dev/engine/internal/llvmcodebuilder.h b/src/dev/engine/internal/llvmcodebuilder.h index 289bea61..9401e048 100644 --- a/src/dev/engine/internal/llvmcodebuilder.h +++ b/src/dev/engine/internal/llvmcodebuilder.h @@ -54,6 +54,7 @@ class LLVMCodeBuilder : public ICodeBuilder void createLn() override; void createLog10() override; void createExp() override; + void createExp10() override; void beginIfStatement() override; void beginElseBranch() override; @@ -112,6 +113,7 @@ class LLVMCodeBuilder : public ICodeBuilder Ln, Log10, Exp, + Exp10, Yield, BeginIf, BeginElse, diff --git a/test/dev/llvm/llvmcodebuilder_test.cpp b/test/dev/llvm/llvmcodebuilder_test.cpp index b4b47ae6..7c357278 100644 --- a/test/dev/llvm/llvmcodebuilder_test.cpp +++ b/test/dev/llvm/llvmcodebuilder_test.cpp @@ -1733,6 +1733,50 @@ TEST_F(LLVMCodeBuilderTest, Exp) addOpTest(nan, 1.0); } +TEST_F(LLVMCodeBuilderTest, Exp10) +{ + std::string expected; + + auto addOpTest = [this, &expected](Value v1, double expectedResult) { + createBuilder(true); + + m_builder->addConstValue(v1); + m_builder->createExp10(); + m_builder->addFunctionCall("test_print_number", Compiler::StaticType::Void, { Compiler::StaticType::Number }); + + m_builder->addConstValue(v1); + m_builder->addFunctionCall("test_const_number", Compiler::StaticType::Number, { Compiler::StaticType::Number }); + m_builder->createExp10(); + m_builder->addFunctionCall("test_print_number", Compiler::StaticType::Void, { Compiler::StaticType::Number }); + + std::stringstream stream; + stream << expectedResult; + std::string str = stream.str() + '\n'; + std::string expected = str + str; + + auto code = m_builder->finalize(); + auto ctx = code->createExecutionContext(&m_target); + + testing::internal::CaptureStdout(); + code->run(ctx.get()); + const std::string quotes1 = v1.isString() ? "\"" : ""; + ASSERT_THAT(testing::internal::GetCapturedStdout(), Eq(expected)) << quotes1 << v1.toString() << quotes1; + }; + + static const double inf = std::numeric_limits::infinity(); + static const double nan = std::numeric_limits::quiet_NaN(); + + addOpTest(1.0, 10.0); + addOpTest(3.0, 1000.0); + addOpTest(0.0, 1.0); + addOpTest(-0.0, 1.0); + addOpTest(-1.0, 0.1); + addOpTest(-5.0, 0.00001); + addOpTest(inf, inf); + addOpTest(-inf, 0.0); + addOpTest(nan, 1.0); +} + TEST_F(LLVMCodeBuilderTest, Yield) { auto build = [this]() { diff --git a/test/mocks/codebuildermock.h b/test/mocks/codebuildermock.h index 3bdcd51b..3de5cf4c 100644 --- a/test/mocks/codebuildermock.h +++ b/test/mocks/codebuildermock.h @@ -42,6 +42,7 @@ class CodeBuilderMock : public ICodeBuilder MOCK_METHOD(void, createLn, (), (override)); MOCK_METHOD(void, createLog10, (), (override)); MOCK_METHOD(void, createExp, (), (override)); + MOCK_METHOD(void, createExp10, (), (override)); MOCK_METHOD(void, beginIfStatement, (), (override)); MOCK_METHOD(void, beginElseBranch, (), (override)); From edb28bfbec58929cf83491d152bcfffdd75aa5fa Mon Sep 17 00:00:00 2001 From: adazem009 <68537469+adazem009@users.noreply.github.com> Date: Thu, 7 Nov 2024 19:10:48 +0100 Subject: [PATCH 20/20] Compiler: Add methods for math instructions --- include/scratchcpp/dev/compiler.h | 17 +++ src/dev/engine/compiler.cpp | 96 +++++++++++++ test/dev/compiler/compiler_test.cpp | 208 ++++++++++++++++++++++++++++ 3 files changed, 321 insertions(+) diff --git a/include/scratchcpp/dev/compiler.h b/include/scratchcpp/dev/compiler.h index 3b579023..d3700a88 100644 --- a/include/scratchcpp/dev/compiler.h +++ b/include/scratchcpp/dev/compiler.h @@ -61,6 +61,23 @@ class LIBSCRATCHCPP_EXPORT Compiler void createOr(); void createNot(); + void createMod(); + void createRound(); + void createAbs(); + void createFloor(); + void createCeil(); + void createSqrt(); + void createSin(); + void createCos(); + void createTan(); + void createAsin(); + void createAcos(); + void createAtan(); + void createLn(); + void createLog10(); + void createExp(); + void createExp10(); + void moveToIf(std::shared_ptr substack); void moveToIfElse(std::shared_ptr substack1, std::shared_ptr substack2); void moveToRepeatLoop(std::shared_ptr substack); diff --git a/src/dev/engine/compiler.cpp b/src/dev/engine/compiler.cpp index 7ff6737e..1d036ba9 100644 --- a/src/dev/engine/compiler.cpp +++ b/src/dev/engine/compiler.cpp @@ -160,6 +160,102 @@ void Compiler::createNot() impl->builder->createNot(); } +/*! Creates a remainder operation using the last 2 values. */ +void Compiler::createMod() +{ + impl->builder->createMod(); +} + +/*! Creates a round operation using the last value. */ +void Compiler::createRound() +{ + impl->builder->createRound(); +} + +/*! Creates an abs operation using the last value. */ +void Compiler::createAbs() +{ + impl->builder->createAbs(); +} + +/*! Creates a floor operation using the last value. */ +void Compiler::createFloor() +{ + impl->builder->createFloor(); +} + +/*! Creates a ceiling operation using the last value. */ +void Compiler::createCeil() +{ + impl->builder->createCeil(); +} + +/*! Creates a square root operation using the last value. */ +void Compiler::createSqrt() +{ + impl->builder->createSqrt(); +} + +/*! Creates a sin operation using the last value. */ +void Compiler::createSin() +{ + impl->builder->createSin(); +} + +/*! Creates a cos operation using the last value. */ +void Compiler::createCos() +{ + impl->builder->createCos(); +} + +/*! Creates a tan operation using the last value. */ +void Compiler::createTan() +{ + impl->builder->createTan(); +} + +/*! Creates an asin operation using the last value. */ +void Compiler::createAsin() +{ + impl->builder->createAsin(); +} + +/*! Creates an acos operation using the last value. */ +void Compiler::createAcos() +{ + impl->builder->createAcos(); +} + +/*! Creates an atan operation using the last value. */ +void Compiler::createAtan() +{ + impl->builder->createAtan(); +} + +/*! Creates an ln operation using the last value. */ +void Compiler::createLn() +{ + impl->builder->createLn(); +} + +/*! Creates a log10 operation using the last value. */ +void Compiler::createLog10() +{ + impl->builder->createLog10(); +} + +/*! Creates an e^x operation using the last value. */ +void Compiler::createExp() +{ + impl->builder->createExp(); +} + +/*! Creates a 10^x operation using the last value. */ +void Compiler::createExp10() +{ + impl->builder->createExp10(); +} + /*! Jumps to the given if substack. */ void Compiler::moveToIf(std::shared_ptr substack) { diff --git a/test/dev/compiler/compiler_test.cpp b/test/dev/compiler/compiler_test.cpp index 0ebe69c5..fc59fb86 100644 --- a/test/dev/compiler/compiler_test.cpp +++ b/test/dev/compiler/compiler_test.cpp @@ -349,6 +349,214 @@ TEST_F(CompilerTest, CreateNot) compile(compiler, block); } +TEST_F(CompilerTest, CreateMod) +{ + Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); + + block->setCompileFunction([](Compiler *compiler) { + EXPECT_CALL(*m_builder, createMod); + compiler->createMod(); + }); + + compile(compiler, block); +} + +TEST_F(CompilerTest, CreateRound) +{ + Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); + + block->setCompileFunction([](Compiler *compiler) { + EXPECT_CALL(*m_builder, createRound); + compiler->createRound(); + }); + + compile(compiler, block); +} + +TEST_F(CompilerTest, CreateAbs) +{ + Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); + + block->setCompileFunction([](Compiler *compiler) { + EXPECT_CALL(*m_builder, createAbs); + compiler->createAbs(); + }); + + compile(compiler, block); +} + +TEST_F(CompilerTest, CreateFloor) +{ + Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); + + block->setCompileFunction([](Compiler *compiler) { + EXPECT_CALL(*m_builder, createFloor); + compiler->createFloor(); + }); + + compile(compiler, block); +} + +TEST_F(CompilerTest, CreateCeil) +{ + Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); + + block->setCompileFunction([](Compiler *compiler) { + EXPECT_CALL(*m_builder, createCeil); + compiler->createCeil(); + }); + + compile(compiler, block); +} + +TEST_F(CompilerTest, CreateSqrt) +{ + Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); + + block->setCompileFunction([](Compiler *compiler) { + EXPECT_CALL(*m_builder, createSqrt); + compiler->createSqrt(); + }); + + compile(compiler, block); +} + +TEST_F(CompilerTest, CreateSin) +{ + Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); + + block->setCompileFunction([](Compiler *compiler) { + EXPECT_CALL(*m_builder, createSin); + compiler->createSin(); + }); + + compile(compiler, block); +} + +TEST_F(CompilerTest, CreateCos) +{ + Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); + + block->setCompileFunction([](Compiler *compiler) { + EXPECT_CALL(*m_builder, createCos); + compiler->createCos(); + }); + + compile(compiler, block); +} + +TEST_F(CompilerTest, CreateTan) +{ + Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); + + block->setCompileFunction([](Compiler *compiler) { + EXPECT_CALL(*m_builder, createTan); + compiler->createTan(); + }); + + compile(compiler, block); +} + +TEST_F(CompilerTest, CreateAsin) +{ + Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); + + block->setCompileFunction([](Compiler *compiler) { + EXPECT_CALL(*m_builder, createAsin); + compiler->createAsin(); + }); + + compile(compiler, block); +} + +TEST_F(CompilerTest, CreateAcos) +{ + Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); + + block->setCompileFunction([](Compiler *compiler) { + EXPECT_CALL(*m_builder, createAcos); + compiler->createAcos(); + }); + + compile(compiler, block); +} + +TEST_F(CompilerTest, CreateAtan) +{ + Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); + + block->setCompileFunction([](Compiler *compiler) { + EXPECT_CALL(*m_builder, createAtan); + compiler->createAtan(); + }); + + compile(compiler, block); +} + +TEST_F(CompilerTest, CreateLn) +{ + Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); + + block->setCompileFunction([](Compiler *compiler) { + EXPECT_CALL(*m_builder, createLn); + compiler->createLn(); + }); + + compile(compiler, block); +} + +TEST_F(CompilerTest, CreateLog10) +{ + Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); + + block->setCompileFunction([](Compiler *compiler) { + EXPECT_CALL(*m_builder, createLog10); + compiler->createLog10(); + }); + + compile(compiler, block); +} + +TEST_F(CompilerTest, CreateExp) +{ + Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); + + block->setCompileFunction([](Compiler *compiler) { + EXPECT_CALL(*m_builder, createExp); + compiler->createExp(); + }); + + compile(compiler, block); +} + +TEST_F(CompilerTest, CreateExp10) +{ + Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); + + block->setCompileFunction([](Compiler *compiler) { + EXPECT_CALL(*m_builder, createExp10); + compiler->createExp10(); + }); + + compile(compiler, block); +} + TEST_F(CompilerTest, MoveToIf) { Compiler compiler(&m_engine, &m_target);