浏览代码

big: Add `pow`.

Jeroen van Rijn 4 年之前
父节点
当前提交
d953e40fb3
共有 3 个文件被更改,包括 54 次插入7 次删除
  1. 6 1
      core/math/big/basic.odin
  2. 46 4
      core/math/big/log.odin
  3. 2 2
      core/math/big/radix.odin

+ 6 - 1
core/math/big/basic.odin

@@ -516,7 +516,7 @@ int_mul_digit :: proc(dest, src: ^Int, multiplier: DIGIT) -> (err: Error) {
 	}
 	if is_power_of_two(int(multiplier)) {
 		ix: int;
-		if ix, err = log_n(multiplier, 2); err != .None { return err; }
+		if ix, err = log(multiplier, 2); err != .None { return err; }
 		return shl(dest, src, ix);
 	}
 
@@ -648,6 +648,11 @@ int_mul :: proc(dest, src, multiplier: ^Int) -> (err: Error) {
 
 mul :: proc { int_mul, int_mul_digit, };
 
+sqr :: proc(dest, src: ^Int) -> (err: Error) {
+	return mul(dest, src, src);
+}
+
+
 /*
 	==========================
 		Low-level routines    

+ 46 - 4
core/math/big/log.odin

@@ -9,7 +9,7 @@ package big
 	The code started out as an idiomatic source port of libTomMath, which is in the public domain, with thanks.
 */
 
-log_n_int :: proc(a: ^Int, base: DIGIT) -> (log: int, err: Error) {
+int_log :: proc(a: ^Int, base: DIGIT) -> (res: int, err: Error) {
 	if base < 2 || DIGIT(base) > _DIGIT_MAX {
 		return -1, .Invalid_Argument;
 	}
@@ -35,7 +35,7 @@ log_n_int :: proc(a: ^Int, base: DIGIT) -> (log: int, err: Error) {
 		Fast path for `Int`s that fit within a single `DIGIT`.
 	*/
 	if a.used == 1 {
-		return log_n_digit(a.digit[0], DIGIT(base));
+		return log(a.digit[0], DIGIT(base));
 	}
 
     // if (MP_HAS(S_MP_LOG)) {
@@ -45,7 +45,49 @@ log_n_int :: proc(a: ^Int, base: DIGIT) -> (log: int, err: Error) {
 	return -1, .Unimplemented;
 }
 
-log_n :: proc{log_n_int, log_n_digit};
+log :: proc { int_log, int_log_digit, };
+
+/*
+	Calculate c = a**b  using a square-multiply algorithm.
+*/
+int_pow :: proc(dest, base: ^Int, power: int) -> (err: Error) {
+	if err = clear_if_uninitialized(dest); err != .None { return err; }
+	if err = clear_if_uninitialized(base); err != .None { return err; }
+
+// 	if ((err = mp_init_copy(&g, a)) != MP_OKAY) {
+// 		return err;
+// 	}
+
+// 	/* set initial result */
+// 	mp_set(c, 1uL);
+
+// 	while (b > 0) {
+// 		/* if the bit is set multiply */
+// 		if ((b & 1) != 0) {
+// 			if ((err = mp_mul(c, &g, c)) != MP_OKAY) {
+// 				goto LBL_ERR;
+// 			}
+// 		}
+
+// 		/* square */
+// 		if (b > 1) {
+// 			if ((err = mp_sqr(&g, &g)) != MP_OKAY) {
+// 				goto LBL_ERR;
+// 			}
+// 		}
+
+// 		/* shift to next bit */
+// 		b >>= 1;
+// 	}
+
+// LBL_ERR:
+// 	mp_clear(&g);
+// 	return err;
+	return err;
+}
+
+
+pow :: proc { int_pow, };
 
 /*
 	Returns the log2 of an `Int`, provided `base` is a power of two.
@@ -79,7 +121,7 @@ small_pow :: proc(base: _WORD, exponent: _WORD) -> (result: _WORD) {
    	return result;
 }
 
-log_n_digit :: proc(a: DIGIT, base: DIGIT) -> (log: int, err: Error) {
+int_log_digit :: proc(a: DIGIT, base: DIGIT) -> (log: int, err: Error) {
 	/*
 		If the number is smaller than the base, it fits within a fraction.
 		Therefore, we return 0.

+ 2 - 2
core/math/big/radix.odin

@@ -207,7 +207,7 @@ itoa_raw :: proc(a: ^Int, radix: i8, buffer: []u8, size := int(-1), zero_termina
 
 		shift, count: int;
 		// mask  := _WORD(radix - 1);
-		shift, err = log_n(DIGIT(radix), 2);
+		shift, err = log(DIGIT(radix), 2);
 		count, err = count_bits(a);
 		digit: _WORD;
 
@@ -263,7 +263,7 @@ radix_size :: proc(a: ^Int, radix: i8, zero_terminate := false) -> (size: int, e
 		digit     = a.digit,
 	};
 
-	if size, err = log_n(t, DIGIT(radix)); err != .None {
+	if size, err = log(t, DIGIT(radix)); err != .None {
 		return 0, err;
 	}