#### libremiliacr
#### Copyright(C) 2020-2024 Remilia Scarlet <remilia@posteo.jp>
####
#### This program is free software: you can redistribute it and/or modify
#### it under the terms of the GNU General Public License as published
#### the Free Software Foundation, either version 3 of the License, or
#### (at your option) any later version.
####
#### This program is distributed in the hope that it will be useful,
#### but WITHOUT ANY WARRANTY; without even the implied warranty of
#### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
#### GNU General Public License for more details.
####
#### You should have received a copy of the GNU General Public License
#### along with this program.If not, see<http:####www.gnu.org/licenses/.>
require "math"
module RemiMath
extend self
# The value of pi divided by 2.
HALF_PI = ::Math::PI / 2.0
# The value of pi multiplied by 2.
TWO_PI = ::Math::PI * 2.0
# The value of pi multiplied by 4.
FOUR_PI = ::Math::PI * 4.0
# The value of pi divided by 4.
QUARTER_PI = ::Math::PI / 4.0
# A version of sine that trades accuracy for speed. The intended
# domain is [0, pi/2].
def fastSin(val)
sqr = val * val
ret = -2.39e-08
ret *= sqr
ret += 2.7526e-06
ret *= sqr
ret -= 1.98409e-04
ret *= sqr
ret += 8.3333315e-03
ret *= sqr
ret -= 1.666666664e-01
ret *= sqr
ret += 1.0
ret * val
end
# A version of sine that trades even more accuracy for speed. The
# intended domain is [0, pi/2].
def fasterSin(val)
sqr = val * val
ret = 7.61e-03
ret *= sqr
ret -= 1.6605e-01
ret *= sqr
ret += 1.0
ret * val
end
# A version of cosine that trades accuracy for speed. The intended
# domain is [0, pi/2].
def fastCos (val)
sqr = val * val
ret = -2.605e-07
ret *= sqr
ret += 2.47609e-05
ret *= sqr
ret -= 1.3888397e-03
ret *= sqr
ret += 4.16666418e-02
ret *= sqr
ret -= 4.999999963e-01
ret *= sqr
ret + 1.0
end
# A version of cosine that trades even more accuracy for speed. The
# intended domain is [0, pi/2].
def fasterCos (val)
sqr = val * val
ret = 3.705e-02
ret *= sqr
ret -= 4.967e-01
ret *= sqr
ret + 1.0
end
# A version of tangent that trades accuracy for speed. The intended
# domain is [0, pi/4].
def fastTan (val)
sqr = val * val
ret = 9.5168091e-03
ret *= sqr
ret += 2.900525e-03
ret *= sqr
ret += 2.45650893e-02
ret *= sqr
ret += 5.33740603e-02
ret *= sqr
ret += 1.333923995e-01
ret *= sqr
ret += 3.333314036e-01
ret *= sqr
ret += 1.0
ret * val
end
# A version of tangent that trades even more accuracy for speed.
# The intended domain is [0, pi/4].
def fasterTan (val)
sqr = val * val
ret = 2.033e-01
ret *= sqr
ret += 3.1755e-01
ret *= sqr
ret += 1.0
ret * val
end
# A version of inverse sine that trades accuracy for speed. The
# intended domain is [0, 1]
def fastInvSin (val)
root = ::Math.sqrt(1.0 - val)
ret = -0.0187293
ret *= val
ret += 0.0742610
ret *= val
ret -= 0.2121144
ret *= val
ret += 1.5707288
HALF_PI - root * ret
end
# A version of inverse cosine that trades accuracy for speed. The
# intended domain is [0, 1]
def fastInvCos (val)
root = ::Math.sqrt(1.0 - val)
ret = -0.0187293
ret *= val
ret += 0.0742610
ret *= val
ret -= 0.2121144
ret *= val
ret += 1.5707288
ret * root
end
# A version of inverse tangent that trades accuracy for speed. The
# intended domain is [-1, 1]
def fastInvTan (val)
sqr = val * val
ret = 0.0028662257
ret *= sqr
ret -= 0.0161657367
ret *= sqr
ret += 0.0429096138
ret *= sqr
ret -= 0.0752896400
ret *= sqr
ret += 0.1065626393
ret *= sqr
ret -= 0.1420889944
ret *= sqr
ret += 0.1999355085
ret *= sqr
ret -= 0.3333314528
ret *= sqr
ret += 1.0
ret * val
end
# A version of inverse tangent that trades even more accuracy for
# speed. The intended domain is [-1, 1]
def fasterInvTan (val)
sqr = val * val
ret = 0.0208351
ret *= sqr
ret -= 0.085133
ret *= sqr
ret += 0.180141
ret *= sqr
ret -= 0.3302995
ret *= sqr
ret += 0.999866
ret * val
end
# A version of inverse hyperbolic tangent that trades accuracy for speed. The
# intended domain is [-3, 3]. The minimum error in this range is about 0.0,
# and the maximum error is about 0.024.
#
# Note: This enforces its intended domain. If `x` is less than -3, then this
# always returns -1.0. Likewise, if `x` is greater than 3, this always
# returns 1.0.
@[AlwaysInline]
def fastTanh(x : Float64) : Float64
if x < -3
-1.0
elsif x > 3
1.0
else
x * ( 27.0 + x * x ) / ( 27.0 + 9.0 * x * x )
end
end
# A version of arc tangent that trades accuracy for speed. The intended
# domain is [-1, 1]. The maximum error in this range is about 0.0015089
# radians.
@[AlwaysInline]
def fastAtan(x : Float64) : Float64
# https://nghiaho.com/?p=997
QUARTER_PI * x - x * (x.abs - 1) * (0.2447 + 0.0663 * x.abs)
end
end
|