13
13
import com .oracle .graal .python .builtins .objects .tuple .PTuple ;
14
14
import com .oracle .graal .python .nodes .ErrorMessages ;
15
15
import com .oracle .graal .python .nodes .function .PythonBuiltinBaseNode ;
16
+ import com .oracle .graal .python .nodes .function .builtins .PythonBinaryBuiltinNode ;
16
17
import com .oracle .graal .python .nodes .function .builtins .PythonUnaryBuiltinNode ;
17
18
import com .oracle .graal .python .nodes .truffle .PythonArithmeticTypes ;
18
19
import com .oracle .graal .python .nodes .util .CoerceToComplexNode ;
20
+ import com .oracle .graal .python .nodes .util .CoerceToDoubleNode ;
19
21
import com .oracle .graal .python .runtime .PythonCore ;
22
+ import com .oracle .graal .python .runtime .object .PythonObjectFactory ;
20
23
import com .oracle .truffle .api .CompilerDirectives ;
21
24
import com .oracle .truffle .api .dsl .Cached ;
22
25
import com .oracle .truffle .api .dsl .GenerateNodeFactory ;
28
31
29
32
import java .util .List ;
30
33
34
+ import static com .oracle .graal .python .runtime .exception .PythonErrorType .ValueError ;
35
+
31
36
@ CoreFunctions (defineModule = "cmath" )
32
37
public class CmathModuleBuiltins extends PythonBuiltins {
33
38
39
+ // Constants used for the definition of special values tables in node classes
40
+ static final double INF = Double .POSITIVE_INFINITY ;
41
+ static final double NAN = Double .NaN ;
42
+
34
43
@ Override
35
44
protected List <? extends NodeFactory <? extends PythonBuiltinBaseNode >> getNodeFactories () {
36
45
return CmathModuleBuiltinsFactory .getFactories ();
@@ -49,84 +58,79 @@ public void initialize(PythonCore core) {
49
58
super .initialize (core );
50
59
}
51
60
52
- @ TypeSystemReference (PythonArithmeticTypes .class )
53
- @ ImportStatic (MathGuards .class )
54
- abstract static class CmathComplexUnaryBuiltinNode extends PythonUnaryBuiltinNode {
61
+ static PComplex specialValue (PythonObjectFactory factory , ComplexConstant [][] table , double real , double imag ) {
62
+ if (!Double .isFinite (real ) || !Double .isFinite (imag )) {
63
+ ComplexConstant c = table [SpecialType .ofDouble (real ).ordinal ()][SpecialType .ofDouble (imag ).ordinal ()];
64
+ if (c == null ) {
65
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
66
+ throw new IllegalStateException ("should not be reached" );
67
+ }
68
+ return factory .createComplex (c .real , c .imag );
69
+ }
70
+ return null ;
71
+ }
55
72
56
- // Constants used for the definition of special values tables in subclassess
57
- static final double INF = Double .POSITIVE_INFINITY ;
58
- static final double NAN = Double .NaN ;
73
+ /**
74
+ * Creates an instance of ComplexConstant. The name of this factory method is intentionally
75
+ * short to allow nested classess compact definition of their tables of special values.
76
+ *
77
+ * @param real the real part of the complex constant
78
+ * @param imag the imaginary part of the complex constant
79
+ * @return a new instance of ComplexConstant representing the complex number real + i * imag
80
+ */
81
+ static ComplexConstant C (double real , double imag ) {
82
+ return new ComplexConstant (real , imag );
83
+ }
59
84
60
- protected static class ComplexConstant {
61
- final double real ;
62
- final double imag ;
85
+ static class ComplexConstant {
86
+ final double real ;
87
+ final double imag ;
63
88
64
- ComplexConstant (double real , double imag ) {
65
- this .real = real ;
66
- this .imag = imag ;
67
- }
89
+ ComplexConstant (double real , double imag ) {
90
+ this .real = real ;
91
+ this .imag = imag ;
68
92
}
93
+ }
69
94
70
- private enum SpecialType {
71
- NINF , // 0, negative infinity
72
- NEG , // 1, negative finite number (nonzero)
73
- NZERO , // 2, -0.0
74
- PZERO , // 3, +0.0
75
- POS , // 4, positive finite number (nonzero)
76
- PINF , // 5, positive infinity
77
- NAN ; // 6, Not a Number
78
-
79
- static SpecialType ofDouble (double d ) {
80
- if (Double .isFinite (d )) {
81
- if (d != 0 ) {
82
- if (Math .copySign (1.0 , d ) == 1.0 ) {
83
- return POS ;
84
- } else {
85
- return NEG ;
86
- }
95
+ enum SpecialType {
96
+ NINF , // 0, negative infinity
97
+ NEG , // 1, negative finite number (nonzero)
98
+ NZERO , // 2, -0.0
99
+ PZERO , // 3, +0.0
100
+ POS , // 4, positive finite number (nonzero)
101
+ PINF , // 5, positive infinity
102
+ NAN ; // 6, Not a Number
103
+
104
+ static SpecialType ofDouble (double d ) {
105
+ if (Double .isFinite (d )) {
106
+ if (d != 0 ) {
107
+ if (Math .copySign (1.0 , d ) == 1.0 ) {
108
+ return POS ;
87
109
} else {
88
- if (Math .copySign (1.0 , d ) == 1.0 ) {
89
- return PZERO ;
90
- } else {
91
- return NZERO ;
92
- }
110
+ return NEG ;
93
111
}
94
- }
95
- if (Double .isNaN (d )) {
96
- return NAN ;
97
- }
98
- if (Math .copySign (1.0 , d ) == 1.0 ) {
99
- return PINF ;
100
112
} else {
101
- return NINF ;
113
+ if (Math .copySign (1.0 , d ) == 1.0 ) {
114
+ return PZERO ;
115
+ } else {
116
+ return NZERO ;
117
+ }
102
118
}
103
119
}
104
- }
105
-
106
- protected PComplex specialValue (ComplexConstant [][] table , double real , double imag ) {
107
- if (!Double .isFinite (real ) || !Double .isFinite (imag )) {
108
- ComplexConstant c = table [SpecialType .ofDouble (real ).ordinal ()][SpecialType .ofDouble (imag ).ordinal ()];
109
- if (c == null ) {
110
- CompilerDirectives .transferToInterpreterAndInvalidate ();
111
- throw new IllegalStateException ("should not be reached" );
112
- }
113
- return factory ().createComplex (c .real , c .imag );
120
+ if (Double .isNaN (d )) {
121
+ return NAN ;
122
+ }
123
+ if (Math .copySign (1.0 , d ) == 1.0 ) {
124
+ return PINF ;
125
+ } else {
126
+ return NINF ;
114
127
}
115
- return null ;
116
- }
117
-
118
- /**
119
- * Creates an instance of ComplexConstant. The name of this factory method is intentionally
120
- * short to allow subclassess compact definition of their tables of special values.
121
- *
122
- * @param real the real part of the complex constant
123
- * @param imag the imaginary part of the complex constant
124
- * @return a new instance of ComplexConstant representing the complex number real + i * imag
125
- */
126
- protected static ComplexConstant C (double real , double imag ) {
127
- return new ComplexConstant (real , imag );
128
128
}
129
+ }
129
130
131
+ @ TypeSystemReference (PythonArithmeticTypes .class )
132
+ @ ImportStatic (MathGuards .class )
133
+ abstract static class CmathComplexUnaryBuiltinNode extends PythonUnaryBuiltinNode {
130
134
PComplex compute (@ SuppressWarnings ("unused" ) double real , @ SuppressWarnings ("unused" ) double imag ) {
131
135
CompilerDirectives .transferToInterpreterAndInvalidate ();
132
136
throw new IllegalStateException ("should not be reached" );
@@ -270,6 +274,78 @@ private PTuple toPolar(PComplex value, ComplexBuiltins.AbsNode absNode) {
270
274
}
271
275
}
272
276
277
+ @ Builtin (name = "rect" , minNumOfPositionalArgs = 2 )
278
+ @ TypeSystemReference (PythonArithmeticTypes .class )
279
+ @ ImportStatic (MathGuards .class )
280
+ @ GenerateNodeFactory
281
+ abstract static class RectNode extends PythonBinaryBuiltinNode {
282
+
283
+ // @formatter:off
284
+ @ CompilerDirectives .CompilationFinal (dimensions = 2 )
285
+ private static final ComplexConstant [][] SPECIAL_VALUES = {
286
+ {C (INF , NAN ), null , C (-INF , 0.0 ), C (-INF , -0.0 ), null , C (INF , NAN ), C (INF , NAN )},
287
+ {C (NAN , NAN ), null , null , null , null , C (NAN , NAN ), C (NAN , NAN )},
288
+ {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 )},
289
+ {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 )},
290
+ {C (NAN , NAN ), null , null , null , null , C (NAN , NAN ), C (NAN , NAN )},
291
+ {C (INF , NAN ), null , C (INF , -0.0 ), C (INF , 0.0 ), null , C (INF , NAN ), C (INF , NAN )},
292
+ {C (NAN , NAN ), C (NAN , NAN ), C (NAN , 0.0 ), C (NAN , 0.0 ), C (NAN , NAN ), C (NAN , NAN ), C (NAN , NAN )},
293
+ };
294
+ // @formatter:on
295
+
296
+ @ Specialization
297
+ PComplex doLL (long r , long phi ) {
298
+ return rect (r , phi );
299
+ }
300
+
301
+ @ Specialization
302
+ PComplex doLD (long r , double phi ) {
303
+ return rect (r , phi );
304
+ }
305
+
306
+ @ Specialization
307
+ PComplex doDL (double r , long phi ) {
308
+ return rect (r , phi );
309
+ }
310
+
311
+ @ Specialization
312
+ PComplex doDD (double r , double phi ) {
313
+ return rect (r , phi );
314
+ }
315
+
316
+ @ Specialization
317
+ PComplex doGeneral (VirtualFrame frame , Object r , Object phi ,
318
+ @ Cached CoerceToDoubleNode coerceRToDouble ,
319
+ @ Cached CoerceToDoubleNode coercePhiToDouble ) {
320
+ return rect (coerceRToDouble .execute (frame , r ), coercePhiToDouble .execute (frame , phi ));
321
+ }
322
+
323
+ private PComplex rect (double r , double phi ) {
324
+ // deal with special values
325
+ if (!Double .isFinite (r ) || !Double .isFinite (phi )) {
326
+ // need to raise an exception if r is a nonzero number and phi is infinite
327
+ if (r != 0.0 && !Double .isNaN (r ) && Double .isInfinite (phi )) {
328
+ throw raise (ValueError , "math domain error" );
329
+ }
330
+
331
+ // if r is +/-infinity and phi is finite but nonzero then
332
+ // result is (+-INF +-INF i), but we need to compute cos(phi)
333
+ // and sin(phi) to figure out the signs.
334
+ if (Double .isInfinite (r ) && Double .isFinite (phi ) && phi != 0.0 ) {
335
+ double real = Math .copySign (Double .POSITIVE_INFINITY , Math .cos (phi ));
336
+ double imag = Math .copySign (Double .POSITIVE_INFINITY , Math .sin (phi ));
337
+ if (r > 0 ) {
338
+ return factory ().createComplex (real , imag );
339
+ } else {
340
+ return factory ().createComplex (-real , -imag );
341
+ }
342
+ }
343
+ return specialValue (factory (), SPECIAL_VALUES , r , phi );
344
+ }
345
+ return factory ().createComplex (r * Math .cos (phi ), r * Math .sin (phi ));
346
+ }
347
+ }
348
+
273
349
@ Builtin (name = "sqrt" , minNumOfPositionalArgs = 1 )
274
350
@ GenerateNodeFactory
275
351
abstract static class SqrtNode extends CmathComplexUnaryBuiltinNode {
@@ -289,7 +365,7 @@ abstract static class SqrtNode extends CmathComplexUnaryBuiltinNode {
289
365
290
366
@ Override
291
367
PComplex compute (double real , double imag ) {
292
- PComplex result = specialValue (SPECIAL_VALUES , real , imag );
368
+ PComplex result = specialValue (factory (), SPECIAL_VALUES , real , imag );
293
369
if (result != null ) {
294
370
return result ;
295
371
}
0 commit comments