Skip to content

Commit 0c2acef

Browse files
committed
Implementation of cmath.log
1 parent 0783391 commit 0c2acef

File tree

2 files changed

+94
-1
lines changed

2 files changed

+94
-1
lines changed

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

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import com.oracle.graal.python.builtins.Builtin;
99
import com.oracle.graal.python.builtins.CoreFunctions;
1010
import com.oracle.graal.python.builtins.PythonBuiltins;
11+
import com.oracle.graal.python.builtins.objects.PNone;
1112
import com.oracle.graal.python.builtins.objects.complex.ComplexBuiltins;
1213
import com.oracle.graal.python.builtins.objects.complex.PComplex;
1314
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
@@ -39,6 +40,13 @@ public class CmathModuleBuiltins extends PythonBuiltins {
3940
// Constants used for the definition of special values tables in node classes
4041
static final double INF = Double.POSITIVE_INFINITY;
4142
static final double NAN = Double.NaN;
43+
static final double P = Math.PI;
44+
static final double P14 = 0.25 * Math.PI;
45+
static final double P12 = 0.5 * Math.PI;
46+
static final double P34 = 0.75 * Math.PI;
47+
48+
static final double largeDouble = Double.MAX_VALUE / 4.0; // used to avoid overflow
49+
static final double ln2 = 0.6931471805599453094; // natural log of 2
4250

4351
@Override
4452
protected List<? extends NodeFactory<? extends PythonBuiltinBaseNode>> getNodeFactories() {
@@ -346,6 +354,83 @@ private PComplex rect(double r, double phi) {
346354
}
347355
}
348356

357+
@Builtin(name = "log", minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2)
358+
@TypeSystemReference(PythonArithmeticTypes.class)
359+
@ImportStatic(MathGuards.class)
360+
@GenerateNodeFactory
361+
abstract static class LogNode extends PythonBinaryBuiltinNode {
362+
363+
// @formatter:off
364+
@CompilerDirectives.CompilationFinal(dimensions = 2)
365+
private static final ComplexConstant[][] SPECIAL_VALUES = {
366+
{C(INF, -P34), C(INF, -P), C(INF, -P), C(INF, P), C(INF, P), C(INF, P34), C(INF, NAN)},
367+
{C(INF, -P12), null, null, null, null, C(INF, P12), C(NAN, NAN)},
368+
{C(INF, -P12), null, C(-INF, -P), C(-INF, P), null, C(INF, P12), C(NAN, NAN)},
369+
{C(INF, -P12), null, C(-INF, -0.0), C(-INF, 0.0), null, C(INF, P12), C(NAN, NAN)},
370+
{C(INF, -P12), null, null, null, null, C(INF, P12), C(NAN, NAN)},
371+
{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)},
372+
{C(INF, NAN), C(NAN, NAN), C(NAN, NAN), C(NAN, NAN), C(NAN, NAN), C(INF, NAN), C(NAN, NAN)},
373+
};
374+
// @formatter:on
375+
376+
@Specialization(guards = "isNoValue(y)")
377+
PComplex doComplexNone(PComplex x, @SuppressWarnings("unused") PNone y) {
378+
return log(x);
379+
}
380+
381+
@Specialization
382+
PComplex doComplexComplex(VirtualFrame frame, PComplex x, PComplex y, @Cached ComplexBuiltins.DivNode divNode) {
383+
return divNode.executeComplex(frame, log(x), log(y));
384+
}
385+
386+
@Specialization(guards = "isNoValue(yObj)")
387+
PComplex doGeneral(VirtualFrame frame, Object xObj, @SuppressWarnings("unused") PNone yObj,
388+
@Cached CoerceToComplexNode coerceXToComplex) {
389+
return log(coerceXToComplex.execute(frame, xObj));
390+
}
391+
392+
@Specialization(guards = "!isNoValue(yObj)")
393+
PComplex doGeneral(VirtualFrame frame, Object xObj, Object yObj, @Cached CoerceToComplexNode coerceXToComplex,
394+
@Cached CoerceToComplexNode coerceYToComplex, @Cached ComplexBuiltins.DivNode divNode) {
395+
PComplex x = log(coerceXToComplex.execute(frame, xObj));
396+
PComplex y = log(coerceYToComplex.execute(frame, yObj));
397+
return divNode.executeComplex(frame, x, y);
398+
}
399+
400+
private PComplex log(PComplex z) {
401+
PComplex r = specialValue(factory(), SPECIAL_VALUES, z.getReal(), z.getImag());
402+
if (r != null) {
403+
return r;
404+
}
405+
double real = computeRealPart(z.getReal(), z.getImag());
406+
double imag = Math.atan2(z.getImag(), z.getReal());
407+
return factory().createComplex(real, imag);
408+
}
409+
410+
private double computeRealPart(double real, double imag) {
411+
double ax = Math.abs(real);
412+
double ay = Math.abs(imag);
413+
414+
if (ax > largeDouble || ay > largeDouble) {
415+
return Math.log(Math.hypot(ax / 2.0, ay / 2.0)) + ln2;
416+
}
417+
if (ax < Double.MIN_NORMAL && ay < Double.MIN_NORMAL) {
418+
if (ax > 0.0 || ay > 0.0) {
419+
final double scaleUp = 0x1.0p53;
420+
return Math.log(Math.hypot(ax * scaleUp, ay * scaleUp)) - 53 * ln2;
421+
}
422+
throw raise(ValueError, "math domain error");
423+
}
424+
double h = Math.hypot(ax, ay);
425+
if (0.71 <= h && h <= 1.73) {
426+
double am = Math.max(ax, ay);
427+
double an = Math.min(ax, ay);
428+
return Math.log1p((am - 1) * (am + 1) + an * an) / 2.0;
429+
}
430+
return Math.log(h);
431+
}
432+
}
433+
349434
@Builtin(name = "sqrt", minNumOfPositionalArgs = 1)
350435
@GenerateNodeFactory
351436
abstract static class SqrtNode extends CmathComplexUnaryBuiltinNode {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/complex/ComplexBuiltins.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@
8888
import com.oracle.truffle.api.dsl.NodeFactory;
8989
import com.oracle.truffle.api.dsl.Specialization;
9090
import com.oracle.truffle.api.dsl.TypeSystemReference;
91+
import com.oracle.truffle.api.frame.VirtualFrame;
9192
import com.oracle.truffle.api.profiles.ConditionProfile;
9293

9394
@CoreFunctions(extendClasses = PythonBuiltinClassType.PComplex)
@@ -166,7 +167,14 @@ abstract static class RAddNode extends AddNode {
166167
@GenerateNodeFactory
167168
@Builtin(name = __TRUEDIV__, minNumOfPositionalArgs = 2)
168169
@TypeSystemReference(PythonArithmeticTypes.class)
169-
abstract static class DivNode extends PythonBinaryBuiltinNode {
170+
public abstract static class DivNode extends PythonBinaryBuiltinNode {
171+
172+
public abstract PComplex executeComplex(VirtualFrame frame, Object left, Object right);
173+
174+
public static DivNode create() {
175+
return ComplexBuiltinsFactory.DivNodeFactory.create();
176+
}
177+
170178
@Specialization
171179
PComplex doComplexDouble(PComplex left, double right) {
172180
double opNormSq = right * right;

0 commit comments

Comments
 (0)