@@ -284,6 +284,38 @@ std::shared_ptr<ExecutableCode> LLVMCodeBuilder::finalize()
284284 break ;
285285 }
286286
287+ case Step::Type::Tan: {
288+ assert (step.args .size () == 1 );
289+ const auto &arg = step.args [0 ];
290+ // ((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)
291+ // +0.0 to avoid -0.0
292+ llvm::Constant *zero = llvm::ConstantFP::get (m_ctx, llvm::APFloat (0.0 ));
293+ llvm::Constant *full = llvm::ConstantFP::get (m_ctx, llvm::APFloat (360.0 ));
294+ llvm::Constant *posInf = llvm::ConstantFP::getInfinity (m_builder.getDoubleTy (), false );
295+ llvm::Constant *negInf = llvm::ConstantFP::getInfinity (m_builder.getDoubleTy (), true );
296+ llvm::Constant *undefined1 = llvm::ConstantFP::get (m_ctx, llvm::APFloat (-270.0 ));
297+ llvm::Constant *undefined2 = llvm::ConstantFP::get (m_ctx, llvm::APFloat (90.0 ));
298+ llvm::Constant *undefined3 = llvm::ConstantFP::get (m_ctx, llvm::APFloat (-90.0 ));
299+ llvm::Constant *undefined4 = llvm::ConstantFP::get (m_ctx, llvm::APFloat (270.0 ));
300+ llvm::Constant *pi = llvm::ConstantFP::get (m_ctx, llvm::APFloat (std::acos (-1.0 )));
301+ llvm::Constant *piDeg = llvm::ConstantFP::get (m_ctx, llvm::APFloat (180.0 ));
302+ llvm::Constant *factor = llvm::ConstantFP::get (m_ctx, llvm::APFloat (1e10 ));
303+ llvm::Function *tanFunc = llvm::Intrinsic::getDeclaration (m_module.get (), llvm::Intrinsic::tan, m_builder.getDoubleTy ());
304+ llvm::Function *roundFunc = llvm::Intrinsic::getDeclaration (m_module.get (), llvm::Intrinsic::round, m_builder.getDoubleTy ());
305+ llvm::Value *num = removeNaN (castValue (arg.second , arg.first ));
306+ llvm::Value *mod = m_builder.CreateFRem (num, full);
307+ llvm::Value *isUndefined1 = m_builder.CreateFCmpOEQ (mod, undefined1); // rem(x, 360.0) == -270.0
308+ llvm::Value *isUndefined2 = m_builder.CreateFCmpOEQ (mod, undefined2); // rem(x, 360.0) == 90.0
309+ llvm::Value *isUndefined3 = m_builder.CreateFCmpOEQ (mod, undefined3); // rem(x, 360.0) == -90.0
310+ llvm::Value *isUndefined4 = m_builder.CreateFCmpOEQ (mod, undefined4); // rem(x, 360.0) == 270.0
311+ llvm::Value *tanResult = m_builder.CreateCall (tanFunc, m_builder.CreateFDiv (m_builder.CreateFMul (num, pi), piDeg)); // tan(x * pi / 180)
312+ llvm::Value *rounded = m_builder.CreateCall (roundFunc, m_builder.CreateFMul (tanResult, factor)); // round(tan(x * 180) * 1e10)
313+ llvm::Value *result = m_builder.CreateFAdd (m_builder.CreateFDiv (rounded, factor), zero); // round(tan(x * pi / 180.0) * 1e10) / 1e10 + 0.0
314+ llvm::Value *inner = m_builder.CreateSelect (m_builder.CreateOr (isUndefined3, isUndefined4), negInf, result);
315+ step.functionReturnReg ->value = m_builder.CreateSelect (m_builder.CreateOr (isUndefined1, isUndefined2), posInf, inner);
316+ break ;
317+ }
318+
287319 case Step::Type::Yield:
288320 if (!m_warp) {
289321 freeHeap ();
@@ -692,6 +724,11 @@ void LLVMCodeBuilder::createCos()
692724 createOp (Step::Type::Cos, Compiler::StaticType::Number, Compiler::StaticType::Number, 1 );
693725}
694726
727+ void LLVMCodeBuilder::createTan ()
728+ {
729+ createOp (Step::Type::Tan, Compiler::StaticType::Number, Compiler::StaticType::Number, 1 );
730+ }
731+
695732void LLVMCodeBuilder::beginIfStatement ()
696733{
697734 Step step (Step::Type::BeginIf);
0 commit comments