OILS / core / num.py View on Github | oilshell.org

81 lines, 39 significant
1"""num.py - math functions"""
2from __future__ import print_function
3
4from _devbuild.gen.value_asdl import value
5from mycpp import mops
6
7
8def ToBig(i):
9 # type: (int) -> value.Int
10 return value.Int(mops.IntWiden(i))
11
12
13def Exponent(x, y):
14 # type: (mops.BigInt, mops.BigInt) -> mops.BigInt
15
16 # TODO: can we avoid this?
17 y_int = mops.BigTruncate(y)
18
19 assert y_int >= 0, 'checked by caller'
20
21 result = mops.BigInt(1)
22 for i in xrange(y_int):
23 result = mops.Mul(result, x)
24 return result
25
26
27def IntDivide(x, y):
28 # type: (mops.BigInt, mops.BigInt) -> mops.BigInt
29 """
30 Implementation that only uses the host language (Python or C++) to divide
31 non-negative numbers. Python rounds toward negative infinity, while C++
32 rounds toward zero.
33
34 Oils rounds toward zero.
35 """
36 assert y.i != 0, 'checked by caller'
37
38 sign = 1
39
40 if mops.Greater(mops.ZERO, x):
41 ax = mops.Negate(x)
42 sign = -1
43 else:
44 ax = x
45
46 if mops.Greater(mops.ZERO, y):
47 ay = mops.Negate(y)
48 sign = -sign
49 else:
50 ay = y
51
52 return mops.Mul(mops.IntWiden(sign), mops.Div(ax, ay))
53
54
55def IntRemainder(x, y):
56 # type: (mops.BigInt, mops.BigInt) -> mops.BigInt
57 """
58 Implementation that only uses the host language (Python or C++) to divide
59 non-negative numbers.
60
61 Takes the sign of the first argument x.
62
63 Python % is modulus, while C % is remainder. Both OSH and YSH % is
64 remainder, like C.
65 """
66 assert y.i != 0, 'checked by caller'
67
68 if mops.Greater(mops.ZERO, x):
69 ax = mops.Negate(x)
70 sign = -1
71 else:
72 ax = x
73 sign = 1
74
75 if mops.Greater(mops.ZERO, y):
76 ay = mops.Negate(y)
77 else:
78 ay = y
79
80 # Only use host language % on non-negative numbers. Apply sign afteward.
81 return mops.Mul(mops.IntWiden(sign), mops.Rem(ax, ay))