Click here to Skip to main content
Click here to Skip to main content
Technical Blog

Very Fast Sin Function for Java

, 3 Dec 2012 CPOL
Rate this:
Please Sign up or sign in to vote.
A very fast Sin function for Java.
Shedding some light on high performance.

Copyright: Dr Alexander J Turner - all rights reserved.

Math.sin and the other transcendental functions in the JDKs java.lang.Math package tend to be very slow indeed. There are fast workarounds however.

The reason for the slowness is consistence. The library is designed to produce exactly the same results on all platforms. The results are standards compliant to the last binary bit. This just great if that is what you need. However, for some applications, like audio synthesis for example, it is total over kill.

In DSP outboard processors, wavetables have been used for years. The idea being that you pre-compute a set of values for a wave against phase angle. Then, when a value is required, its offset into the pre-computed table is used to get the value straight away. Sonic-Field stores audio at float (32 bit floating point) precision. A table big enough to hold all the possible values for the sin function where the phase angle is a float is way to big to be practical. It turns out that we really do not require anything like as big a table as that. A relatively modest table with linear interpolation gives results which are within float rounding error of the Math.sin values. The results are plenty good enough for audio work:

static double[]             table = null;
static double               step;
static double               invStep;
static int                  size  = 0;

static
{
    size = 10000;
    table = new double[size];
    step = 2d * Math.PI / size;
    invStep = 1.0f / step;
    for (int i = 0; i < size; ++i)
    {
        table[i] = Math.sin(step * i);
    }
}

/** Find a linear interpolation from the table
 * 
 * @param ang
 *            angle in radians
 * @return sin of angle a
 */
private final static double pi2   = PI * 2;

final public static double sin(double ang)
{
    double t = ang % pi2;
    int indexA = (int) (t / step);
    int indexB = indexA + 1;
    if (indexB >= size) return table[indexA];
    double a = table[indexA];
    return a + (table[indexB] - a) * (t - (indexA * step)) * invStep;
}

The above code is straight from Sonic Field (and is therefore AGPL v3.0). It creates a 10 thousand element table. I tried a bigger table but it did not improve the results noticeably though less did degrade the accuracy rapidly. I have not micro-benchmarked the code, but Sonic Field patches using this code show the functions using sin running up to 10 times faster than using the Math.sin function.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

alex turner
Web Developer
United Kingdom United Kingdom
I am now a Software Systems Developer - Senior Principal at Micro Focus Plc. I am honoured to work in a team developing new compiler and runtime technology for Micro Focus.
 
My past includes a Ph.D. in computational quantum mechanics, software consultancy and several/various software development and architecture positions.
 
For more - see
 
blog: http://nerds-central.blogspot.com
 
twitter: http://twitter.com/alexturner

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.141223.1 | Last Updated 3 Dec 2012
Article Copyright 2012 by alex turner
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid