Skip to content

Commit 96e56c5

Browse files
committed
Implementation of cmath function acosh, asin, asinh, atan and atanh
1 parent e0e002b commit 96e56c5

File tree

1 file changed

+175
-0
lines changed

1 file changed

+175
-0
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/CmathModuleBuiltins.java

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,181 @@ PComplex compute(VirtualFrame frame, double real, double imag) {
577577
}
578578
}
579579

580+
@Builtin(name = "acosh", minNumOfPositionalArgs = 1)
581+
@GenerateNodeFactory
582+
abstract static class AcoshNode extends CmathComplexUnaryBuiltinNode {
583+
584+
@Child private SqrtNode sqrtNode = SqrtNode.create();
585+
@Child private MathModuleBuiltins.AsinhNode realAsinhNode = MathModuleBuiltins.AsinhNode.create();
586+
587+
// @formatter:off
588+
@CompilerDirectives.CompilationFinal(dimensions = 2)
589+
private static final ComplexConstant[][] SPECIAL_VALUES = {
590+
{C(INF, -P34), C(INF, -P), C(INF, -P), C(INF, P), C(INF, P), C(INF, P34), C(INF, NAN)},
591+
{C(INF, -P12), null, null, null, null, C(INF, P12), C(NAN, NAN)},
592+
{C(INF, -P12), null, C(0.0, -P12), C(0.0, P12), null, C(INF, P12), C(NAN, NAN)},
593+
{C(INF, -P12), null, C(0.0, -P12), C(0.0, P12), null, C(INF, P12), C(NAN, NAN)},
594+
{C(INF, -P12), null, null, null, null, C(INF, P12), C(NAN, NAN)},
595+
{C(INF, -P14), C(INF, -0.0), C(INF, -0.), C(INF, 0.0), C(INF, 0.0), C(INF, P14), C(INF, NAN)},
596+
{C(INF, NAN), C(NAN, NAN), C(NAN, NAN), C(NAN, NAN), C(NAN, NAN), C(INF, NAN), C(NAN, NAN)},
597+
};
598+
// @formatter:on
599+
600+
@Override
601+
PComplex compute(VirtualFrame frame, double real, double imag) {
602+
PComplex result = specialValue(factory(), SPECIAL_VALUES, real, imag);
603+
if (result != null) {
604+
return result;
605+
}
606+
double rreal;
607+
double rimag;
608+
if (Math.abs(real) > LARGE_DOUBLE || Math.abs(imag) > LARGE_DOUBLE) {
609+
rreal = Math.log(Math.hypot(real / 2.0, imag / 2.0)) + LN_2 * 2.0;
610+
rimag = Math.atan2(imag, real);
611+
} else {
612+
PComplex s1 = sqrtNode.executeComplex(frame, factory().createComplex(real - 1.0, imag));
613+
PComplex s2 = sqrtNode.executeComplex(frame, factory().createComplex(real + 1.0, imag));
614+
rreal = realAsinhNode.executeObject(frame, s1.getReal() * s2.getReal() + s1.getImag() * s2.getImag());
615+
rimag = 2.0 * Math.atan2(s1.getImag(), s2.getReal());
616+
}
617+
return factory().createComplex(rreal, rimag);
618+
}
619+
}
620+
621+
@Builtin(name = "asin", minNumOfPositionalArgs = 1)
622+
@GenerateNodeFactory
623+
abstract static class AsinNode extends CmathComplexUnaryBuiltinNode {
624+
625+
@Child private AsinhNode asinhNode = AsinhNode.create();
626+
627+
@Override
628+
PComplex compute(VirtualFrame frame, double real, double imag) {
629+
PComplex s = asinhNode.executeComplex(frame, factory().createComplex(-imag, real));
630+
return factory().createComplex(s.getImag(), -s.getReal());
631+
}
632+
}
633+
634+
@Builtin(name = "asinh", minNumOfPositionalArgs = 1)
635+
@GenerateNodeFactory
636+
abstract static class AsinhNode extends CmathComplexUnaryBuiltinNode {
637+
638+
@Child private SqrtNode sqrtNode = SqrtNode.create();
639+
@Child private MathModuleBuiltins.AsinhNode realAsinhNode = MathModuleBuiltins.AsinhNode.create();
640+
641+
// @formatter:off
642+
@CompilerDirectives.CompilationFinal(dimensions = 2)
643+
private static final ComplexConstant[][] SPECIAL_VALUES = {
644+
{C(-INF, -P14), C(-INF, -0.0), C(-INF, -0.0), C(-INF, 0.0), C(-INF, 0.0), C(-INF, P14), C(-INF, NAN)},
645+
{C(-INF, -P12), null, null, null, null, C(-INF, P12), C(NAN, NAN)},
646+
{C(-INF, -P12), null, C(-0.0, -0.0), C(-0.0, 0.0), null, C(-INF, P12), C(NAN, NAN)},
647+
{C(INF, -P12), null, C(0.0, -0.0), C(0.0, 0.0), null, C(INF, P12), C(NAN, NAN)},
648+
{C(INF, -P12), null, null, null, null, C(INF, P12), C(NAN, NAN)},
649+
{C(INF, -P14), C(INF, -0.0), C(INF, -0.0), C(INF, 0.0), C(INF, 0.0), C(INF, P14), C(INF, NAN)},
650+
{C(INF, NAN), C(NAN, NAN), C(NAN, -0.0), C(NAN, 0.0), C(NAN, NAN), C(INF, NAN), C(NAN, NAN)},
651+
};
652+
// @formatter:on
653+
654+
@Override
655+
PComplex compute(VirtualFrame frame, double real, double imag) {
656+
PComplex result = specialValue(factory(), SPECIAL_VALUES, real, imag);
657+
if (result != null) {
658+
return result;
659+
}
660+
double rreal;
661+
double rimag;
662+
if (Math.abs(real) > LARGE_DOUBLE || Math.abs(imag) > LARGE_DOUBLE) {
663+
double s = Math.log(Math.hypot(real / 2.0, imag / 2.0)) + LN_2 * 2.0;
664+
if (imag >= 0.0) {
665+
rreal = Math.copySign(s, real);
666+
} else {
667+
rreal = -Math.copySign(s, -real);
668+
}
669+
rimag = Math.atan2(imag, Math.abs(real));
670+
} else {
671+
PComplex s1 = sqrtNode.executeComplex(frame, factory().createComplex(1.0 + imag, -real));
672+
PComplex s2 = sqrtNode.executeComplex(frame, factory().createComplex(1.0 - imag, real));
673+
rreal = realAsinhNode.executeObject(frame, s1.getReal() * s2.getImag() - s2.getReal() * s1.getImag());
674+
rimag = Math.atan2(imag, s1.getReal() * s2.getReal() - s1.getImag() * s2.getImag());
675+
}
676+
return factory().createComplex(rreal, rimag);
677+
}
678+
679+
static AsinhNode create() {
680+
return CmathModuleBuiltinsFactory.AsinhNodeFactory.create();
681+
}
682+
}
683+
684+
@Builtin(name = "atan", minNumOfPositionalArgs = 1)
685+
@GenerateNodeFactory
686+
abstract static class AtanNode extends CmathComplexUnaryBuiltinNode {
687+
688+
@Child private AtanhNode atanhNode = AtanhNode.create();
689+
690+
@Override
691+
PComplex compute(VirtualFrame frame, double real, double imag) {
692+
PComplex s = atanhNode.executeComplex(frame, factory().createComplex(-imag, real));
693+
return factory().createComplex(s.getImag(), -s.getReal());
694+
}
695+
}
696+
697+
@Builtin(name = "atanh", minNumOfPositionalArgs = 1)
698+
@GenerateNodeFactory
699+
abstract static class AtanhNode extends CmathComplexUnaryBuiltinNode {
700+
701+
static final double SQRT_LARGE_DOUBLE = Math.sqrt(LARGE_DOUBLE);
702+
static final double CM_SQRT_DBL_MIN = Math.sqrt(Double.MIN_NORMAL);
703+
704+
// @formatter:off
705+
@CompilerDirectives.CompilationFinal(dimensions = 2)
706+
private static final ComplexConstant[][] SPECIAL_VALUES = {
707+
{C(-0.0, -P12), C(-0.0, -P12), C(-0.0, -P12), C(-0.0, P12), C(-0.0, P12), C(-0.0, P12), C(-0.0, NAN)},
708+
{C(-0.0, -P12), null, null, null, null, C(-0.0, P12), C(NAN, NAN)},
709+
{C(-0.0, -P12), null, C(-0.0, -0.0), C(-0.0, 0.0), null, C(-0.0, P12), C(-0.0, NAN)},
710+
{C(0.0, -P12), null, C(0.0, -0.0), C(0.0, 0.0), null, C(0.0, P12), C(0.0, NAN)},
711+
{C(0.0, -P12), null, null, null, null, C(0.0, P12), C(NAN, NAN)},
712+
{C(0.0, -P12), C(0.0, -P12), C(0.0, -P12), C(0.0, P12), C(0.0, P12), C(0.0, P12), C(0.0, NAN)},
713+
{C(0.0, -P12), C(NAN, NAN), C(NAN, NAN), C(NAN, NAN), C(NAN, NAN), C(0.0, P12), C(NAN, NAN)},
714+
};
715+
// @formatter:on
716+
717+
@Override
718+
PComplex compute(VirtualFrame frame, double real, double imag) {
719+
PComplex result = specialValue(factory(), SPECIAL_VALUES, real, imag);
720+
if (result != null) {
721+
return result;
722+
}
723+
if (real < 0.0) {
724+
return computeWithRealPositive(-real, -imag, -1.0);
725+
}
726+
return computeWithRealPositive(real, imag, 1.0);
727+
}
728+
729+
private PComplex computeWithRealPositive(double real, double imag, double resultScale) {
730+
double rreal;
731+
double rimag;
732+
double ay = Math.abs(imag);
733+
if (real > SQRT_LARGE_DOUBLE || ay > SQRT_LARGE_DOUBLE) {
734+
double h = Math.hypot(real / 2.0, imag / 2.0);
735+
rreal = real / 4.0 / h / h;
736+
rimag = -Math.copySign(Math.PI / 2.0, -imag);
737+
} else if (real == 1.0 && ay < CM_SQRT_DBL_MIN) {
738+
if (ay == 0.0) {
739+
throw raise(ValueError, ErrorMessages.MATH_DOMAIN_ERROR);
740+
}
741+
rreal = -Math.log(Math.sqrt(ay) / Math.sqrt(Math.hypot(ay, 2.0)));
742+
rimag = Math.copySign(Math.atan2(2.0, -ay) / 2, imag);
743+
} else {
744+
rreal = Math.log1p(((4.0 * real) / ((1 - real) * (1 - real) + ay * ay))) / 4.0;
745+
rimag = -Math.atan2(-2.0 * imag, (1 - real) * (1 + real) - ay * ay) / 2.0;
746+
}
747+
return factory().createComplex(resultScale * rreal, resultScale * rimag);
748+
}
749+
750+
static AtanhNode create() {
751+
return CmathModuleBuiltinsFactory.AtanhNodeFactory.create();
752+
}
753+
}
754+
580755
@Builtin(name = "isclose", minNumOfPositionalArgs = 2, maxNumOfPositionalArgs = 2, keywordOnlyNames = {"rel_tol", "abs_tol"})
581756
@TypeSystemReference(PythonArithmeticTypes.class)
582757
@ImportStatic(MathGuards.class)

0 commit comments

Comments
 (0)