Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenhypot.c
Go to the documentation of this file.
00001 /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ 00002 /* 00003 * hypot() function for DJGPP. 00004 * 00005 * hypot() computes sqrt(x^2 + y^2). The problem with the obvious 00006 * naive implementation is that it might fail for very large or 00007 * very small arguments. For instance, for large x or y the result 00008 * might overflow even if the value of the function should not, 00009 * because squaring a large number might trigger an overflow. For 00010 * very small numbers, their square might underflow and will be 00011 * silently replaced by zero; this won't cause an exception, but might 00012 * have an adverse effect on the accuracy of the result. 00013 * 00014 * This implementation tries to avoid the above pitfals, without 00015 * inflicting too much of a performance hit. 00016 * 00017 */ 00018 #include <precomp.h> 00019 00020 /* Approximate square roots of DBL_MAX and DBL_MIN. Numbers 00021 between these two shouldn't neither overflow nor underflow 00022 when squared. */ 00023 #define __SQRT_DBL_MAX 1.3e+154 00024 #define __SQRT_DBL_MIN 2.3e-162 00025 00026 /* 00027 * @implemented 00028 */ 00029 double 00030 _hypot(double x, double y) 00031 { 00032 double abig = fabs(x), asmall = fabs(y); 00033 double ratio; 00034 00035 /* Make abig = max(|x|, |y|), asmall = min(|x|, |y|). */ 00036 if (abig < asmall) 00037 { 00038 double temp = abig; 00039 00040 abig = asmall; 00041 asmall = temp; 00042 } 00043 00044 /* Trivial case. */ 00045 if (asmall == 0.) 00046 return abig; 00047 00048 /* Scale the numbers as much as possible by using its ratio. 00049 For example, if both ABIG and ASMALL are VERY small, then 00050 X^2 + Y^2 might be VERY inaccurate due to loss of 00051 significant digits. Dividing ASMALL by ABIG scales them 00052 to a certain degree, so that accuracy is better. */ 00053 00054 if ((ratio = asmall / abig) > __SQRT_DBL_MIN && abig < __SQRT_DBL_MAX) 00055 return abig * sqrt(1.0 + ratio*ratio); 00056 else 00057 { 00058 /* Slower but safer algorithm due to Moler and Morrison. Never 00059 produces any intermediate result greater than roughly the 00060 larger of X and Y. Should converge to machine-precision 00061 accuracy in 3 iterations. */ 00062 00063 double r = ratio*ratio, t, s, p = abig, q = asmall; 00064 00065 do { 00066 t = 4. + r; 00067 if (t == 4.) 00068 break; 00069 s = r / t; 00070 p += 2. * s * p; 00071 q *= s; 00072 r = (q / p) * (q / p); 00073 } while (1); 00074 00075 return p; 00076 } 00077 } 00078 00079 #ifdef TEST 00080 00081 #include <msvcrt/stdio.h> 00082 00083 int 00084 main(void) 00085 { 00086 printf("hypot(3, 4) =\t\t\t %25.17e\n", _hypot(3., 4.)); 00087 printf("hypot(3*10^150, 4*10^150) =\t %25.17g\n", _hypot(3.e+150, 4.e+150)); 00088 printf("hypot(3*10^306, 4*10^306) =\t %25.17g\n", _hypot(3.e+306, 4.e+306)); 00089 printf("hypot(3*10^-320, 4*10^-320) =\t %25.17g\n",_hypot(3.e-320, 4.e-320)); 00090 printf("hypot(0.7*DBL_MAX, 0.7*DBL_MAX) =%25.17g\n",_hypot(0.7*DBL_MAX, 0.7*DBL_MAX)); 00091 printf("hypot(DBL_MAX, 1.0) =\t\t %25.17g\n", _hypot(DBL_MAX, 1.0)); 00092 printf("hypot(1.0, DBL_MAX) =\t\t %25.17g\n", _hypot(1.0, DBL_MAX)); 00093 printf("hypot(0.0, DBL_MAX) =\t\t %25.17g\n", _hypot(0.0, DBL_MAX)); 00094 00095 return 0; 00096 } 00097 00098 #endif Generated on Fri May 25 2012 04:34:54 for ReactOS by
1.7.6.1
|