github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/cmd/gc/mparith3.c (about)

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  #include	<u.h>
     6  #include	<libc.h>
     7  #include	"go.h"
     8  
     9  /*
    10   * returns the leading non-zero
    11   * word of the number
    12   */
    13  int
    14  sigfig(Mpflt *a)
    15  {
    16  	int i;
    17  
    18  	for(i=Mpprec-1; i>=0; i--)
    19  		if(a->val.a[i] != 0)
    20  			break;
    21  //print("sigfig %d %d\n", i-z+1, z);
    22  	return i+1;
    23  }
    24  
    25  /*
    26   * shifts the leading non-zero
    27   * word of the number to Mpnorm
    28   */
    29  void
    30  mpnorm(Mpflt *a)
    31  {
    32  	int s, os;
    33  	long x;
    34  
    35  	os = sigfig(a);
    36  	if(os == 0) {
    37  		// zero
    38  		a->exp = 0;
    39  		a->val.neg = 0;
    40  		return;
    41  	}
    42  
    43  	// this will normalize to the nearest word
    44  	x = a->val.a[os-1];
    45  	s = (Mpnorm-os) * Mpscale;
    46  
    47  	// further normalize to the nearest bit
    48  	for(;;) {
    49  		x <<= 1;
    50  		if(x & Mpbase)
    51  			break;
    52  		s++;
    53  		if(x == 0) {
    54  			// this error comes from trying to
    55  			// convert an Inf or something
    56  			// where the initial x=0x80000000
    57  			s = (Mpnorm-os) * Mpscale;
    58  			break;
    59  		}
    60  	}
    61  
    62  	mpshiftfix(&a->val, s);
    63  	a->exp -= s;
    64  }
    65  
    66  /// implements float arihmetic
    67  
    68  void
    69  mpaddfltflt(Mpflt *a, Mpflt *b)
    70  {
    71  	int sa, sb, s;
    72  	Mpflt c;
    73  
    74  	if(Mpdebug)
    75  		print("\n%F + %F", a, b);
    76  
    77  	sa = sigfig(a);
    78  	if(sa == 0) {
    79  		mpmovefltflt(a, b);
    80  		goto out;
    81  	}
    82  
    83  	sb = sigfig(b);
    84  	if(sb == 0)
    85  		goto out;
    86  
    87  	s = a->exp - b->exp;
    88  	if(s > 0) {
    89  		// a is larger, shift b right
    90  		mpmovefltflt(&c, b);
    91  		mpshiftfix(&c.val, -s);
    92  		mpaddfixfix(&a->val, &c.val, 0);
    93  		goto out;
    94  	}
    95  	if(s < 0) {
    96  		// b is larger, shift a right
    97  		mpshiftfix(&a->val, s);
    98  		a->exp -= s;
    99  		mpaddfixfix(&a->val, &b->val, 0);
   100  		goto out;
   101  	}
   102  	mpaddfixfix(&a->val, &b->val, 0);
   103  
   104  out:
   105  	mpnorm(a);
   106  	if(Mpdebug)
   107  		print(" = %F\n\n", a);
   108  }
   109  
   110  void
   111  mpmulfltflt(Mpflt *a, Mpflt *b)
   112  {
   113  	int sa, sb;
   114  
   115  	if(Mpdebug)
   116  		print("%F\n * %F\n", a, b);
   117  
   118  	sa = sigfig(a);
   119  	if(sa == 0) {
   120  		// zero
   121  		a->exp = 0;
   122  		a->val.neg = 0;
   123  		return;
   124  	}
   125  
   126  	sb = sigfig(b);
   127  	if(sb == 0) {
   128  		// zero
   129  		mpmovefltflt(a, b);
   130  		return;
   131  	}
   132  
   133  	mpmulfract(&a->val, &b->val);
   134  	a->exp = (a->exp + b->exp) + Mpscale*Mpprec - Mpscale - 1;
   135  
   136  	mpnorm(a);
   137  	if(Mpdebug)
   138  		print(" = %F\n\n", a);
   139  }
   140  
   141  void
   142  mpdivfltflt(Mpflt *a, Mpflt *b)
   143  {
   144  	int sa, sb;
   145  	Mpflt c;
   146  
   147  	if(Mpdebug)
   148  		print("%F\n / %F\n", a, b);
   149  
   150  	sb = sigfig(b);
   151  	if(sb == 0) {
   152  		// zero and ovfl
   153  		a->exp = 0;
   154  		a->val.neg = 0;
   155  		a->val.ovf = 1;
   156  		yyerror("constant division by zero");
   157  		return;
   158  	}
   159  
   160  	sa = sigfig(a);
   161  	if(sa == 0) {
   162  		// zero
   163  		a->exp = 0;
   164  		a->val.neg = 0;
   165  		return;
   166  	}
   167  
   168  	// adjust b to top
   169  	mpmovefltflt(&c, b);
   170  	mpshiftfix(&c.val, Mpscale);
   171  
   172  	// divide
   173  	mpdivfract(&a->val, &c.val);
   174  	a->exp = (a->exp-c.exp) - Mpscale*(Mpprec-1) + 1;
   175  
   176  	mpnorm(a);
   177  	if(Mpdebug)
   178  		print(" = %F\n\n", a);
   179  }
   180  
   181  double
   182  mpgetflt(Mpflt *a)
   183  {
   184  	int s, i, e;
   185  	uvlong v, vm;
   186  	double f;
   187  
   188  	if(a->val.ovf && nsavederrors+nerrors == 0)
   189  		yyerror("mpgetflt ovf");
   190  
   191  	s = sigfig(a);
   192  	if(s == 0)
   193  		return 0;
   194  
   195  	if(s != Mpnorm) {
   196  		yyerror("mpgetflt norm");
   197  		mpnorm(a);
   198  	}
   199  
   200  	while((a->val.a[Mpnorm-1] & Mpsign) == 0) {
   201  		mpshiftfix(&a->val, 1);
   202  		a->exp -= 1;
   203  	}
   204  
   205  	// the magic numbers (64, 63, 53, 10, -1074) are
   206  	// IEEE specific. this should be done machine
   207  	// independently or in the 6g half of the compiler
   208  
   209  	// pick up the mantissa and a rounding bit in a uvlong
   210  	s = 53+1;
   211  	v = 0;
   212  	for(i=Mpnorm-1; s>=Mpscale; i--) {
   213  		v = (v<<Mpscale) | a->val.a[i];
   214  		s -= Mpscale;
   215  	}
   216  	vm = v;
   217  	if(s > 0)
   218  		vm = (vm<<s) | (a->val.a[i]>>(Mpscale-s));
   219  
   220  	// continue with 64 more bits
   221  	s += 64;
   222  	for(; s>=Mpscale; i--) {
   223  		v = (v<<Mpscale) | a->val.a[i];
   224  		s -= Mpscale;
   225  	}
   226  	if(s > 0)
   227  		v = (v<<s) | (a->val.a[i]>>(Mpscale-s));
   228  
   229  	// gradual underflow
   230  	e = Mpnorm*Mpscale + a->exp - 53;
   231  	if(e < -1074) {
   232  		s = -e - 1074;
   233  		if(s > 54)
   234  			s = 54;
   235  		v |= vm & ((1ULL<<s) - 1);
   236  		vm >>= s;
   237  		e = -1074;
   238  	}
   239  
   240  //print("vm=%.16llux v=%.16llux\n", vm, v);
   241  	// round toward even
   242  	if(v != 0 || (vm&2ULL) != 0)
   243  		vm = (vm>>1) + (vm&1ULL);
   244  	else
   245  		vm >>= 1;
   246  
   247  	f = (double)(vm);
   248  	f = ldexp(f, e);
   249  
   250  	if(a->val.neg)
   251  		f = -f;
   252  	return f;
   253  }
   254  
   255  void
   256  mpmovecflt(Mpflt *a, double c)
   257  {
   258  	int i;
   259  	double f;
   260  	long l;
   261  
   262  	if(Mpdebug)
   263  		print("\nconst %g", c);
   264  	mpmovecfix(&a->val, 0);
   265  	a->exp = 0;
   266  	if(c == 0)
   267  		goto out;
   268  	if(c < 0) {
   269  		a->val.neg = 1;
   270  		c = -c;
   271  	}
   272  
   273  	f = frexp(c, &i);
   274  	a->exp = i;
   275  
   276  	for(i=0; i<10; i++) {
   277  		f = f*Mpbase;
   278  		l = floor(f);
   279  		f = f - l;
   280  		a->exp -= Mpscale;
   281  		a->val.a[0] = l;
   282  		if(f == 0)
   283  			break;
   284  		mpshiftfix(&a->val, Mpscale);
   285  	}
   286  
   287  out:
   288  	mpnorm(a);
   289  	if(Mpdebug)
   290  		print(" = %F\n", a);
   291  }
   292  
   293  void
   294  mpnegflt(Mpflt *a)
   295  {
   296  	a->val.neg ^= 1;
   297  }
   298  
   299  int
   300  mptestflt(Mpflt *a)
   301  {
   302  	int s;
   303  
   304  	if(Mpdebug)
   305  		print("\n%F?", a);
   306  	s = sigfig(a);
   307  	if(s != 0) {
   308  		s = +1;
   309  		if(a->val.neg)
   310  			s = -1;
   311  	}
   312  	if(Mpdebug)
   313  		print(" = %d\n", s);
   314  	return s;
   315  }