From 9c150381bf7ec94557c14b8cc477e9e30312986c Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Wed, 28 Jul 2021 00:58:28 +0200 Subject: [PATCH] big: Add `rand`. --- core/math/big/example.odin | 26 ++++++++-------------- core/math/big/exp_log.odin | 2 +- core/math/big/helpers.odin | 44 ++++++++++++++++++++++++++++++++++++-- core/math/rand/rand.odin | 2 +- 4 files changed, 53 insertions(+), 21 deletions(-) diff --git a/core/math/big/example.odin b/core/math/big/example.odin index 7b0df89ae..c95fde549 100644 --- a/core/math/big/example.odin +++ b/core/math/big/example.odin @@ -59,23 +59,15 @@ demo :: proc() { destination, source, quotient, remainder, numerator, denominator := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}; defer destroy(destination, source, quotient, remainder, numerator, denominator); - // string_buffer := make([]u8, 1024); - // defer delete(string_buffer); - - err = set (numerator, 1024); - err = sqrt(destination, numerator); - fmt.printf("int_sqrt returned: %v\n", err); - - print("num ", numerator); - print("sqrt(num)", destination); - - fmt.println("\n\n"); - - err = root_n(destination, numerator, 2); - fmt.printf("root_n(2) returned: %v\n", err); - - print("num ", numerator); - print("root_n(num)", destination); + for i in 1..=10 { + err = rand(destination, 1200); // 1200 random bits + if err != .None { + fmt.printf("rand error: %v\n", err); + } else { + fmt.printf("#%3d: ", i); + print("", destination); + } + } } main :: proc() { diff --git a/core/math/big/exp_log.odin b/core/math/big/exp_log.odin index 2ccfa7146..943fd51e9 100644 --- a/core/math/big/exp_log.odin +++ b/core/math/big/exp_log.odin @@ -406,7 +406,7 @@ _int_log :: proc(a: ^Int, base: DIGIT) -> (res: int, err: Error) { } if err = set(bi_base, base); err != .None { return -1, err; } - if err = _init_multi(bracket_mid, t); err != .None { return -1, err; } + if err = init_multi(bracket_mid, t); err != .None { return -1, err; } if err = one(bracket_low); err != .None { return -1, err; } if err = set(bracket_high, base); err != .None { return -1, err; } diff --git a/core/math/big/helpers.odin b/core/math/big/helpers.odin index 6d7ef97aa..a15929d2e 100644 --- a/core/math/big/helpers.odin +++ b/core/math/big/helpers.odin @@ -11,6 +11,7 @@ package big import "core:mem" import "core:intrinsics" +import "core:math/rand" /* Deallocates the backing memory of one or more `Int`s. @@ -506,6 +507,43 @@ count_lsb :: proc(a: ^Int) -> (count: int, err: Error) { return count, .None; } +int_random_digit :: proc(r: ^rand.Rand = nil) -> (res: DIGIT) { + when _DIGIT_BITS == 60 { // DIGIT = u64 + return DIGIT(rand.uint64(r)) & _MASK; + } else when _DIGIT_BITS == 28 { // DIGIT = u32 + return DIGIT(rand.uint32(r)) & _MASK; + } else { + panic("Unsupported DIGIT size."); + } + + return 0; // We shouldn't get here. +} + +int_rand :: proc(dest: ^Int, bits: int, r: ^rand.Rand = nil) -> (err: Error) { + bits := bits; + + if bits <= 0 { return .Invalid_Argument; } + + digits := bits / _DIGIT_BITS; + bits %= _DIGIT_BITS; + + if bits > 0 { + digits += 1; + } + + if err = grow(dest, digits); err != .None { return err; } + + for i := 0; i < digits; i += 1 { + dest.digit[i] = int_random_digit(r) & _MASK; + } + if bits > 0 { + dest.digit[digits - 1] &= ((1 << uint(bits)) - 1); + } + dest.used = digits; + return .None; +} +rand :: proc { int_rand, }; + /* Internal helpers. */ @@ -532,10 +570,12 @@ clear_if_uninitialized :: proc(dest: ^Int, minimize := false) -> (err: Error) { return .None; } + + /* Allocates several `Int`s at once. */ -_int_init_multi :: proc(integers: ..^Int) -> (err: Error) { +int_init_multi :: proc(integers: ..^Int) -> (err: Error) { integers := integers; for a in &integers { if err = clear(a); err != .None { return err; } @@ -543,7 +583,7 @@ _int_init_multi :: proc(integers: ..^Int) -> (err: Error) { return .None; } -_init_multi :: proc { _int_init_multi, }; +init_multi :: proc { int_init_multi, }; _copy_digits :: proc(dest, src: ^Int, digits: int) -> (err: Error) { digits := digits; diff --git a/core/math/rand/rand.odin b/core/math/rand/rand.odin index f5558bb8c..812cdc53d 100644 --- a/core/math/rand/rand.odin +++ b/core/math/rand/rand.odin @@ -95,7 +95,7 @@ int63_max :: proc(n: i64, r: ^Rand = nil) -> i64 { int127_max :: proc(n: i128, r: ^Rand = nil) -> i128 { if n <= 0 { - panic("Invalid argument to int63_max"); + panic("Invalid argument to int127_max"); } if n&(n-1) == 0 { return int127(r) & (n-1);