2,278 bytes · the Python implementation · view raw
# Derived from fdlibm e_rem_pio2.c.# Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.# Developed at SunSoft, a Sun Microsystems, Inc. business.# Permission to use, copy, modify, and distribute this# software is freely granted, provided that this notice# is preserved.import math
from .math_sin_cos_types import SinCos
# pi/2 in two parts (fdlibm): PIO2_1 has 33 significant bits, so k * PIO2_1 is# exact for every k up to 2^20, which covers the permitted range.
PIO2_1 = 1.57079632673412561417e+00
PIO2_1T = 6.07710050650619224932e-11
INV_PIO2 = 6.36619772367581382433e-01
LIMIT = 1000000def _sin_small(r: float) -> float:
s = r * r
p = 1 / 355687428096000
p = -1 / 1307674368000 + s * p
p = 1 / 6227020800 + s * p
p = -1 / 39916800 + s * p
p = 1 / 362880 + s * p
p = -1 / 5040 + s * p
p = 1 / 120 + s * p
p = -1 / 6 + s * p
return r + r * s * p
def _cos_small(r: float) -> float:
s = r * r
p = -1 / 6402373705728000
p = 1 / 20922789888000 + s * p
p = -1 / 87178291200 + s * p
p = 1 / 479001600 + s * p
p = -1 / 3628800 + s * p
p = 1 / 40320 + s * p
p = -1 / 720 + s * p
p = 1 / 24 + s * p
p = -1 / 2 + s * p
return1 + s * p
def sin_cos(radians: float) -> SinCos:
"""Sine and cosine using only +, -, * and /, in the same order as the TypeScript and Rust versions, so all three return the same doubles. math.sin and math.cos come from the C library and may differ in the last bit. See the README for the method."""if (
isinstance(radians, bool)
ornot isinstance(radians, (int, float))
ornot math.isfinite(radians)
or radians < -LIMIT
or radians > LIMIT
):
raise ValueError("radians must be a finite number between -1000000 and 1000000, received %r" % (radians,))
x = float(radians)
k = math.floor(x * INV_PIO2 + 0.5)
r = x - k * PIO2_1 - k * PIO2_1T
s = _sin_small(r)
c = _cos_small(r)
quadrant = k % 4if quadrant == 0:
return SinCos(sin=s + 0.0, cos=c + 0.0)
if quadrant == 1:
return SinCos(sin=c + 0.0, cos=-s + 0.0)
if quadrant == 2:
return SinCos(sin=-s + 0.0, cos=-c + 0.0)
return SinCos(sin=-c + 0.0, cos=s + 0.0)