mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
math.big: rework function naming and documentation (#18890)
This commit is contained in:
parent
bd3501affa
commit
a49b8f28b1
@ -364,7 +364,7 @@ fn (mut v Element) to_big_integer() big.Integer {
|
||||
|
||||
// from_big_integer sets v = n, and returns v. The bit length of n must not exceed 256.
|
||||
fn (mut v Element) from_big_integer(n big.Integer) !Element {
|
||||
if n.binary_str().len > 32 * 8 {
|
||||
if n.bin_str().len > 32 * 8 {
|
||||
return error('invalid edwards25519 element input size')
|
||||
}
|
||||
mut bytes, _ := n.bytes()
|
||||
|
@ -119,7 +119,7 @@ fn test_scalar_set_uniform_bytes() {
|
||||
// mod, _ := new(big.Integer).SetString("27742317777372353535851937790883648493", 10)
|
||||
mut mod := big.integer_from_string('27742317777372353535851937790883648493')!
|
||||
// mod.Add(mod, new(big.Integer).Lsh(big.NewInt(1), 252))
|
||||
mod = mod + big.integer_from_i64(1).lshift(252)
|
||||
mod = mod + big.integer_from_i64(1).left_shift(252)
|
||||
|
||||
mut sc := generate_scalar(100)!
|
||||
inp := rand.bytes(64)!
|
||||
|
@ -88,7 +88,7 @@ pub fn (a &Number) % (b &Number) Number {
|
||||
return c
|
||||
}*/
|
||||
|
||||
pub fn divmod(a &Number, b &Number) (Number, Number) {
|
||||
pub fn div_mod(a &Number, b &Number) (Number, Number) {
|
||||
c := Number{}
|
||||
d := Number{}
|
||||
#c.value = a.val.value / b.val.value
|
||||
@ -97,6 +97,11 @@ pub fn divmod(a &Number, b &Number) (Number, Number) {
|
||||
return c, d
|
||||
}
|
||||
|
||||
[deprecated: 'use div_mod(a, b) instead']
|
||||
pub fn divmod(a &Number, b &Number) (Number, Number) {
|
||||
return div_mod(a, b)
|
||||
}
|
||||
|
||||
pub fn cmp(a &Number, b &Number) int {
|
||||
res := 0
|
||||
|
||||
@ -137,37 +142,62 @@ pub fn (a &Number) isqrt() Number {
|
||||
return b
|
||||
}
|
||||
|
||||
[deprecated: 'use bitwise_and(a, b) instead']
|
||||
pub fn b_and(a &Number, b &Number) Number {
|
||||
return bitwise_and(a, b)
|
||||
}
|
||||
|
||||
[deprecated: 'use bitwise_or(a, b) instead']
|
||||
pub fn b_or(a &Number, b &Number) Number {
|
||||
return bitwise_or(a, b)
|
||||
}
|
||||
|
||||
[deprecated: 'use bitwise_xor(a, b) instead']
|
||||
pub fn b_xor(a &Number, b &Number) Number {
|
||||
return bitwise_xor(a, b)
|
||||
}
|
||||
|
||||
pub fn bitwise_and(a &Number, b &Number) Number {
|
||||
c := Number{}
|
||||
#c.value = a.val.value & b.val.value
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
pub fn b_or(a &Number, b &Number) Number {
|
||||
pub fn bitwise_or(a &Number, b &Number) Number {
|
||||
c := Number{}
|
||||
#c.value = a.val.value | b.val.value
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
pub fn b_xor(a &Number, b &Number) Number {
|
||||
pub fn bitwise_xor(a &Number, b &Number) Number {
|
||||
c := Number{}
|
||||
#c.value = a.val.value ^ b.val.value
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
pub fn (a &Number) lshift(nbits int) Number {
|
||||
[deprecated: 'use a.left_shift(amount) instead']
|
||||
pub fn (a &Number) lshift(amount int) Number {
|
||||
return a.left_shift(amount)
|
||||
}
|
||||
|
||||
[deprecated: 'use a.right_shift(amount) instead']
|
||||
pub fn (a &Number) rshift(amount int) Number {
|
||||
return a.right_shift(amount)
|
||||
}
|
||||
|
||||
pub fn (a &Number) left_shift(amount int) Number {
|
||||
c := Number{}
|
||||
#c.value = a.val.value << BigInt(+nbits)
|
||||
#c.value = a.val.value << BigInt(+amount)
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
pub fn (a &Number) rshift(nbits int) Number {
|
||||
pub fn (a &Number) right_shift(amount int) Number {
|
||||
c := Number{}
|
||||
#c.value = a.val.value << BigInt(+nbits)
|
||||
#c.value = a.val.value << BigInt(+amount)
|
||||
|
||||
return c
|
||||
}
|
||||
@ -193,6 +223,11 @@ pub fn factorial(nn &Number) Number {
|
||||
return a
|
||||
}
|
||||
|
||||
[deprecated: 'use factorial_int instead']
|
||||
pub fn fact(n int) Number {
|
||||
return factorial_int(n)
|
||||
}
|
||||
|
||||
pub fn factorial_int(n int) Number {
|
||||
return factorial(from_int(n))
|
||||
}
|
||||
|
@ -389,7 +389,7 @@ const factorial_test_data = [
|
||||
]
|
||||
// vfmt on
|
||||
|
||||
// for lshift and rshift
|
||||
// for left_shift and right_shift
|
||||
struct ShiftTest {
|
||||
base TestInteger
|
||||
amount u32
|
||||
@ -397,7 +397,7 @@ struct ShiftTest {
|
||||
}
|
||||
|
||||
// vfmt off
|
||||
const lshift_test_data = [
|
||||
const left_shift_test_data = [
|
||||
ShiftTest{ 45, 2, 45 * 4 },
|
||||
ShiftTest{ 45, 3, 45 * 8 },
|
||||
ShiftTest{ 45, 4, 45 * 16 },
|
||||
@ -406,7 +406,7 @@ const lshift_test_data = [
|
||||
ShiftTest{ [u8(1), 1, 1], 56, [u8(1), 1, 1, 0, 0, 0, 0, 0, 0, 0] },
|
||||
]
|
||||
|
||||
const rshift_test_data = [
|
||||
const right_shift_test_data = [
|
||||
ShiftTest{ 45, 3, 5 },
|
||||
ShiftTest{ 0x13374956, 16, 0x1337 },
|
||||
ShiftTest{ [u8(1), 1, 1, 0, 0, 0, 0, 0, 0, 0], 56, [u8(1), 1, 1] },
|
||||
@ -435,7 +435,7 @@ const bit_len_test_data = [
|
||||
BitLenTest{ big.zero_int, 0 },
|
||||
BitLenTest{ big.one_int, 1 },
|
||||
BitLenTest{ u32(0xffffffff), 32 },
|
||||
BitLenTest{ big.one_int.lshift(1239), 1240 },
|
||||
BitLenTest{ big.one_int.left_shift(1239), 1240 },
|
||||
BitLenTest{ '4338476092346017364013796407961305761039463198075691378460917856', 212 },
|
||||
]
|
||||
// vfmt on
|
||||
@ -639,15 +639,15 @@ fn test_inc_and_dec() {
|
||||
assert b == c
|
||||
}
|
||||
|
||||
fn test_lshift() {
|
||||
for t in lshift_test_data {
|
||||
assert t.base.parse().lshift(t.amount) == t.expected.parse()
|
||||
fn test_left_shift() {
|
||||
for t in left_shift_test_data {
|
||||
assert t.base.parse().left_shift(t.amount) == t.expected.parse()
|
||||
}
|
||||
}
|
||||
|
||||
fn test_rshift() {
|
||||
for t in rshift_test_data {
|
||||
assert t.base.parse().rshift(t.amount) == t.expected.parse()
|
||||
fn test_right_shift() {
|
||||
for t in right_shift_test_data {
|
||||
assert t.base.parse().right_shift(t.amount) == t.expected.parse()
|
||||
}
|
||||
}
|
||||
|
||||
@ -693,7 +693,7 @@ fn test_isqrt() {
|
||||
}
|
||||
|
||||
fn test_bitwise_ops() {
|
||||
a := big.integer_from_int(1).lshift(512)
|
||||
a := big.integer_from_int(1).left_shift(512)
|
||||
b := a - big.one_int
|
||||
assert a.bitwise_and(b) == big.zero_int
|
||||
assert b.bitwise_xor(b) == big.zero_int
|
||||
@ -732,7 +732,7 @@ fn test_set_bit() {
|
||||
a.set_bit(3, true)
|
||||
assert a.int() == 40
|
||||
a.set_bit(50, true)
|
||||
assert a == big.one_int.lshift(50) + big.integer_from_int(40)
|
||||
assert a == big.one_int.left_shift(50) + big.integer_from_int(40)
|
||||
b := a
|
||||
a.set_bit(100, false)
|
||||
assert a == b
|
||||
|
@ -34,9 +34,9 @@ fn binary_divide_array_by_array(operand_a []u32, operand_b []u32, mut quotient [
|
||||
|
||||
// align
|
||||
if lead_zer_remainder < lead_zer_divisor {
|
||||
lshift_in_place(mut divisor, lead_zer_divisor - lead_zer_remainder)
|
||||
left_shift_in_place(mut divisor, lead_zer_divisor - lead_zer_remainder)
|
||||
} else if lead_zer_remainder > lead_zer_divisor {
|
||||
lshift_in_place(mut remainder, lead_zer_remainder - lead_zer_divisor)
|
||||
left_shift_in_place(mut remainder, lead_zer_remainder - lead_zer_divisor)
|
||||
}
|
||||
|
||||
$if debug {
|
||||
@ -47,13 +47,13 @@ fn binary_divide_array_by_array(operand_a []u32, operand_b []u32, mut quotient [
|
||||
bit_set(mut quotient, bit_idx)
|
||||
subtract_align_last_byte_in_place(mut remainder, divisor)
|
||||
}
|
||||
rshift_in_place(mut divisor, 1)
|
||||
right_shift_in_place(mut divisor, 1)
|
||||
}
|
||||
|
||||
// adjust
|
||||
if lead_zer_remainder > lead_zer_divisor {
|
||||
// rshift_in_place(mut quotient, lead_zer_remainder - lead_zer_divisor)
|
||||
rshift_in_place(mut remainder, lead_zer_remainder - lead_zer_divisor)
|
||||
// right_shift_in_place(mut quotient, lead_zer_remainder - lead_zer_divisor)
|
||||
right_shift_in_place(mut remainder, lead_zer_remainder - lead_zer_divisor)
|
||||
}
|
||||
shrink_tail_zeros(mut remainder)
|
||||
shrink_tail_zeros(mut quotient)
|
||||
@ -115,7 +115,7 @@ fn subtract_align_last_byte_in_place(mut a []u32, b []u32) {
|
||||
// there is no overflow. We know that the last bits are zero
|
||||
// and that n <= 32
|
||||
[direct_array_access; inline]
|
||||
fn lshift_in_place(mut a []u32, n u32) {
|
||||
fn left_shift_in_place(mut a []u32, n u32) {
|
||||
mut carry := u32(0)
|
||||
mut prec_carry := u32(0)
|
||||
mask := ((u32(1) << n) - 1) << (32 - n)
|
||||
@ -130,7 +130,7 @@ fn lshift_in_place(mut a []u32, n u32) {
|
||||
// logical right shift without control because these digits have already been
|
||||
// shift left before
|
||||
[direct_array_access; inline]
|
||||
fn rshift_in_place(mut a []u32, n u32) {
|
||||
fn right_shift_in_place(mut a []u32, n u32) {
|
||||
mut carry := u32(0)
|
||||
mut prec_carry := u32(0)
|
||||
mask := u32((1 << n) - 1)
|
||||
|
@ -2,35 +2,35 @@ module big
|
||||
|
||||
import rand
|
||||
|
||||
fn test_lshift_in_place() {
|
||||
fn test_left_shift_in_place() {
|
||||
mut a := [u32(1), 1, 1, 1, 1]
|
||||
lshift_in_place(mut a, 1)
|
||||
left_shift_in_place(mut a, 1)
|
||||
assert a == [u32(2), 2, 2, 2, 2]
|
||||
lshift_in_place(mut a, 7)
|
||||
left_shift_in_place(mut a, 7)
|
||||
assert a == [u32(256), 256, 256, 256, 256]
|
||||
mut b := [u32(0x80000001), 0xc0000000, 0x80000000, 0x7fffffff]
|
||||
lshift_in_place(mut b, 1)
|
||||
left_shift_in_place(mut b, 1)
|
||||
assert b == [u32(2), 0x80000001, 1, 0xffffffff]
|
||||
mut c := [u32(0x00ffffff), 0xf0f0f0f0, 1, 0x3fffffff, 1]
|
||||
lshift_in_place(mut c, 2)
|
||||
left_shift_in_place(mut c, 2)
|
||||
assert c == [u32(0x3fffffc), 0xc3c3c3c0, 7, 0xfffffffc, 4]
|
||||
}
|
||||
|
||||
fn test_rshift_in_place() {
|
||||
fn test_right_shift_in_place() {
|
||||
mut a := [u32(2), 2, 2, 2, 2]
|
||||
rshift_in_place(mut a, 1)
|
||||
right_shift_in_place(mut a, 1)
|
||||
assert a == [u32(1), 1, 1, 1, 1]
|
||||
a = [u32(256), 256, 256, 256, 256]
|
||||
rshift_in_place(mut a, 7)
|
||||
right_shift_in_place(mut a, 7)
|
||||
assert a == [u32(2), 2, 2, 2, 2]
|
||||
a = [u32(0), 0, 1]
|
||||
rshift_in_place(mut a, 1)
|
||||
right_shift_in_place(mut a, 1)
|
||||
assert a == [u32(0), 0x80000000, 0]
|
||||
mut b := [u32(3), 0x80000001, 1, 0xffffffff]
|
||||
rshift_in_place(mut b, 1)
|
||||
right_shift_in_place(mut b, 1)
|
||||
assert b == [u32(0x80000001), 0xc0000000, 0x80000000, 0x7fffffff]
|
||||
mut c := [u32(0x03ffffff), 0xc3c3c3c0, 7, 0xfffffffc, 4]
|
||||
rshift_in_place(mut c, 2)
|
||||
right_shift_in_place(mut c, 2)
|
||||
assert c == [u32(0x00ffffff), 0xf0f0f0f0, 1, 0x3fffffff, 1]
|
||||
}
|
||||
|
||||
|
@ -29,8 +29,8 @@ fn (m Integer) montgomery() MontgomeryContext {
|
||||
// ri := multiplicative inverse of r in the ring Z/nZ
|
||||
// ri * r == 1 (mod n)
|
||||
// ni = ((ri * 2^(log_2(n))) - 1) / n
|
||||
ni: (one_int.lshift(b).mod_inv(n).lshift(b) - one_int) / n
|
||||
rr: one_int.lshift(b * 2) % n
|
||||
ni: (one_int.left_shift(b).mod_inv(n).left_shift(b) - one_int) / n
|
||||
rr: one_int.left_shift(b * 2) % n
|
||||
}
|
||||
}
|
||||
|
||||
@ -164,7 +164,7 @@ fn (a Integer) mont_even(x Integer, m Integer) Integer {
|
||||
}
|
||||
|
||||
m1, j := m.rsh_to_set_bit()
|
||||
m2 := one_int.lshift(j)
|
||||
m2 := one_int.left_shift(j)
|
||||
|
||||
$if debug {
|
||||
assert m1 * m2 == m
|
||||
@ -321,7 +321,7 @@ fn (a Integer) to_mont(ctx MontgomeryContext) Integer {
|
||||
fn (a Integer) from_mont(ctx MontgomeryContext) Integer {
|
||||
log2n := u32(ctx.n.bit_len())
|
||||
|
||||
r := (a + ((a.mask_bits(log2n) * ctx.ni).mask_bits(log2n) * ctx.n)).rshift(log2n)
|
||||
r := (a + ((a.mask_bits(log2n) * ctx.ni).mask_bits(log2n) * ctx.n)).right_shift(log2n)
|
||||
|
||||
return if r.abs_cmp(ctx.n) >= 0 {
|
||||
r - ctx.n
|
||||
|
@ -265,59 +265,61 @@ fn integer_from_regular_string(characters string, radix u32) Integer {
|
||||
}
|
||||
}
|
||||
|
||||
// abs returns the absolute value of the integer.
|
||||
pub fn (integer Integer) abs() Integer {
|
||||
return if integer.signum == 0 {
|
||||
// abs returns the absolute value of the integer `a`.
|
||||
pub fn (a Integer) abs() Integer {
|
||||
return if a.signum == 0 {
|
||||
zero_int
|
||||
} else {
|
||||
Integer{
|
||||
digits: integer.digits.clone()
|
||||
digits: a.digits.clone()
|
||||
signum: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// neg returns the result of negation of the integer.
|
||||
pub fn (integer Integer) neg() Integer {
|
||||
return if integer.signum == 0 {
|
||||
// neg returns the result of negation of the integer `a`.
|
||||
pub fn (a Integer) neg() Integer {
|
||||
return if a.signum == 0 {
|
||||
zero_int
|
||||
} else {
|
||||
Integer{
|
||||
digits: integer.digits.clone()
|
||||
signum: -integer.signum
|
||||
digits: a.digits.clone()
|
||||
signum: -a.signum
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (integer Integer) + (addend Integer) Integer {
|
||||
// + returns the sum of the integers `augend` and `addend`.
|
||||
pub fn (augend Integer) + (addend Integer) Integer {
|
||||
// Quick exits
|
||||
if integer.signum == 0 {
|
||||
if augend.signum == 0 {
|
||||
return addend.clone()
|
||||
}
|
||||
if addend.signum == 0 {
|
||||
return integer.clone()
|
||||
return augend.clone()
|
||||
}
|
||||
// Non-zero cases
|
||||
return if integer.signum == addend.signum {
|
||||
integer.add(addend)
|
||||
return if augend.signum == addend.signum {
|
||||
augend.add(addend)
|
||||
} else { // Unequal signs
|
||||
integer.subtract(addend)
|
||||
augend.subtract(addend)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (integer Integer) - (subtrahend Integer) Integer {
|
||||
// - returns the difference of the integers `minuend` and `subtrahend`
|
||||
pub fn (minuend Integer) - (subtrahend Integer) Integer {
|
||||
// Quick exits
|
||||
if integer.signum == 0 {
|
||||
if minuend.signum == 0 {
|
||||
return subtrahend.neg()
|
||||
}
|
||||
if subtrahend.signum == 0 {
|
||||
return integer.clone()
|
||||
return minuend.clone()
|
||||
}
|
||||
// Non-zero cases
|
||||
return if integer.signum == subtrahend.signum {
|
||||
integer.subtract(subtrahend)
|
||||
return if minuend.signum == subtrahend.signum {
|
||||
minuend.subtract(subtrahend)
|
||||
} else {
|
||||
integer.add(subtrahend)
|
||||
minuend.add(subtrahend)
|
||||
}
|
||||
}
|
||||
|
||||
@ -346,44 +348,45 @@ fn (integer Integer) subtract(subtrahend Integer) Integer {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (integer Integer) * (multiplicand Integer) Integer {
|
||||
// * returns the product of the integers `multiplicand` and `multiplier`.
|
||||
pub fn (multiplicand Integer) * (multiplier Integer) Integer {
|
||||
// Quick exits
|
||||
if integer.signum == 0 || multiplicand.signum == 0 {
|
||||
if multiplicand.signum == 0 || multiplier.signum == 0 {
|
||||
return zero_int
|
||||
}
|
||||
if integer == one_int {
|
||||
if multiplicand == one_int {
|
||||
return multiplier.clone()
|
||||
}
|
||||
if multiplier == one_int {
|
||||
return multiplicand.clone()
|
||||
}
|
||||
if multiplicand == one_int {
|
||||
return integer.clone()
|
||||
}
|
||||
// The final sign is the product of the signs
|
||||
mut storage := []u32{len: integer.digits.len + multiplicand.digits.len}
|
||||
multiply_digit_array(integer.digits, multiplicand.digits, mut storage)
|
||||
mut storage := []u32{len: multiplicand.digits.len + multiplier.digits.len}
|
||||
multiply_digit_array(multiplicand.digits, multiplier.digits, mut storage)
|
||||
return Integer{
|
||||
signum: integer.signum * multiplicand.signum
|
||||
signum: multiplicand.signum * multiplier.signum
|
||||
digits: storage
|
||||
}
|
||||
}
|
||||
|
||||
// div_mod returns the quotient and remainder of the integer division.
|
||||
pub fn (integer Integer) div_mod(divisor Integer) (Integer, Integer) {
|
||||
// div_mod returns the quotient and remainder from the division of the integers `dividend` divided by `divisor`.
|
||||
pub fn (dividend Integer) div_mod(divisor Integer) (Integer, Integer) {
|
||||
// Quick exits
|
||||
if divisor.signum == 0 {
|
||||
panic('Cannot divide by zero')
|
||||
}
|
||||
if integer.signum == 0 {
|
||||
if dividend.signum == 0 {
|
||||
return zero_int, zero_int
|
||||
}
|
||||
if divisor == one_int {
|
||||
return integer.clone(), zero_int
|
||||
return dividend.clone(), zero_int
|
||||
}
|
||||
if divisor.signum == -1 {
|
||||
q, r := integer.div_mod(divisor.neg())
|
||||
q, r := dividend.div_mod(divisor.neg())
|
||||
return q.neg(), r
|
||||
}
|
||||
if integer.signum == -1 {
|
||||
q, r := integer.neg().div_mod(divisor)
|
||||
if dividend.signum == -1 {
|
||||
q, r := dividend.neg().div_mod(divisor)
|
||||
if r.signum == 0 {
|
||||
return q.neg(), zero_int
|
||||
} else {
|
||||
@ -391,9 +394,9 @@ pub fn (integer Integer) div_mod(divisor Integer) (Integer, Integer) {
|
||||
}
|
||||
}
|
||||
// Division for positive integers
|
||||
mut q := []u32{cap: integer.digits.len - divisor.digits.len + 1}
|
||||
mut r := []u32{cap: integer.digits.len}
|
||||
divide_digit_array(integer.digits, divisor.digits, mut q, mut r)
|
||||
mut q := []u32{cap: dividend.digits.len - divisor.digits.len + 1}
|
||||
mut r := []u32{cap: dividend.digits.len}
|
||||
divide_digit_array(dividend.digits, divisor.digits, mut q, mut r)
|
||||
quotient := Integer{
|
||||
signum: if q.len == 0 { 0 } else { 1 }
|
||||
digits: q
|
||||
@ -405,13 +408,15 @@ pub fn (integer Integer) div_mod(divisor Integer) (Integer, Integer) {
|
||||
return quotient, remainder
|
||||
}
|
||||
|
||||
pub fn (a Integer) / (b Integer) Integer {
|
||||
q, _ := a.div_mod(b)
|
||||
// / returns the quotient of `dividend` divided by `divisor`.
|
||||
pub fn (dividend Integer) / (divisor Integer) Integer {
|
||||
q, _ := dividend.div_mod(divisor)
|
||||
return q
|
||||
}
|
||||
|
||||
pub fn (a Integer) % (b Integer) Integer {
|
||||
_, r := a.div_mod(b)
|
||||
// % returns the remainder of `dividend` divided by `divisor`.
|
||||
pub fn (dividend Integer) % (divisor Integer) Integer {
|
||||
_, r := dividend.div_mod(divisor)
|
||||
return r
|
||||
}
|
||||
|
||||
@ -454,7 +459,7 @@ fn (a Integer) mask_bits(n u32) Integer {
|
||||
}
|
||||
}
|
||||
|
||||
// pow returns the integer `a` raised to the power of the u32 `exponent`.
|
||||
// pow returns the integer `base` raised to the power of the u32 `exponent`.
|
||||
pub fn (base Integer) pow(exponent u32) Integer {
|
||||
if exponent == 0 {
|
||||
return one_int
|
||||
@ -475,7 +480,7 @@ pub fn (base Integer) pow(exponent u32) Integer {
|
||||
return x * y
|
||||
}
|
||||
|
||||
// mod_pow returns the integer `a` raised to the power of the u32 `exponent` modulo the integer `modulus`.
|
||||
// mod_pow returns the integer `base` raised to the power of the u32 `exponent` modulo the integer `modulus`.
|
||||
pub fn (base Integer) mod_pow(exponent u32, modulus Integer) Integer {
|
||||
if exponent == 0 {
|
||||
return one_int
|
||||
@ -545,16 +550,17 @@ pub fn (base Integer) big_mod_pow(exponent Integer, modulus Integer) !Integer {
|
||||
}
|
||||
}
|
||||
|
||||
// inc returns the integer `a` incremented by 1.
|
||||
// inc increments `a` by 1 in place.
|
||||
pub fn (mut a Integer) inc() {
|
||||
a = a + one_int
|
||||
}
|
||||
|
||||
// dec returns the integer `a` decremented by 1.
|
||||
// dec decrements `a` by 1 in place.
|
||||
pub fn (mut a Integer) dec() {
|
||||
a = a - one_int
|
||||
}
|
||||
|
||||
// == returns `true` if the integers `a` and `b` are equal in value and sign.
|
||||
pub fn (a Integer) == (b Integer) bool {
|
||||
return a.signum == b.signum && a.digits.len == b.digits.len && a.digits == b.digits
|
||||
}
|
||||
@ -565,6 +571,7 @@ pub fn (a Integer) abs_cmp(b Integer) int {
|
||||
return compare_digit_array(a.digits, b.digits)
|
||||
}
|
||||
|
||||
// < returns `true` if the integer `a` is less than `b`.
|
||||
pub fn (a Integer) < (b Integer) bool {
|
||||
// Quick exits based on signum value:
|
||||
if a.signum < b.signum {
|
||||
@ -609,7 +616,7 @@ pub fn (mut a Integer) set_bit(i u32, value bool) {
|
||||
|
||||
if target_index >= a.digits.len {
|
||||
if value {
|
||||
a = one_int.lshift(i).bitwise_or(a)
|
||||
a = one_int.left_shift(i).bitwise_or(a)
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -676,8 +683,14 @@ pub fn (a Integer) bitwise_xor(b Integer) Integer {
|
||||
}
|
||||
|
||||
// lshift returns the integer `a` shifted left by `amount` bits.
|
||||
[direct_array_access]
|
||||
[deprecated: 'use a.Integer.left_shift(amount) instead']
|
||||
pub fn (a Integer) lshift(amount u32) Integer {
|
||||
return a.left_shift(amount)
|
||||
}
|
||||
|
||||
// left_shift returns the integer `a` shifted left by `amount` bits.
|
||||
[direct_array_access]
|
||||
pub fn (a Integer) left_shift(amount u32) Integer {
|
||||
if a.signum == 0 {
|
||||
return a
|
||||
}
|
||||
@ -700,8 +713,14 @@ pub fn (a Integer) lshift(amount u32) Integer {
|
||||
}
|
||||
|
||||
// rshift returns the integer `a` shifted right by `amount` bits.
|
||||
[direct_array_access]
|
||||
[deprecated: 'use a.Integer.right_shift(amount) instead']
|
||||
pub fn (a Integer) rshift(amount u32) Integer {
|
||||
return a.right_shift(amount)
|
||||
}
|
||||
|
||||
// right_shift returns the integer `a` shifted right by `amount` bits.
|
||||
[direct_array_access]
|
||||
pub fn (a Integer) right_shift(amount u32) Integer {
|
||||
if a.signum == 0 {
|
||||
return a
|
||||
}
|
||||
@ -727,8 +746,14 @@ pub fn (a Integer) rshift(amount u32) Integer {
|
||||
}
|
||||
|
||||
// binary_str returns the binary string representation of the integer `a`.
|
||||
[direct_array_access]
|
||||
[deprecated: 'use integer.bin_str() instead']
|
||||
pub fn (integer Integer) binary_str() string {
|
||||
return integer.bin_str()
|
||||
}
|
||||
|
||||
// bin_str returns the binary string representation of the integer `a`.
|
||||
[direct_array_access]
|
||||
pub fn (integer Integer) bin_str() string {
|
||||
// We have the zero integer
|
||||
if integer.signum == 0 {
|
||||
return '0'
|
||||
@ -919,9 +944,9 @@ pub fn (a Integer) isqrt() Integer {
|
||||
}
|
||||
mut result := zero_int
|
||||
for shift >= 0 {
|
||||
result = result.lshift(1)
|
||||
result = result.left_shift(1)
|
||||
larger := result + one_int
|
||||
if (larger * larger).abs_cmp(a.rshift(u32(shift))) <= 0 {
|
||||
if (larger * larger).abs_cmp(a.right_shift(u32(shift))) <= 0 {
|
||||
result = larger
|
||||
}
|
||||
shift -= 2
|
||||
@ -968,7 +993,7 @@ fn gcd_binary(x Integer, y Integer) Integer {
|
||||
a, _ = diff.abs().rsh_to_set_bit()
|
||||
}
|
||||
|
||||
return b.lshift(shift)
|
||||
return b.left_shift(shift)
|
||||
}
|
||||
|
||||
// mod_inverse calculates the multiplicative inverse of the integer `a` in the ring `ℤ/nℤ`.
|
||||
@ -1026,7 +1051,7 @@ fn (a Integer) mod_inv(m Integer) Integer {
|
||||
tmp := if q == one_int {
|
||||
x
|
||||
} else if q.digits.len == 1 && q.digits[0] & (q.digits[0] - 1) == 0 {
|
||||
x.lshift(u32(bits.trailing_zeros_32(q.digits[0])))
|
||||
x.left_shift(u32(bits.trailing_zeros_32(q.digits[0])))
|
||||
} else {
|
||||
q * x
|
||||
} + y
|
||||
@ -1065,7 +1090,7 @@ fn (x Integer) rsh_to_set_bit() (Integer, u32) {
|
||||
n++
|
||||
}
|
||||
n = (n << 5) + u32(bits.trailing_zeros_32(x.digits[n]))
|
||||
return x.rshift(n), n
|
||||
return x.right_shift(n), n
|
||||
}
|
||||
|
||||
[direct_array_access; inline]
|
||||
|
@ -27,11 +27,11 @@ fn newton_divide_array_by_array(operand_a []u32, operand_b []u32, mut quotient [
|
||||
digits: operand_b
|
||||
}
|
||||
|
||||
k := bit_length(a) + bit_length(b) // a*b < 2**k
|
||||
k := a.bit_len() + b.bit_len() // a*b < 2**k
|
||||
mut x := integer_from_int(2) // 0 < x < 2**(k+1)/b // initial guess for convergence
|
||||
// https://en.wikipedia.org/wiki/Division_algorithm#Newton%E2%80%93Raphson_division
|
||||
// use 48/17 - 32/17.D (divisor)
|
||||
initial_guess := (((integer_from_int(48) - (integer_from_int(32) * b)) * integer_from_i64(0x0f0f0f0f0f0f0f0f)).rshift(64)).neg() // / 17 == 0x11
|
||||
initial_guess := (((integer_from_int(48) - (integer_from_int(32) * b)) * integer_from_i64(0x0f0f0f0f0f0f0f0f)).right_shift(64)).neg() // / 17 == 0x11
|
||||
if initial_guess > zero_int {
|
||||
x = initial_guess
|
||||
}
|
||||
@ -39,12 +39,12 @@ fn newton_divide_array_by_array(operand_a []u32, operand_b []u32, mut quotient [
|
||||
pow2_k_plus_1 := pow2(k + 1) // outside of the loop to optimize allocatio
|
||||
for lastx != x { // main loop
|
||||
lastx = x
|
||||
x = (x * (pow2_k_plus_1 - (x * b))).rshift(u32(k))
|
||||
x = (x * (pow2_k_plus_1 - (x * b))).right_shift(u32(k))
|
||||
}
|
||||
if x * b < pow2(k) {
|
||||
x.inc()
|
||||
}
|
||||
mut q := (a * x).rshift(u32(k))
|
||||
mut q := (a * x).right_shift(u32(k))
|
||||
// possible adjustments. see literature
|
||||
if q * b > a {
|
||||
q.dec()
|
||||
@ -61,6 +61,7 @@ fn newton_divide_array_by_array(operand_a []u32, operand_b []u32, mut quotient [
|
||||
}
|
||||
|
||||
// bit_length returns the number of bits needed to represent the absolute value of the integer a.
|
||||
[deprecated: 'use a.bit_len() instead']
|
||||
[inline]
|
||||
pub fn bit_length(a Integer) int {
|
||||
return a.digits.len * 32 - bits.leading_zeros_32(a.digits.last())
|
||||
@ -141,9 +142,9 @@ fn karatsuba_multiply_digit_array(operand_a []u32, operand_b []u32, mut storage
|
||||
subtract_in_place(mut p_2, storage) // p_1
|
||||
subtract_in_place(mut p_2, p_3)
|
||||
|
||||
// return p_1.lshift(2 * u32(half * 32)) + p_2.lshift(u32(half * 32)) + p_3
|
||||
lshift_digits_in_place(mut storage, 2 * half)
|
||||
lshift_digits_in_place(mut p_2, half)
|
||||
// return p_1.left_shift(2 * u32(half * 32)) + p_2.left_shift(u32(half * 32)) + p_3
|
||||
left_shift_digits_in_place(mut storage, 2 * half)
|
||||
left_shift_digits_in_place(mut p_2, half)
|
||||
add_in_place(mut storage, p_2)
|
||||
add_in_place(mut storage, p_3)
|
||||
|
||||
@ -224,21 +225,22 @@ fn toom3_multiply_digit_array(operand_a []u32, operand_b []u32, mut storage []u3
|
||||
ptemp += a1
|
||||
qtemp += b1
|
||||
p1 := ptemp * qtemp
|
||||
p2 := ((ptemp + a2).lshift(1) - a0) * ((qtemp + b2).lshift(1) - b0)
|
||||
p2 := ((ptemp + a2).left_shift(1) - a0) * ((qtemp + b2).left_shift(1) - b0)
|
||||
pinf := a2 * b2
|
||||
|
||||
mut t2 := (p2 - vm1) / three_int
|
||||
mut tm1 := (p1 - vm1).rshift(1)
|
||||
mut tm1 := (p1 - vm1).right_shift(1)
|
||||
mut t1 := p1 - p0
|
||||
t2 = (t2 - t1).rshift(1)
|
||||
t2 = (t2 - t1).right_shift(1)
|
||||
t1 = (t1 - tm1 - pinf)
|
||||
t2 = t2 - pinf.lshift(1)
|
||||
t2 = t2 - pinf.left_shift(1)
|
||||
tm1 = tm1 - t2
|
||||
|
||||
// shift amount
|
||||
s := u32(k) << 5
|
||||
|
||||
result := (((pinf.lshift(s) + t2).lshift(s) + t1).lshift(s) + tm1).lshift(s) + p0
|
||||
result := (((pinf.left_shift(s) + t2).left_shift(s) + t1).left_shift(s) + tm1).left_shift(s) +
|
||||
p0
|
||||
|
||||
storage = result.digits.clone()
|
||||
}
|
||||
@ -255,7 +257,7 @@ fn pow2(k int) Integer {
|
||||
|
||||
// optimized left shift in place. amount must be positive
|
||||
[direct_array_access]
|
||||
fn lshift_digits_in_place(mut a []u32, amount int) {
|
||||
fn left_shift_digits_in_place(mut a []u32, amount int) {
|
||||
a_len := a.len
|
||||
// control or allocate capacity
|
||||
for _ in a_len .. a_len + amount {
|
||||
@ -271,7 +273,7 @@ fn lshift_digits_in_place(mut a []u32, amount int) {
|
||||
|
||||
// optimized right shift in place. amount must be positive
|
||||
[direct_array_access]
|
||||
fn rshift_digits_in_place(mut a []u32, amount int) {
|
||||
fn right_shift_digits_in_place(mut a []u32, amount int) {
|
||||
for index := 0; index < a.len - amount; index++ {
|
||||
a[index] = a[index + amount]
|
||||
}
|
||||
|
@ -24,9 +24,9 @@ fn test_add_in_place() {
|
||||
assert a == [u32(0x17ff72ad), 0x1439]
|
||||
}
|
||||
|
||||
fn test_lshift_digits_in_place() {
|
||||
fn test_left_shift_digits_in_place() {
|
||||
mut a := [u32(5), 6, 7, 8]
|
||||
lshift_digits_in_place(mut a, 2)
|
||||
left_shift_digits_in_place(mut a, 2)
|
||||
assert a == [u32(0), 0, 5, 6, 7, 8]
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user