36
36
37
37
import java .util .List ;
38
38
39
+ import static com .oracle .graal .python .runtime .exception .PythonErrorType .OverflowError ;
39
40
import static com .oracle .graal .python .runtime .exception .PythonErrorType .ValueError ;
40
41
41
42
@ CoreFunctions (defineModule = "cmath" )
@@ -50,6 +51,7 @@ public class CmathModuleBuiltins extends PythonBuiltins {
50
51
static final double P34 = 0.75 * Math .PI ;
51
52
52
53
static final double LARGE_DOUBLE = Double .MAX_VALUE / 4.0 ; // used to avoid overflow
54
+ static final double LOG_LARGE_DOUBLE = Math .log (LARGE_DOUBLE );
53
55
static final double LN_2 = 0.6931471805599453094 ; // natural log of 2
54
56
static final double LN_10 = 2.302585092994045684 ; // natural log of 10
55
57
@@ -752,6 +754,245 @@ static AtanhNode create() {
752
754
}
753
755
}
754
756
757
+ @ Builtin (name = "exp" , minNumOfPositionalArgs = 1 )
758
+ @ GenerateNodeFactory
759
+ abstract static class ExpNode extends CmathComplexUnaryBuiltinNode {
760
+
761
+ // @formatter:off
762
+ @ CompilerDirectives .CompilationFinal (dimensions = 2 )
763
+ private static final ComplexConstant [][] SPECIAL_VALUES = {
764
+ {C (0.0 , 0.0 ), null , C (0.0 , -0.0 ), C (0.0 , 0.0 ), null , C (0.0 , 0.0 ), C (0.0 , 0.0 )},
765
+ {C (NAN , NAN ), null , null , null , null , C (NAN , NAN ), C (NAN , NAN )},
766
+ {C (NAN , NAN ), null , C (1.0 , -0.0 ), C (1.0 , 0.0 ), null , C (NAN , NAN ), C (NAN , NAN )},
767
+ {C (NAN , NAN ), null , C (1.0 , -0.0 ), C (1.0 , 0.0 ), null , C (NAN , NAN ), C (NAN , NAN )},
768
+ {C (NAN , NAN ), null , null , null , null , C (NAN , NAN ), C (NAN , NAN )},
769
+ {C (INF , NAN ), null , C (INF , -0.0 ), C (INF , 0.0 ), null , C (INF , NAN ), C (INF , NAN )},
770
+ {C (NAN , NAN ), C (NAN , NAN ), C (NAN , -0.0 ), C (NAN , 0.0 ), C (NAN , NAN ), C (NAN , NAN ), C (NAN , NAN )},
771
+ };
772
+ // @formatter:on
773
+
774
+ @ Override
775
+ PComplex compute (VirtualFrame frame , double real , double imag ) {
776
+ if (!Double .isFinite (real ) || !Double .isFinite (imag )) {
777
+ PComplex r ;
778
+ if (Double .isInfinite (real ) && Double .isFinite (imag ) && imag != 0.0 ) {
779
+ if (real > 0 ) {
780
+ r = factory ().createComplex (Math .copySign (INF , Math .cos (imag )), Math .copySign (INF , Math .sin (imag )));
781
+ } else {
782
+ r = factory ().createComplex (Math .copySign (0.0 , Math .cos (imag )), Math .copySign (0.0 , Math .sin (imag )));
783
+ }
784
+ } else {
785
+ r = specialValue (factory (), SPECIAL_VALUES , real , imag );
786
+ }
787
+ if (Double .isInfinite (imag ) && (Double .isFinite (real ) || (Double .isInfinite (real ) && real > 0 ))) {
788
+ throw raise (ValueError , ErrorMessages .MATH_DOMAIN_ERROR );
789
+ }
790
+ return r ;
791
+ }
792
+
793
+ double rreal , rimag ;
794
+ if (real > LOG_LARGE_DOUBLE ) {
795
+ double l = Math .exp (real - 1.0 );
796
+ rreal = l * Math .cos (imag ) * Math .E ;
797
+ rimag = l * Math .sin (imag ) * Math .E ;
798
+ } else {
799
+ double l = Math .exp (real );
800
+ rreal = l * Math .cos (imag );
801
+ rimag = l * Math .sin (imag );
802
+ }
803
+ if (Double .isInfinite (rreal ) || Double .isInfinite (rimag )) {
804
+ throw raise (OverflowError , ErrorMessages .MATH_RANGE_ERROR );
805
+ }
806
+ return factory ().createComplex (rreal , rimag );
807
+ }
808
+ }
809
+
810
+ @ Builtin (name = "cos" , minNumOfPositionalArgs = 1 )
811
+ @ GenerateNodeFactory
812
+ abstract static class CosNode extends CmathComplexUnaryBuiltinNode {
813
+
814
+ @ Child private CoshNode coshNode = CoshNode .create ();
815
+
816
+ @ Override
817
+ PComplex compute (VirtualFrame frame , double real , double imag ) {
818
+ return coshNode .executeComplex (frame , factory ().createComplex (-imag , real ));
819
+ }
820
+ }
821
+
822
+ @ Builtin (name = "cosh" , minNumOfPositionalArgs = 1 )
823
+ @ GenerateNodeFactory
824
+ abstract static class CoshNode extends CmathComplexUnaryBuiltinNode {
825
+
826
+ // @formatter:off
827
+ @ CompilerDirectives .CompilationFinal (dimensions = 2 )
828
+ private static final ComplexConstant [][] SPECIAL_VALUES = {
829
+ {C (INF , NAN ), null , C (INF , 0.0 ), C (INF , -0.0 ), null , C (INF , NAN ), C (INF , NAN )},
830
+ {C (NAN , NAN ), null , null , null , null , C (NAN , NAN ), C (NAN , NAN )},
831
+ {C (NAN , 0.0 ), null , C (1.0 , 0.0 ), C (1.0 , -0.0 ), null , C (NAN , 0.0 ), C (NAN , 0.0 )},
832
+ {C (NAN , 0.0 ), null , C (1.0 , -0.0 ), C (1.0 , 0.0 ), null , C (NAN , 0.0 ), C (NAN , 0.0 )},
833
+ {C (NAN , NAN ), null , null , null , null , C (NAN , NAN ), C (NAN , NAN )},
834
+ {C (INF , NAN ), null , C (INF , -0.0 ), C (INF , 0.0 ), null , C (INF , NAN ), C (INF , NAN )},
835
+ {C (NAN , NAN ), C (NAN , NAN ), C (NAN , 0.0 ), C (NAN , 0.0 ), C (NAN , NAN ), C (NAN , NAN ), C (NAN , NAN )},
836
+ };
837
+ // @formatter:on
838
+
839
+ @ Override
840
+ PComplex compute (VirtualFrame frame , double real , double imag ) {
841
+ if (!Double .isFinite (real ) || !Double .isFinite (imag )) {
842
+ if (Double .isInfinite (imag ) && !Double .isNaN (real )) {
843
+ throw raise (ValueError , ErrorMessages .MATH_DOMAIN_ERROR );
844
+ }
845
+ if (Double .isInfinite (real ) && Double .isFinite (imag ) && imag != 0.0 ) {
846
+ double r = Math .copySign (INF , Math .sin (imag ));
847
+ return factory ().createComplex (Math .copySign (INF , Math .cos (imag )), real > 0 ? r : -r );
848
+ } else {
849
+ return specialValue (factory (), SPECIAL_VALUES , real , imag );
850
+ }
851
+ }
852
+
853
+ double rreal , rimag ;
854
+ if (Math .abs (real ) > LOG_LARGE_DOUBLE ) {
855
+ double x_minus_one = real - Math .copySign (1.0 , real );
856
+ rreal = Math .cos (imag ) * Math .cosh (x_minus_one ) * Math .E ;
857
+ rimag = Math .sin (imag ) * Math .sinh (x_minus_one ) * Math .E ;
858
+ } else {
859
+ rreal = Math .cos (imag ) * Math .cosh (real );
860
+ rimag = Math .sin (imag ) * Math .sinh (real );
861
+ }
862
+ if (Double .isInfinite (rreal ) || Double .isInfinite (rimag )) {
863
+ throw raise (OverflowError , ErrorMessages .MATH_RANGE_ERROR );
864
+ }
865
+ return factory ().createComplex (rreal , rimag );
866
+ }
867
+
868
+ static CoshNode create () {
869
+ return CmathModuleBuiltinsFactory .CoshNodeFactory .create ();
870
+ }
871
+ }
872
+
873
+ @ Builtin (name = "sin" , minNumOfPositionalArgs = 1 )
874
+ @ GenerateNodeFactory
875
+ abstract static class SinNode extends CmathComplexUnaryBuiltinNode {
876
+
877
+ @ Child private SinhNode sinhNode = SinhNode .create ();
878
+
879
+ @ Override
880
+ PComplex compute (VirtualFrame frame , double real , double imag ) {
881
+ PComplex s = sinhNode .executeComplex (frame , factory ().createComplex (-imag , real ));
882
+ return factory ().createComplex (s .getImag (), -s .getReal ());
883
+ }
884
+ }
885
+
886
+ @ Builtin (name = "sinh" , minNumOfPositionalArgs = 1 )
887
+ @ GenerateNodeFactory
888
+ abstract static class SinhNode extends CmathComplexUnaryBuiltinNode {
889
+
890
+ // @formatter:off
891
+ @ CompilerDirectives .CompilationFinal (dimensions = 2 )
892
+ private static final ComplexConstant [][] SPECIAL_VALUES = {
893
+ {C (INF , NAN ), null , C (-INF , -0.0 ), C (-INF , 0.0 ), null , C (INF , NAN ), C (INF , NAN )},
894
+ {C (NAN , NAN ), null , null , null , null , C (NAN , NAN ), C (NAN , NAN )},
895
+ {C (0.0 , NAN ), null , C (-0.0 , -0.0 ), C (-0.0 , 0.0 ), null , C (0.0 , NAN ), C (0.0 , NAN )},
896
+ {C (0.0 , NAN ), null , C (0.0 , -0.0 ), C (0.0 , 0.0 ), null , C (0.0 , NAN ), C (0.0 , NAN )},
897
+ {C (NAN , NAN ), null , null , null , null , C (NAN , NAN ), C (NAN , NAN )},
898
+ {C (INF , NAN ), null , C (INF , -0.0 ), C (INF , 0.0 ), null , C (INF , NAN ), C (INF , NAN )},
899
+ {C (NAN , NAN ), C (NAN , NAN ), C (NAN , -0.0 ), C (NAN , 0.0 ), C (NAN , NAN ), C (NAN , NAN ), C (NAN , NAN )},
900
+ };
901
+ // @formatter:on
902
+
903
+ @ Override
904
+ PComplex compute (VirtualFrame frame , double real , double imag ) {
905
+ if (!Double .isFinite (real ) || !Double .isFinite (imag )) {
906
+ if (Double .isInfinite (imag ) && !Double .isNaN (real )) {
907
+ throw raise (ValueError , ErrorMessages .MATH_DOMAIN_ERROR );
908
+ }
909
+ if (Double .isInfinite (real ) && Double .isFinite (imag ) && imag != 0.0 ) {
910
+ double r = Math .copySign (INF , Math .cos (imag ));
911
+ return factory ().createComplex (real > 0 ? r : -r , Math .copySign (INF , Math .sin (imag )));
912
+ } else {
913
+ return specialValue (factory (), SPECIAL_VALUES , real , imag );
914
+ }
915
+ }
916
+
917
+ double rreal , rimag ;
918
+ if (Math .abs (real ) > LOG_LARGE_DOUBLE ) {
919
+ double x_minus_one = real - Math .copySign (1.0 , real );
920
+ rreal = Math .cos (imag ) * Math .sinh (x_minus_one ) * Math .E ;
921
+ rimag = Math .sin (imag ) * Math .cosh (x_minus_one ) * Math .E ;
922
+ } else {
923
+ rreal = Math .cos (imag ) * Math .sinh (real );
924
+ rimag = Math .sin (imag ) * Math .cosh (real );
925
+ }
926
+ if (Double .isInfinite (rreal ) || Double .isInfinite (rimag )) {
927
+ throw raise (OverflowError , ErrorMessages .MATH_RANGE_ERROR );
928
+ }
929
+ return factory ().createComplex (rreal , rimag );
930
+ }
931
+
932
+ static SinhNode create () {
933
+ return CmathModuleBuiltinsFactory .SinhNodeFactory .create ();
934
+ }
935
+ }
936
+
937
+ @ Builtin (name = "tan" , minNumOfPositionalArgs = 1 )
938
+ @ GenerateNodeFactory
939
+ abstract static class TanNode extends CmathComplexUnaryBuiltinNode {
940
+
941
+ @ Child private TanhNode tanhNode = TanhNode .create ();
942
+
943
+ @ Override
944
+ PComplex compute (VirtualFrame frame , double real , double imag ) {
945
+ PComplex s = tanhNode .executeComplex (frame , factory ().createComplex (-imag , real ));
946
+ return factory ().createComplex (s .getImag (), -s .getReal ());
947
+ }
948
+ }
949
+
950
+ @ Builtin (name = "tanh" , minNumOfPositionalArgs = 1 )
951
+ @ GenerateNodeFactory
952
+ abstract static class TanhNode extends CmathComplexUnaryBuiltinNode {
953
+
954
+ // @formatter:off
955
+ @ CompilerDirectives .CompilationFinal (dimensions = 2 )
956
+ private static final ComplexConstant [][] SPECIAL_VALUES = {
957
+ {C (-1.0 , 0.0 ), null , C (-1.0 , -0.0 ), C (-1.0 , 0.0 ), null , C (-1.0 , 0.0 ), C (-1.0 , 0.0 )},
958
+ {C (NAN , NAN ), null , null , null , null , C (NAN , NAN ), C (NAN , NAN )},
959
+ {C (NAN , NAN ), null , C (-0.0 , -0.0 ), C (-0.0 , 0.0 ), null , C (NAN , NAN ), C (NAN , NAN )},
960
+ {C (NAN , NAN ), null , C (0.0 , -0.0 ), C (0.0 , 0.0 ), null , C (NAN , NAN ), C (NAN , NAN )},
961
+ {C (NAN , NAN ), null , null , null , null , C (NAN , NAN ), C (NAN , NAN )},
962
+ {C (1.0 , 0.0 ), null , C (1.0 , -0.0 ), C (1.0 , 0.0 ), null , C (1.0 , 0.0 ), C (1.0 , 0.0 )},
963
+ {C (NAN , NAN ), C (NAN , NAN ), C (NAN , -0.0 ), C (NAN , 0.0 ), C (NAN , NAN ), C (NAN , NAN ), C (NAN , NAN )},
964
+ };
965
+ // @formatter:on
966
+
967
+ @ Override
968
+ PComplex compute (VirtualFrame frame , double real , double imag ) {
969
+ if (!Double .isFinite (real ) || !Double .isFinite (imag )) {
970
+ if (Double .isInfinite (imag ) && Double .isFinite (real )) {
971
+ throw raise (ValueError , ErrorMessages .MATH_DOMAIN_ERROR );
972
+ }
973
+ if (Double .isInfinite (real ) && Double .isFinite (imag ) && imag != 0.0 ) {
974
+ return factory ().createComplex (real > 0 ? 1.0 : -1.0 , Math .copySign (0.0 , 2.0 * Math .sin (imag ) * Math .cos (imag )));
975
+ } else {
976
+ return specialValue (factory (), SPECIAL_VALUES , real , imag );
977
+ }
978
+ }
979
+ if (Math .abs (real ) > LOG_LARGE_DOUBLE ) {
980
+ return factory ().createComplex (Math .copySign (1.0 , real ),
981
+ 4.0 * Math .sin (imag ) * Math .cos (imag ) * Math .exp (-20. * Math .abs (real )));
982
+ }
983
+ double tx = Math .tanh (real );
984
+ double ty = Math .tan (imag );
985
+ double cx = 1.0 / Math .cosh (real );
986
+ double txty = tx * ty ;
987
+ double denom = 1.0 + txty * txty ;
988
+ return factory ().createComplex (tx * (1.0 + ty * ty ) / denom , ((ty / denom ) * cx ) * cx );
989
+ }
990
+
991
+ static TanhNode create () {
992
+ return CmathModuleBuiltinsFactory .TanhNodeFactory .create ();
993
+ }
994
+ }
995
+
755
996
@ Builtin (name = "isclose" , minNumOfPositionalArgs = 2 , maxNumOfPositionalArgs = 2 , keywordOnlyNames = {"rel_tol" , "abs_tol" })
756
997
@ TypeSystemReference (PythonArithmeticTypes .class )
757
998
@ ImportStatic (MathGuards .class )
0 commit comments