diff --git a/examples/pidigits.v b/examples/pidigits.v new file mode 100644 index 0000000000..85265cb875 --- /dev/null +++ b/examples/pidigits.v @@ -0,0 +1,52 @@ +module main + +import os +import math.big + +const digits_to_print = os.args[1] or { '1000' }.int() + +const zero = big.integer_from_int(0) +const one = big.integer_from_int(1) +const two = big.integer_from_int(2) +const three = big.integer_from_int(3) +const four = big.integer_from_int(4) +const ten = big.integer_from_int(10) + +fn main() { + unbuffer_stdout() + mut digits_printed := 0 + mut k := one + mut n1 := four + mut n2 := three + mut d := one + mut u := zero + mut v := zero + mut w := zero + for { + u = n1 / d + v = n2 / d + u_int := u.int() + v_int := v.int() + if u_int == v_int { + print(u_int) + digits_printed++ + if digits_printed >= digits_to_print { + println('') + return + } + to_minus := u * ten * d + n1 = n1 * ten - to_minus + n2 = n2 * ten - to_minus + } else { + k2 := k * two + u = n1 * (k2 - one) + v = n2 * two + w = n1 * (k - one) + n1 = u + v + u = n2 * (k + two) + n2 = w + u + d = d * (k2 + one) + k += one + } + } +} diff --git a/vlib/math/big/array_ops.v b/vlib/math/big/array_ops.v index e785299e81..7a023197cf 100644 --- a/vlib/math/big/array_ops.v +++ b/vlib/math/big/array_ops.v @@ -199,9 +199,7 @@ fn divide_digit_array(operand_a []u32, operand_b []u32, mut quotient []u32, mut // a < b => q, r = 0, a if cmp_result < 0 { quotient.clear() - for index in 0 .. operand_a.len { - remainder << operand_a[index] - } + remainder << operand_a return } if operand_b.len == 1 { diff --git a/vlib/math/big/division_array_ops.v b/vlib/math/big/division_array_ops.v index bf4a2a50f6..e7f277498b 100644 --- a/vlib/math/big/division_array_ops.v +++ b/vlib/math/big/division_array_ops.v @@ -6,9 +6,7 @@ import math.bits // Both quotient and remaider are allocated but of length 0 @[direct_array_access] fn binary_divide_array_by_array(operand_a []u32, operand_b []u32, mut quotient []u32, mut remainder []u32) { - for index in 0 .. operand_a.len { - remainder << operand_a[index] - } + remainder << operand_a len_diff := operand_a.len - operand_b.len $if debug { @@ -20,9 +18,7 @@ fn binary_divide_array_by_array(operand_a []u32, operand_b []u32, mut quotient [ for _ in 0 .. len_diff { divisor << u32(0) } - for index in 0 .. operand_b.len { - divisor << operand_b[index] - } + divisor << operand_b for _ in 0 .. len_diff + 1 { quotient << u32(0) } diff --git a/vlib/math/big/integer.v b/vlib/math/big/integer.v index 76f03a0022..ae809dfa50 100644 --- a/vlib/math/big/integer.v +++ b/vlib/math/big/integer.v @@ -615,12 +615,14 @@ pub fn (mut a Integer) dec() { } // == returns `true` if the integers `a` and `b` are equal in value and sign. +@[inline] pub fn (a Integer) == (b Integer) bool { return a.signum == b.signum && a.digits.len == b.digits.len && a.digits == b.digits } // abs_cmp returns the result of comparing the magnitudes of the integers `a` and `b`. // It returns a negative int if `|a| < |b|`, 0 if `|a| == |b|`, and a positive int if `|a| > |b|`. +@[inline] pub fn (a Integer) abs_cmp(b Integer) int { return compare_digit_array(a.digits, b.digits) } @@ -921,6 +923,7 @@ fn u32_to_hex_with_lz(value u32) string { // int returns the integer value of the integer `a`. // NOTE: This may cause loss of precision. +@[direct_array_access] pub fn (a Integer) int() int { if a.signum == 0 { return 0 diff --git a/vlib/math/big/special_array_ops.v b/vlib/math/big/special_array_ops.v index b609aec127..b1437aeedb 100644 --- a/vlib/math/big/special_array_ops.v +++ b/vlib/math/big/special_array_ops.v @@ -114,8 +114,8 @@ fn karatsuba_multiply_digit_array(operand_a []u32, operand_b []u32, mut storage // thanks to the base cases we can pass zero-length arrays to the mult func half := imax(operand_a.len, operand_b.len) / 2 - a_l := operand_a[0..half] - a_h := operand_a[half..] + a_l := unsafe { operand_a[0..half] } + a_h := unsafe { operand_a[half..] } mut b_l := []u32{} mut b_h := []u32{} if half <= operand_b.len { @@ -169,15 +169,15 @@ fn toom3_multiply_digit_array(operand_a []u32, operand_b []u32, mut storage []u3 // Slices of a and b a0 := Integer{ - digits: operand_a[0..k] + digits: unsafe { operand_a[0..k] } signum: 1 } a1 := Integer{ - digits: operand_a[k..k2] + digits: unsafe { operand_a[k..k2] } signum: 1 } a2 := Integer{ - digits: operand_a[k2..] + digits: unsafe { operand_a[k2..] } signum: 1 }