@@ -328,3 +328,197 @@ func Len64(x uint64) (n int) {
328
328
}
329
329
return n + int (len8tab [x ])
330
330
}
331
+
332
+ // --- Add with carry ---
333
+
334
+ // Add returns the sum with carry of x, y and carry: sum = x + y + carry.
335
+ // The carry input must be 0 or 1; otherwise the behavior is undefined.
336
+ // The carryOut output is guaranteed to be 0 or 1.
337
+ func Add (x , y , carry uint ) (sum , carryOut uint ) {
338
+ yc := y + carry
339
+ sum = x + yc
340
+ if sum < x || yc < y {
341
+ carryOut = 1
342
+ }
343
+ return
344
+ }
345
+
346
+ // Add32 returns the sum with carry of x, y and carry: sum = x + y + carry.
347
+ // The carry input must be 0 or 1; otherwise the behavior is undefined.
348
+ // The carryOut output is guaranteed to be 0 or 1.
349
+ func Add32 (x , y , carry uint32 ) (sum , carryOut uint32 ) {
350
+ yc := y + carry
351
+ sum = x + yc
352
+ if sum < x || yc < y {
353
+ carryOut = 1
354
+ }
355
+ return
356
+ }
357
+
358
+ // Add64 returns the sum with carry of x, y and carry: sum = x + y + carry.
359
+ // The carry input must be 0 or 1; otherwise the behavior is undefined.
360
+ // The carryOut output is guaranteed to be 0 or 1.
361
+ func Add64 (x , y , carry uint64 ) (sum , carryOut uint64 ) {
362
+ yc := y + carry
363
+ sum = x + yc
364
+ if sum < x || yc < y {
365
+ carryOut = 1
366
+ }
367
+ return
368
+ }
369
+
370
+ // --- Subtract with borrow ---
371
+
372
+ // Sub returns the difference of x, y and borrow: diff = x - y - borrow.
373
+ // The borrow input must be 0 or 1; otherwise the behavior is undefined.
374
+ // The borrowOut output is guaranteed to be 0 or 1.
375
+ func Sub (x , y , borrow uint ) (diff , borrowOut uint ) {
376
+ yb := y + borrow
377
+ diff = x - yb
378
+ if diff > x || yb < y {
379
+ borrowOut = 1
380
+ }
381
+ return
382
+ }
383
+
384
+ // Sub32 returns the difference of x, y and borrow, diff = x - y - borrow.
385
+ // The borrow input must be 0 or 1; otherwise the behavior is undefined.
386
+ // The borrowOut output is guaranteed to be 0 or 1.
387
+ func Sub32 (x , y , borrow uint32 ) (diff , borrowOut uint32 ) {
388
+ yb := y + borrow
389
+ diff = x - yb
390
+ if diff > x || yb < y {
391
+ borrowOut = 1
392
+ }
393
+ return
394
+ }
395
+
396
+ // Sub64 returns the difference of x, y and borrow: diff = x - y - borrow.
397
+ // The borrow input must be 0 or 1; otherwise the behavior is undefined.
398
+ // The borrowOut output is guaranteed to be 0 or 1.
399
+ func Sub64 (x , y , borrow uint64 ) (diff , borrowOut uint64 ) {
400
+ yb := y + borrow
401
+ diff = x - yb
402
+ if diff > x || yb < y {
403
+ borrowOut = 1
404
+ }
405
+ return
406
+ }
407
+
408
+ // --- Full-width multiply ---
409
+
410
+ // Mul returns the full-width product of x and y: (hi, lo) = x * y
411
+ // with the product bits' upper half returned in hi and the lower
412
+ // half returned in lo.
413
+ func Mul (x , y uint ) (hi , lo uint ) {
414
+ if UintSize == 32 {
415
+ h , l := Mul32 (uint32 (x ), uint32 (y ))
416
+ return uint (h ), uint (l )
417
+ }
418
+ h , l := Mul64 (uint64 (x ), uint64 (y ))
419
+ return uint (h ), uint (l )
420
+ }
421
+
422
+ // Mul32 returns the 64-bit product of x and y: (hi, lo) = x * y
423
+ // with the product bits' upper half returned in hi and the lower
424
+ // half returned in lo.
425
+ func Mul32 (x , y uint32 ) (hi , lo uint32 ) {
426
+ tmp := uint64 (x ) * uint64 (y )
427
+ hi , lo = uint32 (tmp >> 32 ), uint32 (tmp )
428
+ return
429
+ }
430
+
431
+ // Mul64 returns the 128-bit product of x and y: (hi, lo) = x * y
432
+ // with the product bits' upper half returned in hi and the lower
433
+ // half returned in lo.
434
+ func Mul64 (x , y uint64 ) (hi , lo uint64 ) {
435
+ const mask32 = 1 << 32 - 1
436
+ x0 := x & mask32
437
+ x1 := x >> 32
438
+ y0 := y & mask32
439
+ y1 := y >> 32
440
+ w0 := x0 * y0
441
+ t := x1 * y0 + w0 >> 32
442
+ w1 := t & mask32
443
+ w2 := t >> 32
444
+ w1 += x0 * y1
445
+ hi = x1 * y1 + w2 + w1 >> 32
446
+ lo = x * y
447
+ return
448
+ }
449
+
450
+ // --- Full-width divide ---
451
+
452
+ // Div returns the quotient and remainder of (hi, lo) divided by y:
453
+ // quo = (hi, lo)/y, rem = (hi, lo)%y with the dividend bits' upper
454
+ // half in parameter hi and the lower half in parameter lo.
455
+ // hi must be < y otherwise the behavior is undefined (the quotient
456
+ // won't fit into quo).
457
+ func Div (hi , lo , y uint ) (quo , rem uint ) {
458
+ if UintSize == 32 {
459
+ q , r := Div32 (uint32 (hi ), uint32 (lo ), uint32 (y ))
460
+ return uint (q ), uint (r )
461
+ }
462
+ q , r := Div64 (uint64 (hi ), uint64 (lo ), uint64 (y ))
463
+ return uint (q ), uint (r )
464
+ }
465
+
466
+ // Div32 returns the quotient and remainder of (hi, lo) divided by y:
467
+ // quo = (hi, lo)/y, rem = (hi, lo)%y with the dividend bits' upper
468
+ // half in parameter hi and the lower half in parameter lo.
469
+ // hi must be < y otherwise the behavior is undefined (the quotient
470
+ // won't fit into quo).
471
+ func Div32 (hi , lo , y uint32 ) (quo , rem uint32 ) {
472
+ z := uint64 (hi )<< 32 | uint64 (lo )
473
+ quo , rem = uint32 (z / uint64 (y )), uint32 (z % uint64 (y ))
474
+ return
475
+ }
476
+
477
+ // Div64 returns the quotient and remainder of (hi, lo) divided by y:
478
+ // quo = (hi, lo)/y, rem = (hi, lo)%y with the dividend bits' upper
479
+ // half in parameter hi and the lower half in parameter lo.
480
+ // hi must be < y otherwise the behavior is undefined (the quotient
481
+ // won't fit into quo).
482
+ func Div64 (hi , lo , y uint64 ) (quo , rem uint64 ) {
483
+ const (
484
+ two32 = 1 << 32
485
+ mask32 = two32 - 1
486
+ )
487
+ if hi >= y {
488
+ return 1 << 64 - 1 , 1 << 64 - 1
489
+ }
490
+
491
+ s := uint (LeadingZeros64 (y ))
492
+ y <<= s
493
+
494
+ yn1 := y >> 32
495
+ yn0 := y & mask32
496
+ un32 := hi << s | lo >> (64 - s )
497
+ un10 := lo << s
498
+ un1 := un10 >> 32
499
+ un0 := un10 & mask32
500
+ q1 := un32 / yn1
501
+ rhat := un32 - q1 * yn1
502
+
503
+ for q1 >= two32 || q1 * yn0 > two32 * rhat + un1 {
504
+ q1 --
505
+ rhat += yn1
506
+ if rhat >= two32 {
507
+ break
508
+ }
509
+ }
510
+
511
+ un21 := un32 * two32 + un1 - q1 * y
512
+ q0 := un21 / yn1
513
+ rhat = un21 - q0 * yn1
514
+
515
+ for q0 >= two32 || q0 * yn0 > two32 * rhat + un0 {
516
+ q0 --
517
+ rhat += yn1
518
+ if rhat >= two32 {
519
+ break
520
+ }
521
+ }
522
+
523
+ return q1 * two32 + q0 , (un21 * two32 + un0 - q0 * y ) >> s
524
+ }
0 commit comments