github.com/razvanm/vanadium-go-1.3@v0.0.0-20160721203343-4a65068e5915/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  				if(s.ovf) {
   305  					q.ovf = 1;
   306  					goto out;
   307  				}
   308  				mpaddfixfix(&q, &s, 1);
   309  				if(q.ovf)
   310  					goto out;
   311  			}
   312  			mplsh(&s, 1);
   313  			x >>= 1;
   314  		}
   315  	}
   316  
   317  out:
   318  	q.neg = a->neg ^ b->neg;
   319  	mpmovefixfix(a, &q);
   320  	if(a->ovf)
   321  		yyerror("constant multiplication overflow");
   322  }
   323  
   324  void
   325  mpmulfract(Mpint *a, Mpint *b)
   326  {
   327  
   328  	int i, j;
   329  	long *a1, x;
   330  	Mpint s, q;
   331  
   332  	if(a->ovf || b->ovf) {
   333  		if(nsavederrors+nerrors == 0)
   334  			yyerror("ovf in mpmulflt");
   335  		a->ovf = 1;
   336  		return;
   337  	}
   338  
   339  	mpmovefixfix(&s, b);
   340  	a1 = &a->a[Mpprec];
   341  	s.neg = 0;
   342  	mpmovecfix(&q, 0);
   343  
   344  	x = *--a1;
   345  	if(x != 0)
   346  		yyerror("mpmulfract not normal");
   347  
   348  	for(i=0; i<Mpprec-1; i++) {
   349  		x = *--a1;
   350  		if(x == 0) {
   351  			mprshw(&s);
   352  			continue;
   353  		}
   354  		for(j=0; j<Mpscale; j++) {
   355  			x <<= 1;
   356  			if(x & Mpbase)
   357  				mpaddfixfix(&q, &s, 1);
   358  			mprsh(&s);
   359  		}
   360  	}
   361  
   362  	q.neg = a->neg ^ b->neg;
   363  	mpmovefixfix(a, &q);
   364  	if(a->ovf)
   365  		yyerror("constant multiplication overflow");
   366  }
   367  
   368  void
   369  mporfixfix(Mpint *a, Mpint *b)
   370  {
   371  	int i;
   372  	long x, *a1, *b1;
   373  
   374  	x = 0;
   375  	if(a->ovf || b->ovf) {
   376  		if(nsavederrors+nerrors == 0)
   377  			yyerror("ovf in mporfixfix");
   378  		mpmovecfix(a, 0);
   379  		a->ovf = 1;
   380  		return;
   381  	}
   382  	if(a->neg) {
   383  		a->neg = 0;
   384  		mpneg(a);
   385  	}
   386  	if(b->neg)
   387  		mpneg(b);
   388  
   389  	a1 = &a->a[0];
   390  	b1 = &b->a[0];
   391  	for(i=0; i<Mpprec; i++) {
   392  		x = *a1 | *b1++;
   393  		*a1++ = x;
   394  	}
   395  
   396  	if(b->neg)
   397  		mpneg(b);
   398  	if(x & Mpsign) {
   399  		a->neg = 1;
   400  		mpneg(a);
   401  	}
   402  }
   403  
   404  void
   405  mpandfixfix(Mpint *a, Mpint *b)
   406  {
   407  	int i;
   408  	long x, *a1, *b1;
   409  
   410  	x = 0;
   411  	if(a->ovf || b->ovf) {
   412  		if(nsavederrors+nerrors == 0)
   413  			yyerror("ovf in mpandfixfix");
   414  		mpmovecfix(a, 0);
   415  		a->ovf = 1;
   416  		return;
   417  	}
   418  	if(a->neg) {
   419  		a->neg = 0;
   420  		mpneg(a);
   421  	}
   422  	if(b->neg)
   423  		mpneg(b);
   424  
   425  	a1 = &a->a[0];
   426  	b1 = &b->a[0];
   427  	for(i=0; i<Mpprec; i++) {
   428  		x = *a1 & *b1++;
   429  		*a1++ = x;
   430  	}
   431  
   432  	if(b->neg)
   433  		mpneg(b);
   434  	if(x & Mpsign) {
   435  		a->neg = 1;
   436  		mpneg(a);
   437  	}
   438  }
   439  
   440  void
   441  mpandnotfixfix(Mpint *a, Mpint *b)
   442  {
   443  	int i;
   444  	long x, *a1, *b1;
   445  
   446  	x = 0;
   447  	if(a->ovf || b->ovf) {
   448  		if(nsavederrors+nerrors == 0)
   449  			yyerror("ovf in mpandnotfixfix");
   450  		mpmovecfix(a, 0);
   451  		a->ovf = 1;
   452  		return;
   453  	}
   454  	if(a->neg) {
   455  		a->neg = 0;
   456  		mpneg(a);
   457  	}
   458  	if(b->neg)
   459  		mpneg(b);
   460  
   461  	a1 = &a->a[0];
   462  	b1 = &b->a[0];
   463  	for(i=0; i<Mpprec; i++) {
   464  		x = *a1 & ~*b1++;
   465  		*a1++ = x;
   466  	}
   467  
   468  	if(b->neg)
   469  		mpneg(b);
   470  	if(x & Mpsign) {
   471  		a->neg = 1;
   472  		mpneg(a);
   473  	}
   474  }
   475  
   476  void
   477  mpxorfixfix(Mpint *a, Mpint *b)
   478  {
   479  	int i;
   480  	long x, *a1, *b1;
   481  
   482  	x = 0;
   483  	if(a->ovf || b->ovf) {
   484  		if(nsavederrors+nerrors == 0)
   485  			yyerror("ovf in mporfixfix");
   486  		mpmovecfix(a, 0);
   487  		a->ovf = 1;
   488  		return;
   489  	}
   490  	if(a->neg) {
   491  		a->neg = 0;
   492  		mpneg(a);
   493  	}
   494  	if(b->neg)
   495  		mpneg(b);
   496  
   497  	a1 = &a->a[0];
   498  	b1 = &b->a[0];
   499  	for(i=0; i<Mpprec; i++) {
   500  		x = *a1 ^ *b1++;
   501  		*a1++ = x;
   502  	}
   503  
   504  	if(b->neg)
   505  		mpneg(b);
   506  	if(x & Mpsign) {
   507  		a->neg = 1;
   508  		mpneg(a);
   509  	}
   510  }
   511  
   512  void
   513  mplshfixfix(Mpint *a, Mpint *b)
   514  {
   515  	vlong s;
   516  
   517  	if(a->ovf || b->ovf) {
   518  		if(nsavederrors+nerrors == 0)
   519  			yyerror("ovf in mporfixfix");
   520  		mpmovecfix(a, 0);
   521  		a->ovf = 1;
   522  		return;
   523  	}
   524  	s = mpgetfix(b);
   525  	if(s < 0 || s >= Mpprec*Mpscale) {
   526  		yyerror("stupid shift: %lld", s);
   527  		mpmovecfix(a, 0);
   528  		return;
   529  	}
   530  
   531  	mpshiftfix(a, s);
   532  }
   533  
   534  void
   535  mprshfixfix(Mpint *a, Mpint *b)
   536  {
   537  	vlong s;
   538  
   539  	if(a->ovf || b->ovf) {
   540  		if(nsavederrors+nerrors == 0)
   541  			yyerror("ovf in mprshfixfix");
   542  		mpmovecfix(a, 0);
   543  		a->ovf = 1;
   544  		return;
   545  	}
   546  	s = mpgetfix(b);
   547  	if(s < 0 || s >= Mpprec*Mpscale) {
   548  		yyerror("stupid shift: %lld", s);
   549  		if(a->neg)
   550  			mpmovecfix(a, -1);
   551  		else
   552  			mpmovecfix(a, 0);
   553  		return;
   554  	}
   555  
   556  	mpshiftfix(a, -s);
   557  }
   558  
   559  void
   560  mpnegfix(Mpint *a)
   561  {
   562  	a->neg ^= 1;
   563  }
   564  
   565  vlong
   566  mpgetfix(Mpint *a)
   567  {
   568  	vlong v;
   569  
   570  	if(a->ovf) {
   571  		if(nsavederrors+nerrors == 0)
   572  			yyerror("constant overflow");
   573  		return 0;
   574  	}
   575  
   576  	v = (uvlong)a->a[0];
   577  	v |= (uvlong)a->a[1] << Mpscale;
   578  	v |= (uvlong)a->a[2] << (Mpscale+Mpscale);
   579  	if(a->neg)
   580  		v = -(uvlong)v;
   581  	return v;
   582  }
   583  
   584  void
   585  mpmovecfix(Mpint *a, vlong c)
   586  {
   587  	int i;
   588  	long *a1;
   589  	vlong x;
   590  
   591  	a->neg = 0;
   592  	a->ovf = 0;
   593  
   594  	x = c;
   595  	if(x < 0) {
   596  		a->neg = 1;
   597  		x = -(uvlong)x;
   598  	}
   599  
   600  	a1 = &a->a[0];
   601  	for(i=0; i<Mpprec; i++) {
   602  		*a1++ = x&Mpmask;
   603  		x >>= Mpscale;
   604  	}
   605  }
   606  
   607  void
   608  mpdivmodfixfix(Mpint *q, Mpint *r, Mpint *n, Mpint *d)
   609  {
   610  	int i, ns, ds;
   611  
   612  	ns = n->neg;
   613  	ds = d->neg;
   614  	n->neg = 0;
   615  	d->neg = 0;
   616  
   617  	mpmovefixfix(r, n);
   618  	mpmovecfix(q, 0);
   619  
   620  	// shift denominator until it
   621  	// is larger than numerator
   622  	for(i=0; i<Mpprec*Mpscale; i++) {
   623  		if(mpcmp(d, r) > 0)
   624  			break;
   625  		mplsh(d, 1);
   626  	}
   627  
   628  	// if it never happens
   629  	// denominator is probably zero
   630  	if(i >= Mpprec*Mpscale) {
   631  		q->ovf = 1;
   632  		r->ovf = 1;
   633  		n->neg = ns;
   634  		d->neg = ds;
   635  		yyerror("constant division overflow");
   636  		return;
   637  	}
   638  
   639  	// shift denominator back creating
   640  	// quotient a bit at a time
   641  	// when done the remaining numerator
   642  	// will be the remainder
   643  	for(; i>0; i--) {
   644  		mplsh(q, 1);
   645  		mprsh(d);
   646  		if(mpcmp(d, r) <= 0) {
   647  			mpaddcfix(q, 1);
   648  			mpsubfixfix(r, d);
   649  		}
   650  	}
   651  
   652  	n->neg = ns;
   653  	d->neg = ds;
   654  	r->neg = ns;
   655  	q->neg = ns^ds;
   656  }
   657  
   658  static int
   659  mpiszero(Mpint *a)
   660  {
   661  	long *a1;
   662  	int i;
   663  	a1 = &a->a[0] + Mpprec;
   664  	for(i=0; i<Mpprec; i++) {
   665  		if(*--a1 != 0)
   666  			return 0;
   667  	}
   668  	return 1;
   669  }
   670  
   671  void
   672  mpdivfract(Mpint *a, Mpint *b)
   673  {
   674  	Mpint n, d;
   675  	int i, j, neg;
   676  	long *a1, x;
   677  
   678  	mpmovefixfix(&n, a);	// numerator
   679  	mpmovefixfix(&d, b);	// denominator
   680  	a1 = &a->a[Mpprec];	// quotient
   681  
   682  	neg = n.neg ^ d.neg;
   683  	n.neg = 0;
   684  	d.neg = 0;
   685  	for(i=0; i<Mpprec; i++) {
   686  		x = 0;
   687  		for(j=0; j<Mpscale; j++) {
   688  			x <<= 1;
   689  			if(mpcmp(&d, &n) <= 0) {
   690  				if(!mpiszero(&d))
   691  					x |= 1;
   692  				mpsubfixfix(&n, &d);
   693  			}
   694  			mprsh(&d);
   695  		}
   696  		*--a1 = x;
   697  	}
   698  	a->neg = neg;
   699  }
   700  
   701  int
   702  mptestfix(Mpint *a)
   703  {
   704  	Mpint b;
   705  	int r;
   706  
   707  	mpmovecfix(&b, 0);
   708  	r = mpcmp(a, &b);
   709  	if(a->neg) {
   710  		if(r > 0)
   711  			return -1;
   712  		if(r < 0)
   713  			return +1;
   714  	}
   715  	return r;
   716  }