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 }