1 | """num.py - math functions"""
|
2 | from __future__ import print_function
|
3 |
|
4 | from _devbuild.gen.value_asdl import value
|
5 | from mycpp import mops
|
6 |
|
7 |
|
8 | def ToBig(i):
|
9 | # type: (int) -> value.Int
|
10 | return value.Int(mops.IntWiden(i))
|
11 |
|
12 |
|
13 | def 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 |
|
27 | def 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 |
|
55 | def 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))
|