Skip to content

Commit 2c3c62c

Browse files
committed
LLVMCodeBuilder: Implement cos operator
1 parent a042b64 commit 2c3c62c

File tree

5 files changed

+72
-0
lines changed

5 files changed

+72
-0
lines changed

src/dev/engine/internal/icodebuilder.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class ICodeBuilder
4444
virtual void createCeil() = 0;
4545
virtual void createSqrt() = 0;
4646
virtual void createSin() = 0;
47+
virtual void createCos() = 0;
4748

4849
virtual void beginIfStatement() = 0;
4950
virtual void beginElseBranch() = 0;

src/dev/engine/internal/llvmcodebuilder.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,22 @@ std::shared_ptr<ExecutableCode> LLVMCodeBuilder::finalize()
268268
break;
269269
}
270270

271+
case Step::Type::Cos: {
272+
assert(step.args.size() == 1);
273+
const auto &arg = step.args[0];
274+
// round(cos(x * pi / 180.0) * 1e10) / 1e10
275+
llvm::Constant *pi = llvm::ConstantFP::get(m_ctx, llvm::APFloat(std::acos(-1.0)));
276+
llvm::Constant *piDeg = llvm::ConstantFP::get(m_ctx, llvm::APFloat(180.0));
277+
llvm::Constant *factor = llvm::ConstantFP::get(m_ctx, llvm::APFloat(1e10));
278+
llvm::Function *cosFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::cos, m_builder.getDoubleTy());
279+
llvm::Function *roundFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::round, m_builder.getDoubleTy());
280+
llvm::Value *num = removeNaN(castValue(arg.second, arg.first));
281+
llvm::Value *cosResult = m_builder.CreateCall(cosFunc, m_builder.CreateFDiv(m_builder.CreateFMul(num, pi), piDeg)); // cos(x * pi / 180)
282+
llvm::Value *rounded = m_builder.CreateCall(roundFunc, m_builder.CreateFMul(cosResult, factor)); // round(cos(x * 180) * 1e10)
283+
step.functionReturnReg->value = m_builder.CreateFDiv(rounded, factor);
284+
break;
285+
}
286+
271287
case Step::Type::Yield:
272288
if (!m_warp) {
273289
freeHeap();
@@ -671,6 +687,11 @@ void LLVMCodeBuilder::createSin()
671687
createOp(Step::Type::Sin, Compiler::StaticType::Number, Compiler::StaticType::Number, 1);
672688
}
673689

690+
void LLVMCodeBuilder::createCos()
691+
{
692+
createOp(Step::Type::Cos, Compiler::StaticType::Number, Compiler::StaticType::Number, 1);
693+
}
694+
674695
void LLVMCodeBuilder::beginIfStatement()
675696
{
676697
Step step(Step::Type::BeginIf);

src/dev/engine/internal/llvmcodebuilder.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ class LLVMCodeBuilder : public ICodeBuilder
4646
void createCeil() override;
4747
void createSqrt() override;
4848
void createSin() override;
49+
void createCos() override;
4950

5051
void beginIfStatement() override;
5152
void beginElseBranch() override;
@@ -96,6 +97,7 @@ class LLVMCodeBuilder : public ICodeBuilder
9697
Ceil,
9798
Sqrt,
9899
Sin,
100+
Cos,
99101
Yield,
100102
BeginIf,
101103
BeginElse,

test/dev/llvm/llvmcodebuilder_test.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1369,6 +1369,53 @@ TEST_F(LLVMCodeBuilderTest, Sin)
13691369
addOpTest(nan, 0);
13701370
}
13711371

1372+
TEST_F(LLVMCodeBuilderTest, Cos)
1373+
{
1374+
std::string expected;
1375+
1376+
auto addOpTest = [this, &expected](Value v1, double expectedResult) {
1377+
createBuilder(true);
1378+
1379+
m_builder->addConstValue(v1);
1380+
m_builder->createCos();
1381+
m_builder->addFunctionCall("test_print_number", Compiler::StaticType::Void, { Compiler::StaticType::Number });
1382+
1383+
m_builder->addConstValue(v1);
1384+
m_builder->addFunctionCall("test_const_number", Compiler::StaticType::Number, { Compiler::StaticType::Number });
1385+
m_builder->createCos();
1386+
m_builder->addFunctionCall("test_print_number", Compiler::StaticType::Void, { Compiler::StaticType::Number });
1387+
1388+
std::stringstream stream;
1389+
stream << expectedResult;
1390+
std::string str = stream.str() + '\n';
1391+
std::string expected = str + str;
1392+
1393+
auto code = m_builder->finalize();
1394+
auto ctx = code->createExecutionContext(&m_target);
1395+
1396+
testing::internal::CaptureStdout();
1397+
code->run(ctx.get());
1398+
const std::string quotes1 = v1.isString() ? "\"" : "";
1399+
ASSERT_THAT(testing::internal::GetCapturedStdout(), Eq(expected)) << quotes1 << v1.toString() << quotes1;
1400+
};
1401+
1402+
static const double inf = std::numeric_limits<double>::infinity();
1403+
static const double nan = std::numeric_limits<double>::quiet_NaN();
1404+
1405+
addOpTest(60.0, 0.5);
1406+
addOpTest(90.0, 0.0);
1407+
addOpTest(600.0, -0.5);
1408+
addOpTest(89.9999999971352, 1e-10);
1409+
addOpTest(89.999999999, 0.0);
1410+
addOpTest(-60.0, 0.5);
1411+
addOpTest(-90.0, 0.0);
1412+
addOpTest(0.0, 1.0);
1413+
addOpTest(-0.0, 1.0);
1414+
addOpTest(inf, -nan); // negative NaN shouldn't be a problem
1415+
addOpTest(-inf, -nan);
1416+
addOpTest(nan, 1.0);
1417+
}
1418+
13721419
TEST_F(LLVMCodeBuilderTest, Yield)
13731420
{
13741421
auto build = [this]() {

test/mocks/codebuildermock.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class CodeBuilderMock : public ICodeBuilder
3434
MOCK_METHOD(void, createCeil, (), (override));
3535
MOCK_METHOD(void, createSqrt, (), (override));
3636
MOCK_METHOD(void, createSin, (), (override));
37+
MOCK_METHOD(void, createCos, (), (override));
3738

3839
MOCK_METHOD(void, beginIfStatement, (), (override));
3940
MOCK_METHOD(void, beginElseBranch, (), (override));

0 commit comments

Comments
 (0)