big: Remove core:fmt usage + Add a little demo to examples/demo.

This commit is contained in:
Jeroen van Rijn
2021-09-06 23:26:19 +02:00
parent b0edac58b9
commit 5619b349be
6 changed files with 179 additions and 180 deletions
+1 -1
View File
@@ -5,7 +5,7 @@
set TEST_ARGS=-fast-tests
:set TEST_ARGS=
:odin build . -build-mode:shared -show-timings -o:minimal -no-bounds-check -define:MATH_BIG_EXE=false && python test.py %TEST_ARGS%
odin build . -build-mode:shared -show-timings -o:size -no-bounds-check -define:MATH_BIG_EXE=false && python test.py %TEST_ARGS%
:odin build . -build-mode:shared -show-timings -o:size -no-bounds-check -define:MATH_BIG_EXE=false && python test.py %TEST_ARGS%
:odin build . -build-mode:shared -show-timings -o:size -define:MATH_BIG_EXE=false && python test.py %TEST_ARGS%
:odin build . -build-mode:shared -show-timings -o:speed -no-bounds-check -define:MATH_BIG_EXE=false && python test.py %TEST_ARGS%
:odin build . -build-mode:shared -show-timings -o:speed -define:MATH_BIG_EXE=false && python test.py -fast-tests %TEST_ARGS%
+1
View File
@@ -174,6 +174,7 @@ Error :: enum int {
}
Error_String :: #partial [Error]string{
.Okay = "Okay",
.Out_Of_Memory = "Out of memory",
.Invalid_Pointer = "Invalid pointer",
.Invalid_Argument = "Invalid argument",
-152
View File
@@ -1,152 +0,0 @@
//+ignore
/*
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
Made available under Odin's BSD-3 license.
A BigInt implementation in Odin.
For the theoretical underpinnings, see Knuth's The Art of Computer Programming, Volume 2, section 4.3.
The code started out as an idiomatic source port of libTomMath, which is in the public domain, with thanks.
*/
package math_big
import "core:fmt"
import "core:mem"
print_configation :: proc() {
fmt.printf(
`
Configuration:
_DIGIT_BITS %v
_SMALL_MEMORY %v
_MIN_DIGIT_COUNT %v
_MAX_DIGIT_COUNT %v
_DEFAULT_DIGIT_COUNT %v
_MAX_COMBA %v
_WARRAY %v
_TAB_SIZE %v
_MAX_WIN_SIZE %v
MATH_BIG_USE_LUCAS_SELFRIDGE_TEST %v
Runtime tunable:
MUL_KARATSUBA_CUTOFF %v
SQR_KARATSUBA_CUTOFF %v
MUL_TOOM_CUTOFF %v
SQR_TOOM_CUTOFF %v
MAX_ITERATIONS_ROOT_N %v
FACTORIAL_MAX_N %v
FACTORIAL_BINARY_SPLIT_CUTOFF %v
FACTORIAL_BINARY_SPLIT_MAX_RECURSIONS %v
USE_MILLER_RABIN_ONLY %v
MAX_ITERATIONS_RANDOM_PRIME %v
`, _DIGIT_BITS,
_LOW_MEMORY,
_MIN_DIGIT_COUNT,
_MAX_DIGIT_COUNT,
_DEFAULT_DIGIT_COUNT,
_MAX_COMBA,
_WARRAY,
_TAB_SIZE,
_MAX_WIN_SIZE,
MATH_BIG_USE_LUCAS_SELFRIDGE_TEST,
MUL_KARATSUBA_CUTOFF,
SQR_KARATSUBA_CUTOFF,
MUL_TOOM_CUTOFF,
SQR_TOOM_CUTOFF,
MAX_ITERATIONS_ROOT_N,
FACTORIAL_MAX_N,
FACTORIAL_BINARY_SPLIT_CUTOFF,
FACTORIAL_BINARY_SPLIT_MAX_RECURSIONS,
USE_MILLER_RABIN_ONLY,
MAX_ITERATIONS_RANDOM_PRIME,
)
}
print :: proc(name: string, a: ^Int, base := i8(10), print_name := true, newline := true, print_extra_info := false) {
assert_if_nil(a)
as, err := itoa(a, base)
defer delete(as)
cb := internal_count_bits(a)
if print_name {
fmt.printf("%v", name)
}
if err != nil {
fmt.printf("%v (error: %v | %v)", name, err, a)
}
fmt.printf("%v", as)
if print_extra_info {
fmt.printf(" (base: %v, bits: %v (digits: %v), flags: %v)", base, cb, a.used, a.flags)
}
if newline {
fmt.println()
}
}
// printf :: fmt.printf;
demo :: proc() {
a, b, c, d, e, f, res := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}
defer destroy(a, b, c, d, e, f, res)
bits := 111
trials := -1
flags := Primality_Flags{}
fmt.printf("Trying to generate a %v bit prime using %v Miller-Rabin trials and options %v.\n", bits, trials, flags)
err: Error
{
SCOPED_TIMING(.random_prime)
err = internal_random_prime(a, bits, trials, flags)
}
print("a(10): ", a, 10, true, true, true)
fmt.printf("err: %v\n", err)
fmt.printf("RANDOM_PRIME_ITERATIONS_USED: %v\n", RANDOM_PRIME_ITERATIONS_USED)
nails := 0
count := internal_int_pack_count(a, u8, nails)
buf := make([]u8, count)
defer delete(buf)
written: int
order := Order.LSB_First
fmt.printf("\na.digit: %v\n", a.digit[:a.used])
written, err = internal_int_pack(a, buf, nails, order)
fmt.printf("\nPacked into buf: %v | err: %v | written: %v\n", buf, err, written)
err = internal_int_unpack(b, buf, nails, order)
print("\nUnpacked into b: ", b)
fmt.printf("err: %v\n", err)
fmt.printf("b.digit: %v\n", b.digit[:b.used])
}
main :: proc() {
ta := mem.Tracking_Allocator{}
mem.tracking_allocator_init(&ta, context.allocator)
context.allocator = mem.tracking_allocator(&ta)
demo()
print_configation()
print_timings()
if len(ta.allocation_map) > 0 {
for _, v in ta.allocation_map {
fmt.printf("Leaked %v bytes @ %v\n", v.size, v.location)
}
}
if len(ta.bad_free_array) > 0 {
fmt.println("Bad frees:")
for v in ta.bad_free_array {
fmt.println(v)
}
}
}
-2
View File
@@ -11,8 +11,6 @@ package math_big
import "core:intrinsics"
import rnd "core:math/rand"
// import "core:fmt"
/*
TODO: Int.flags and Constants like ONE, NAN, etc, are not yet properly handled everywhere.
*/
+100 -24
View File
@@ -9,8 +9,84 @@
*/
package math_big
import "core:fmt"
import "core:time"
import "core:runtime"
print_value :: proc(name: string, value: i64) {
runtime.print_string("\t")
runtime.print_string(name)
runtime.print_string(": ")
runtime.print_i64(value)
runtime.print_string("\n")
}
print_bool :: proc(name: string, value: bool) {
runtime.print_string("\t")
runtime.print_string(name)
if value {
runtime.print_string(": true\n")
} else {
runtime.print_string(": false\n")
}
}
print_configation :: proc() {
runtime.print_string("Configuration:\n")
print_value("_DIGIT_BITS ", _DIGIT_BITS)
print_bool ("MATH_BIG_SMALL_MEMORY ", _LOW_MEMORY)
print_value("_MIN_DIGIT_COUNT ", _MIN_DIGIT_COUNT)
print_value("_MAX_DIGIT_COUNT ", i64(_MAX_DIGIT_COUNT))
print_value("_DEFAULT_DIGIT_COUNT ", _DEFAULT_DIGIT_COUNT)
print_value("_MAX_COMBA ", _MAX_COMBA)
print_value("_WARRAY ", _WARRAY)
print_value("_TAB_SIZE ", _TAB_SIZE)
print_value("_MAX_WIN_SIZE ", _MAX_WIN_SIZE)
print_bool ("MATH_BIG_USE_LUCAS_SELFRIDGE_TEST ", MATH_BIG_USE_LUCAS_SELFRIDGE_TEST)
runtime.print_string("\nRuntime tunable:\n")
print_value("MUL_KARATSUBA_CUTOFF ", i64(MUL_KARATSUBA_CUTOFF))
print_value("SQR_KARATSUBA_CUTOFF ", i64(SQR_KARATSUBA_CUTOFF))
print_value("MUL_TOOM_CUTOFF ", i64(MUL_TOOM_CUTOFF))
print_value("SQR_TOOM_CUTOFF ", i64(SQR_TOOM_CUTOFF))
print_value("MAX_ITERATIONS_ROOT_N ", i64(MAX_ITERATIONS_ROOT_N))
print_value("FACTORIAL_MAX_N ", i64(FACTORIAL_MAX_N))
print_value("FACTORIAL_BINARY_SPLIT_CUTOFF ", i64(FACTORIAL_BINARY_SPLIT_CUTOFF))
print_value("FACTORIAL_BINARY_SPLIT_MAX_RECURSIONS", i64(FACTORIAL_BINARY_SPLIT_MAX_RECURSIONS))
print_value("FACTORIAL_BINARY_SPLIT_CUTOFF ", i64(FACTORIAL_BINARY_SPLIT_CUTOFF))
print_bool ("USE_MILLER_RABIN_ONLY ", USE_MILLER_RABIN_ONLY)
print_value("MAX_ITERATIONS_RANDOM_PRIME ", i64(MAX_ITERATIONS_RANDOM_PRIME))
}
print :: proc(name: string, a: ^Int, base := i8(10), print_name := true, newline := true, print_extra_info := false) {
assert_if_nil(a)
as, err := itoa(a, base)
defer delete(as)
cb := internal_count_bits(a)
if print_name {
runtime.print_string(name)
}
if err != nil {
runtime.print_string("(Error: ")
es := Error_String
runtime.print_string(es[err])
runtime.print_string(")")
}
runtime.print_string(as)
if print_extra_info {
runtime.print_string(" (base: ")
runtime.print_i64(i64(base))
runtime.print_string(", bits: ")
runtime.print_i64(i64(cb))
runtime.print_string(", digits: ")
runtime.print_i64(i64(a.used))
runtime.print_string(")")
}
if newline {
runtime.print_string("\n")
}
}
Category :: enum {
itoa,
@@ -35,32 +111,32 @@ Event :: struct {
Timings := [Category]Event{}
print_timings :: proc() {
duration :: proc(d: time.Duration) -> (res: string) {
switch {
case d < time.Microsecond:
return fmt.tprintf("%v ns", time.duration_nanoseconds(d))
case d < time.Millisecond:
return fmt.tprintf("%v µs", time.duration_microseconds(d))
case:
return fmt.tprintf("%v ms", time.duration_milliseconds(d))
}
}
// duration :: proc(d: time.Duration) -> (res: string) {
// switch {
// case d < time.Microsecond:
// return fmt.tprintf("%v ns", time.duration_nanoseconds(d))
// case d < time.Millisecond:
// return fmt.tprintf("%v µs", time.duration_microseconds(d))
// case:
// return fmt.tprintf("%v ms", time.duration_milliseconds(d))
// }
// }
for v in Timings {
if v.count > 0 {
fmt.println("\nTimings:")
break
}
}
// for v in Timings {
// if v.count > 0 {
// fmt.println("\nTimings:")
// break
// }
// }
for v, i in Timings {
if v.count > 0 {
avg_ticks := time.Duration(f64(v.ticks) / f64(v.count))
avg_cycles := f64(v.cycles) / f64(v.count)
// for v, i in Timings {
// if v.count > 0 {
// avg_ticks := time.Duration(f64(v.ticks) / f64(v.count))
// avg_cycles := f64(v.cycles) / f64(v.count)
fmt.printf("\t%v: %s / %v cycles (avg), %s / %v cycles (total, %v calls)\n", i, duration(avg_ticks), avg_cycles, duration(v.ticks), v.cycles, v.count)
}
}
// fmt.printf("\t%v: %s / %v cycles (avg), %s / %v cycles (total, %v calls)\n", i, duration(avg_ticks), avg_cycles, duration(v.ticks), v.cycles, v.count)
// }
// }
}
@(deferred_in_out=_SCOPE_END)