// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file provides Go implementations of elementary multi-precision
// arithmetic operations on word vectors. Needed for platforms without
// assembly implementations of these routines.

package big

import "unsafe"

type Word uintptr

const (
	_S    = uintptr(unsafe.Sizeof(Word(0))) // TODO(gri) should Sizeof return a uintptr?
	_logW = (0x650 >> _S) & 7
	_W    = 1 << _logW
	_B    = 1 << _W
	_M    = _B - 1
	_W2   = _W / 2
	_B2   = 1 << _W2
	_M2   = _B2 - 1
)


// ----------------------------------------------------------------------------
// Elementary operations on words
//
// These operations are used by the vector operations below.

// z1<<_W + z0 = x+y+c, with c == 0 or 1
func addWW_g(x, y, c Word) (z1, z0 Word) {
	yc := y + c
	z0 = x + yc
	if z0 < x || yc < y {
		z1 = 1
	}
	return
}


// z1<<_W + z0 = x-y-c, with c == 0 or 1
func subWW_g(x, y, c Word) (z1, z0 Word) {
	yc := y + c
	z0 = x - yc
	if z0 > x || yc < y {
		z1 = 1
	}
	return
}


// z1<<_W + z0 = x*y
func mulWW_g(x, y Word) (z1, z0 Word) {
	// Split x and y into 2 halfWords each, multiply
	// the halfWords separately while avoiding overflow,
	// and return the product as 2 Words.

	if x < y {
		x, y = y, x
	}

	if x < _B2 {
		// y < _B2 because y <= x
		// sub-digits of x and y are (0, x) and (0, y)
		// z = z[0] = x*y
		z0 = x * y
		return
	}

	if y < _B2 {
		// sub-digits of x and y are (x1, x0) and (0, y)
		// x = (x1*_B2 + x0)
		// y = (y1*_B2 + y0)
		x1, x0 := x>>_W2, x&_M2

		// x*y = t2*_B2*_B2 + t1*_B2 + t0
		t0 := x0 * y
		t1 := x1 * y

		// compute result digits but avoid overflow
		// z = z[1]*_B + z[0] = x*y
		z0 = t1<<_W2 + t0
		z1 = (t1 + t0>>_W2) >> _W2
		return
	}

	// general case
	// sub-digits of x and y are (x1, x0) and (y1, y0)
	// x = (x1*_B2 + x0)
	// y = (y1*_B2 + y0)
	x1, x0 := x>>_W2, x&_M2
	y1, y0 := y>>_W2, y&_M2

	// x*y = t2*_B2*_B2 + t1*_B2 + t0
	t0 := x0 * y0
	// t1 := x1*y0 + x0*y1;
	var c Word
	t1 := x1 * y0
	t1a := t1
	t1 += x0 * y1
	if t1 < t1a {
		c++
	}
	t2 := x1*y1 + c*_B2

	// compute result digits but avoid overflow
	// z = z[1]*_B + z[0] = x*y
	// This may overflow, but that's ok because we also sum t1 and t0 above
	// and we take care of the overflow there.
	z0 = t1<<_W2 + t0

	// z1 = t2 + (t1 + t0>>_W2)>>_W2;
	var c3 Word
	z1 = t1 + t0>>_W2
	if z1 < t1 {
		c3++
	}
	z1 >>= _W2
	z1 += c3 * _B2
	z1 += t2
	return
}


// z1<<_W + z0 = x*y + c
func mulAddWWW_g(x, y, c Word) (z1, z0 Word) {
	// Split x and y into 2 halfWords each, multiply
	// the halfWords separately while avoiding overflow,
	// and return the product as 2 Words.

	// TODO(gri) Should implement special cases for faster execution.

	// general case
	// sub-digits of x, y, and c are (x1, x0), (y1, y0), (c1, c0)
	// x = (x1*_B2 + x0)
	// y = (y1*_B2 + y0)
	x1, x0 := x>>_W2, x&_M2
	y1, y0 := y>>_W2, y&_M2
	c1, c0 := c>>_W2, c&_M2

	// x*y + c = t2*_B2*_B2 + t1*_B2 + t0
	// (1<<32-1)^2 == 1<<64 - 1<<33 + 1, so there's space to add c0 in here.
	t0 := x0*y0 + c0

	// t1 := x1*y0 + x0*y1 + c1;
	var c2 Word // extra carry
	t1 := x1*y0 + c1
	t1a := t1
	t1 += x0 * y1
	if t1 < t1a { // If the number got smaller then we overflowed.
		c2++
	}

	t2 := x1*y1 + c2*_B2

	// compute result digits but avoid overflow
	// z = z[1]*_B + z[0] = x*y
	// z0 = t1<<_W2 + t0;
	// This may overflow, but that's ok because we also sum t1 and t0 below
	// and we take care of the overflow there.
	z0 = t1<<_W2 + t0

	var c3 Word
	z1 = t1 + t0>>_W2
	if z1 < t1 {
		c3++
	}
	z1 >>= _W2
	z1 += t2 + c3*_B2

	return
}


// q = (x1<<_W + x0 - r)/y
// The most significant bit of y must be 1.
func divStep(x1, x0, y Word) (q, r Word) {
	d1, d0 := y>>_W2, y&_M2
	q1, r1 := x1/d1, x1%d1
	m := q1 * d0
	r1 = r1*_B2 | x0>>_W2
	if r1 < m {
		q1--
		r1 += y
		if r1 >= y && r1 < m {
			q1--
			r1 += y
		}
	}
	r1 -= m

	r0 := r1 % d1
	q0 := r1 / d1
	m = q0 * d0
	r0 = r0*_B2 | x0&_M2
	if r0 < m {
		q0--
		r0 += y
		if r0 >= y && r0 < m {
			q0--
			r0 += y
		}
	}
	r0 -= m

	q = q1*_B2 | q0
	r = r0
	return
}


