summaryrefslogtreecommitdiff
path: root/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_div_d.c
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/heimdal/lib/hcrypto/libtommath/bn_mp_div_d.c')
-rw-r--r--third_party/heimdal/lib/hcrypto/libtommath/bn_mp_div_d.c84
1 files changed, 84 insertions, 0 deletions
diff --git a/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_div_d.c b/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_div_d.c
new file mode 100644
index 00000000000..b9d718bb062
--- /dev/null
+++ b/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_div_d.c
@@ -0,0 +1,84 @@
+#include "tommath_private.h"
+#ifdef BN_MP_DIV_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/* single digit division (based on routine from MPI) */
+mp_err mp_div_d(const mp_int *a, mp_digit b, mp_int *c, mp_digit *d)
+{
+ mp_int q;
+ mp_word w;
+ mp_digit t;
+ mp_err err;
+ int ix;
+
+ /* cannot divide by zero */
+ if (b == 0u) {
+ return MP_VAL;
+ }
+
+ /* quick outs */
+ if ((b == 1u) || MP_IS_ZERO(a)) {
+ if (d != NULL) {
+ *d = 0;
+ }
+ if (c != NULL) {
+ return mp_copy(a, c);
+ }
+ return MP_OKAY;
+ }
+
+ /* power of two ? */
+ if ((b & (b - 1u)) == 0u) {
+ ix = 1;
+ while ((ix < MP_DIGIT_BIT) && (b != (((mp_digit)1)<<ix))) {
+ ix++;
+ }
+ if (d != NULL) {
+ *d = a->dp[0] & (((mp_digit)1<<(mp_digit)ix) - 1uL);
+ }
+ if (c != NULL) {
+ return mp_div_2d(a, ix, c, NULL);
+ }
+ return MP_OKAY;
+ }
+
+ /* three? */
+ if (MP_HAS(MP_DIV_3) && (b == 3u)) {
+ return mp_div_3(a, c, d);
+ }
+
+ /* no easy answer [c'est la vie]. Just division */
+ if ((err = mp_init_size(&q, a->used)) != MP_OKAY) {
+ return err;
+ }
+
+ q.used = a->used;
+ q.sign = a->sign;
+ w = 0;
+ for (ix = a->used - 1; ix >= 0; ix--) {
+ w = (w << (mp_word)MP_DIGIT_BIT) | (mp_word)a->dp[ix];
+
+ if (w >= b) {
+ t = (mp_digit)(w / b);
+ w -= (mp_word)t * (mp_word)b;
+ } else {
+ t = 0;
+ }
+ q.dp[ix] = t;
+ }
+
+ if (d != NULL) {
+ *d = (mp_digit)w;
+ }
+
+ if (c != NULL) {
+ mp_clamp(&q);
+ mp_exch(&q, c);
+ }
+ mp_clear(&q);
+
+ return err;
+}
+
+#endif