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