Подтвердить что ты не робот

Собственный код для Java Math class

Мне было интересно, есть ли способ получить доступ к собственному коду для класса Math. В частности, мне нужно увидеть код для метода sin().

4b9b3361

Ответ 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 аналогичен.