github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/cmd/gc/mparith2.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  // return the significant
    11  // words of the argument
    12  //
    13  static int
    14  mplen(Mpint *a)
    15  {
    16  	int i, n;
    17  	long *a1;
    18  
    19  	n = -1;
    20  	a1 = &a->a[0];
    21  	for(i=0; i<Mpprec; i++) {
    22  		if(*a1++ != 0)
    23  			n = i;
    24  	}
    25  	return n+1;
    26  }
    27  
    28  //
    29  // left shift mpint by one
    30  // ignores sign
    31  //
    32  static void
    33  mplsh(Mpint *a, int quiet)
    34  {
    35  	long *a1, x;
    36  	int i, c;
    37  
    38  	c = 0;
    39  	a1 = &a->a[0];
    40  	for(i=0; i<Mpprec; i++) {
    41  		x = (*a1 << 1) + c;
    42  		c = 0;
    43  		if(x >= Mpbase) {
    44  			x -= Mpbase;
    45  			c = 1;
    46  		}
    47  		*a1++ = x;
    48  	}
    49  	a->ovf = c;
    50  	if(a->ovf && !quiet)
    51  		yyerror("constant shift overflow");
    52  }
    53  
    54  //
    55  // left shift mpint by Mpscale
    56  // ignores sign
    57  //
    58  static void
    59  mplshw(Mpint *a, int quiet)
    60  {
    61  	long *a1;
    62  	int i;
    63  
    64  	a1 = &a->a[Mpprec-1];
    65  	if(*a1) {
    66  		a->ovf = 1;
    67  		if(!quiet)
    68  			yyerror("constant shift overflow");
    69  	}
    70  	for(i=1; i<Mpprec; i++) {
    71  		a1[0] = a1[-1];
    72  		a1--;
    73  	}
    74  	a1[0] = 0;
    75  }
    76  
    77  //
    78  // right shift mpint by one
    79  // ignores sign and overflow
    80  //
    81  static void
    82  mprsh(Mpint *a)
    83  {
    84  	long *a1, x, lo;
    85  	int i, c;
    86  
    87  	c = 0;
    88  	lo = a->a[0] & 1;
    89  	a1 = &a->a[Mpprec];
    90  	for(i=0; i<Mpprec; i++) {
    91  		x = *--a1;
    92  		*a1 = (x + c) >> 1;
    93  		c = 0;
    94  		if(x & 1)
    95  			c = Mpbase;
    96  	}
    97  	if(a->neg && lo != 0)
    98  		mpaddcfix(a, -1);
    99  }
   100  
   101  //
   102  // right shift mpint by Mpscale
   103  // ignores sign and overflow
   104  //
   105  static void
   106  mprshw(Mpint *a)
   107  {
   108  	long *a1, lo;
   109  	int i;
   110  
   111  	lo = a->a[0];
   112  	a1 = &a->a[0];
   113  	for(i=1; i<Mpprec; i++) {
   114  		a1[0] = a1[1];
   115  		a1++;
   116  	}
   117  	a1[0] = 0;
   118  	if(a->neg && lo != 0)
   119  		mpaddcfix(a, -1);
   120  }
   121  
   122  //
   123  // return the sign of (abs(a)-abs(b))
   124  //
   125  static int
   126  mpcmp(Mpint *a, Mpint *b)
   127  {
   128  	long x, *a1, *b1;
   129  	int i;
   130  
   131  	if(a->ovf || b->ovf) {
   132  		if(nsavederrors+nerrors == 0)
   133  			yyerror("ovf in cmp");
   134  		return 0;
   135  	}
   136  
   137  	a1 = &a->a[0] + Mpprec;
   138  	b1 = &b->a[0] + Mpprec;
   139  
   140  	for(i=0; i<Mpprec; i++) {
   141  		x = *--a1 - *--b1;
   142  		if(x > 0)
   143  			return +1;
   144  		if(x < 0)
   145  			return -1;
   146  	}
   147  	return 0;
   148  }
   149  
   150  //
   151  // negate a
   152  // ignore sign and ovf
   153  //
   154  static void
   155  mpneg(Mpint *a)
   156  {
   157  	long x, *a1;
   158  	int i, c;
   159  
   160  	a1 = &a->a[0];
   161  	c = 0;
   162  	for(i=0; i<Mpprec; i++) {
   163  		x = -*a1 -c;
   164  		c = 0;
   165  		if(x < 0) {
   166  			x += Mpbase;
   167  			c = 1;
   168  		}
   169  		*a1++ = x;
   170  	}
   171  }
   172  
   173  // shift left by s (or right by -s)
   174  void
   175  mpshiftfix(Mpint *a, int s)
   176  {
   177  	if(s >= 0) {
   178  		while(s >= Mpscale) {
   179  			mplshw(a, 0);
   180  			s -= Mpscale;
   181  		}
   182  		while(s > 0) {
   183  			mplsh(a, 0);
   184  			s--;
   185  		}
   186  	} else {
   187  		s = -s;
   188  		while(s >= Mpscale) {
   189  			mprshw(a);
   190  			s -= Mpscale;
   191  		}
   192  		while(s > 0) {
   193  			mprsh(a);
   194  			s--;
   195  		}
   196  	}
   197  }
   198  
   199  /// implements fix arihmetic
   200  
   201  void
   202  mpaddfixfix(Mpint *a, Mpint *b, int quiet)
   203  {
   204  	int i, c;
   205  	long x, *a1, *b1;
   206  
   207  	if(a->ovf || b->ovf) {
   208  		if(nsavederrors+nerrors == 0)
   209  			yyerror("ovf in mpaddxx");
   210  		a->ovf = 1;
   211  		return;
   212  	}
   213  
   214  	c = 0;
   215  	a1 = &a->a[0];
   216  	b1 = &b->a[0];
   217  	if(a->neg != b->neg)
   218  		goto sub;
   219  
   220  	// perform a+b
   221  	for(i=0; i<Mpprec; i++) {
   222  		x = *a1 + *b1++ + c;
   223  		c = 0;
   224  		if(x >= Mpbase) {
   225  			x -= Mpbase;
   226  			c = 1;
   227  		}
   228  		*a1++ = x;
   229  	}
   230  	a->ovf = c;
   231  	if(a->ovf && !quiet)
   232  		yyerror("constant addition overflow");
   233  
   234  	return;
   235  
   236  sub:
   237  	// perform a-b
   238  	switch(mpcmp(a, b)) {
   239  	case 0:
   240  		mpmovecfix(a, 0);
   241  		break;
   242  
   243  	case 1:
   244  		for(i=0; i<Mpprec; i++) {
   245  			x = *a1 - *b1++ - c;
   246  			c = 0;
   247  			if(x < 0) {
   248  				x += Mpbase;
   249  				c = 1;
   250  			}
   251  			*a1++ = x;
   252  		}
   253  		break;
   254  
   255  	case -1:
   256  		a->neg ^= 1;
   257  		for(i=0; i<Mpprec; i++) {
   258  			x = *b1++ - *a1 - c;
   259  			c = 0;
   260  			if(x < 0) {
   261  				x += Mpbase;
   262  				c = 1;
   263  			}
   264  			*a1++ = x;
   265  		}
   266  		break;
   267  	}
   268  }
   269  
   270  void
   271  mpmulfixfix(Mpint *a, Mpint *b)
   272  {
   273  
   274  	int i, j, na, nb;
   275  	long *a1, x;
   276  	Mpint s, q;
   277  
   278  	if(a->ovf || b->ovf) {
   279  		if(nsavederrors+nerrors == 0)
   280  			yyerror("ovf in mpmulfixfix");
   281  		a->ovf = 1;
   282  		return;
   283  	}
   284  
   285  	// pick the smaller
   286  	// to test for bits
   287  	na = mplen(a);
   288  	nb = mplen(b);
   289  	if(na > nb) {
   290  		mpmovefixfix(&s, a);
   291  		a1 = &b->a[0];
   292  		na = nb;
   293  	} else {
   294  		mpmovefixfix(&s, b);
   295  		a1 = &a->a[0];
   296  	}
   297  	s.neg = 0;
   298  
   299  	mpmovecfix(&q, 0);
   300  	for(i=0; i<na; i++) {
   301  		x = *a1++;
   302  		for(j=0; j<Mpscale; j++) {
   303  			if(x & 1)
   304  				mpaddfixfix(&q, &s, 1);
   305  			mplsh(&s, 1);
   306  			x >>= 1;
   307  		}
   308  	}
   309  
   310  	q.neg = a->neg ^ b->neg;
   311  	mpmovefixfix(a, &q);
   312  	if(a->ovf)
   313  		yyerror("constant multiplication overflow");
   314  }
   315  
   316  void
   317  mpmulfract(Mpint *a, Mpint *b)
   318  {
   319  
   320  	int i, j;
   321  	long *a1, x;
   322  	Mpint s, q;
   323  
   324  	if(a->ovf || b->ovf) {
   325  		if(nsavederrors+nerrors == 0)
   326  			yyerror("ovf in mpmulflt");
   327  		a->ovf = 1;
   328  		return;
   329  	}
   330  
   331  	mpmovefixfix(&s, b);
   332  	a1 = &a->a[Mpprec];
   333  	s.neg = 0;
   334  	mpmovecfix(&q, 0);
   335  
   336  	x = *--a1;
   337  	if(x != 0)
   338  		yyerror("mpmulfract not normal");
   339  
   340  	for(i=0; i<Mpprec-1; i++) {
   341  		x = *--a1;
   342  		if(x == 0) {
   343  			mprshw(&s);
   344  			continue;
   345  		}
   346  		for(j=0; j<Mpscale; j++) {
   347  			x <<= 1;
   348  			if(x & Mpbase)
   349  				mpaddfixfix(&q, &s, 1);
   350  			mprsh(&s);
   351  		}
   352  	}
   353  
   354  	q.neg = a->neg ^ b->neg;
   355  	mpmovefixfix(a, &q);
   356  	if(a->ovf)
   357  		yyerror("constant multiplication overflow");
   358  }
   359  
   360  void
   361  mporfixfix(Mpint *a, Mpint *b)
   362  {
   363  	int i;
   364  	long x, *a1, *b1;
   365  
   366  	x = 0;
   367  	if(a->ovf || b->ovf) {
   368  		if(nsavederrors+nerrors == 0)
   369  			yyerror("ovf in mporfixfix");
   370  		mpmovecfix(a, 0);
   371  		a->ovf = 1;
   372  		return;
   373  	}
   374  	if(a->neg) {
   375  		a->neg = 0;
   376  		mpneg(a);
   377  	}
   378  	if(b->neg)
   379  		mpneg(b);
   380  
   381  	a1 = &a->a[0];
   382  	b1 = &b->a[0];
   383  	for(i=0; i<Mpprec; i++) {
   384  		x = *a1 | *b1++;
   385  		*a1++ = x;
   386  	}
   387  
   388  	if(b->neg)
   389  		mpneg(b);
   390  	if(x & Mpsign) {
   391  		a->neg = 1;
   392  		mpneg(a);
   393  	}
   394  }
   395  
   396  void
   397  mpandfixfix(Mpint *a, Mpint *b)
   398  {
   399  	int i;
   400  	long x, *a1, *b1;
   401  
   402  	x = 0;
   403  	if(a->ovf || b->ovf) {
   404  		if(nsavederrors+nerrors == 0)
   405  			yyerror("ovf in mpandfixfix");
   406  		mpmovecfix(a, 0);
   407  		a->ovf = 1;
   408  		return;
   409  	}
   410  	if(a->neg) {
   411  		a->neg = 0;
   412  		mpneg(a);
   413  	}
   414  	if(b->neg)
   415  		mpneg(b);
   416  
   417  	a1 = &a->a[0];
   418  	b1 = &b->a[0];
   419  	for(i=0; i<Mpprec; i++) {
   420  		x = *a1 & *b1++;
   421  		*a1++ = x;
   422  	}
   423  
   424  	if(b->neg)
   425  		mpneg(b);
   426  	if(x & Mpsign) {
   427  		a->neg = 1;
   428  		mpneg(a);
   429  	}
   430  }
   431  
   432  void
   433  mpandnotfixfix(Mpint *a, Mpint *b)
   434  {
   435  	int i;
   436  	long x, *a1, *b1;
   437  
   438  	x = 0;
   439  	if(a->ovf || b->ovf) {
   440  		if(nsavederrors+nerrors == 0)
   441  			yyerror("ovf in mpandnotfixfix");
   442  		mpmovecfix(a, 0);
   443  		a->ovf = 1;
   444  		return;
   445  	}
   446  	if(a->neg) {
   447  		a->neg = 0;
   448  		mpneg(a);
   449  	}
   450  	if(b->neg)
   451  		mpneg(b);
   452  
   453  	a1 = &a->a[0];
   454  	b1 = &b->a[0];
   455  	for(i=0; i<Mpprec; i++) {
   456  		x = *a1 & ~*b1++;
   457  		*a1++ = x;
   458  	}
   459  
   460  	if(b->neg)
   461  		mpneg(b);
   462  	if(x & Mpsign) {
   463  		a->neg = 1;
   464  		mpneg(a);
   465  	}
   466  }
   467  
   468  void
   469  mpxorfixfix(Mpint *a, Mpint *b)
   470  {
   471  	int i;
   472  	long x, *a1, *b1;
   473  
   474  	x = 0;
   475  	if(a->ovf || b->ovf) {
   476  		if(nsavederrors+nerrors == 0)
   477  			yyerror("ovf in mporfixfix");
   478  		mpmovecfix(a, 0);
   479  		a->ovf = 1;
   480  		return;
   481  	}
   482  	if(a->neg) {
   483  		a->neg = 0;
   484  		mpneg(a);
   485  	}
   486  	if(b->neg)
   487  		mpneg(b);
   488  
   489  	a1 = &a->a[0];
   490  	b1 = &b->a[0];
   491  	for(i=0; i<Mpprec; i++) {
   492  		x = *a1 ^ *b1++;
   493  		*a1++ = x;
   494  	}
   495  
   496  	if(b->neg)
   497  		mpneg(b);
   498  	if(x & Mpsign) {
   499  		a->neg = 1;
   500  		mpneg(a);
   501  	}
   502  }
   503  
   504  void
   505  mplshfixfix(Mpint *a, Mpint *b)
   506  {
   507  	vlong s;
   508  
   509  	if(a->ovf || b->ovf) {
   510  		if(nsavederrors+nerrors == 0)
   511  			yyerror("ovf in mporfixfix");
   512  		mpmovecfix(a, 0);
   513  		a->ovf = 1;
   514  		return;
   515  	}
   516  	s = mpgetfix(b);
   517  	if(s < 0 || s >= Mpprec*Mpscale) {
   518  		yyerror("stupid shift: %lld", s);
   519  		mpmovecfix(a, 0);
   520  		return;
   521  	}
   522  
   523  	mpshiftfix(a, s);
   524  }
   525  
   526  void
   527  mprshfixfix(Mpint *a, Mpint *b)
   528  {
   529  	vlong s;
   530  
   531  	if(a->ovf || b->ovf) {
   532  		if(nsavederrors+nerrors == 0)
   533  			yyerror("ovf in mprshfixfix");
   534  		mpmovecfix(a, 0);
   535  		a->ovf = 1;
   536  		return;
   537  	}
   538  	s = mpgetfix(b);
   539  	if(s < 0 || s >= Mpprec*Mpscale) {
   540  		yyerror("stupid shift: %lld", s);
   541  		if(a->neg)
   542  			mpmovecfix(a, -1);
   543  		else
   544  			mpmovecfix(a, 0);
   545  		return;
   546  	}
   547  
   548  	mpshiftfix(a, -s);
   549  }
   550  
   551  void
   552  mpnegfix(Mpint *a)
   553  {
   554  	a->neg ^= 1;
   555  }
   556  
   557  vlong
   558  mpgetfix(Mpint *a)
   559  {
   560  	vlong v;
   561  
   562  	if(a->ovf) {
   563  		if(nsavederrors+nerrors == 0)
   564  			yyerror("constant overflow");
   565  		return 0;
   566  	}
   567  
   568  	v = (uvlong)a->a[0];
   569  	v |= (uvlong)a->a[1] << Mpscale;
   570  	v |= (uvlong)a->a[2] << (Mpscale+Mpscale);
   571  	if(a->neg)
   572  		v = -(uvlong)v;
   573  	return v;
   574  }
   575  
   576  void
   577  mpmovecfix(Mpint *a, vlong c)
   578  {
   579  	int i;
   580  	long *a1;
   581  	vlong x;
   582  
   583  	a->neg = 0;
   584  	a->ovf = 0;
   585  
   586  	x = c;
   587  	if(x < 0) {
   588  		a->neg = 1;
   589  		x = -(uvlong)x;
   590  	}
   591  
   592  	a1 = &a->a[0];
   593  	for(i=0; i<Mpprec; i++) {
   594  		*a1++ = x&Mpmask;
   595  		x >>= Mpscale;
   596  	}
   597  }
   598  
   599  void
   600  mpdivmodfixfix(Mpint *q, Mpint *r, Mpint *n, Mpint *d)
   601  {
   602  	int i, ns, ds;
   603  
   604  	ns = n->neg;
   605  	ds = d->neg;
   606  	n->neg = 0;
   607  	d->neg = 0;
   608  
   609  	mpmovefixfix(r, n);
   610  	mpmovecfix(q, 0);
   611  
   612  	// shift denominator until it
   613  	// is larger than numerator
   614  	for(i=0; i<Mpprec*Mpscale; i++) {
   615  		if(mpcmp(d, r) > 0)
   616  			break;
   617  		mplsh(d, 1);
   618  	}
   619  
   620  	// if it never happens
   621  	// denominator is probably zero
   622  	if(i >= Mpprec*Mpscale) {
   623  		q->ovf = 1;
   624  		r->ovf = 1;
   625  		n->neg = ns;
   626  		d->neg = ds;
   627  		yyerror("constant division overflow");
   628  		return;
   629  	}
   630  
   631  	// shift denominator back creating
   632  	// quotient a bit at a time
   633  	// when done the remaining numerator
   634  	// will be the remainder
   635  	for(; i>0; i--) {
   636  		mplsh(q, 1);
   637  		mprsh(d);
   638  		if(mpcmp(d, r) <= 0) {
   639  			mpaddcfix(q, 1);
   640  			mpsubfixfix(r, d);
   641  		}
   642  	}
   643  
   644  	n->neg = ns;
   645  	d->neg = ds;
   646  	r->neg = ns;
   647  	q->neg = ns^ds;
   648  }
   649  
   650  static int
   651  iszero(Mpint *a)
   652  {
   653  	long *a1;
   654  	int i;
   655  	a1 = &a->a[0] + Mpprec;
   656  	for(i=0; i<Mpprec; i++) {
   657  		if(*--a1 != 0)
   658  			return 0;
   659  	}
   660  	return 1;
   661  }
   662  
   663  void
   664  mpdivfract(Mpint *a, Mpint *b)
   665  {
   666  	Mpint n, d;
   667  	int i, j, neg;
   668  	long *a1, x;
   669  
   670  	mpmovefixfix(&n, a);	// numerator
   671  	mpmovefixfix(&d, b);	// denominator
   672  	a1 = &a->a[Mpprec];	// quotient
   673  
   674  	neg = n.neg ^ d.neg;
   675  	n.neg = 0;
   676  	d.neg = 0;
   677  	for(i=0; i<Mpprec; i++) {
   678  		x = 0;
   679  		for(j=0; j<Mpscale; j++) {
   680  			x <<= 1;
   681  			if(mpcmp(&d, &n) <= 0) {
   682  				if(!iszero(&d))
   683  					x |= 1;
   684  				mpsubfixfix(&n, &d);
   685  			}
   686  			mprsh(&d);
   687  		}
   688  		*--a1 = x;
   689  	}
   690  	a->neg = neg;
   691  }
   692  
   693  int
   694  mptestfix(Mpint *a)
   695  {
   696  	Mpint b;
   697  	int r;
   698  
   699  	mpmovecfix(&b, 0);
   700  	r = mpcmp(a, &b);
   701  	if(a->neg) {
   702  		if(r > 0)
   703  			return -1;
   704  		if(r < 0)
   705  			return +1;
   706  	}
   707  	return r;
   708  }