Browse Source

big: Add `internal_int_exponent_mod`.

Jeroen van Rijn 4 years ago
parent
commit
7d7ed6b95f
2 changed files with 53 additions and 56 deletions
  1. 1 1
      core/math/big/example.odin
  2. 52 55
      core/math/big/prime.odin

+ 1 - 1
core/math/big/example.odin

@@ -218,7 +218,7 @@ demo :: proc() {
 	set(b, 6);
 	set(b, 6);
 	set(c, 131);
 	set(c, 131);
 
 
-	if err := _private_int_exponent_mod(res, a, b, c, 1); err != nil {
+	if err := internal_int_exponent_mod(res, a, b, c); err != nil {
 		fmt.printf("Error: %v\n", err);
 		fmt.printf("Error: %v\n", err);
 	}
 	}
 
 

+ 52 - 55
core/math/big/prime.odin

@@ -43,73 +43,70 @@ internal_int_prime_is_divisible :: proc(a: ^Int, allocator := context.allocator)
 internal_int_exponent_mod :: proc(res, G, X, P: ^Int, allocator := context.allocator) -> (err: Error) {
 internal_int_exponent_mod :: proc(res, G, X, P: ^Int, allocator := context.allocator) -> (err: Error) {
 	context.allocator = allocator;
 	context.allocator = allocator;
 
 
-/*
-	int dr;
-
-	/* modulus P must be positive */
-	if (mp_isneg(P)) {
-		return MP_VAL;
-	}
-
-	/* if exponent X is negative we have to recurse */
-	if (mp_isneg(X)) {
-		mp_int tmpG, tmpX;
-		mp_err err;
-
-		if (!MP_HAS(MP_INVMOD)) {
-			return MP_VAL;
-		}
-
-		if ((err = mp_init_multi(&tmpG, &tmpX, NULL)) != MP_OKAY) {
-			return err;
-		}
-
-		/* first compute 1/G mod P */
-		if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) {
-			goto LBL_ERR;
-		}
+	dr: int;
 
 
-		/* now get |X| */
-		if ((err = mp_abs(X, &tmpX)) != MP_OKAY) {
-			goto LBL_ERR;
-		}
+	/*
+		Modulus P must be positive.
+	*/
+	if internal_is_negative(P) { return .Invalid_Argument; }
 
 
-		/* and now compute (1/G)**|X| instead of G**X [X < 0] */
-		err = mp_exptmod(&tmpG, &tmpX, P, Y);
-LBL_ERR:
-		mp_clear_multi(&tmpG, &tmpX, NULL);
-		return err;
+	/*
+		If exponent X is negative we have to recurse.
+	*/
+	if internal_is_negative(X) {
+		tmpG, tmpX := &Int{}, &Int{};
+		defer internal_destroy(tmpG, tmpX);
+
+		internal_init_multi(tmpG, tmpX) or_return;
+
+		/*
+			First compute 1/G mod P.
+		*/
+		internal_invmod(tmpG, G, P) or_return;
+
+		/*
+			now get |X|.
+		*/
+		internal_abs(tmpX, X) or_return;
+
+		/*
+			And now compute (1/G)**|X| instead of G**X [X < 0].
+		*/
+		return internal_int_exponent_mod(res, tmpG, tmpX, P);
 	}
 	}
 
 
-	/* modified diminished radix reduction */
-	if (MP_HAS(MP_REDUCE_IS_2K_L) && MP_HAS(MP_REDUCE_2K_L) && MP_HAS(S_MP_EXPTMOD) &&
-		 mp_reduce_is_2k_l(P)) {
-		return s_mp_exptmod(G, X, P, Y, 1);
+	/*
+		Modified diminished radix reduction.
+	*/
+	can_reduce_2k_l := _private_int_reduce_is_2k_l(P) or_return;
+	if can_reduce_2k_l {
+		return _private_int_exponent_mod(res, G, X, P, 1);
 	}
 	}
 
 
-	/* is it a DR modulus? default to no */
-	dr = (MP_HAS(MP_DR_IS_MODULUS) && mp_dr_is_modulus(P)) ? 1 : 0;
-
-	/* if not, is it a unrestricted DR modulus? */
-	if (MP_HAS(MP_REDUCE_IS_2K) && (dr == 0)) {
-		dr = (mp_reduce_is_2k(P)) ? 2 : 0;
-	}
+	/*
+		Is it a DR modulus? default to no.
+	*/
+	dr = 1 if _private_dr_is_modulus(P) else 0;
 
 
-	/* if the modulus is odd or dr != 0 use the montgomery method */
-	if (MP_HAS(S_MP_EXPTMOD_FAST) && (mp_isodd(P) || (dr != 0))) {
-		return s_mp_exptmod_fast(G, X, P, Y, dr);
+	/*
+		If not, is it a unrestricted DR modulus?
+	*/
+	if dr == 0 {
+		reduce_is_2k := _private_int_reduce_is_2k(P) or_return;
+		dr = 2 if reduce_is_2k else 0;
 	}
 	}
 
 
-	/* otherwise use the generic Barrett reduction technique */
-	if (MP_HAS(S_MP_EXPTMOD)) {
-		return s_mp_exptmod(G, X, P, Y, 0);
+	/*
+		If the modulus is odd or dr != 0 use the montgomery method.
+	*/
+	if internal_int_is_odd(P) || dr != 0 {
+		return _private_int_exponent_mod(res, G, X, P, dr);
 	}
 	}
 
 
-	/* no exptmod for evens */
-	return MP_VAL;
-
+	/*
+		Otherwise use the generic Barrett reduction technique.
 	*/
 	*/
-	return nil;
+	return _private_int_exponent_mod(res, G, X, P, 0);
 }
 }
 
 
 /*
 /*