examples: add pidigits.v; optimise math.big's Integer divide a bit (#21239)

This commit is contained in:
Delyan Angelov 2024-04-09 17:01:05 +03:00 committed by GitHub
parent d25e349020
commit 4dcc9265e1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 63 additions and 14 deletions

52
examples/pidigits.v Normal file
View File

@ -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
}
}
}

View File

@ -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 {

View File

@ -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)
}

View File

@ -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

View File

@ -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
}