Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: 32-bit fp implementation of Math.sqrt()

The standard Math.sqrt() method seems pretty fast in Java already, but it has the inherent drawback that it is always going to involve 64-bit operations which does nothing but reduce speed when dealing with 32-bit float values. Is it possible to do better with a custom method that uses a float as a parameter, performs 32-bit operations only, and returns a float as a result?

I saw:

Fast sqrt in Java at the expense of accuracy

and it did little more than reinforce the notion that Math.sqrt() is generally hard-to-beat. I also saw:

http://www.codeproject.com/Articles/69941/Best-Square-Root-Method-Algorithm-Function-Precisi

which showed me a bunch of interesting C++/ASM hacks that I am simply too ignorant to port directly to Java. Though sqrt14 might be interesting as a part of a JNI call . . .

I also looked at Apache Commons FastMath, but it looks like that library defaults to the standard Math.sqrt() so no help there. And then there's Yeppp!:

http://www.yeppp.info/

but I haven't bothered with that yet.

like image 619
user3765373 Avatar asked Jun 11 '15 08:06

user3765373


People also ask

How is sqrt implemented in Java?

Math. sqrt() returns the square root of a value of type double passed to it as argument. If the argument is NaN or negative, then the result is NaN. If the argument is positive infinity, then the result is positive infinity.

What is the time complexity of math sqrt?

Time Complexity: O(√ n).

How do you write a math square in Java?

1) Java: Square a number by multiplying it by itself int i = 2; int square = i * i; In this example if you print the value of square , it will be 4.


1 Answers

You need nothing to speed up sqrt for 32-bit values. HotSpot JVM does it automatically for you.

JIT compiler is smart enough to recognize f2d -> Math.sqrt() -> d2f pattern and replace it with faster sqrtss CPU instruction instead of sqrtsd. The source.

The benchmark:

@State(Scope.Benchmark)
public class Sqrt {
    double d = Math.random();
    float f = (float) d;

    @Benchmark
    public double sqrtD() {
        return Math.sqrt(d);
    }

    @Benchmark
    public float sqrtF() {
        return (float) Math.sqrt(f);
    }
}

And the results:

Benchmark    Mode  Cnt       Score      Error   Units
Sqrt.sqrtD  thrpt    5  145501,072 ± 2211,666  ops/ms
Sqrt.sqrtF  thrpt    5  223657,110 ± 2268,735  ops/ms
like image 131
apangin Avatar answered Nov 28 '22 16:11

apangin