github.com/prattmic/llgo-embedded@v0.0.0-20150820070356-41cfecea0e1e/third_party/gofrontend/libgo/go/math/big/arith.go (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  // This file provides Go implementations of elementary multi-precision
     6  // arithmetic operations on word vectors. Needed for platforms without
     7  // assembly implementations of these routines.
     8  
     9  package big
    10  
    11  // A Word represents a single digit of a multi-precision unsigned integer.
    12  type Word uintptr
    13  
    14  const (
    15  	// Compute the size _S of a Word in bytes.
    16  	_m    = ^Word(0)
    17  	_logS = _m>>8&1 + _m>>16&1 + _m>>32&1
    18  	_S    = 1 << _logS
    19  
    20  	_W = _S << 3 // word size in bits
    21  	_B = 1 << _W // digit base
    22  	_M = _B - 1  // digit mask
    23  
    24  	_W2 = _W / 2   // half word size in bits
    25  	_B2 = 1 << _W2 // half digit base
    26  	_M2 = _B2 - 1  // half digit mask
    27  )
    28  
    29  // ----------------------------------------------------------------------------
    30  // Elementary operations on words
    31  //
    32  // These operations are used by the vector operations below.
    33  
    34  // z1<<_W + z0 = x+y+c, with c == 0 or 1
    35  func addWW_g(x, y, c Word) (z1, z0 Word) {
    36  	yc := y + c
    37  	z0 = x + yc
    38  	if z0 < x || yc < y {
    39  		z1 = 1
    40  	}
    41  	return
    42  }
    43  
    44  // z1<<_W + z0 = x-y-c, with c == 0 or 1
    45  func subWW_g(x, y, c Word) (z1, z0 Word) {
    46  	yc := y + c
    47  	z0 = x - yc
    48  	if z0 > x || yc < y {
    49  		z1 = 1
    50  	}
    51  	return
    52  }
    53  
    54  // z1<<_W + z0 = x*y
    55  func mulWW(x, y Word) (z1, z0 Word) { return mulWW_g(x, y) }
    56  
    57  // Adapted from Warren, Hacker's Delight, p. 132.
    58  func mulWW_g(x, y Word) (z1, z0 Word) {
    59  	x0 := x & _M2
    60  	x1 := x >> _W2
    61  	y0 := y & _M2
    62  	y1 := y >> _W2
    63  	w0 := x0 * y0
    64  	t := x1*y0 + w0>>_W2
    65  	w1 := t & _M2
    66  	w2 := t >> _W2
    67  	w1 += x0 * y1
    68  	z1 = x1*y1 + w2 + w1>>_W2
    69  	z0 = x * y
    70  	return
    71  }
    72  
    73  // z1<<_W + z0 = x*y + c
    74  func mulAddWWW_g(x, y, c Word) (z1, z0 Word) {
    75  	z1, zz0 := mulWW(x, y)
    76  	if z0 = zz0 + c; z0 < zz0 {
    77  		z1++
    78  	}
    79  	return
    80  }
    81  
    82  // Length of x in bits.
    83  func bitLen(x Word) (n int) { return bitLen_g(x) }
    84  func bitLen_g(x Word) (n int) {
    85  	for ; x >= 0x8000; x >>= 16 {
    86  		n += 16
    87  	}
    88  	if x >= 0x80 {
    89  		x >>= 8
    90  		n += 8
    91  	}
    92  	if x >= 0x8 {
    93  		x >>= 4
    94  		n += 4
    95  	}
    96  	if x >= 0x2 {
    97  		x >>= 2
    98  		n += 2
    99  	}
   100  	if x >= 0x1 {
   101  		n++
   102  	}
   103  	return
   104  }
   105  
   106  // log2 computes the integer binary logarithm of x.
   107  // The result is the integer n for which 2^n <= x < 2^(n+1).
   108  // If x == 0, the result is -1.
   109  func log2(x Word) int {
   110  	return bitLen(x) - 1
   111  }
   112  
   113  // Number of leading zeros in x.
   114  func leadingZeros(x Word) uint {
   115  	return uint(_W - bitLen(x))
   116  }
   117  
   118  // q = (u1<<_W + u0 - r)/y
   119  func divWW(x1, x0, y Word) (q, r Word) { return divWW_g(x1, x0, y) }
   120  
   121  // Adapted from Warren, Hacker's Delight, p. 152.
   122  func divWW_g(u1, u0, v Word) (q, r Word) {
   123  	if u1 >= v {
   124  		return 1<<_W - 1, 1<<_W - 1
   125  	}
   126  
   127  	s := leadingZeros(v)
   128  	v <<= s
   129  
   130  	vn1 := v >> _W2
   131  	vn0 := v & _M2
   132  	un32 := u1<<s | u0>>(_W-s)
   133  	un10 := u0 << s
   134  	un1 := un10 >> _W2
   135  	un0 := un10 & _M2
   136  	q1 := un32 / vn1
   137  	rhat := un32 - q1*vn1
   138  
   139  	for q1 >= _B2 || q1*vn0 > _B2*rhat+un1 {
   140  		q1--
   141  		rhat += vn1
   142  		if rhat >= _B2 {
   143  			break
   144  		}
   145  	}
   146  
   147  	un21 := un32*_B2 + un1 - q1*v
   148  	q0 := un21 / vn1
   149  	rhat = un21 - q0*vn1
   150  
   151  	for q0 >= _B2 || q0*vn0 > _B2*rhat+un0 {
   152  		q0--
   153  		rhat += vn1
   154  		if rhat >= _B2 {
   155  			break
   156  		}
   157  	}
   158  
   159  	return q1*_B2 + q0, (un21*_B2 + un0 - q0*v) >> s
   160  }
   161  
   162  func addVV(z, x, y []Word) (c Word) { return addVV_g(z, x, y) }
   163  func addVV_g(z, x, y []Word) (c Word) {
   164  	for i := range z {
   165  		c, z[i] = addWW_g(x[i], y[i], c)
   166  	}
   167  	return
   168  }
   169  
   170  func subVV(z, x, y []Word) (c Word) { return subVV_g(z, x, y) }
   171  func subVV_g(z, x, y []Word) (c Word) {
   172  	for i := range z {
   173  		c, z[i] = subWW_g(x[i], y[i], c)
   174  	}
   175  	return
   176  }
   177  
   178  func addVW(z, x []Word, y Word) (c Word) { return addVW_g(z, x, y) }
   179  func addVW_g(z, x []Word, y Word) (c Word) {
   180  	c = y
   181  	for i := range z {
   182  		c, z[i] = addWW_g(x[i], c, 0)
   183  	}
   184  	return
   185  }
   186  
   187  func subVW(z, x []Word, y Word) (c Word) { return subVW_g(z, x, y) }
   188  func subVW_g(z, x []Word, y Word) (c Word) {
   189  	c = y
   190  	for i := range z {
   191  		c, z[i] = subWW_g(x[i], c, 0)
   192  	}
   193  	return
   194  }
   195  
   196  func shlVU(z, x []Word, s uint) (c Word) { return shlVU_g(z, x, s) }
   197  func shlVU_g(z, x []Word, s uint) (c Word) {
   198  	if n := len(z); n > 0 {
   199  		ŝ := _W - s
   200  		w1 := x[n-1]
   201  		c = w1 >> ŝ
   202  		for i := n - 1; i > 0; i-- {
   203  			w := w1
   204  			w1 = x[i-1]
   205  			z[i] = w<<s | w1>>ŝ
   206  		}
   207  		z[0] = w1 << s
   208  	}
   209  	return
   210  }
   211  
   212  func shrVU(z, x []Word, s uint) (c Word) { return shrVU_g(z, x, s) }
   213  func shrVU_g(z, x []Word, s uint) (c Word) {
   214  	if n := len(z); n > 0 {
   215  		ŝ := _W - s
   216  		w1 := x[0]
   217  		c = w1 << ŝ
   218  		for i := 0; i < n-1; i++ {
   219  			w := w1
   220  			w1 = x[i+1]
   221  			z[i] = w>>s | w1<<ŝ
   222  		}
   223  		z[n-1] = w1 >> s
   224  	}
   225  	return
   226  }
   227  
   228  func mulAddVWW(z, x []Word, y, r Word) (c Word) { return mulAddVWW_g(z, x, y, r) }
   229  func mulAddVWW_g(z, x []Word, y, r Word) (c Word) {
   230  	c = r
   231  	for i := range z {
   232  		c, z[i] = mulAddWWW_g(x[i], y, c)
   233  	}
   234  	return
   235  }
   236  
   237  func addMulVVW(z, x []Word, y Word) (c Word) { return addMulVVW_g(z, x, y) }
   238  func addMulVVW_g(z, x []Word, y Word) (c Word) {
   239  	for i := range z {
   240  		z1, z0 := mulAddWWW_g(x[i], y, z[i])
   241  		c, z[i] = addWW_g(z0, c, 0)
   242  		c += z1
   243  	}
   244  	return
   245  }
   246  
   247  func divWVW(z []Word, xn Word, x []Word, y Word) (r Word) { return divWVW_g(z, xn, x, y) }
   248  func divWVW_g(z []Word, xn Word, x []Word, y Word) (r Word) {
   249  	r = xn
   250  	for i := len(z) - 1; i >= 0; i-- {
   251  		z[i], r = divWW_g(r, x[i], y)
   252  	}
   253  	return
   254  }