tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

e_log10.cpp (2485B)


      1 /* @(#)e_log10.c 1.3 95/01/18 */
      2 /*
      3 * ====================================================
      4 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
      5 *
      6 * Developed at SunSoft, a Sun Microsystems, Inc. business.
      7 * Permission to use, copy, modify, and distribute this
      8 * software is freely granted, provided that this notice 
      9 * is preserved.
     10 * ====================================================
     11 */
     12 
     13 //#include <sys/cdefs.h>
     14 //__FBSDID("$FreeBSD$");
     15 
     16 /*
     17 * Return the base 10 logarithm of x.  See e_log.c and k_log.h for most
     18 * comments.
     19 *
     20 *    log10(x) = (f - 0.5*f*f + k_log1p(f)) / ln10 + k * log10(2)
     21 * in not-quite-routine extra precision.
     22 */
     23 
     24 #include <float.h>
     25 
     26 #include "math_private.h"
     27 #include "k_log.h"
     28 
     29 static const double
     30 two54      =  1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
     31 ivln10hi   =  4.34294481878168880939e-01, /* 0x3fdbcb7b, 0x15200000 */
     32 ivln10lo   =  2.50829467116452752298e-11, /* 0x3dbb9438, 0xca9aadd5 */
     33 log10_2hi  =  3.01029995663611771306e-01, /* 0x3FD34413, 0x509F6000 */
     34 log10_2lo  =  3.69423907715893078616e-13; /* 0x3D59FEF3, 0x11F12B36 */
     35 
     36 static const double zero   =  0.0;
     37 static volatile double vzero = 0.0;
     38 
     39 double
     40 __ieee754_log10(double x)
     41 {
     42 double f,hfsq,hi,lo,r,val_hi,val_lo,w,y,y2;
     43 int32_t i,k,hx;
     44 u_int32_t lx;
     45 
     46 EXTRACT_WORDS(hx,lx,x);
     47 
     48 k=0;
     49 if (hx < 0x00100000) {			/* x < 2**-1022  */
     50     if (((hx&0x7fffffff)|lx)==0)
     51 	return -two54/vzero;		/* log(+-0)=-inf */
     52     if (hx<0) return (x-x)/zero;	/* log(-#) = NaN */
     53     k -= 54; x *= two54; /* subnormal number, scale up x */
     54     GET_HIGH_WORD(hx,x);
     55 }
     56 if (hx >= 0x7ff00000) return x+x;
     57 if (hx == 0x3ff00000 && lx == 0)
     58     return zero;			/* log(1) = +0 */
     59 k += (hx>>20)-1023;
     60 hx &= 0x000fffff;
     61 i = (hx+0x95f64)&0x100000;
     62 SET_HIGH_WORD(x,hx|(i^0x3ff00000));	/* normalize x or x/2 */
     63 k += (i>>20);
     64 y = (double)k;
     65 f = x - 1.0;
     66 hfsq = 0.5*f*f;
     67 r = k_log1p(f);
     68 
     69 /* See e_log2.c for most details. */
     70 hi = f - hfsq;
     71 SET_LOW_WORD(hi,0);
     72 lo = (f - hi) - hfsq + r;
     73 val_hi = hi*ivln10hi;
     74 y2 = y*log10_2hi;
     75 val_lo = y*log10_2lo + (lo+hi)*ivln10lo + lo*ivln10hi;
     76 
     77 /*
     78  * Extra precision in for adding y*log10_2hi is not strictly needed
     79  * since there is no very large cancellation near x = sqrt(2) or
     80  * x = 1/sqrt(2), but we do it anyway since it costs little on CPUs
     81  * with some parallelism and it reduces the error for many args.
     82  */
     83 w = y2 + val_hi;
     84 val_lo += (y2 - w) + val_hi;
     85 val_hi = w;
     86 
     87 return val_lo + val_hi;
     88 }