tags:

views:

98

answers:

3

I am making some approximation functions for exp, log, and sqrt in C for java. I'm a little rusty on how pointers work -- is this grammar correct?

#include <math.h>
#include "QDMath.h"

JNIEXPORT jdouble JNICALL Java_QDMath_exp
  (JNIEnv *env, jclass class, jdouble val)
{
    jint tmp = (jint) (1512775 * val + 1072632447);
    jdouble p = 0.0;
    *(1 + (jint * ) &p) = tmp;
    return p;
}

JNIEXPORT jdouble JNICALL Java_QDMath_log
  (JNIEnv *env, jclass class, jdouble val)
{
    jint tmp = (*(1 + (jint *) &val));
    jdouble p = ((jdouble) tmp - 1072632447) / 1512775;
    return p;
}

JNIEXPORT jdouble JNICALL Java_QDMath_sqrt
  (JNIEnv *env, jclass class, jdouble val)
{
    jlong tmp = ((*(jlong *) &val) - 1065353216)>>1;
    return *(jdouble *) &tmp;
}
A: 

Pointer syntax looks correct.

Alexandre C.
+4  A: 

At a glance, the syntax looks correct (although a compiler would tell you quicker than we can).

However, what you're doing with them looks pretty grim. Reinterpreting doubles as ints is platform dependent (think endianness and sizeof issues), and will also fall foul of "strict aliasing" rules.

Oli Charlesworth
Moreover, some of those calculations can produce floating-point values too large for an int to hold, thereby invoking undefined behavior. These functions are very implementation-specific, assuming they work at all.
David Thornley
http://cnl.salk.edu/~schraudo/pubs/Schraudolph99.pdf is the source of the exp and log functionshttp://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Approximations_that_depend_on_IEEE_representation explains sqrt
ShahQermez
I would personally guard all code like this with some aggressive compile time assertions that validate that the target floats have the representation they depend on. The big scary guards will alert a future code reviewer that yes it is magic, and that you did think about where the magic will be effective. Remember, that reviewer might be you, five years from now. Also, stuff in some comments pointing at references that explain how and why it works. Your future self will be less likely to want to time travel to beat sense into your head that way ;-)
RBerteig
+2  A: 

In general this looks very wrong and raised some red flags for me, but you might be OK.

The use of the Java types is helping. If you were casting to an int, you would have problems on some machines because ints might be 32-bit or 64-bit. Using jint, it should always be 32-bit, so in that respect you are safe.

I'm still not entirely clear what you are attempting. For example, this line:

*(1 + (jint * ) &p) = tmp;

What you are saying to do is to take the address of p ( a double ), treat it as an Java integer address, and then add one to it. This would mean to take the location of the double and look 4 bytes into it... putting you somewhere in the fractional part of the IEEE encoded double.

Then you are setting that location to the value in tmp... which is an integer and not IEEE encoded.

Unless you are doing something incredibly clever by manipulating the bits of the double directly, what you are doing will produce meaningless results.

Chris Arguin
This sort of thing looks a lot like the old "inverse square root" trick: http://en.wikipedia.org/wiki/Fast_inverse_square_root. Grim.
Oli Charlesworth
My guess is that `jint` would be a Java `int`, which is four bytes. However, I don't know of any format that has exponent and mantissa each occupying four bytes (put the sign bit where you will).
David Thornley
Good call on the jints... I had forgotten that the JDK would ensure those were sized to match the fixed Java specification. I've updated accordingly.
Chris Arguin