1 // Copyright 2018 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 package math
6 7 import "internal/goarch"
8 9 const (
10 MaxUint32 = ^uint32(0)
11 MaxUint64 = ^uint64(0)
12 MaxUintptr = ^uintptr(0)
13 14 MaxInt64 = int64(MaxUint64 >> 1)
15 )
16 17 // MulUintptr returns a * b and whether the multiplication overflowed.
18 // On supported platforms this is an intrinsic lowered by the compiler.
19 func MulUintptr(a, b uintptr) (uintptr, bool) {
20 if a|b < 1<<(4*goarch.PtrSize) || a == 0 {
21 return a * b, false
22 }
23 overflow := b > MaxUintptr/a
24 return a * b, overflow
25 }
26 27 // Mul64 returns the 128-bit product of x and y: (hi, lo) = x * y
28 // with the product bits' upper half returned in hi and the lower
29 // half returned in lo.
30 // This is a copy from math/bits.Mul64
31 // On supported platforms this is an intrinsic lowered by the compiler.
32 func Mul64(x, y uint64) (hi, lo uint64) {
33 const mask32 = 1<<32 - 1
34 x0 := x & mask32
35 x1 := x >> 32
36 y0 := y & mask32
37 y1 := y >> 32
38 w0 := x0 * y0
39 t := x1*y0 + w0>>32
40 w1 := t & mask32
41 w2 := t >> 32
42 w1 += x0 * y1
43 hi = x1*y1 + w2 + w1>>32
44 lo = x * y
45 return
46 }
47 48 // Add64 returns the sum with carry of x, y and carry: sum = x + y + carry.
49 // The carry input must be 0 or 1; otherwise the behavior is undefined.
50 // The carryOut output is guaranteed to be 0 or 1.
51 //
52 // This function's execution time does not depend on the inputs.
53 // On supported platforms this is an intrinsic lowered by the compiler.
54 func Add64(x, y, carry uint64) (sum, carryOut uint64) {
55 sum = x + y + carry
56 // The sum will overflow if both top bits are set (x & y) or if one of them
57 // is (x | y), and a carry from the lower place happened. If such a carry
58 // happens, the top bit will be 1 + 0 + 1 = 0 (&^ sum).
59 carryOut = ((x & y) | ((x | y) &^ sum)) >> 63
60 return
61 }
62