C近似函数

时间:2010-09-09 20:27:00

标签: java c java-native-interface

我正在为Java中的exp,log和sqrt制作一些近似函数。关于指针如何工作我有点生疏 - 这个语法是否正确?

#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;
}

2 个答案:

答案 0 :(得分:5)

一目了然,语法看起来是正确的(尽管编译器会告诉你比我们更快)。

然而,你在做什么看起来非常严峻。将double重新解释为int s取决于平台(认为字节顺序和sizeof问题),并且还会违反“严格别名”规则。

答案 1 :(得分:2)

一般来说,这看起来非常错误,并为我提出了一些危险信号,但你可能没问题。

使用Java类型有所帮助。如果您要转换为int,则在某些计算机上会出现问题,因为ints可能是32位或64位。使用jint,它应该始终是32位,所以在这方面你是安全的。

我还不完全清楚你在尝试什么。例如,这一行:

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

你要说的是取p(双精度)的地址,把它当作Java整数地址,然后加一个。这意味着获取double的位置并将4个字节放入其中...将您放在IEEE encoded double的小数部分。

然后,您将该位置设置为tmp中的值...这是一个整数而不是IEEE编码。

除非你通过直接操纵双重位来做某事incredibly clever,否则你所做的将会产生毫无意义的结果。