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 Exponent2(x, y):
|
28 | # type: (int, int) -> int
|
29 | return mops.BigTruncate(Exponent(mops.IntWiden(x), mops.IntWiden(y)))
|
30 |
|
31 |
|
32 | def IntDivide(x, y):
|
33 | # type: (mops.BigInt, mops.BigInt) -> mops.BigInt
|
34 | """
|
35 | Implementation that only uses the host language (Python or C++) to divide
|
36 | non-negative numbers. Python rounds toward negative infinity, while C++
|
37 | rounds toward zero.
|
38 |
|
39 | Oils rounds toward zero.
|
40 | """
|
41 | assert y.i != 0, 'checked by caller'
|
42 |
|
43 | ZERO = mops.BigInt(0)
|
44 | sign = 1
|
45 |
|
46 | if mops.Greater(ZERO, x):
|
47 | ax = mops.Negate(x)
|
48 | sign = -1
|
49 | else:
|
50 | ax = x
|
51 |
|
52 | if mops.Greater(ZERO, y):
|
53 | ay = mops.Negate(y)
|
54 | sign = -sign
|
55 | else:
|
56 | ay = y
|
57 |
|
58 | return mops.Mul(mops.IntWiden(sign), mops.Div(ax, ay))
|
59 |
|
60 |
|
61 | def IntDivide2(x, y):
|
62 | # type: (int, int) -> int
|
63 | return mops.BigTruncate(IntDivide(mops.IntWiden(x), mops.IntWiden(y)))
|
64 |
|
65 |
|
66 | def IntRemainder(x, y):
|
67 | # type: (mops.BigInt, mops.BigInt) -> mops.BigInt
|
68 | """
|
69 | Implementation that only uses the host language (Python or C++) to divide
|
70 | non-negative numbers.
|
71 |
|
72 | Takes the sign of the first argument x.
|
73 |
|
74 | Python % is modulus, while C % is remainder. Both OSH and YSH % is
|
75 | remainder, like C.
|
76 | """
|
77 | assert y.i != 0, 'checked by caller'
|
78 |
|
79 | ZERO = mops.BigInt(0)
|
80 |
|
81 | if mops.Greater(ZERO, x):
|
82 | ax = mops.Negate(x)
|
83 | sign = -1
|
84 | else:
|
85 | ax = x
|
86 | sign = 1
|
87 |
|
88 | if mops.Greater(ZERO, y):
|
89 | ay = mops.Negate(y)
|
90 | else:
|
91 | ay = y
|
92 |
|
93 | # Only use host language % on non-negative numbers. Apply sign afteward.
|
94 | return mops.Mul(mops.IntWiden(sign), mops.Rem(ax, ay))
|
95 |
|
96 |
|
97 | def IntRemainder2(x, y):
|
98 | # type: (int, int) -> int
|
99 | return mops.BigTruncate(IntRemainder(mops.IntWiden(x), mops.IntWiden(y)))
|