HEIMDAL: move code from source4/heimdal* to third_party/heimdal*
[samba.git] / third_party / heimdal / lib / hcrypto / libtommath / bn_mp_div_2d.c
1 #include "tommath_private.h"
2 #ifdef BN_MP_DIV_2D_C
3 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
4 /* SPDX-License-Identifier: Unlicense */
5
6 /* shift right by a certain bit count (store quotient in c, optional remainder in d) */
7 mp_err mp_div_2d(const mp_int *a, int b, mp_int *c, mp_int *d)
8 {
9    mp_digit D, r, rr;
10    int     x;
11    mp_err err;
12
13    /* if the shift count is <= 0 then we do no work */
14    if (b <= 0) {
15       err = mp_copy(a, c);
16       if (d != NULL) {
17          mp_zero(d);
18       }
19       return err;
20    }
21
22    /* copy */
23    if ((err = mp_copy(a, c)) != MP_OKAY) {
24       return err;
25    }
26    /* 'a' should not be used after here - it might be the same as d */
27
28    /* get the remainder */
29    if (d != NULL) {
30       if ((err = mp_mod_2d(a, b, d)) != MP_OKAY) {
31          return err;
32       }
33    }
34
35    /* shift by as many digits in the bit count */
36    if (b >= MP_DIGIT_BIT) {
37       mp_rshd(c, b / MP_DIGIT_BIT);
38    }
39
40    /* shift any bit count < MP_DIGIT_BIT */
41    D = (mp_digit)(b % MP_DIGIT_BIT);
42    if (D != 0u) {
43       mp_digit *tmpc, mask, shift;
44
45       /* mask */
46       mask = ((mp_digit)1 << D) - 1uL;
47
48       /* shift for lsb */
49       shift = (mp_digit)MP_DIGIT_BIT - D;
50
51       /* alias */
52       tmpc = c->dp + (c->used - 1);
53
54       /* carry */
55       r = 0;
56       for (x = c->used - 1; x >= 0; x--) {
57          /* get the lower  bits of this word in a temp */
58          rr = *tmpc & mask;
59
60          /* shift the current word and mix in the carry bits from the previous word */
61          *tmpc = (*tmpc >> D) | (r << shift);
62          --tmpc;
63
64          /* set the carry to the carry bits of the current word found above */
65          r = rr;
66       }
67    }
68    mp_clamp(c);
69    return MP_OKAY;
70 }
71 #endif