// Number of leading zeros in x.
func leadingZeros(x Word) (n uint) {
	if x == 0 {
		return _W
	}
	for x&(1<<(_W-1)) == 0 {
		n++
		x <<= 1
	}
	return
}


// q = (x1<<_W + x0 - r)/y
func divWW_g(x1, x0, y Word) (q, r Word) {
	if x1 == 0 {
		q, r = x0/y, x0%y
		return
	}

	var q0, q1 Word
	z := leadingZeros(y)
	if y > x1 {
		if z != 0 {
			y <<= z
			x1 = (x1 << z) | (x0 >> (_W - z))
			x0 <<= z
		}
		q0, x0 = divStep(x1, x0, y)
		q1 = 0
	} else {
		if z == 0 {
			x1 -= y
			q1 = 1
		} else {
			z1 := _W - z
			y <<= z
			x2 := x1 >> z1
			x1 = (x1 << z) | (x0 >> z1)
			x0 <<= z
			q1, x1 = divStep(x2, x1, y)
		}

		q0, x0 = divStep(x1, x0, y)
	}

	r = x0 >> z

	if q1 != 0 {
		panic("div out of range")
	}

	return q0, r
}


// ----------------------------------------------------------------------------
// Elementary operations on vectors

// All higher-level functions use these elementary vector operations.
// The function pointers f are initialized with default implementations
// f_g, written in Go for portability. The corresponding assembly routines
// f_s should be installed if they exist.
var (
	// addVV sets z and returns c such that z+c = x+y.
	addVV func(z, x, y *Word, n int) (c Word) = addVV_g

	// subVV sets z and returns c such that z-c = x-y.
	subVV func(z, x, y *Word, n int) (c Word) = subVV_g

	// addVW sets z and returns c such that z+c = x-y.
	addVW func(z, x *Word, y Word, n int) (c Word) = addVW_g

	// subVW sets z and returns c such that z-c = x-y.
	subVW func(z, x *Word, y Word, n int) (c Word) = subVW_g

	// mulAddVWW sets z and returns c such that z+c = x*y + r.
	mulAddVWW func(z, x *Word, y, r Word, n int) (c Word) = mulAddVWW_g

	// addMulVVW sets z and returns c such that z+c = z + x*y.
	addMulVVW func(z, x *Word, y Word, n int) (c Word) = addMulVVW_g

	// divWVW sets z and returns r such that z-r = (xn<<(n*_W) + x) / y.
	divWVW func(z *Word, xn Word, x *Word, y Word, n int) (r Word) = divWVW_g
)


func init() {
	// Uncomment to use generic routines.
	//return;

	// Install assembly routines.
	addVV = addVV_s
	subVV = subVV_s
	addVW = addVW_s
	subVW = subVW_s
	mulAddVWW = mulAddVWW_s
	addMulVVW = addMulVVW_s
	divWVW = divWVW_s
}


func (p *Word) at(i int) *Word {
	return (*Word)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + uintptr(i)*_S))
}


func addVV_s(z, x, y *Word, n int) (c Word)
func addVV_g(z, x, y *Word, n int) (c Word) {
	for i := 0; i < n; i++ {
		c, *z.at(i) = addWW_g(*x.at(i), *y.at(i), c)
	}
	return
}


func subVV_s(z, x, y *Word, n int) (c Word)
func subVV_g(z, x, y *Word, n int) (c Word) {
	for i := 0; i < n; i++ {
		c, *z.at(i) = subWW_g(*x.at(i), *y.at(i), c)
	}
	return
}


func addVW_s(z, x *Word, y Word, n int) (c Word)
func addVW_g(z, x *Word, y Word, n int) (c Word) {
	c = y
	for i := 0; i < n; i++ {
		c, *z.at(i) = addWW_g(*x.at(i), c, 0)
	}
	return
}


func subVW_s(z, x *Word, y Word, n int) (c Word)
func subVW_g(z, x *Word, y Word, n int) (c Word) {
	c = y
	for i := 0; i < n; i++ {
		c, *z.at(i) = subWW_g(*x.at(i), c, 0)
	}
	return
}


func mulAddVWW_s(z, x *Word, y, r Word, n int) (c Word)
func mulAddVWW_g(z, x *Word, y, r Word, n int) (c Word) {
	c = r
	for i := 0; i < n; i++ {
		c, *z.at(i) = mulAddWWW_g(*x.at(i), y, c)
	}
	return
}


func addMulVVW_s(z, x *Word, y Word, n int) (c Word)
func addMulVVW_g(z, x *Word, y Word, n int) (c Word) {
	for i := 0; i < n; i++ {
		z1, z0 := mulAddWWW_g(*x.at(i), y, *z.at(i))
		c, *z.at(i) = addWW_g(z0, c, 0)
		c += z1
	}
	return
}


func divWVW_s(z *Word, xn Word, x *Word, y Word, n int) (r Word)
func divWVW_g(z *Word, xn Word, x *Word, y Word, n int) (r Word) {
	r = xn
	for i := n - 1; i >= 0; i-- {
		*z.at(i), r = divWW_g(r, *x.at(i), y)
	}
	return
}
