The unexpected complexity of Java's Math.pow

Tags: java, programming, code, jdk,

Added: 2025-09-14T00:00

The unexpected complexity of Java's Math.pow

How much code do you think it takes to calculate the power of a number? Say 6^3? (216)
Can't be hard.

Just loop around twice, multiplying 6 by 6, right?

OK, it might be harder with negative numbers - 6 ^ -4
Oh, and with decimals - 6 ^ 2.7
And negative decimals - 6 ^ -2.7

Anyway, surely it shouldn't be too hard. Maybe 100 lines of code, or something.

I forget why, but I ended up following Java's Math.pow method down through the call hierarchy, and boy was I shocked. If you don't have an IDE around, here is what it does:

Math.pow calls StrictMath.pow, which calls FdLibm.Pow.compute, which contains 248 lines. And that's not including the contents of the other methods it calls:

compute(double, double) in Pow in FdLibm
  Double.isNaN(double) (2 usages)
  Math.abs(double) (2 usages)
  Math.sqrt(double)
  FdLibm.__HI(double) (5 usages)
    Double.doubleToRawLongBits(double)
  FdLibm.__LO(double, int) (7 usages)
    Double.doubleToRawLongBits(double)
    Double.longBitsToDouble(long)
  FdLibm.__HI(double, int) (4 usages)
    Double.doubleToRawLongBits(double)
    Double.longBitsToDouble(long)
  FdLibm.__LO(double)
    Double.doubleToRawLongBits(double)
  Math.scalb(double, int)
Lots of magic numbers in there, and short, non-descriptive variable names. Yum. I mean - what are these?
// Poly coefs for (3/2)*(log(x)-2s-2/3*s**3
                final double L1      =  0x1.3333_3333_33303p-1;  //  5.99999999999994648725e-01
                final double L2      =  0x1.b6db_6db6_fabffp-2;  //  4.28571428578550184252e-01
                final double L3      =  0x1.5555_5518_f264dp-2;  //  3.33333329818377432918e-01
                final double L4      =  0x1.1746_0a91_d4101p-2;  //  2.72728123808534006489e-01
                final double L5      =  0x1.d864_a93c_9db65p-3;  //  2.30660745775561754067e-01
                final double L6      =  0x1.a7e2_84a4_54eefp-3;  //  2.06975017800338417784e-01
I'm sure it all makes sense to mathematicians.

So it turns out that it's quite a lot more involved than you might expect.

I think this is a classic case that shows that optimising almost always makes code less readable.
Although in this case, it's so widely used that the optimisations are worth it.

It's made me wonder though - what is the longest method in the Java JDK, and are there any methods that are harder to understand? I asked Google Gemini, and it suggested that ConcurrentHashMap.transfer was also pretty complex, due to migrating shared state across many threads without blocking.
Add a comment

Your IP:
Please enter 8291523 here: