Мне было интересно, есть ли способ получить доступ к собственному коду для класса Math. В частности, мне нужно увидеть код для метода sin().
Собственный код для Java Math class
Ответ 1
Это зависит от реализации. Как указано в документации для java.lang.Math
:
В отличие от некоторых числовых методов класса
StrictMath
, все реализации эквивалентных функций классаMath
не определены, чтобы возвращать бит-бит для одинаковых результатов. Эта релаксация позволяет выполнять более эффективные реализации, где не требуется строгая воспроизводимость.... Генераторам кода рекомендуется использовать встроенные библиотеки для конкретных платформ или инструкции для микропроцессора, если они доступны, для обеспечения более высокопроизводительных реализаций методов
Math
. Такие высокопроизводительные реализации по-прежнему должны соответствовать спецификации дляMath
.
Для Dalvik (реализация Java для Java):
Dalvik/VM/InlineNative.c
/*
* public static double sin(double)
*/
static bool javaLangMath_sin(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
JValue* pResult)
{
Convert64 convert;
convert.arg[0] = arg0;
convert.arg[1] = arg1;
pResult->d = sin(convert.dd);
return true;
}
Таким образом, он вызывает функцию libm
sin
, которая на Android предоставляется bionic libc. Это выглядит как
бионическая /libm/SRC/s _sin.c
double
sin(double x)
{
double y[2],z=0.0;
int32_t n, ix;
/* High word of x. */
GET_HIGH_WORD(ix,x);
/* |x| ~< pi/4 */
ix &= 0x7fffffff;
if(ix <= 0x3fe921fb) {
if(ix<0x3e400000) /* |x| < 2**-27 */
{if((int)x==0) return x;} /* generate inexact */
return __kernel_sin(x,z,0);
}
/* sin(Inf or NaN) is NaN */
else if (ix>=0x7ff00000) return x-x;
/* argument reduction needed */
else {
n = __ieee754_rem_pio2(x,y);
switch(n&3) {
case 0: return __kernel_sin(y[0],y[1],1);
case 1: return __kernel_cos(y[0],y[1]);
case 2: return -__kernel_sin(y[0],y[1],1);
default:
return -__kernel_cos(y[0],y[1]);
}
}
}
а реализация __kernel_sin
выглядит как
бионическая /libm/SRC/k _sin.c
static const double
half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
S1 = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */
S2 = 8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */
S3 = -1.98412698298579493134e-04, /* 0xBF2A01A0, 0x19C161D5 */
S4 = 2.75573137070700676789e-06, /* 0x3EC71DE3, 0x57B1FE7D */
S5 = -2.50507602534068634195e-08, /* 0xBE5AE5E6, 0x8A2B9CEB */
S6 = 1.58969099521155010221e-10; /* 0x3DE5D93A, 0x5ACFD57C */
double
__kernel_sin(double x, double y, int iy)
{
double z,r,v;
z = x*x;
v = z*x;
r = S2+z*(S3+z*(S4+z*(S5+z*S6)));
if(iy==0) return x+v*(S1+z*r);
else return x-((z*(half*y-v*r)-y)-v*S1);
}
__kernel_cos
аналогичен.