This repository has been archived by the owner on Mar 23, 2023. It is now read-only.
Added math module #33
Merged
Merged
Changes from 8 commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
eaa4fd6
Added math library
lalaithion 2f87a70
Moved a helper function inside main function
lalaithion 232087e
Arguments now wrapped in call to float
lalaithion 737dad4
factorial has better error messages and accepts 0
lalaithion 225f020
Added Tests for Math Library
lalaithion 169141b
Added tests for domain errors in factorial()
lalaithion a010362
Made factorial() more performant
lalaithion 8afc1d1
Removed NOTE comment that had been resolved
lalaithion 2f8e076
Removed PyPy factorial() implementation
lalaithion File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,244 @@ | ||
from __go__.math import (Pi, E, Ceil, Copysign, Abs, Floor, Mod, Frexp, IsInf, | ||
IsNaN, Exp2, Modf, Trunc, Exp, Expm1, Log, Log1p, Log10, Pow, Sqrt, Acos, | ||
Asin, Atan, Atan2, Hypot, Sin, Cos, Tan, Acosh, Asinh, Atanh, Sinh, Cosh, | ||
Tanh, Erf, Erfc, Gamma, Lgamma) # pylint: disable=g-multiple-import | ||
|
||
# Constants | ||
|
||
pi = Pi | ||
|
||
|
||
e = E | ||
|
||
|
||
# Number-theoretic and representation functions | ||
|
||
def ceil(x): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not an import with alias, like from __go__.math import (
Pi as pi,
E as e,
Ceil as ceil,
...
) ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Makes sense |
||
return Ceil(float(x)) | ||
|
||
|
||
def copysign(x, y): | ||
return Copysign(float(x), float(y)) | ||
|
||
|
||
def fabs(x): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Inputs should be converted to floats so that the following works:
Applies to most functions in this file. |
||
return Abs(float(x)) | ||
|
||
|
||
def factorial(x): | ||
try: | ||
xi = int(x) | ||
except TypeError: | ||
xi = None | ||
|
||
try: | ||
xf = float(x) | ||
except TypeError: | ||
xf = None | ||
|
||
if xi is None: | ||
xi = int(xf) | ||
if xi != xf: | ||
raise ValueError("factorial() only accepts integral values") | ||
elif xf is None and xi is None: | ||
raise TypeError("an integer is required") | ||
elif xf is None: | ||
pass | ||
elif xf != xi: | ||
raise ValueError("factorial() only accepts integral values") | ||
|
||
x = xi | ||
|
||
# The rest of this implementation is taken from PyPy | ||
if x <= 100: | ||
if x < 0: | ||
raise ValueError("x must be >= 0") | ||
res = 1 | ||
for i in range(2, x + 1): | ||
res *= i | ||
return res | ||
|
||
# Experimentally this gap seems good | ||
gap = max(100, x >> 7) | ||
def _fac_odd(low, high): | ||
if low + gap >= high: | ||
t = 1 | ||
for i in range(low, high, 2): | ||
t *= i | ||
return t | ||
|
||
mid = ((low + high) >> 1) | 1 | ||
return _fac_odd(low, mid) * _fac_odd(mid, high) | ||
|
||
def _fac1(x): | ||
if x <= 2: | ||
return 1, 1, x - 1 | ||
x2 = x >> 1 | ||
f, g, shift = _fac1(x2) | ||
g *= _fac_odd((x2 + 1) | 1, x + 1) | ||
return (f * g, g, shift + x2) | ||
|
||
res, _, shift = _fac1(x) | ||
return res << shift | ||
|
||
|
||
def floor(x): | ||
return Floor(float(x)) | ||
|
||
|
||
def fmod(x): | ||
return Mod(float(x)) | ||
|
||
|
||
def frexp(x): | ||
return Frexp(float(x)) | ||
|
||
|
||
# TODO: Implement fsum() | ||
# def fsum(x): | ||
# pass | ||
|
||
|
||
def isinf(x): | ||
return IsInf(float(x),0) | ||
|
||
|
||
def isnan(x): | ||
return IsNaN(float(x)) | ||
|
||
|
||
def ldexp(x, i): | ||
return float(x) * Exp2(float(i)) | ||
|
||
|
||
def modf(x): | ||
#Modf returns (int, frac), but python should return (frac, int). | ||
a, b = Modf(float(x)) | ||
return b, a | ||
|
||
|
||
def trunc(x): | ||
return Trunc(float(x)) | ||
|
||
|
||
# Power and logarithmic functions | ||
|
||
def exp(x): | ||
return Exp(float(x)) | ||
|
||
|
||
def expm1(x): | ||
return Expm1(float(x)) | ||
|
||
|
||
def log(x, b=None): | ||
if b is None: | ||
return Log(float(x)) | ||
|
||
# NOTE: We can try and catch more special cases to delegate to specific | ||
# Go functions or maybe there is a function that does this and I missed it. | ||
return Log(float(x)) / Log(float(b)) | ||
|
||
|
||
def log1p(x): | ||
return Log1p(float(x)) | ||
|
||
|
||
def log10(x): | ||
return Log10(float(x)) | ||
|
||
|
||
def pow(x, y): | ||
return Pow(float(x), float(y)) | ||
|
||
|
||
def sqrt(x): | ||
return Sqrt(float(x)) | ||
|
||
|
||
# Trigonometric functions | ||
|
||
def acos(x): | ||
return Acos(float(x)) | ||
|
||
|
||
def asin(x): | ||
return Asin(float(x)) | ||
|
||
|
||
def atan(x): | ||
return Atan(float(x)) | ||
|
||
|
||
def atan2(y, x): | ||
return Atan2(float(y), float(x)) | ||
|
||
|
||
def cos(x): | ||
return Cos(float(x)) | ||
|
||
|
||
def hypot(x, y): | ||
return Hypot(float(x), float(y)) | ||
|
||
|
||
def sin(x): | ||
return Sin(float(x)) | ||
|
||
|
||
def tan(x): | ||
return Tan(float(x)) | ||
|
||
|
||
# Angular conversion | ||
|
||
def degrees(x): | ||
return (float(x) * 180) / pi | ||
|
||
|
||
def radians(x): | ||
return (float(x) * pi) / 180 | ||
|
||
|
||
# Hyperbolic functions | ||
|
||
def acosh(x): | ||
return Acosh(float(x)) | ||
|
||
|
||
def asinh(x): | ||
return Asinh(float(x)) | ||
|
||
|
||
def atanh(x): | ||
return Atanh(float(x)) | ||
|
||
|
||
def cosh(x): | ||
return Cosh(float(x)) | ||
|
||
|
||
def sinh(x): | ||
return Sinh(float(x)) | ||
|
||
|
||
def tanh(x): | ||
return Tanh(float(x)) | ||
|
||
|
||
# Special functions | ||
|
||
def erf(x): | ||
return Erf(float(x)) | ||
|
||
|
||
def erfc(x): | ||
return Erfc(float(x)) | ||
|
||
|
||
def gamma(x): | ||
return Gamma(float(x)) | ||
|
||
|
||
def lgamma(x): | ||
return Lgamma(float(x)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import math | ||
|
||
import weetest | ||
|
||
# Tests exist for all functions which have logic in the math.py module, instead | ||
# of simply calling the go equivalent. | ||
|
||
|
||
def TestFactorial(): | ||
assert math.factorial(0) == 1 | ||
assert math.factorial(1) == 1 | ||
assert math.factorial(2) == 2 | ||
assert math.factorial(3) == 6 | ||
assert math.factorial(4) == 24 | ||
assert math.factorial(5) == 120 | ||
|
||
|
||
def TestFactorialError(): | ||
try: | ||
math.factorial(-1) | ||
except ValueError: | ||
pass | ||
else: | ||
raise AssertionError | ||
|
||
try: | ||
math.factorial(0.5) | ||
except ValueError: | ||
pass | ||
else: | ||
raise AssertionError | ||
|
||
|
||
def TestLdexp(): | ||
assert math.ldexp(1,1) == 2 | ||
assert math.ldexp(1,2) == 4 | ||
assert math.ldexp(1.5,1) == 3 | ||
assert math.ldexp(1.5,2) == 6 | ||
|
||
|
||
def TestLog(): | ||
assert math.log(math.e) == 1 | ||
assert math.log(2,2) == 1 | ||
assert math.log(10,10) == 1 | ||
assert math.log(100,10) == 2 | ||
|
||
|
||
def TestRadians(): | ||
assert math.radians(180) == math.pi | ||
assert math.radians(360) == 2 * math.pi | ||
|
||
|
||
def TestDegrees(): | ||
assert math.degrees(math.pi) == 180 | ||
assert math.degrees(2 * math.pi) == 360 | ||
|
||
|
||
if __name__ == '__main__': | ||
weetest.RunTests() |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add the file header here and in math_test.py: