2009-05-05 12 views
14

मुझे पता है कि Math.sqrt कहते हैं StrictMath.sqrt (डबल ए) मैं इसकी गणना करने के लिए उपयोग किए गए वास्तविक कोड को देखना चाहता था।जावा के स्क्वायर रूट फ़ंक्शन के लिए मुझे स्रोत कोड कहां मिल सकता है?

+0

मैंने सोचा कि इंटेल के पास एक वर्ग निर्देश था - क्या यह सच नहीं है? – Marichyasana

उत्तर

0

ओपनजेडीके से स्रोत कोड डाउनलोड करें।

0

मुझे बिल्कुल नहीं पता लेकिन मुझे लगता है कि आपको अंत बिंदु पर न्यूटन के एल्गोरिदम मिलेगा।

यूपीडी: टिप्पणियों के अनुसार कंक्रीट कार्यान्वयन ठोस जावा मशीन पर निर्भर करता है। विंडोज़ के लिए यह शायद असेंबलर कार्यान्वयन का उपयोग कर रहा है, जहां मानक ऑपरेटर sqrt मौजूद है

+0

असेंबलर ऑपोड ओएस-निर्भर नहीं हैं, इसलिए इसका विंडोज़ से कोई लेना देना नहीं है। लेकिन हाँ, JVM सी स्रोत की विभिन्न टिप्पणियों में विस्तृत के रूप में मूल निर्देश का पक्ष लेगा। – Joey

30

जब आप जेडीके स्थापित करते हैं तो मानक पुस्तकालय का स्रोत कोड src.zip के अंदर पाया जा सकता है। यह, StrictMath के लिए आप में मदद नहीं करेगा, हालांकि, के रूप में StrictMath.sqrt(double) इस प्रकार लागू किया गया है:

public static native double sqrt(double a); 

तो यह वास्तव में सिर्फ एक देशी कॉल है और जावा द्वारा विभिन्न प्लेटफार्मों पर अलग ढंग से लागू किया जा सकता है।

हालांकि, StrictMath राज्यों के प्रलेखन के रूप में:

मदद करने के लिए जावा कार्यक्रमों की पोर्टेबिलिटी सुनिश्चित, इस पैकेज में संख्यात्मक कार्यों में से कुछ की परिभाषा की आवश्यकता होती है कि वे कुछ प्रकाशित एल्गोरिदम के रूप में एक ही परिणाम का उत्पादन। ये एल्गोरिदम प्रसिद्ध नेटवर्क लाइब्रेरी netlib पैकेज "फ्रीली डिस्ट्रीब्यूटेबल मैथ लाइब्रेरी", fdlibm पैकेज के रूप में उपलब्ध हैं। इन एल्गोरिदम, जो सी प्रोग्रामिंग भाषा में लिखे गए हैं, को जावा फ्लोटिंग-पॉइंट अंकगणितीय के नियमों के बाद सभी फ़्लोटिंग-पॉइंट ऑपरेशंस के साथ निष्पादित किया जाता है।

जावा गणित पुस्तकालय को fdlibm संस्करण 5.3 के संबंध में परिभाषित किया गया है। जहां fdlibm फ़ंक्शन (जैसे एकोस) के लिए एक से अधिक परिभाषा प्रदान करता है, "आईईईई 754 कोर फ़ंक्शन" संस्करण का उपयोग करें (फ़ाइल में रहना जिसका नाम अक्षर ई से शुरू होता है)। जिन तरीकों को एफडीएलआईबीएम अर्थशास्त्र की आवश्यकता होती है वे पाप, कोस, तन, एसीन, एकोस, एटान, एक्सप, लॉग, लॉग 10, सीब्रेट, एटान 2, पाउ, सिन्हा, कोश, टैन, हाइपोट, एक्सपीएम 1 और लॉग 1 पी हैं।

तो fdlibm स्रोत के उचित संस्करण को ढूंढकर, आपको जावा द्वारा उपयोग किए जाने वाले सटीक कार्यान्वयन को भी ढूंढना चाहिए (और यहां विनिर्देश द्वारा अनिवार्य)। जब से मैं OpenJDK चारों ओर झूठ बोल रही है के लिए हो

कार्यान्वयन fdlibm द्वारा प्रयोग किया जाता

static const double one = 1.0, tiny=1.0e-300; 

double z; 
int sign = (int) 0x80000000; 
unsigned r, t1, s1, ix1, q1; 
int ix0, s0, q, m, t, i; 

ix0 = __HI(x); /* high word of x */ 
ix1 = __LO(x); /* low word of x */ 

/* take care of Inf and NaN */ 
if ((ix0 & 0x7ff00000) == 0x7ff00000) {    
    return x*x+x; /* sqrt(NaN) = NaN, 
        sqrt(+inf) = +inf, 
        sqrt(-inf) = sNaN */ 
} 

/* take care of zero */ 
if (ix0 <= 0) { 
    if (((ix0&(~sign)) | ix1) == 0) { 
     return x; /* sqrt(+-0) = +-0 */ 
    } else if (ix0 < 0) { 
     return (x-x)/(x-x); /* sqrt(-ve) = sNaN */ 
    } 
} 

/* normalize x */ 
m = (ix0 >> 20); 
if (m == 0) { /* subnormal x */ 
    while (ix0==0) { 
     m -= 21; 
     ix0 |= (ix1 >> 11); ix1 <<= 21; 
    } 
    for (i=0; (ix0&0x00100000)==0; i++) { 
     ix0 <<= 1; 
    } 
    m -= i-1; 
    ix0 |= (ix1 >> (32-i)); 
    ix1 <<= i; 
} 

m -= 1023; /* unbias exponent */ 
ix0 = (ix0&0x000fffff)|0x00100000; 
if (m&1) { /* odd m, double x to make it even */ 
    ix0 += ix0 + ((ix1&sign) >> 31); 
    ix1 += ix1; 
} 

m >>= 1; /* m = [m/2] */ 

/* generate sqrt(x) bit by bit */ 
ix0 += ix0 + ((ix1 & sign)>>31); 
ix1 += ix1; 
q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */ 
r = 0x00200000; /* r = moving bit from right to left */ 

while (r != 0) { 
    t = s0 + r; 
    if (t <= ix0) { 
     s0 = t+r; 
     ix0 -= t; 
     q += r; 
    } 
    ix0 += ix0 + ((ix1&sign)>>31); 
    ix1 += ix1; 
    r>>=1; 
} 

r = sign; 
while (r != 0) { 
    t1 = s1+r; 
    t = s0; 
    if ((t<ix0) || ((t == ix0) && (t1 <= ix1))) { 
     s1 = t1+r; 
     if (((t1&sign) == sign) && (s1 & sign) == 0) { 
      s0 += 1; 
     } 
     ix0 -= t; 
     if (ix1 < t1) { 
      ix0 -= 1; 
     } 
     ix1 -= t1; 
     q1 += r; 
    } 
    ix0 += ix0 + ((ix1&sign) >> 31); 
    ix1 += ix1; 
    r >>= 1; 
} 

/* use floating add to find out rounding direction */ 
if((ix0 | ix1) != 0) { 
    z = one - tiny; /* trigger inexact flag */ 
    if (z >= one) { 
     z = one+tiny; 
     if (q1 == (unsigned) 0xffffffff) { 
      q1=0; 
      q += 1; 
     } 
    } else if (z > one) { 
     if (q1 == (unsigned) 0xfffffffe) { 
      q+=1; 
     } 
     q1+=2; 
    } else 
     q1 += (q1&1); 
    } 
} 

ix0 = (q>>1) + 0x3fe00000; 
ix1 = q 1>> 1; 
if ((q&1) == 1) ix1 |= sign; 
ix0 += (m <<20); 
__HI(z) = ix0; 
__LO(z) = ix1; 
return z; 
+1

एमएमएमएम। यह लगभग बहुत आसान है :-) –

+0

मुझे समझ में नहीं आता कि यह चर-लंबाई लूप लॉल के बिना कैसे कार्यान्वित किया जाता है। क्या आप जानते हैं कि इसके लिए स्पष्टीकरण कहां मिलना है? –

+0

@GershomMaes: मैं शायद इस बारे में पूछूंगा कि कैसे एल्गोरिदम गणित StackExchange साइटों में से एक पर काम करता है। टिप्पणियां प्रश्नों के लिए नहीं हैं। एचजी में स्रोत के लिंक के लिए – Joey

7

है, मैं इसके कार्यान्वयन यहां दिखाएंगे।

JDK में/src/शेयर/देशी/जावा/लैंग/StrictMath.c:/src/शेयर/देशी/जावा/लैंग/fdlibm/src

JNIEXPORT jdouble JNICALL 
Java_java_lang_StrictMath_sqrt(JNIEnv *env, jclass unused, jdouble d) 
{ 
    return (jdouble) jsqrt((double)d); 
} 

jsqrt JDK में sqrt के रूप में परिभाषित किया गया है/w_sqrt.c (नाम पूर्वप्रक्रमक के माध्यम से बदल दिया गया है):

#ifdef __STDC__ 
     double sqrt(double x)   /* wrapper sqrt */ 
#else 
     double sqrt(x)     /* wrapper sqrt */ 
     double x; 
#endif 
{ 
#ifdef _IEEE_LIBM 
     return __ieee754_sqrt(x); 
#else 
     double z; 
     z = __ieee754_sqrt(x); 
     if(_LIB_VERSION == _IEEE_ || isnan(x)) return z; 
     if(x<0.0) { 
      return __kernel_standard(x,x,26); /* sqrt(negative) */ 
     } else 
      return z; 
#endif 
} 

और __ieee754_sqrt JDK में परिभाषित किया गया है/src/शेयर/देशी/जावा/लैंग/fdlibm/src/e_sqrt।सी के रूप में:

#ifdef __STDC__ 
static const double one  = 1.0, tiny=1.0e-300; 
#else 
static double one  = 1.0, tiny=1.0e-300; 
#endif 

#ifdef __STDC__ 
     double __ieee754_sqrt(double x) 
#else 
     double __ieee754_sqrt(x) 
     double x; 
#endif 
{ 
     double z; 
     int  sign = (int)0x80000000; 
     unsigned r,t1,s1,ix1,q1; 
     int ix0,s0,q,m,t,i; 

     ix0 = __HI(x);     /* high word of x */ 
     ix1 = __LO(x);   /* low word of x */ 

    /* take care of Inf and NaN */ 
     if((ix0&0x7ff00000)==0x7ff00000) { 
      return x*x+x;    /* sqrt(NaN)=NaN, sqrt(+inf)=+inf 
              sqrt(-inf)=sNaN */ 
     } 
    /* take care of zero */ 
     if(ix0<=0) { 
      if(((ix0&(~sign))|ix1)==0) return x;/* sqrt(+-0) = +-0 */ 
      else if(ix0<0) 
       return (x-x)/(x-x);    /* sqrt(-ve) = sNaN */ 
     } 
    /* normalize x */ 
     m = (ix0>>20); 
     if(m==0) {        /* subnormal x */ 
      while(ix0==0) { 
       m -= 21; 
       ix0 |= (ix1>>11); ix1 <<= 21; 
      } 
      for(i=0;(ix0&0x00100000)==0;i++) ix0<<=1; 
      m -= i-1; 
      ix0 |= (ix1>>(32-i)); 
      ix1 <<= i; 
     } 
     m -= 1023;  /* unbias exponent */ 
     ix0 = (ix0&0x000fffff)|0x00100000; 
     if(m&1){  /* odd m, double x to make it even */ 
      ix0 += ix0 + ((ix1&sign)>>31); 
      ix1 += ix1; 
     } 
     m >>= 1;  /* m = [m/2] */ 

    /* generate sqrt(x) bit by bit */ 
     ix0 += ix0 + ((ix1&sign)>>31); 
     ix1 += ix1; 
     q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */ 
     r = 0x00200000;   /* r = moving bit from right to left */ 

     while(r!=0) { 
      t = s0+r; 
      if(t<=ix0) { 
       s0 = t+r; 
       ix0 -= t; 
       q += r; 
      } 
      ix0 += ix0 + ((ix1&sign)>>31); 
      ix1 += ix1; 
      r>>=1; 
     } 

     r = sign; 
     while(r!=0) { 
      t1 = s1+r; 
      t = s0; 
      if((t<ix0)||((t==ix0)&&(t1<=ix1))) { 
       s1 = t1+r; 
       if(((t1&sign)==sign)&&(s1&sign)==0) s0 += 1; 
       ix0 -= t; 
       if (ix1 < t1) ix0 -= 1; 
       ix1 -= t1; 
       q1 += r; 
      } 
      ix0 += ix0 + ((ix1&sign)>>31); 
      ix1 += ix1; 
      r>>=1; 
     } 

    /* use floating add to find out rounding direction */ 
     if((ix0|ix1)!=0) { 
      z = one-tiny; /* trigger inexact flag */ 
      if (z>=one) { 
       z = one+tiny; 
       if (q1==(unsigned)0xffffffff) { q1=0; q += 1;} 
       else if (z>one) { 
        if (q1==(unsigned)0xfffffffe) q+=1; 
        q1+=2; 
       } else 
        q1 += (q1&1); 
      } 
     } 
     ix0 = (q>>1)+0x3fe00000; 
     ix1 = q1>>1; 
     if ((q&1)==1) ix1 |= sign; 
     ix0 += (m <<20); 
     __HI(z) = ix0; 
     __LO(z) = ix1; 
     return z; 
} 

फाइलों में उपयोग की जाने वाली विधियों को समझाते हुए फाइल में अत्यधिक टिप्पणियां हैं, जिन्हें मैंने (सेमी-) ब्रेवटी के लिए छोड़ा है। Here's the file in Mercurial (मुझे आशा है कि यह लिंक करने का यह सही तरीका है)।

+0

प्लस वन – Will

संबंधित मुद्दे