Software APIs
math.c
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 
6 
7 #include <stddef.h>
8 
9 /**
10  * Extern declaration of inline function.
11  */
12 extern size_t ceil_div(size_t a, size_t b);
13 
14 uint64_t udiv64_slow(uint64_t a, uint64_t b, uint64_t *rem_out) {
15  uint64_t quot = 0, rem = 0;
16 
17  // Schoolbook long division in base 2. See
18  // https://en.wikipedia.org/wiki/Long_division to recall precisely how this
19  // works. This algorithm is a bit different from the elementary school base-10
20  // version, since we can use shifts instead of multiplication.
21  //
22  // If `b` is zero, `quot == -1` and `rem == a`. This should not be relied
23  // upon.
24  size_t bits = sizeof(uint64_t) * 8;
25  for (size_t i = 0; i < bits; ++i) {
26  rem <<= 1;
27  quot <<= 1;
28  rem |= (a >> (bits - i - 1)) & 1;
29 
30  // We need to keep bringing down zeros until `rem`, the running total, is
31  // large enough that we can subtract off `b`; this tells us the value we
32  // would have had to multiply `a` by to produce this current step in the
33  // division.
34  if (rem >= b) {
35  rem -= b;
36  quot |= 1;
37  }
38  }
39 
40  if (rem_out != NULL) {
41  *rem_out = rem;
42  }
43  return quot;
44 }