speed up ==, hash, <, >, <=, and >= for plain_data
[nmutil.git] / src / nmutil / divmod.py
1 # SPDX-License-Identifier: LGPL-3-or-later
2 """
3 This work is funded through NLnet under Grant 2019-02-012
4
5 License: LGPLv3+
6
7
8 """
9
10 from copy import copy
11 # this is a POWER ISA 3.0B compatible *signed* div function
12 # however it is also the c, c++, rust, java *and* x86 way of doing things
13
14
15 def trunc_divs(n, d):
16 abs_n = abs(n.to_signed_int())
17 abs_d = abs(d.to_signed_int())
18 print("trunc_div n", abs_n, n.to_signed_int())
19 print("trunc_div d", abs_d, d.to_signed_int())
20 abs_q = abs_n // abs_d
21 sign_n = n.value & (1 << (n.bits - 1)) != 0
22 sign_d = d.value & (1 << (d.bits - 1)) != 0
23 print("trunc_div", hex(n.value), hex(d.value),
24 hex(abs_n), hex(abs_d), hex(abs_q),
25 sign_n, sign_d)
26 res = copy(n)
27 if (sign_n == sign_d):
28 res.value = abs_q
29 if res.value & (1 << (res.bits - 1)) != 0:
30 # result should be positive but is negative
31 raise OverflowError()
32 return res
33 mask = (1 << res.bits) - 1
34 res.value = (-abs_q) & mask
35
36 return res
37
38
39 # this is a POWER ISA 3.0B compatible *signed* mod / remainder function
40 # however it is also the c, c++, rust, java *and* x86 way of doing things
41 def trunc_rems(n, d):
42 m = d * trunc_divs(n, d)
43
44 # cheat - really shouldn't do this. mul returns full length
45 m.bits = n.bits
46 return n - m