2013-02-20 14 views
11

Zastanawiam się, czy jest jakikolwiek sposób uzyskania dostępu do kodu natywnego dla klasy Math. Dokładniej muszę zobaczyć kod metody sin().kod macierzysty dla klasy Java Math

+0

Czy chcesz dekompilator? – EAKAE

+0

Nie. Chcę stworzyć własną metodę sinusoidalną i wierzę, że wiedza, jak działa metoda klasy matematycznej, pomogłaby. – user2089351

Odpowiedz

17

Jest to zależne od wdrożenia. Jak podano w dokumentacji dla java.lang.Math:

przeciwieństwie do niektórych metod numerycznych klasy StrictMath, wszystkich implementacjach równoważnych funkcjach klasy Math nie są zdefiniowane, aby przywrócić bit-for-bit same wyniki. To rozluźnienie pozwala na lepsze wykonywanie implementacji, w których ścisła powtarzalność nie jest wymagana.

... Zaleca się, aby generatory kodów korzystały z bibliotek natywnych specyficznych dla platformy lub instrukcji mikroprocesora, o ile są dostępne, w celu zapewnienia lepszych implementacji metod Math. Takie rozwiązania o wyższej wydajności nadal muszą być zgodne ze specyfikacją dla Math.

Dla Dalvik (Android implementacji Javy):

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

Więc to wywołuje funkcję libmsin, który na Androida jest dostarczany przez bioniczny libc. Że wygląda

Bionic/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]); 
     } 
    } 
} 

i realizacja __kernel_sin wygląda jak

Bionic/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 jest podobna.

+0

...? po co to jest? – nneonneo

+0

Zostałem również odrzucony. jakiś idiota tutaj. – AlexWien