├── doc ├── notes.md ├── refs.md └── precision.md ├── src ├── const │ ├── README.md │ ├── DD.jl │ └── TD.jl ├── eft │ ├── README.md │ ├── single.jl │ ├── double.jl │ └── triple.jl ├── README.md ├── arith │ ├── README.md │ ├── DDmanip.jl │ ├── TDmanip.jl │ ├── DD.jl │ └── TD.jl ├── config.jl ├── io │ ├── DD.jl │ └── TD.jl ├── util │ └── domainCheck.jl ├── mag │ ├── DD.jl │ └── TD.jl ├── atrig │ ├── TD.jl │ └── DD.jl ├── FLOAT128.jl ├── trigh │ ├── TD.jl │ └── DD.jl ├── pow │ └── DD.jl ├── atrigh │ └── DD.jl ├── types.jl ├── trig │ └── DD.jl └── exp │ ├── DD.jl │ └── TD.jl ├── test └── util │ ├── timeit.jl │ ├── randnums.jl │ ├── testit.jl │ └── nearest.jl ├── LICENSE └── README.md /doc/notes.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | about BigFloat: https://github.com/JuliaLang/julia/issues/10040 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/const/README.md: -------------------------------------------------------------------------------- 1 | | file | supports | 2 | |------|----------| 3 | | DD.jl| double-double constants | 4 | | TD.jl| triple-double counstants | 5 | -------------------------------------------------------------------------------- /src/eft/README.md: -------------------------------------------------------------------------------- 1 | | file | supports | 2 | |------|----------| 3 | | single.jl| error free transformations of 1 arg | 4 | | double.jl| error free transformations of 2 args | 5 | | triple.jl | error free transformations of 3 args | 6 | 7 | -------------------------------------------------------------------------------- /src/README.md: -------------------------------------------------------------------------------- 1 | 2 | |dir| holds | 3 | |---|-------| 4 | |arith| arithmetic functions | 5 | |const| constant values | 6 | |eft | error free transformations | 7 | |exp | exp, expm1, log, log1p, log2, log10 | 8 | |io | show, hex, parse | 9 | |trig | sin, cos, tan, csc, sec, cot | 10 | 11 | -------------------------------------------------------------------------------- /src/arith/README.md: -------------------------------------------------------------------------------- 1 | |file | supports | 2 | |-----|----------| 3 | | DD.jl | slightly better than double-double arithmetic | 4 | | TD.jl | triple-double arithmetic for DD.jl | 5 | | DDmanip.jl | low level double-double manipulations | 6 | | TDmanip.jl | low level triple-double manipulations | 7 | -------------------------------------------------------------------------------- /src/config.jl: -------------------------------------------------------------------------------- 1 | #= 2 | The typealias *FloatingPoint* is used as a parameter for error free transformations. 3 | If you want multiple Floating Point types available, use a Union here. 4 | For most purposes, it should be either Float64 or, e.g. for CUDA Float32. 5 | =# 6 | typealias FloatingPoint Float64 7 | -------------------------------------------------------------------------------- /test/util/timeit.jl: -------------------------------------------------------------------------------- 1 | 2 | function timeit(fn::Function, arg::Real, n::Int) 3 | mn = 9999999.9; md=0.0; 4 | a=fn(arg) 5 | for i in 1:n 6 | a = time_ns() 7 | b = fn(arg) 8 | c = time_ns()-a 9 | if (c < mn) mn = c end; 10 | md = md+c; 11 | end 12 | md1 = div(md,n) 13 | div(6*Int(mn)+Int(md1),7) 14 | end 15 | 16 | -------------------------------------------------------------------------------- /src/eft/single.jl: -------------------------------------------------------------------------------- 1 | @inline function eftSquare(a::FloatingPoint) 2 | x = a * a 3 | y = fma(a, a, -x) 4 | x,y 5 | end 6 | 7 | function eftCube(a::FloatingPoint) 8 | p = a*a; e = fma(a, a, -p) 9 | x = p*a; p = fma(p, a, -x) 10 | y = e*a 11 | x,y 12 | end 13 | 14 | # !!sassafrass!! 15 | # presently 'y' must be negated to get the right result 16 | # I do not know why. 17 | # 18 | @inline function eftRecip(a::FloatingPoint) 19 | x = one(Float64)/a 20 | y = fma(x,a,-1.0)/a 21 | x,-y 22 | end 23 | -------------------------------------------------------------------------------- /src/io/DD.jl: -------------------------------------------------------------------------------- 1 | const DD_typename = "Float128" 2 | 3 | function show(io::IO, x::DD) 4 | hi=string(x.hi) 5 | lo=string(x.lo) 6 | print(io, string(DD_typename,"(",hi,", ",lo,")")) 7 | end 8 | 9 | function showcompact(io::IO, x::DD) 10 | hi=string(x.hi) 11 | print(io, hi) 12 | end 13 | 14 | function parse(::Type{DD}, str::AbstractString) 15 | if !(startswith(str,DD_typename)) 16 | throw(ErrorException("$(DD_typename) not found in $(str)")) 17 | end 18 | s = str[10:(end-1)] 19 | hilo = split(s,',') 20 | if length(hilo)==1 21 | hilo = [hilo[1],"0.0"] 22 | end 23 | shi,slo = hilo[1],hilo[2] 24 | hi = parse(Float64,shi) 25 | lo = parse(Float64,slo) 26 | hi,lo = eftSum2(hi,lo) 27 | DD(hi,lo) 28 | end 29 | 30 | function hex(x::DD) 31 | hi,lo = x.hi, x.lo 32 | shi = @sprintf("%a",hi) 33 | slo = @sprintf("%a",lo) 34 | s = string(DD_typename,"(",shi,", ",slo,")") 35 | s 36 | end 37 | -------------------------------------------------------------------------------- /src/io/TD.jl: -------------------------------------------------------------------------------- 1 | const TD_typename = "Float192" 2 | 3 | function show(io::IO, x::TD) 4 | hi=string(x.hi) 5 | md=string(x.md) 6 | lo=string(x.lo) 7 | print(io, string(TD_typename,"(",hi,", ",md,", ",lo,")")) 8 | end 9 | 10 | function parse(::Type{TD}, str::AbstractString) 11 | if !(startswith(str,TD_typename)) 12 | throw(ErrorException("$(TD_typename) not found in $(str)")) 13 | end 14 | s = str[10:(end-1)] 15 | himdlo = split(s,',') 16 | if length(hilo)==1 17 | himdlo = [himdlo[1],"0.0","0.0"] 18 | elseif length(himdlo)==2 19 | himdlo = [himdlo[1],himdlo[2],"0.0"] 20 | end 21 | 22 | shi,smd,slo = himdlo[1],himdlo[2],himdlo[3] 23 | hi = parse(Float64,shi) 24 | md = parse(Float64,smd) 25 | lo = parse(Float64,slo) 26 | hi,md,lo = eftSum3(hi,md,lo) 27 | TD(hi,md,lo) 28 | end 29 | 30 | 31 | function hex(x::TD) 32 | hi,md,lo = x.hi, x.md, x.lo 33 | shi = @sprintf("%a",hi) 34 | smd = @sprintf("%a",lo) 35 | slo = @sprintf("%a",lo) 36 | s = string(TD_typename,"(",shi,", ",smd,", ",slo,")") 37 | s 38 | end 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 DiademSpecialProjects 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FLOAT128.jl 2 | ### *(work in progress -- incomplete)* 3 | 100+ valid significand bits for elementary functions with conventionally small values. 4 | 5 | ### exports 6 | 7 | type Float128 8 | 9 | convert from Float64|32|16, Int128|64|32|16, BigFloat 10 | 11 | convert to BigFloat, convert to nearest Float64|32|16 Int128|64|32|16 12 | 13 | ldexp, frexp, abs, sign, signbit, trunc, floor, ceil, round, 14 | 15 | ==, !=, <, <=, >=, >, isless, isequal 16 | 17 | +, -, *, /, %, mod, rem, div, fld, cld, divrem, fldmod 18 | 19 | sqrt, exp, log, ^ 20 | 21 | sin, cos, tan, csc, sec, cot, asin, acos, atan, acsc, asec, acot 22 | 23 | sinh, cosh, tanh, csch, sech, coth, asinh, acosh, atanh, acsch, asech, acoth 24 | 25 | string, show, showcompact 26 | 27 | dict Float128s{Symbol, Float128} 28 | 29 | :zero, :one, :two, :three, :four, :sqrt2, :log2, :log10, :exp1, :pi, :twopi 30 | 31 | reciprocals :half, :quarter, :_sqrt2, :_log2, :_log10, :_exp1, :_pi, :_twopi 32 | 33 | add your own by converting from parsed BigFloat values 34 | 35 | clean(x::Float128) 36 | 37 | zeros the low order part when it approaches eps(eps(high order part)) 38 | 39 | ### Use 40 | 41 | -------------------------------------------------------------------------------- /src/eft/double.jl: -------------------------------------------------------------------------------- 1 | 2 | @inline function eftSum2{T<:FloatingPoint}(a::T, b::T) 3 | x = a + b 4 | t = x - a 5 | y = (a - (x - t)) + (b - t) 6 | x,y 7 | end 8 | 9 | 10 | @inline function eftSum2inOrder{T<:FloatingPoint}(a::T, b::T) 11 | x = a + b 12 | y = b - (x - a) 13 | x,y 14 | end 15 | 16 | 17 | @inline function eftDiff2{T<:FloatingPoint}(a::T, b::T) 18 | x = a - b 19 | t = x - a 20 | y = (a - (x - t)) - (b + t) 21 | x,y 22 | end 23 | 24 | 25 | @inline function eftDiff2inOrder{T<:FloatingPoint}(a::T, b::T) 26 | x = a - b 27 | y = (a - x) - b 28 | x,y 29 | end 30 | 31 | @inline function eftProd2{T<:FloatingPoint}(a::T, b::T) 32 | x = a * b 33 | y = fma(a, b, -x) 34 | x,y 35 | end 36 | 37 | # !!sassafrass!! 38 | # presently 'y' must be negated to get the right result 39 | # I do not know why. 40 | 41 | @inline function eftDiv2{T<:FloatingPoint}(a::T,b::T) 42 | x = a/b 43 | y = fma(x,b,-a)/b 44 | x,-y 45 | end 46 | 47 | #= 48 | """ 49 | (a,b) ↦ (x,y)\\ 50 | x⊕y ≖ a⊕b and x⊕y≖x 51 | """->eftSum2 52 | 53 | """ 54 | (a,b) ↦ (x,y)\\ 55 | x⊕y ≖ a⊕b and x⊕y≖x\\ 56 | *presumes* |a| ≥ |b| 57 | """->eftSum2InOrder 58 | 59 | """ 60 | (a,b) ↦ (x,y)\\ 61 | x⊕y ≖ a⊝b and x⊕y≖x 62 | """->eftDiff2 63 | 64 | """ 65 | (a,b) ↦ (x,y)\\ 66 | x⊕y ≖ a⊝b and x⊕y≖x\\ 67 | *presumes* |a| ≥ |b| 68 | """->eftDiff2inOrder 69 | =# 70 | -------------------------------------------------------------------------------- /doc/refs.md: -------------------------------------------------------------------------------- 1 | 2 | "Some Functions Computaable with a Fused-mac" 3 | by Sylvie Boldo and Jean-Michel Muller 4 | 5 | Fast Algorithms for High-Precision Computation of Elementary Functions 6 | Richard P. Brent, 2006 7 | 8 | Modern Computer Arithmetic 9 | by Richard P. Brent and Paul Zimmermann 10 | 11 | "The Right Way To Calculate Stuff" 12 | by Don Hatch 13 | http://www.plunk.org/~hatch/rightway.php 14 | 15 | "Algorithms for Quad-Double Precision Floating Point Arithmetic" 16 | by Yozo Hida, Xiaoy S. Li, David H. Bailey 17 | 18 | "Efficient implementation of elementary functions in the medium-precision range" 19 | by Fredrik Johansson 20 | 21 | 22 | "High Precision Division and Square Root" 23 | by Alan H. Karp, Peter Markstein, revised 1994 24 | 25 | 26 | "Basic building blocks for a triple-double intermediate format" 27 | by Christoph Quirin Lauter 28 | 29 | Handbook of Floating-Point Arithmetic 30 | by Vincent Lefèvre, Guillaume Melquiond, Nathalie Revol, Damien Stehlé, Serge Torres 31 | © Birkh¨auser Boston, a part of Springer Science+Business Media, LLC 2010 32 | ISBN 978-0-8176-4704-9 e-ISBN 978-0-8176-4705-6 DOI 10.1007/978-0-8176-4705-6 33 | 34 | An Atlas of Functions (2nd ed) 35 | by Keith Oldham, Jan Myland, Jerome Spanier 36 | 37 | "Accurate Floating-Point Summation Part I: Faithful Rounding" 38 | by Siegfried M. Rump, Takeshi Ogita, Shin'ichi Oishi 39 | 40 | -------------------------------------------------------------------------------- /test/util/randnums.jl: -------------------------------------------------------------------------------- 1 | #= 2 | random numbers for testing 3 | 4 | bitgap is count of zero bits separating paired values 5 | frval is the value used as frexp(val)[1] 6 | expon is the value used as frexp(val)[2] 7 | =# 8 | 9 | if !isdefined(:DD) 10 | DD = FLOAT128.DD 11 | end 12 | if !isdefined(:TD) 13 | TD = FLOAT128.TD 14 | end 15 | 16 | using(Distributions) 17 | 18 | baseBitgapDist = Geometric(0.435) 19 | wideBitgapDist = Geometric(0.235) 20 | 21 | baseBitgap() = rand(baseBitgapDist) 22 | wideBitgap() = rand(wideBitgapDist) 23 | 24 | function frval() 25 | s = rand() 26 | if (s < 0.5) 27 | s += 0.5 28 | end 29 | s 30 | end 31 | 32 | expon() = rand(-5:5) 33 | 34 | msval() = ldexp(frval(),expon()) 35 | function lsval(frval::AbstractFloat, bitgap::Function) 36 | vexpon = frexp(frval)[2] - 54 - bitgap() 37 | ldexp(frval,vexpon) 38 | end 39 | 40 | function randhighlow(bitgap::Function=wideBitgap, expow2::Function=expon) 41 | fr = frval() 42 | xp = expow2() 43 | hi = ldexp(fr,xp) 44 | xp = xp - 54 - bitgap() 45 | lo = ldexp(frval(),xp) 46 | hi,lo 47 | end 48 | 49 | function randhighmedlow(bitgap::Function=wideBitgap, expow2::Function=expon) 50 | fr = frval() 51 | xp = expow2() 52 | hi = ldexp(fr,xp) 53 | xp = xp - 54 - bitgap() 54 | md = ldexp(frval(),xp) 55 | xp = xp - 54 - bitgap() 56 | lo = ldexp(frval(),xp) 57 | hi,md,lo 58 | end 59 | 60 | randhilo(bitgap::Function=wideBitgap, expow2::Function=expon) = DD(randhighlow(bitgap,expow2)...) 61 | randhml(bitgap::Function=wideBitgap, expow2::Function=expon) = TD(randhighmedlow(bitgap,expow2)...) 62 | 63 | rangedhilo(bg::Float64,en::Float64) = DD(rand(bg:en)) 64 | -------------------------------------------------------------------------------- /src/util/domainCheck.jl: -------------------------------------------------------------------------------- 1 | abstract BoundingPair{T <: Real} 2 | 3 | immutable BotTop{T} <: BoundingPair 4 | bot::T 5 | top::T 6 | 7 | function BotTop(bot::T, top::T) 8 | bot, top = min(bot,top), max(bot,top) 9 | new(bot, top) 10 | end 11 | end 12 | 13 | @inline function isBetween{T<:Real}(value::T, bounds::BotTop{T}) 14 | bounds.bot < value < bounds.top 15 | end 16 | @inline function isNotBetween{T<:Real}(value::T, bounds::BotTop{T}) 17 | !isBetween(value,bounds) 18 | end 19 | @inline function isAmoung{T<:Real}(value::T, bounds::BotTop{T}) 20 | bounds.bot <= value <= bounds.top 21 | end 22 | @inline function isNotAmoung{T<:Real}(value::T, bounds::BotTop{T}) 23 | !isAmoung(value,bounds) 24 | end 25 | 26 | @inline function isInClosedOpen{T<:Real}(value::T, bounds::BotTop{T}) 27 | bounds.bot <= value < bounds.top 28 | end 29 | @inline function isNotInClosedOpen{T<:Real}(value::T, bounds::BotTop{T}) 30 | !isInClosedOpen(value,lowerBound,upperBound) 31 | end 32 | @inline function isInOpenClosed{T<:Real}(value::T, bounds::BotTop{T}) 33 | bounds.bot < value <= bounds.top 34 | end 35 | @inline function isNotInOpenClosed{T<:Real}(value::T, bounds::BotTop{T}) 36 | !isInOpenClosed(value,lowerBound,upperBound) 37 | end 38 | 39 | @inline function isAbove{T<:Real}(value::T, bounds::BotTop{T}) 40 | bounds.bot < value 41 | end 42 | @inline function isNotAbove{T<:Real}(value::T, bounds::BotTop{T}) 43 | !isAbove(value,lowerBound) 44 | end 45 | @inline function isBelow{T<:Real}(value::T, bounds::BotTop{T}) 46 | value < bounds.top 47 | end 48 | @inline function isNotBelow{T<:Real}(value::T, bounds::BotTop{T}) 49 | !isBelow(value,upperBound) 50 | end 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /src/mag/DD.jl: -------------------------------------------------------------------------------- 1 | @inline function isless(a::DD, b::DD) 2 | (a.hi < b.hi) || (a.hi==b.hi && a.lo)(a::DD,b::DD) = (a.hi > b.hi) || (a.hi==b.hi && a.lo>b.lo) 24 | @inline (>=)(a::DD,b::DD) = (a.hi > b.hi) || (a.hi==b.hi && a.lo>=b.lo) 25 | 26 | 27 | 28 | 29 | function (floor)(a::DD) 30 | hi = floor(a.hi) 31 | lo = 0.0 32 | if (hi == a.hi) 33 | lo = floor(a.lo) 34 | hi,lo = eftSum2inOrder(hi,lo) 35 | end 36 | DD(hi,lo) 37 | end 38 | 39 | function (ceil)(a::DD) 40 | hi = ceil(a.hi) 41 | lo = 0.0 42 | if (hi == a.hi) 43 | lo = ceil(a.lo) 44 | hi,lo = eftSum2inOrder(hi,lo) 45 | end 46 | DD(hi,lo) 47 | end 48 | 49 | @inline function (trunc)(a::DD) 50 | a.hi >= zero(F) ? floor(a) : ceil(a) 51 | end 52 | 53 | function ldexp(a::DD,xp::Int) 54 | DD(ldexp(a.hi,xp),ldexp(a.lo,xp)) 55 | end 56 | 57 | function frexp(a::DD) 58 | frhi, xphi = frexp(a.hi) 59 | frlo, xplo = frexp(a.lo) 60 | DD(frhi, ldexp(frlo,xplo-xphi)), xphi 61 | end 62 | -------------------------------------------------------------------------------- /src/atrig/TD.jl: -------------------------------------------------------------------------------- 1 | 2 | function sincos(x::TD) 3 | s,c=sincos(DD(x)) 4 | slo,clo = TD(sin(x.lo)),TD(cos(x.lo)) 5 | s*clo+c*slo, c*clo-s*slo 6 | end 7 | 8 | # use Newton's iteration to solve 9 | # sin(z) = y/r (1) 10 | # cos(z) = x/r (2) 11 | # where r = sqrt(x^2 + y^2). 12 | # The iteration is given by 13 | # 14 | # z' = z + (y - sin(z)) / cos(z) (for equation 1) 15 | # z' = z - (x - cos(z)) / sin(z) (for equation 2) 16 | # 17 | # Here, x and y are normalized so that x^2 + y^2 = 1. 18 | # If |x| > |y|, then first iteration is used since the 19 | # denominator is larger. Otherwise, the second is used. 20 | 21 | 22 | function atan2{T<:TD}(y::T,x::T) 23 | if x.hi == zero(Float64) 24 | if y.hi == zero(Float64) 25 | # Both x and y are zero 26 | throw(ErrorException("atan2: Both arguments zero.")) 27 | return td_NaN 28 | end 29 | return (y.hi > zero(Float64) ? td_pi_over_2 : -td_pi_over_2) 30 | elseif y.hi == zero(Float64) 31 | return (x.hi > zero(Float64) ? zero(TD) : td_pi) 32 | end 33 | 34 | if (x == y) 35 | return (y.hi > zero(Float64) ? td_pi_over_4 : -td_3pi_over_4) 36 | elseif (x == -y) 37 | return (y.hi > zero(Float64) ? td_3pi_over_4 : -td_pi_over_4) 38 | end 39 | 40 | r = sqrt(sqr(x) + sqr(y)) 41 | xx = x / r 42 | yy = y / r 43 | 44 | # Compute double precision approximation to atan. 45 | z = TD(atan2(y.hi,x.hi)) 46 | 47 | if (abs(xx.hi) > abs(yy.hi)) 48 | # Use Newton iteration 1. z' = z + (y - sin(z)) / cos(z) 49 | sin_z,cos_z = sincos(z) 50 | z += (yy - sin_z) / cos_z 51 | sin_z,cos_z = sincos(z) 52 | z += (yy - sin_z) / cos_z 53 | sin_z,cos_z = sincos(z) 54 | z += (yy - sin_z) / cos_z 55 | else 56 | # Use Newton iteration 2. z' = z - (x - cos(z)) / sin(z) 57 | sin_z,cos_z = sincos(z) 58 | z -= (xx - cos_z) / sin_z; 59 | sin_z,cos_z = sincos(z) 60 | z -= (xx - cos_z) / sin_z; 61 | sin_z,cos_z = sincos(z) 62 | z -= (xx - cos_z) / sin_z; 63 | end 64 | 65 | z 66 | end 67 | 68 | atan(x::TD) = atan2(x,one(TD)) 69 | 70 | -------------------------------------------------------------------------------- /src/FLOAT128.jl: -------------------------------------------------------------------------------- 1 | VERSION >= v"0.4.0" && __precompile__() 2 | 3 | module FLOAT128 4 | 5 | # using 6 | 7 | # import 8 | import Base: convert, promote_rule, 9 | zero, one, isinf, isnan, isfinite, 10 | (-), abs, sign, signbit, copysign, flipsign, 11 | isequal, isless, (<),(<=),(==),(>=),(>), 12 | (+),(*),(/),(\), fma, 13 | round, floor, ceil, trunc, fld, cld, 14 | ldexp, frexp, modf, 15 | div, rem, divrem, mod, fldmod, (%), 16 | sqrt, hypot, (^), 17 | exp, log, log2, log10, expm1, log1p, 18 | sin, cos, tan, csc, sec, cot, 19 | sinh, cosh, tanh, csch, sech, coth, 20 | asin, acos, atan, acsc, asec, acot, atan2, 21 | asinh, acosh, atanh, acsch, asech, acoth, 22 | string, show, showcompact, parse, hex 23 | 24 | # export 25 | 26 | export Float128, clean, Float128s, 27 | # for development only 28 | fnTest, fnTest2, hilo, hml, nearest12 29 | 30 | # include 31 | 32 | include("config.jl") 33 | include("types.jl") 34 | 35 | # error-free transformations by number of args in & vals out 36 | include("eft/single.jl") 37 | include("eft/double.jl") 38 | include("eft/triple.jl") 39 | 40 | # working types 41 | include("const/DD.jl") 42 | include("const/TD.jl") 43 | 44 | # internal 45 | include("util/domainCheck.jl") 46 | 47 | # magnitude: comparison and subnumeric composition 48 | include("mag/DD.jl") 49 | include("mag/TD.jl") 50 | 51 | # arithmetic and arithmetic support 52 | include("arith/DD.jl") 53 | include("arith/TD.jl") 54 | include("arith/DDmanip.jl") 55 | include("arith/TDmanip.jl") 56 | 57 | # integer powers, reciprocal roots 58 | include("pow/DD.jl") 59 | 60 | # log, exp 61 | include("exp/DD.jl") 62 | include("exp/TD.jl") 63 | 64 | # trig, arctrig 65 | include("trig/DD.jl") 66 | include("atrig/DD.jl") 67 | include("atrig/TD.jl") 68 | 69 | # trigh 70 | include("trigh/DD.jl") 71 | include("trigh/TD.jl") 72 | include("atrigh/DD.jl") 73 | 74 | # io 75 | include("io/DD.jl") 76 | include("io/TD.jl") 77 | 78 | # for development only 79 | include("../test/util/nearest.jl") 80 | include("../test/util/randnums.jl") 81 | include("../test/util/testit.jl") 82 | 83 | #include("try.jl") 84 | end # module 85 | -------------------------------------------------------------------------------- /src/trigh/TD.jl: -------------------------------------------------------------------------------- 1 | const td_tanh_coeff = TD[ 2 | TD(1.0, 0.0, 0.0), 3 | TD(-0.3333333333333333, -1.850371707708594e-17, -1.0271626370065257e-33), 4 | TD(0.13333333333333333, 1.8503717077085942e-18, 2.5679065925163144e-35), 5 | TD(-0.05396825396825397, 2.5552752154071065e-18, -1.6630252218200895e-34), 6 | TD(0.021869488536155203, -1.7377829530067485e-19, -4.831808370177854e-36), 7 | TD(-0.008863235529902197, 7.63300580171831e-19, 4.7974399233588223e-35), 8 | TD(0.003592128036572481, -1.253823608406629e-19, 4.795236421907504e-36), 9 | TD(-0.0014558343870513183, 6.214492640136062e-20, -6.0162151902653385e-37), 10 | TD(0.000590027440945586, 3.478690842383652e-20, 4.680211252424582e-37), 11 | TD(-0.00023912911424355248, -3.564613898329782e-21, -3.07545625243076e-38), 12 | TD(9.691537956929451e-5, -6.2386628755632464e-21, -4.0017079836981273e-38), 13 | TD(-3.927832388331683e-5, -1.3737015743076767e-21, -2.426928811391287e-38), 14 | TD(1.5918905069328964e-5, 1.0427554807190543e-21, 2.193706324479927e-39), 15 | TD(-6.451689215655431e-6, -1.1519922496640058e-22, 1.3352659990971372e-39), 16 | TD(2.6147711512907546e-6, -9.313685621299801e-23, -1.3198106922390603e-40), 17 | TD(-1.0597268320104654e-6, -2.3670525505213632e-24, 6.338164573280627e-41), 18 | TD(4.294911078273806e-7, 1.1643520863702653e-23, 2.25974956639863e-40), 19 | ]; 20 | 21 | function tanh_taylor_series(radian::TD) 22 | x = radian 23 | x2 = x*x 24 | x3 = x*x2 25 | x4 = x2*x2 26 | x5 = x2*x3 27 | x6 = x3*x3 28 | x7 = x3*x4 29 | x8 = x4*x4 30 | x9 = x4*x5 31 | x17 = x8*x9 32 | x25 = x17*x8 33 | 34 | z = x + x*(td_tanh_coeff[2]*x2 + td_tanh_coeff[3]*x4 + td_tanh_coeff[4]*x6) 35 | z2 = x9 * (td_tanh_coeff[5] + x2*td_tanh_coeff[6] + x4*td_tanh_coeff[7] + x6*td_tanh_coeff[8]) 36 | z3 = x17 * (td_tanh_coeff[9] + x2*td_tanh_coeff[10] + x4*td_tanh_coeff[11] + x6*td_tanh_coeff[12]) 37 | z4 = x25 * (td_tanh_coeff[13] + x2*td_tanh_coeff[14] + x4*td_tanh_coeff[15] + x6*td_tanh_coeff[16]) 38 | 39 | z + ((z4+z3)+z2) 40 | end 41 | 42 | function sinh(x::TD) 43 | epx = exp(x) 44 | emx = 1.0/epx 45 | epx = epx - emx 46 | divby2(epx) 47 | end 48 | 49 | function cosh(x::TD) 50 | epx = exp(x) 51 | emx = 1.0/epx 52 | epx = epx + emx 53 | divby2(epx) 54 | end 55 | 56 | function tanh(x::TD) 57 | epx = exp(x) 58 | emx = exp(-x) # do not use 1.0/exp(x) here 59 | n = (epx - emx) 60 | d = (epx + emx) 61 | n/d 62 | end 63 | -------------------------------------------------------------------------------- /doc/precision.md: -------------------------------------------------------------------------------- 1 | # FLOAT128.jl 2 | ### *(work in progress -- incomplete)* 3 | 100+ valid significand bits for elementary functions with conventionally small values. 4 | 5 | relative errors (*max found with 20,000 random double-double values each function*) 6 | 7 | ∝64 is time fn(Float128)/fn(Float64), @time (on 1 machine, so ymmv) 8 | 9 | ∝Big is time n(Float128)/fn(BigFloat_160) similarly 10 | 11 | 12 | | func | over | sig bits | rel err | ∝64 | ∝Big | 13 | |------|------|----------|---------|------|-------| 14 | | sqrt | 0..64G | 106 | 1.2e-32 | 1.6| 0.6 | 15 | | | | | | | | 16 | | exp | -15..15 | 104 | 4.9e-32 |2.75 | 0.35 | 17 | | exp | -300..-15,15..300 | 103 | 5.2e-32 |2.35| 0.66 | 18 | | | | | | | 19 | | log | 1..64G | 105 | 1.9e-33 |4.8 | 0.6 | 20 | | | | | | | 21 | | sin, cos | -2pi..2pi | 106 | 1.2e-32 | 1.9 | 0.2 | 22 | | tan | -2pi..2pi | 104 | 4.8e-32 | 2.3 | 0.4 | 23 | | csc, sec, cot | -2pi..2pi | 104 | 4.8e-32 | | | 24 | | | | | | | 25 | | asin, acos | -1..1 | 106 | 8e-33 | 20 | 2.0 | 26 | | atan, acot | -1..1 | 106 | 1.2e-32 | 15 | 1.8 | 27 | | acsc | -64G..-1,1..64G | 106 | 2.5e-32 | | | 28 | | asec | -4096..-1,1..4096 | 104 | 2.7e-32 | | | 29 | | | | | | 30 | | sinh, cosh | -1..1 | 104 | 4.5e-32 | 2.3 | 0.34 | 31 | | tanh | -1..1 | 104 | 4.5e-32 | 3.5 | 0.4 | 32 | | csch, sech, coth | -1..1| 104 | 4.6e-32 | | | 33 | | | | | | 34 | | asinh | -1..1 | 105 | 2.2e-32 | 8.6 | 1.4 | 35 | | acosh | 1..16 | 105 | 2.0e-32 | 8.6 | 1.4 | 36 | | atanh | -1..1 | 109 | 1.5e-33 | 9 | 2 | 37 | | acsch, asech, acoth | | ? | | | 38 | | | | | | 39 | | | | | | 40 | | sin, cos | -64Gpi..64Gpi | 105 | 2.25-32 | | | 41 | | tan | -64Gpi..64Gpi | 103 | 5.9e-32 | | | 42 | | csc, sec, cot | -64Gpi..64Gpi | 103 | 8.8e-32 | | | 43 | | | | | | 44 | | sinh, cosh, tanh | -256..256 | 104 | 4.5e-32 | | | 45 | | csch, sech, coth | -256..256 | 103 | 6.7e-32 | | | 46 | 47 | ** 64G = 4096^3 ** 48 | 49 | ##### outliers 50 | | function | arg | eval | true | 51 | |----------|-----|------|------| 52 | | tanh |(5.551170634277014e-17, -6.162975822039155e-33) | (5.551170634277014e-17, -6.162975822039155e-33) | (5.551170634277013e-17, 6.162975822039155e-33) | 53 | | asinh |(1.1102341268554029e-16, -1.232595164407831e-32) | (1.1102341268554029e-16, -1.232595164407831e-32) | (1.1102341268554026e-16, 1.232595164407831e-32) | 54 | 55 | 56 | -------------------------------------------------------------------------------- /src/eft/triple.jl: -------------------------------------------------------------------------------- 1 | function eftSum3{T<:FloatingPoint}(a::T,b::T,c::T) 2 | s,t = eftSum2(b, c) 3 | x,u = eftSum2(a, s) 4 | y,z = eftSum2(u, t) 5 | x,y = eftSum2inOrder(x, y) 6 | x,y,z 7 | end 8 | 9 | function eftSum3inOrder{T<:FloatingPoint}(a::T,b::T,c::T) 10 | s,t = eftSum2inOrder(b, c) 11 | x,u = eftSum2inOrder(a, s) 12 | y,z = eftSum2inOrder(u, t) 13 | x,y = eftSum2inOrder(x, y) 14 | x,y,z 15 | end 16 | 17 | @inline function eftSum3as2{T<:FloatingPoint}(a::T,b::T,c::T) 18 | s,t = eftSum2(b, c) 19 | x,u = eftSum2(a, s) 20 | y = u+t 21 | x,y = eftSum2inOrder(x, y) 22 | x,y 23 | end 24 | 25 | @inline function eftSum3inOrderAs2{T<:FloatingPoint}(a::T,b::T,c::T) 26 | s,t = eftSum2inOrder(b, c) 27 | x,u = eftSum2inOrder(a, s) 28 | y = u+t 29 | x,y = eftSum2inOrder(x, y) 30 | x,y 31 | end 32 | 33 | function eftProd3{T<:FloatingPoint}(a::T, b::T, c::T) 34 | p,e = eftProd2(a,b) 35 | x,p = eftProd2(p,c) 36 | y,z = eftProd2(e,c) 37 | x,y,z 38 | end 39 | 40 | @inline function eftProd3as2{T<:FloatingPoint}(a::T, b::T, c::T) 41 | p,e = eftProd2(a,b) 42 | x,p = eftProd2(p,c) 43 | y = e*c 44 | x,y 45 | end 46 | 47 | 48 | 49 | function eftFMA{T<:FloatingPoint}(a::T, b::T, c::T) 50 | x = fma(a,b,c) 51 | u1,u2 = eftProd2(a,b) 52 | a1,a2 = eftSum2(u2,c) 53 | b1,b2 = eftSum2(u1,a1) 54 | g = (b1-x)+b2 55 | y,z = eftSum2inOrder(g,a2) 56 | x,y,z 57 | end 58 | 59 | function eftFMS{T<:FloatingPoint}(a::T, b::T, c::T) 60 | x = fma(a,b,c) 61 | u1,u2 = eftProd2(a,b) 62 | a1,a2 = eftDiff2(u2,c) 63 | b1,b2 = eftSum2(u1,a1) 64 | g = (b1-x)+b2 65 | y,z = eftSum2inOrder(g,a2) 66 | x,y,z 67 | end 68 | 69 | # experimental (a/b)+c 70 | function eftFDA{T<:FloatingPoint}(a::T,b::T,c::T) 71 | x = (a/b) 72 | y = fma(x,b,-a)/b 73 | z = -y 74 | eftSum3as2(x,z,c) 75 | end 76 | 77 | # experimental (a/b)-c 78 | function eftFDS{T<:FloatingPoint}(a::T,b::T,c::T) 79 | x = (a/b) 80 | y = fma(x,b,-a)/b 81 | z = -y 82 | eftSum3as2(x,z,-c) 83 | end 84 | 85 | 86 | #= 87 | 88 | """ 89 | error free transformation for fused multiply add (fma) 90 | (a,b,c) ↦ (x,y,z)\\ 91 | x⊕y⊕z ≖ a⊗b⊕c and x==fma(a,b,c) and x⊕y≖x, y⊕z≖y 92 | 93 | ref: 94 | Some functions computable with a fused-mac 95 | by Sylvie Boldo and Jean-Michel Muller 96 | Proceedings of the 17th IEEE Symposium on Computer Arithmetic, 2005 97 | """->eftFMA 98 | 99 | 100 | """ 101 | error free transformation for fused multiply subtract (fms) 102 | (a,b,c) ↦ (x,y,z)\\ 103 | x⊕y⊕z ≖ a⊗b⊝c and x==fma(a,b,-c) and x⊕y≖x, y⊕z≖y 104 | """->eftFMS 105 | 106 | =# 107 | -------------------------------------------------------------------------------- /src/mag/TD.jl: -------------------------------------------------------------------------------- 1 | @inline function isless(a::TD, b::TD) 2 | (a.hi < b.hi) || (a.hi==b.hi && a.mdzero(Float64)) 9 | end 10 | @inline function isequal(a::TD, b::TD) 11 | (a.hi == b.hi) && (a.md == b.md) && (a.lo == b.lo) 12 | end 13 | @inline function isequal(a::TD, b::Float64) 14 | (a.hi == b) && (a.md == zero(Float64)) 15 | end 16 | @inline function isequal(a::Float64, b::TD) 17 | (a == b.hi) && (b.md == zero(Float64)) 18 | end 19 | 20 | @inline (==)(a::TD,b::TD) = (a.hi == b.hi) && (a.md == b.md) && (a.lo == b.lo) 21 | @inline (< )(a::TD,b::TD) = (a.hi < b.hi) || (a.hi==b.hi && a.md )(a::TD,b::TD) = (a.hi > b.hi) || (a.hi==b.hi && a.md>b.md) || (a.hi==b.hi && a.md==b.md && a.lo>b.lo) 24 | @inline (>=)(a::TD,b::TD) = (a.hi > b.hi) || (a.hi==b.hi && a.md>b.md) || (a.hi==b.hi && a.md==b.md && a.lo>=b.lo) 25 | 26 | @inline (==)(a::TD,b::DD) = (==)(a,TD(b)) 27 | @inline (< )(a::TD,b::DD) = (< )(a,TD(b)) 28 | @inline (<=)(a::TD,b::DD) = (==)(a,TD(b)) 29 | @inline (> )(a::TD,b::DD) = (> )(a,TD(b)) 30 | @inline (>=)(a::TD,b::DD) = (>=)(a,TD(b)) 31 | 32 | @inline (==)(a::DD,b::TD) = (==)(TD(a),b) 33 | @inline (< )(a::DD,b::TD) = (< )(TD(a),b) 34 | @inline (<=)(a::DD,b::TD) = (==)(TD(a),b) 35 | @inline (> )(a::DD,b::TD) = (> )(TD(a),b) 36 | @inline (>=)(a::DD,b::TD) = (>=)(TD(a),b) 37 | 38 | 39 | function (floor)(a::TD) 40 | hi = floor(a.hi) 41 | md = lo = 0.0 42 | if (hi == a.hi) 43 | md = floor(a.md) 44 | hi,md = eftSum2inOrder(hi,md) 45 | if md == a.md 46 | lo = floor(a.lo) 47 | md,lo = eftSum2inOrder(md,lo) 48 | hi,md = eftSum2inOrder(hi,md) 49 | end 50 | end 51 | TD(hi,md,lo) 52 | end 53 | 54 | function (ceil)(a::TD) 55 | hi = ceil(a.hi) 56 | md = lo = 0.0 57 | if (hi == a.hi) 58 | md = ceil(a.md) 59 | hi,md = eftSum2inOrder(hi,md) 60 | if md == a.md 61 | lo = ceil(a.lo) 62 | md,lo = eftSum2inOrder(md,lo) 63 | hi,md = eftSum2inOrder(hi,md) 64 | end 65 | end 66 | end 67 | 68 | @inline function (trunc)(a::TD) 69 | a.hi >= zero(F) ? floor(a) : ceil(a) 70 | end 71 | 72 | function ldexp(a::TD,xp::Int) 73 | TD(ldexp(a.hi,xp),ldexp(a.md,xp),ldexp(a.lo,xp)) 74 | end 75 | 76 | function frexp(a::TD) 77 | frhi, xphi = frexp(a.hi) 78 | frmd, xpmd = frexp(a.md) 79 | frlo, xplo = frexp(a.lo) 80 | TD(frhi, ldexp(frmd,xpmd-xphi), ldexp(frlo,xplo-xphi)), xphi 81 | end 82 | 83 | -------------------------------------------------------------------------------- /src/pow/DD.jl: -------------------------------------------------------------------------------- 1 | 2 | function (sqr){T<:DD}(a::T) 3 | t1,t2 = eftProd2(a.hi,a.hi) 4 | t3 = a.hi * a.lo 5 | t5 = t3 + t3 6 | t6 = t2 + t5 7 | t1,t6 = eftSum2inOrder(t1,t6) 8 | DD(t1,t6) 9 | end 10 | 11 | function (cub){T<:DD}(a::T) 12 | t1,t2 = eftProd2(a.hi,a.hi) 13 | t3 = a.hi * a.lo 14 | t5 = t3 + t3 15 | t6 = t2 + t5 16 | t1,t6 = eftSum2inOrder(t1,t6) 17 | a * DD(t1,t6) 18 | end 19 | 20 | function npow{T<:DD,N<:Integer}(a::T,n::N) 21 | if n == zero(N) 22 | if a.hi == zero(typeof(a.hi)) 23 | throw(DomainError) 24 | else 25 | one(typeof(a)) 26 | end 27 | end 28 | 29 | r = a 30 | s = one(typeof(a)) 31 | m = abs(n) 32 | 33 | if m > one(N) 34 | # binary exponentiation 35 | while (m > 0) 36 | if m%2 == one(N) 37 | s = s*r 38 | end 39 | m >>= 1 40 | if m > zero(N) 41 | r = sqr(r) 42 | end 43 | end 44 | else 45 | s = r 46 | end 47 | 48 | if (n < zero(N)) 49 | s = recip(s) 50 | end 51 | 52 | s 53 | end 54 | 55 | #= 56 | function sqrt(a::DD) 57 | if a.hi <= zero(Float64) 58 | if a.hi == zero(Float64) 59 | return zero(DD) 60 | else 61 | throw(DomainError("sqrt expects a nonnegative base")) 62 | end 63 | end 64 | 65 | fl1 = one(Float64) 66 | r = one(Float64)/sqrt(a.hi) 67 | r += (r * (fl1 - (a * (r*r)))) * 0.5 68 | r += (r * (fl1 - (a * (r*r)))) * 0.5 69 | 70 | r*a 71 | end 72 | =# 73 | 74 | function cubrt{T<:DD}(a::T) 75 | if a.hi <= zero(typeof(a.hi)) 76 | if a.hi == zero(typeof(a.hi)) 77 | return zero(typeof(a)) 78 | else 79 | throw(DomainError("cubrt expects a nonnegative base")) 80 | end 81 | end 82 | 83 | fl1 = one(typeof(a.hi)) 84 | r = a.hi^(-fl1/3.0) 85 | r += r * (fl1 - (a * (r*r))) / dd_three 86 | r += r * (fl1 - (a * (r*r))) / dd_three 87 | 88 | 89 | recip(r) 90 | end 91 | 92 | function nroot{T<:DD,N<:Integer}(a::T,p::N) 93 | if p <= one(N) 94 | if p == zero(N) 95 | return one(typeof(a)) 96 | elseif p == one(N) 97 | return a 98 | end 99 | elseif a.hi <= zero(typeof(a.hi)) 100 | if a.hi == zero(typeof(a.hi)) 101 | return zero(typeof(a)) 102 | else 103 | throw(DomainError("iroot expects a nonnegative base")) 104 | end 105 | end 106 | 107 | fl1 = one(typeof(a.hi)) 108 | flp = convert(Float64,p) 109 | f2p = (T)(flp,zero(typeof(a.hi))) 110 | r = a.hi^(-fl1/flp) 111 | r += r * (fl1 - (a * (npowr(r,p)))) / f2p 112 | r += r * (fl1 - (a * (npowr(r,p)))) / f2p 113 | 114 | recip(r) 115 | end 116 | 117 | ^(a::DD,i::Int) = npow(a,i) 118 | 119 | function (^)(a::DD,r::Float64) 120 | p = 1.0/r 121 | if (p == trunc(p)) 122 | nroot(a,trunc(Int,p)) 123 | else 124 | exp(r * log(a)) 125 | end 126 | end 127 | 128 | function (^)(a::DD,r::DD) 129 | p = 1.0/r 130 | if (p == trunc(p.hi)) 131 | nroot(a,trunc(Int,p.hi)) 132 | else 133 | exp(r * log(a)) 134 | end 135 | end 136 | 137 | (^)(a::Float64,r::DD) = (^)(DD(a),r) 138 | -------------------------------------------------------------------------------- /src/atrigh/DD.jl: -------------------------------------------------------------------------------- 1 | # |a| <= 0.00275 2 | function atanh_series(a::DD) 3 | x = a 4 | x2 = x*x 5 | x4 = x2*x2 6 | x6 = x2*x4 7 | x8 = x4*x4 8 | x16 = x8*x8 9 | x24 = x8*x16 10 | 11 | z = dd_recip_int[3]*x2 + dd_recip_int[5]*x4 + dd_recip_int[7]*x6 12 | z1 = x8*(dd_recip_int[9] + dd_recip_int[11]*x2 + dd_recip_int[14]*x4 + dd_recip_int[15]*x6) 13 | z2 = x16*(dd_recip_int[17] + dd_recip_int[19]*x2 + dd_recip_int[21]*x4 + dd_recip_int[23]*x6) 14 | z3 = x24*(dd_recip_int[25] + dd_recip_int[27]*x2 + dd_recip_int[29]*x4 + dd_recip_int[31]*x6) 15 | 16 | (((z3+z2)+z1)+z+one(DD))*x 17 | end 18 | 19 | const dd_asinh_coeff = DD[ 20 | DD(1.0), 21 | DD(-0.16666666666666666, -9.25185853854297e-18), 22 | DD(0.075, 2.7755575615628915e-18), 23 | DD(-0.044642857142857144, 9.912705577010326e-19), 24 | DD(0.030381944444444444, 3.854941057726238e-19), 25 | DD(-0.022372159090909092, 9.462128050782583e-19), 26 | DD(0.017352764423076924, -8.006416042969879e-19), 27 | DD(-0.01396484375, 6.938893903907229e-19), 28 | DD(0.011551800896139705, 8.163404592832033e-19), 29 | DD(-0.009761609529194078, -5.478074134663601e-19), 30 | DD(0.008390335809616815, 4.130293990420969e-19), 31 | DD(-0.0073125258735988454, 3.394024192128536e-19), 32 | DD(0.006447210311889649, -3.1225022567582527e-19), 33 | DD(-0.005740037670841924, 1.2849803525754126e-19), 34 | DD(0.005153309682319905, -3.888173308223878e-19), 35 | DD(-0.004660143486915096, 2.7979410902851727e-20), 36 | DD(0.004240907093679363, -1.5770213417970974e-19), 37 | DD(-0.003880964558837669, -1.858632295689436e-19), 38 | DD(0.0035692053938259347, -1.992587776459846e-19) 39 | ]; 40 | 41 | # |a| <= 0.045 42 | function asinh_series(a::DD) 43 | x = a 44 | x2 = x*x 45 | x4 = x2*x2 46 | x6 = x2*x4 47 | x8 = x4*x4 48 | x16 = x8*x8 49 | x24 = x8*x16 50 | 51 | z = dd_asinh_coeff[2]*x2 + dd_asinh_coeff[3]*x4 + dd_asinh_coeff[4]*x6 52 | z1 = x8*(dd_asinh_coeff[5] + dd_asinh_coeff[6]*x2 + dd_asinh_coeff[7]*x4 + dd_asinh_coeff[8]*x6) 53 | z2 = x16*(dd_asinh_coeff[9] + dd_asinh_coeff[10]*x2 + dd_asinh_coeff[11]*x4 + dd_asinh_coeff[12]*x6) 54 | z3 = x24*(dd_asinh_coeff[13] + dd_asinh_coeff[14]*x2 + dd_asinh_coeff[15]*x4 + dd_asinh_coeff[16]*x6) 55 | 56 | (((z3+z2)+z1)+z+one(DD))*x 57 | end 58 | 59 | 60 | function atanh(x::DD) 61 | isneg, abs_x = signbit(x.hi), abs(x) 62 | if abs_x.hi > one(DD) 63 | throw(ErrorException("atanh arg $(x) outside -1..+1")) 64 | return dd_NaN 65 | elseif abs_x >= (one(DD)-1.0e-96) 66 | return isneg ? -dd_Inf : dd_Inf 67 | end 68 | if abs_x.hi <= 0.00275 69 | z = atanh_series(abs_x) 70 | else 71 | nm = one(TD) + abs_x 72 | dn = one(TD) - abs_x 73 | q = nm/dn 74 | q = log(DD(q)) 75 | z = divby2(q) 76 | end 77 | isneg ? -z : z 78 | end 79 | 80 | function asinh(x::DD) 81 | isneg, abs_x = signbit(x),abs(x) 82 | if isneg 83 | -asinh(abs_x) 84 | elseif abs_x.hi <= 0.045 85 | b = asinh_series(abs_x) 86 | else 87 | y = one(TD)+sqrt(TD(x)*x+one(TD)) 88 | y = TD(x) / y 89 | y = atanh(DD(y)) 90 | mulby2(y) 91 | end 92 | end 93 | 94 | function acosh(x::DD) 95 | isneg, abs_x = signbit(x.hi), abs(x) 96 | if isneg || abs_x.hi < one(Float64) 97 | throw(ErrorException("acosh arg $(x) outside +1..")) 98 | return dd_NaN 99 | elseif abs_x <= (one(DD)+1.0e-96) 100 | return zero(DD) 101 | end 102 | 103 | if abs_x.hi <= 1.01 #1.00275 104 | a = sqrt(TD(abs_x)*abs_x - one(TD)) 105 | b = asinh(DD(a)) 106 | b 107 | else 108 | a = sqrt(TD(abs_x)*abs_x - one(TD)) 109 | b = a + abs_x 110 | b = log(DD(b)) 111 | b 112 | end 113 | end 114 | -------------------------------------------------------------------------------- /src/arith/DDmanip.jl: -------------------------------------------------------------------------------- 1 | isnan(a::DD) = isnan(a.hi) 2 | isinf(a::DD) = isinf(a.hi) 3 | isfinite(a::DD) = isfinite(a.hi) 4 | 5 | sign(a::DD) = sign(a.hi) 6 | signbit(a::DD) = signbit(a.hi) 7 | 8 | (-)(a::DD) = DD(-a.hi,-a.lo) 9 | (abs)(a::DD) = (a.hi >= zero(Float64) ? a : -a) 10 | 11 | @inline flipsign(a::DD,b::DD) = DD(flipsign(a.hi,b.hi), flipsign(a.lo,b.hi)) 12 | @inline flipsign(a::DD,b::Float64) = DD(flipsign(a.hi,b), flipsign(a.lo,b)) 13 | @inline flipsign(a::DD,b::Integer) = DD(flipsign(a.hi,b), flipsign(a.lo,b)) 14 | 15 | @inline function copysign(a::DD,b::Float64) 16 | if (b < zero(Float64)) 17 | a.hi < zero(Float64) ? a : -a 18 | else 19 | a.hi < zero(Float64) ? -a : a 20 | end 21 | end 22 | @inline copysign(a::DD,b::Integer) = copysign(a,convert(Float64,b)) 23 | @inline copysign(a::DD,b::DD) = copysign(a,b.hi) 24 | 25 | 26 | function (floorceil)(fn::Function, a::DD) 27 | hi = fn(a.hi) 28 | lo = zero(Float64) 29 | if (hi == a.hi) 30 | lo = fn(a.lo) 31 | hi,lo = eftSum2inOrder(hi,lo) 32 | end 33 | DD(hi,lo) 34 | end 35 | 36 | (floor)(a::DD) = floorceil(floor,a) 37 | (ceil)(a::DD) = floorceil(ceil,a) 38 | 39 | 40 | function round(a::DD) 41 | hi = round(a.hi) 42 | lo = zero(Float64) 43 | if (hi == a.hi) 44 | lo = round(a.lo) 45 | hi,lo = eftSum2inOrder(hi,lo) 46 | end 47 | DD(hi,lo) 48 | end 49 | #(round)(a::DD) = floorceil(round,a) 50 | 51 | @inline function (trunc)(a::DD) 52 | a.hi >= zero(Float64) ? floor(a) : ceil(a) 53 | end 54 | 55 | """ 56 | stretch is the opposite of trunc() 57 | it extends to the nearest integer away from zero 58 | """ 59 | @inline function (stretch)(a::DD) 60 | a.hi >= zero(Float64) ? ceil(a) : floor(a) 61 | end 62 | 63 | 64 | function fld{T<:DD}(a::T,b::T) 65 | if (b.hi == zero(Float64)) 66 | throw(DomainError("denominator must be nonzero")) 67 | end 68 | floor( a/b ) 69 | end 70 | 71 | function cld{T<:DD}(a::T,b::T) 72 | if (b.hi == zero(Float64)) 73 | throw(DomainError("denominator must be nonzero")) 74 | end 75 | ceil( a/b ) 76 | end 77 | 78 | 79 | @inline function mulby2(a::DD) 80 | DD(a.hi*2.0, a.lo*2.0) 81 | end 82 | 83 | @inline function divby2(a::DD) 84 | DD(a.hi*0.5, a.lo*0.5) 85 | end 86 | 87 | @inline function mulbypow2(a::DD,p::Float64) 88 | DD(a.hi*p, a.lo*p) 89 | end 90 | 91 | @inline function divbypow2(a::DD,p::Float64) 92 | fr,xp = frexp(p) 93 | mulbypow2(a, ldexp(fr,-xp)) 94 | end 95 | 96 | function div{T<:DD}(a::T,b::T) 97 | if (b.hi == zero(Float64)) 98 | throw(DomainError("denominator must be nonzero")) 99 | end 100 | temp = a/b 101 | trunc(temp) 102 | end 103 | div(a::DD,b::Float64) = div(a,DD(b)) 104 | div(a::Float64,b::DD) = div(DD(a),b) 105 | 106 | function rem{T<:DD}(a::T,b::T) 107 | if (b.hi == zero(Float64)) 108 | throw(DomainError("denominator must be nonzero")) 109 | end 110 | a - div(a,b)*b 111 | end 112 | 113 | 114 | %{T<:TD}(a::T,b::T) = a - trunc(a/b) 115 | %(a::TD,b::Float64) = %(a,b) 116 | %(a::Float64,b::TD) = %(a,b) 117 | 118 | function divrem{T<:DD}(a::T,b::T) 119 | if (b.hi == zero(Float64)) 120 | throw(DomainError("denominator must be nonzero")) 121 | end 122 | temp = a/b 123 | d = trunc(temp) 124 | r = a - d*b 125 | d,r 126 | end 127 | 128 | 129 | function mod{T<:DD}(a::T,b::T) 130 | if (b.hi == zero(Float64)) 131 | throw(DomainError("modulus must be nonzero")) 132 | end 133 | if signbit(a.hi)==signbit(b.hi) 134 | rem(a,b) 135 | else 136 | d = floor(a/b) 137 | a - d*b 138 | end 139 | end 140 | 141 | mod(a::DD,b::Float64) = mod(a,convert(DD,b)) 142 | mod(a::Float64,b::DD) = mod(convert(DD,a),b) 143 | 144 | function fldmod{T<:DD}(a::T,b::T) 145 | d = floor(a/b) 146 | a - d*b 147 | d,a 148 | end 149 | 150 | 151 | 152 | -------------------------------------------------------------------------------- /src/trigh/DD.jl: -------------------------------------------------------------------------------- 1 | const dd_tanh_coeff = DD[ 2 | TD(1.0, 0.0), 3 | TD(-0.3333333333333333, -1.850371707708594e-17), 4 | TD(0.13333333333333333, 1.8503717077085942e-18), 5 | TD(-0.05396825396825397, 2.5552752154071065e-18), 6 | TD(0.021869488536155203, -1.7377829530067485e-19), 7 | TD(-0.008863235529902197, 7.63300580171831e-19), 8 | TD(0.003592128036572481, -1.253823608406629e-19), 9 | TD(-0.0014558343870513183, 6.214492640136062e-20), 10 | TD(0.000590027440945586, 3.478690842383652e-20), 11 | TD(-0.00023912911424355248, -3.564613898329782e-21), 12 | TD(9.691537956929451e-5, -6.2386628755632464e-21), 13 | TD(-3.927832388331683e-5, -1.3737015743076767e-21), 14 | TD(1.5918905069328964e-5, 1.0427554807190543e-21), 15 | TD(-6.451689215655431e-6, -1.1519922496640058e-22), 16 | TD(2.6147711512907546e-6, -9.313685621299801e-23), 17 | TD(-1.0597268320104654e-6, -2.3670525505213632e-24), 18 | TD(4.294911078273806e-7, 1.1643520863702653e-23) 19 | ]; 20 | 21 | function sinh_taylor_series(a::DD) 22 | x = a 23 | x2 = x*x 24 | x3 = x*x2 25 | x4 = x2*x2 26 | x5 = x2*x3 27 | x6 = x3*x3 28 | x7 = x3*x4 29 | x8 = x4*x4 30 | x9 = x4*x5 31 | x17 = x8*x9 32 | x25 = x17*x8 33 | 34 | z = TD(x) + x*(dd_inv_fact[3]*x2 + dd_inv_fact[5]*x4 + dd_inv_fact[7]*x6) 35 | z2 = x9 * (dd_inv_fact[9] + x2*dd_inv_fact[11] + x4*dd_inv_fact[13] + x6*dd_inv_fact[15]) 36 | z3 = x17 * (dd_inv_fact[17] + x2*dd_inv_fact[19] + x4*dd_inv_fact[21] + x6*dd_inv_fact[23]) 37 | z4 = x25 * (dd_inv_fact[25] + x2*dd_inv_fact[27] + x4*dd_inv_fact[29] + x6*dd_inv_fact[31]) 38 | 39 | DD(z + ((z4+z3)+z2)) 40 | end 41 | 42 | function cosh_taylor_series(a::DD) 43 | x = a 44 | x2 = x*x 45 | x4 = x2*x2 46 | x6 = x2*x4 47 | x8 = x4*x4 48 | x16 = x8*x8 49 | x24 = x8*x16 50 | 51 | z = (dd_inv_fact[2]*x2 + dd_inv_fact[4]*x4 + dd_inv_fact[6]*x6) 52 | z2 = x8 * (dd_inv_fact[8] + x2*dd_inv_fact[10] + x4*dd_inv_fact[12] + x6*dd_inv_fact[14]) 53 | z3 = x16 * (dd_inv_fact[16] + x2*dd_inv_fact[18] + x4*dd_inv_fact[20] + x6*dd_inv_fact[22]) 54 | z4 = x24 * (dd_inv_fact[24] + x2*dd_inv_fact[26] + x4*dd_inv_fact[28] + x6*dd_inv_fact[30]) 55 | 56 | ((z4+z3)+z2)+z + 1.0 57 | end 58 | 59 | 60 | 61 | function tanh_taylor_series(radian::DD) 62 | x = radian 63 | x2 = x*x 64 | x3 = x*x2 65 | x4 = x2*x2 66 | x5 = x2*x3 67 | x6 = x3*x3 68 | x7 = x3*x4 69 | x8 = x4*x4 70 | x9 = x4*x5 71 | x17 = x8*x9 72 | 73 | z = x + x*(dd_tanh_coeff[2]*x2 + dd_tanh_coeff[3]*x4 + dd_tanh_coeff[4]*x6) 74 | z2 = x9 * (dd_tanh_coeff[5] + x2*dd_tanh_coeff[6] + x4*dd_tanh_coeff[7] + x6*dd_tanh_coeff[8]) 75 | z3 = x17 * (dd_tanh_coeff[9] + x2*dd_tanh_coeff[10] + x4*dd_tanh_coeff[11] + x6*dd_tanh_coeff[12]) 76 | 77 | (z + (z3+z2)) 78 | end 79 | 80 | #= 81 | tanh z = z / (1 + z^2/(3 + z^2/5 + ...)) 82 | =# 83 | 84 | function sinh(x::DD) 85 | isneg, abs_a = signbit(x), abs(x) 86 | if (abs_a.hi <= 0.1) 87 | s = sinh_taylor_series(abs_a) 88 | else 89 | epx = exp(abs_a) 90 | emx = 1.0/epx 91 | epx = epx - emx 92 | s = divby2(epx) 93 | end 94 | isneg ? -s : s 95 | end 96 | 97 | function cosh(x::DD) 98 | abs_a = abs(x) 99 | if abs_a.hi <= 0.1 100 | c = cosh_taylor_series(abs_a) 101 | else 102 | epx = exp(abs_a) 103 | emx = 1.0/epx 104 | epx = epx + emx 105 | c = divby2(epx) 106 | end 107 | c 108 | end 109 | 110 | function tanh(x::DD) 111 | isneg, abs_a = signbit(x), abs(x) 112 | if abs_a.hi < 0.0325 113 | t = tanh_taylor_series(abs_a) 114 | elseif abs_a.hi > 0.05 115 | ea = exp(abs_a) 116 | inv_ea = exp(-abs_a) # do not use 1/ea here 117 | t = (ea - inv_ea) / (ea + inv_ea) 118 | else 119 | s = sinh(abs_a) 120 | c = s*s 121 | c = 1.0 - c 122 | c = sqrt(c) 123 | t = s/c 124 | end 125 | isneg ? -t : t 126 | end 127 | 128 | 129 | #tanh(a::DD) = sinh(a)/cosh(a) # DD(tanhAsTD(a)) 130 | 131 | csch(a::DD) = recip(sinh(a)) 132 | sech(a::DD) = recip(cosh(a)) 133 | coth(a::DD) = recip(tanh(a)) 134 | -------------------------------------------------------------------------------- /src/arith/TDmanip.jl: -------------------------------------------------------------------------------- 1 | #= 2 | # Internal Use Only 3 | =# 4 | 5 | isnan(a::TD) = isnan(a.hi) 6 | isinf(a::TD) = isinf(a.hi) 7 | isfinite(a::TD) = isfinite(a.hi) 8 | 9 | sign(a::TD) = sign(a.hi) 10 | signbit(a::TD) = signbit(a.hi) 11 | 12 | (-)(a::TD) = TD(-a.hi,-a.md,-a.lo) 13 | (abs)(a::TD) = (a.hi >= zero(Float64) ? a : -a) 14 | 15 | 16 | @inline flipsign(a::TD,b::TD) = TD(flipsign(a.hi,b.hi), flipsign(a.md,b.hi), flipsign(a.lo,b.hi)) 17 | @inline flipsign(a::TD,b::DD) = TD(flipsign(a.hi,b.hi), flipsign(a.md,b.hi), flipsign(a.lo,b.hi)) 18 | flipsign(a::DD,b::TD) = DD(flipsign(a.hi,b.hi), flipsign(a.lo,b.hi)) 19 | flipsign(a::TD,b::Float64) = TD(flipsign(a.hi,b), flipsign(a.md,b.hi), flipsign(a.lo,b)) 20 | flipsign(a::TD,b::Integer) = TD(flipsign(a.hi,b), flipsign(a.md,b.hi), flipsign(a.lo,b)) 21 | 22 | @inline function copysign(a::TD,b::Float64) 23 | if (b < zero(Float64)) 24 | a.hi < zero(Float64) ? a : -a 25 | else 26 | a.hi < zero(Float64) ? -a : a 27 | end 28 | end 29 | copysign(a::TD,b::Integer) = copysign(a,convert(Float64,b)) 30 | copysign(a::TD,b::DD) = copysign(a,b.hi) 31 | @inline copysign(a::TD,b::TD) = copysign(a, b.hi) 32 | copysign(a::DD,b::TD) = copysign(a.hi,b.hi) 33 | 34 | 35 | @inline function mulby2(a::TD) 36 | TD(a.hi*2.0, a.md*2.0, a.lo*2.0) 37 | end 38 | 39 | @inline function divby2(a::TD) 40 | TD(a.hi*0.5, a.md*0.5, a.lo*0.5) 41 | end 42 | 43 | @inline function mulbypow2(a::TD,p::Float64) 44 | TD(a.hi*p, a.md*p, a.lo*p) 45 | end 46 | 47 | @inline function divbypow2(a::TD,p::Float64) 48 | fr,xp = frexp(p) 49 | mulbypow2(a, ldexp(fr,-xp)) 50 | end 51 | 52 | 53 | function (floorceil)(fn::Function, a::TD) 54 | hi = fn(a.hi) 55 | md = lo = zero(Float64) 56 | if (hi == a.hi) 57 | md = fn(a.md) 58 | hi,md = eftSum2inOrder(hi,md) 59 | if md == a.md 60 | lo = fn(a.lo) 61 | md,lo = eftSum2inOrder(md,lo) 62 | hi,md = eftSum2inOrder(hi,md) 63 | end 64 | end 65 | TD(hi,md,lo) 66 | end 67 | 68 | (floor)(a::TD) = floorceil(floor,a) 69 | (ceil)(a::TD) = floorceil(ceil,a) 70 | 71 | 72 | function round(a::TD) 73 | hi = round(a.hi) 74 | md = lo = zero(Float64) 75 | if (hi == a.hi) 76 | md = round(a.md) 77 | hi,md = eftSum2inOrder(hi,md) 78 | if md == a.md 79 | lo = round(a.lo) 80 | md,lo = eftSum2inOrder(md,lo) 81 | hi,md = eftSum2inOrder(hi,md) 82 | end 83 | end 84 | TD(hi,md,lo) 85 | end 86 | #(round)(a::TD) = floorceil(round,a) 87 | 88 | 89 | @inline function (trunc)(a::TD) 90 | a.hi >= zero(Float64) ? floor(a) : ceil(a) 91 | end 92 | 93 | """ 94 | stretch is the opposite of trunc() 95 | it extends to the nearest integer away from zero 96 | """ 97 | @inline function (stretch)(a::TD) 98 | a.hi >= zero(Float64) ? ceil(a) : floor(a) 99 | end 100 | 101 | function fld{T<:TD}(a::T,b::T) 102 | if (b.hi == zero(Float64)) 103 | throw(DomainError("denominator must be nonzero")) 104 | end 105 | floor( a/b ) 106 | end 107 | 108 | function cld{T<:TD}(a::T,b::T) 109 | if (b.hi == zero(Float64)) 110 | throw(DomainError("denominator must be nonzero")) 111 | end 112 | ceil( a/b ) 113 | end 114 | 115 | 116 | function div{T<:TD}(a::T,b::T) 117 | if (b.hi == zero(Float64)) 118 | throw(DomainError("denominator must be nonzero")) 119 | end 120 | temp = a/b 121 | trunc(temp) 122 | end 123 | div(a::TD,b::Float64) = div(a,TD(b)) 124 | div(a::Float64,b::TD) = div(TD(a),b) 125 | 126 | function rem{T<:TD}(a::T,b::T) 127 | if (b.hi == zero(Float64)) 128 | throw(DomainError("denominator must be nonzero")) 129 | end 130 | a - div(a,b)*b 131 | end 132 | 133 | %{T<:TD}(a::T,b::T) = a - trunc(a/b) 134 | %(a::TD,b::Float64) = %(a,b) 135 | %(a::Float64,b::TD) = %(a,b) 136 | 137 | function divrem{T<:TD}(a::T,b::T) 138 | if (b.hi == zero(Float64)) 139 | throw(DomainError("denominator must be nonzero")) 140 | end 141 | temp = a/b 142 | d = trunc(temp) 143 | r = a - d*b 144 | d,r 145 | end 146 | 147 | 148 | function mod{T<:TD}(a::T,b::T) 149 | if (b.hi == zero(Float64)) 150 | throw(DomainError("modulus must be nonzero")) 151 | end 152 | if signbit(a.hi)==signbit(b.hi) 153 | rem(a,b) 154 | else 155 | d = floor(a/b) 156 | a - d*b 157 | end 158 | end 159 | 160 | mod(a::TD,b::Float64) = mod(a,convert(TD,b)) 161 | mod(a::Float64,b::TD) = mod(convert(TD,a),b) 162 | 163 | function fldmod{T<:TD}(a::T,b::T) 164 | d = floor(a/b) 165 | a - d*b 166 | d,a 167 | end 168 | -------------------------------------------------------------------------------- /test/util/testit.jl: -------------------------------------------------------------------------------- 1 | #= 2 | relerr testing 3 | =# 4 | 5 | set_bigfloat_precision(320); 6 | 7 | @inline abserr(xIdeal::Real,xActual::Real) = abs(xIdeal-xActual) 8 | relerr(xIdeal::Real,xActual::Real) = xIdeal==0 ? 0 : abserr(float(xIdeal),float(xActual))/abs(float(xIdeal)) 9 | 10 | function relerr1{T<:Float64}(xIdeal::T,xActual::T) 11 | a = abserr(xIdeal,xActual) 12 | x = abs(xActual) 13 | if x < eps(eps(1.0)) 14 | zero(Float64) 15 | else 16 | a / xIdeal 17 | end 18 | end 19 | 20 | function relerr{T<:DD}(xIdeal::T,xActual::T) 21 | if (xIdeal.hi != xActual.hi) 22 | relerr1(xIdeal.hi, xActual.hi) 23 | else 24 | a = abs(xIdeal-xActual) 25 | x = abs(xActual) 26 | if (a.hi < 1e-90) || (x.hi < 1.e-90) 27 | zero(Float64) 28 | else 29 | (a / x).hi 30 | end 31 | end 32 | end 33 | 34 | relerr(xIdeal::TD,xActual::TD) = relerr(DD(xIdeal), DD(xActual)) 35 | 36 | #julia> r=[abs(tst3()) for i in 1:20000];sort(r)[end] 37 | 38 | function runFnTestWide(fn::Function, n::Int=20_000, bitgap::Function=wideBitgap, expow2::Function=expon) 39 | src = zeros(DD,n) 40 | err = zeros(Float64,n) 41 | rerr = TD(0.0) 42 | serr = TD(0.0) 43 | for i in 1:n 44 | r = randhilo(bitgap,expow2) 45 | src[i] = r 46 | ideal = besthilo(fn,r) 47 | actual = fn(r) 48 | rerr1 = relerr(ideal,actual) 49 | if rerr1 > rerr 50 | rerr = rerr1 51 | serr = r 52 | end 53 | # err[i] = rerr 54 | end 55 | #src, err 56 | serr, rerr 57 | end 58 | 59 | 60 | 61 | function runFnTest(fn::Function, n::Int=20_000, lo::Float64=0.0, hi::Float64=1.0, bitgap::Function=baseBitgap) 62 | src = zeros(DD,n) 63 | err = zeros(Float64,n) 64 | rerr = DD(0.0) 65 | serr = DD(0.0) 66 | for i in 1:n 67 | r1 = rand(lo:hi) 68 | bg = bitgap() 69 | r2 = ldexp(rand(-0.99999:0.999999),-53-bg) 70 | r = DD(r1)+DD(r2) 71 | src[i] = r 72 | ideal = besthilo(fn,r) 73 | actual = fn(r) 74 | rerr1 = relerr(ideal,actual) 75 | #err[i] = rerr 76 | if rerr1 > rerr 77 | rerr = rerr1 78 | serr = r 79 | end 80 | 81 | end 82 | #src, err 83 | serr,rerr 84 | end 85 | 86 | function fnTestWide(fn::Function, n::Int=20_000, bitgap::Function=wideBitgap, expow2::Function=expon) 87 | #src, err = runFnTest(fn,n,bitgap,expow2) 88 | #maxerr = sort(err)[end] 89 | #srcmaxerr = src[ maxerr .== err ][1] 90 | srcmaxerr,maxerr=runFnTesWidet(fn,n,bitgap,expow2) 91 | frexp(maxerr)[2], maxerr, srcmaxerr 92 | end 93 | 94 | function fnTest(fn::Function, n::Int=20_000, lo::Float64=0.0, hi::Float64=1.0, bitgap::Function=baseBitgap) 95 | #src, err = runFnTest2(fn,n,lo,hi,bitgap) 96 | #maxerr = sort(err)[end] 97 | #srcmaxerr = src[ maxerr .== err ][1] 98 | #frexp(maxerr)[2], maxerr, srcmaxerr 99 | srcmaxerr,maxerr=runFnTest(fn,n,lo,hi,bitgap) 100 | frexp(maxerr)[2], maxerr, srcmaxerr 101 | end 102 | 103 | 104 | 105 | 106 | function runFnTestWideTD(fn::Function, n::Int=20_000, bitgap::Function=wideBitgap, expow2::Function=expon) 107 | src = zeros(TD,n) 108 | err = zeros(Float64,n) 109 | for i in 1:n 110 | r = randhml(bitgap,expow2) 111 | src[i] = r 112 | ideal = besthml(fn,r) 113 | actual = fn(r) 114 | rerr = relerr(ideal,actual) 115 | err[i] = rerr 116 | end 117 | src, err 118 | end 119 | 120 | function runFnTestTD(fn::Function, n::Int=20_000, bitgap::Function=wideBitgap, expow2::Function=expon) 121 | src = zeros(TD,n) 122 | err = zeros(Float64,n) 123 | for i in 1:n 124 | r = randhml(bitgap,expow2) 125 | src[i] = r 126 | ideal = besthml(fn,r) 127 | actual = fn(r) 128 | rerr = relerr(ideal,actual) 129 | err[i] = rerr 130 | end 131 | src, err 132 | end 133 | 134 | function fnTestWideTD(fn::Function, n::Int=20_000, bitgap::Function=wideBitgap, expow2::Function=expon) 135 | #src, err = runFnTest(fn,n,bitgap,expow2) 136 | #maxerr = sort(err)[end] 137 | #srcmaxerr = src[ maxerr .== err ][1] 138 | srcmaxerr,maxerr=runFnTesWideTD(fn,n,bitgap,expow2) 139 | frexp(maxerr)[2], maxerr, srcmaxerr 140 | end 141 | 142 | function fnTestTD(fn::Function, n::Int=20_000, lo::Float64=0.0, hi::Float64=1.0, bitgap::Function=baseBitgap) 143 | #src, err = runFnTest2(fn,n,lo,hi,bitgap) 144 | #maxerr = sort(err)[end] 145 | #srcmaxerr = src[ maxerr .== err ][1] 146 | #frexp(maxerr)[2], maxerr, srcmaxerr 147 | srcmaxerr,maxerr=runFnTestTD(fn,n,lo,hi,bitgap) 148 | frexp(maxerr)[2], maxerr, srcmaxerr 149 | end 150 | 151 | -------------------------------------------------------------------------------- /src/arith/DD.jl: -------------------------------------------------------------------------------- 1 | # addition 2 | 3 | function (+){T<:DD}(a::T,b::T) 4 | s1, s2 = eftSum2(a.hi,b.hi) 5 | t1, t2 = eftSum2(a.lo,b.lo) 6 | s2 += t1 7 | s1, s2 = eftSum2inOrder(s1,s2) 8 | s2 += t2 9 | s1, s2 = eftSum2inOrder(s1,s2) 10 | DD(s1,s2) 11 | end 12 | 13 | function (+)(a::DD,b::Float64) 14 | s1, s2 = eftSum2(a.hi,b) 15 | s2 += a.lo 16 | s1, s2 = eftSum2inOrder(s1,s2) 17 | DD(s1,s2) 18 | end 19 | 20 | (+)(a::Float64,b::DD) = (+)(b,a) 21 | (+)(a::DD,b::Signed) = (+)(a,convert(Float64,b)) 22 | (+)(a::Signed,b::DD) = (+)(b,a) 23 | 24 | # subtraction 25 | 26 | function (-){T<:DD}(a::T,b::T) 27 | s1, s2 = eftDiff2(a.hi,b.hi) 28 | t1, t2 = eftDiff2(a.lo,b.lo) 29 | s2 += t1 30 | s1, s2 = eftSum2inOrder(s1,s2) 31 | s2 += t2 32 | s1, s2 = eftSum2inOrder(s1,s2) 33 | DD(s1,s2) 34 | end 35 | 36 | function (-)(a::DD,b::Float64) 37 | s1, s2 = eftDiff2(a.hi,b) 38 | s2 += a.lo 39 | s1, s2 = eftSum2inOrder(s1,s2) 40 | DD(s1,s2) 41 | end 42 | 43 | function (-)(a::Float64,b::DD) 44 | s1, s2 = eftDiff2(a,b.hi) 45 | s2 -= b.lo 46 | s1, s2 = eftSum2inOrder(s1,s2) 47 | DD(s1,s2) 48 | end 49 | 50 | (-)(a::DD,b::Signed) = (-)(a,convert(Float64,b)) 51 | (-)(a::Signed,b::DD) = (-)(convert(Float64,a),b) 52 | 53 | # multiplication 54 | 55 | 56 | function (sqr)(a::DD) 57 | t1,t2 = eftProd2(a.hi,a.hi) 58 | t3 = a.hi * a.lo 59 | t5 = t3 + t3 60 | t6 = t2 + t5 61 | t1,t6 = eftSum2inOrder(t1,t6) 62 | DD(t1,t6) 63 | end 64 | 65 | function (*){T<:DD}(a::T,b::T) 66 | t1,t2 = eftProd2(a.hi,b.hi) 67 | t3 = a.hi * b.lo 68 | t4 = a.lo * b.hi 69 | t5 = t3 + t4 70 | t6 = t2 + t5 71 | t1,t6 = eftSum2inOrder(t1,t6) 72 | DD(t1,t6) 73 | end 74 | 75 | function (*)(a::DD,b::Float64) 76 | t1,t2 = eftProd2(a.hi,b) 77 | t4 = a.lo * b 78 | t6 = t2 + t4 79 | t1,t6 = eftSum2inOrder(t1,t6) 80 | DD(t1,t6) 81 | end 82 | 83 | (*)(a::Float64,b::DD) = (*)(b,a) 84 | (*)(a::DD,b::Signed) = (*)(a,convert(Float64,b)) 85 | (*)(a::Signed,b::DD) = (*)(convert(Float64,a),b) 86 | 87 | 88 | function fma{T<:DD}(a::T,b::T,c::T) 89 | p = a*TD(b) 90 | p = p+c 91 | DD(p.hi,p.md) 92 | end 93 | 94 | 95 | # reciprocation 96 | 97 | #= 98 | # faster, less accurate 99 | =# 100 | 101 | function (recip)(b::DD) 102 | q1 = one(Float64) / b.hi 103 | r = DD(one(TD) - q1*TD(b)) 104 | 105 | q2 = r.hi / b.hi 106 | r = r - (q2 * b) 107 | 108 | q2 += r.hi / b.hi 109 | 110 | q3 = r.hi / b.hi 111 | 112 | q1,q2 = eftSum2inOrder(q1, q2) 113 | q1,q2 = eftSum3as2(q1,q2,q3) 114 | DD(q1,q2) 115 | end 116 | 117 | # division 118 | 119 | function (/){T<:DD}(a::T,b::T) 120 | q1 = a.hi / b.hi 121 | r = a - (q1 * b) 122 | 123 | q2 = r.hi / b.hi 124 | r = r - (q2 * b) 125 | 126 | q3 = r.hi / b.hi 127 | 128 | q1,q2 = eftSum2inOrder(q1, q2) 129 | q1,q2 = eftSum3as2(q1,q2,q3) 130 | DD(q1,q2) 131 | end 132 | 133 | # powers 134 | 135 | 136 | # roots 137 | 138 | function sqrt(a::DD) 139 | if a.hi <= zero(Float64) 140 | if a.hi == zero(Float64) 141 | return zero(DD) 142 | else 143 | throw(ArgumentError("sqrt expects a nonnegative base")) 144 | end 145 | #elseif (a.hi < 1.0e-18) | (a.hi > 1.0e18) 146 | # throw(ArgumentError("sqrt arg ($a) outside domain")) 147 | end 148 | 149 | if (a.hi < 1.0e-7) # -log2(1.0e-7) < (1/2) Float64 significand bits 150 | return one(DD) / sqrt(one(DD)/a) 151 | end 152 | 153 | # initial approximation to 1/sqrt(a) 154 | r = DD(one(Float64)/sqrt(a.hi), zero(Float64)) 155 | 156 | r = r + divby2( r * (one(DD) - (a*(r*r))) ) 157 | r = r + divby2( r * (one(DD) - (a*(r*r))) ) 158 | r = r + divby2( r * (one(DD) - (a*(r*r))) ) 159 | 160 | r = a*r 161 | divby2(r + a/r) 162 | end 163 | 164 | 165 | 166 | 167 | #= 168 | for a in [1e-15..1e18] 169 | relerr ~1.3e-32 (106 bits) 170 | =# 171 | function sqrt(a::DD) 172 | if a.hi <= zero(Float64) 173 | if a.hi == zero(Float64) 174 | return zero(DD) 175 | else 176 | throw(ArgumentError("sqrt expects a nonnegative base")) 177 | end 178 | elseif (a.hi < 1.0e-18) | (a.hi > 1.0e18) 179 | throw(ArgumentError("sqrt arg ($a) outside domain")) 180 | end 181 | 182 | if (a.hi < 1.0e-7) # -log2(1.0e-7) < (1/2) Float64 significand bits 183 | return one(DD) / sqrt(one(DD)/a) 184 | end 185 | 186 | # initial approximation to 1/sqrt(a) 187 | r = DD(one(Float64)/sqrt(a.hi), zero(Float64)) 188 | 189 | r = r + divby2( r * (one(DD) - (a*(r*r))) ) 190 | r = r + divby2( r * (one(DD) - (a*(r*r))) ) 191 | r = r + divby2( r * (one(DD) - (a*(r*r))) ) 192 | 193 | r = a*r 194 | divby2(r + a/r) 195 | end 196 | 197 | 198 | function hypot(a::DD, b::DD) 199 | a = abs(a) 200 | b = abs(b) 201 | t, x = min(a,b), max(a,b) 202 | t = t/a 203 | x * sqrt(1.0 + t*t) 204 | end 205 | -------------------------------------------------------------------------------- /src/const/DD.jl: -------------------------------------------------------------------------------- 1 | const dd_Inf = DD(Inf,NaN); 2 | const dd_NaN = DD(NaN,NaN); 3 | 4 | const dd_zero = DD(0.0,0.0); 5 | const dd_one = DD(1.0,0.0); 6 | const dd_two = DD(2.0,0.0); 7 | const dd_three = DD(3.0,0.0); 8 | const dd_four = DD(4.0,0.0); 9 | 10 | const dd_half = DD(0.5,0.0); 11 | const dd_third = DD(0.3333333333333333, 1.850371707708594e-17); 12 | const dd_qrtr = DD(0.25,0.0); 13 | 14 | const dd_sqrt2 = DD(1.4142135623730951,-9.667293313452913e-17); 15 | const dd_sqrt2_over_2 = DD(0.7071067811865476,-4.833646656726457e-17); 16 | const dd_1_over_sqrt2 = DD(0.7071067811865476,-4.833646656726457e-17); 17 | 18 | const dd_sqrt3_over_2 = DD(0.8660254037844386,5.0175421109034514e-17); 19 | const dd_sqrt3_over_3 = DD(0.5773502691896257,3.3450280739356345e-17); 20 | 21 | const dd_twopi = DD(6.283185307179586,2.4492935982947064e-16); 22 | const dd_twopi_part2 = DD(-5.989539619436679e-33,2.2249084417267306e-49); 23 | const dd_twopi_part3 = DD(1.1344463959280631e-65,3.489972432270497e-83); 24 | const dd_twopi_part4 = DD(1.205874546449908e-99,3.82024709375998e-116); 25 | 26 | const dd_1_over_twopi = DD(0.15915494309189535,-9.839338337591243e-18); 27 | const dd_1_over_twopi_part2 = DD(-5.360718141446502e-34,4.026781963297056e-50); 28 | const dd_1_over_twopi_part3 = DD(-7.801382953409857e-67,1.4185069655957361e-83); 29 | const dd_1_over_twopi_part4 = DD(-7.836906288373592e-100,-1.908123641189411e-116); 30 | 31 | const dd_pi = DD(3.141592653589793,1.2246467991473532e-16); 32 | const dd_pi_part2 = DD(-2.9947698097183397e-33,1.1124542208633653e-49); 33 | const dd_1_over_pi = DD(0.3183098861837907,-1.9678676675182486e-17); 34 | const dd_1_over_pi_part2 = DD(-1.0721436282893004e-33,8.053563926594112e-50,); 35 | 36 | const dd_pi_over_2 = DD(1.5707963267948966,6.123233995736766e-17); 37 | const dd_pi_over_2_part2 = DD(-1.4973849048591698e-33,5.562271104316826e-50); 38 | const dd_2_over_pi = DD(0.6366197723675814,-3.935735335036497e-17); 39 | const dd_2_over_pi_part2 = DD(-2.1442872565786008e-33,1.6107127853188224e-49); 40 | 41 | const dd_pi_over_4 = DD(0.7853981633974483,3.061616997868383e-17); 42 | const dd_pi_over_4_part2 = DD(-7.486924524295849e-34,2.781135552158413e-50); 43 | const dd_4_over_pi = DD(1.2732395447351628,-7.871470670072994e-17); 44 | const dd_4_over_pi_part2 = DD(-4.2885745131572016e-33,3.2214255706376448e-49); 45 | 46 | const dd_pi_over_6 = DD(0.5235987755982989,-5.360408832255455e-17); 47 | const dd_pi_over_6_part2 = DD(-4.991283016197232e-34,-3.8478076800910752e-50); 48 | const dd_6_over_pi = DD(1.909859317102744,-7.049757588579267e-18); 49 | const dd_6_over_pi_part2 = DD(-2.698859476966472e-34,1.2807246619420275e-50); 50 | 51 | const dd_3pi_over_2 = DD(4.71238898038469, 1.8369701987210297e-16) 52 | const dd_2_over_3pi = DD(0.2122065907891938, -1.3119117783454992e-17); 53 | const dd_3pi_over_4 = DD(2.356194490192345,9.184850993605148e-17); 54 | const dd_4_over_3pi = DD(0.4244131815783876,-2.6238235566909983e-17); 55 | 56 | const dd_pi_over_1024 = DD(0.0030679615757712823,1.195944139792337e-19); 57 | const dd_1024_over_pi = DD(325.94932345220167,-2.0150964915386866e-14); 58 | 59 | const dd_exp1 = DD(2.718281828459045,1.4456468917292502e-16); 60 | const dd_log10 = DD(2.302585092994046,-2.1707562233822494e-16); 61 | 62 | 63 | const dd_log2 = DD(0.6931471805599453,2.3190468138462996e-17); 64 | const dd_log2_part2 = DD(5.707708438416212e-34, -3.5824322106018114e-50); 65 | const dd_log2_part3 = DD(-1.352169675798863e-66,6.080638740240814e-83); 66 | const dd_log2_part4 = DD(2.8955024332347147e-99,2.351386712145641e-116); 67 | 68 | const dd_1_over_log2 = DD(1.4426950408889634,2.0355273740931033e-17); 69 | const dd_1_over_log2_part2 = DD(-1.0614659956117258e-33,-1.3836716780181402e-50); 70 | const dd_1_over_log2_part3 = DD(9.509563257128724e-67,-6.180554812704206e-83); 71 | const dd_1_over_log2_part4 = DD(3.1030020372190077e-99,1.9878535252881986e-115); 72 | 73 | 74 | const dd_sin_3pi_over_8 = DD(0.9238795325112867, 1.7645047084336677e-17); 75 | const dd_cos_3pi_over_8 = DD(0.3826834323650898, -1.0050772696461588e-17); 76 | 77 | const dd_golden_ratio = DD(1.618033988749895,-5.432115203682506e-17); 78 | const dd_1_over_golden_ratio = DD(0.6180339887498949,-5.432115203682506e-17); 79 | const dd_catalan = DD(0.915965594177219,3.747558421514984e-18); 80 | const dd_eulergamma = DD(0.5772156649015329,-4.942915152430645e-18); 81 | 82 | Float128s = Dict{Symbol,DD}( 83 | :zero => dd_zero, 84 | :quarter => dd_qrtr, 85 | :half => dd_half, 86 | :one => dd_one, 87 | :two => dd_two, 88 | :three => dd_three, 89 | :four => dd_four, 90 | :sqrt2 => dd_sqrt2, 91 | :log2 => dd_log2, 92 | :log10 => dd_log10, 93 | :exp1 => dd_exp1, 94 | :pi => dd_pi, 95 | :twopi => dd_twopi, 96 | :catalan => dd_catalan, 97 | :π => dd_pi, 98 | :e => dd_exp1, 99 | :eu => dd_exp1, 100 | :φ => dd_golden_ratio, 101 | :golden => dd_golden_ratio, 102 | :γ => dd_eulergamma, 103 | :eulergamma => dd_eulergamma, 104 | :_two => dd_half, 105 | :_three => dd_third, 106 | :_four => dd_qrtr, 107 | :_log2 => dd_1_over_log2, 108 | :_pi => dd_1_over_pi, 109 | :_twopi => dd_1_over_twopi, 110 | ); 111 | -------------------------------------------------------------------------------- /test/util/nearest.jl: -------------------------------------------------------------------------------- 1 | import Base:convert 2 | 3 | 4 | function ieeedouble(xx::BigFloat) 5 | x=logabs=powermin=0.0 6 | mantissa=exponent=expmin=expmax=expmiddle=powermax=powermiddle=infmantissa=0.0 7 | sgn=0 8 | set_bigfloat_precision(320) ; #Digits = 100; 9 | x = xx;#$evalf(xx); 10 | if (x==0) 11 | sgn, exponent, mantissa = 1, -1022, 0 12 | else 13 | if (x < 0) 14 | sgn = -1 15 | else 16 | sgn = 1 17 | end 18 | x = abs(x); 19 | if x >= 2.0^(1023)*(2-2.0^(-53)) 20 | mantissa = Inf 21 | exponent = 1023 22 | elseif x <= 2.0^(-1075) 23 | mantissa = 0; exponent = -1022 24 | elseif x <= 2.0^(-1022) 25 | exponent = -1022 26 | else 27 | # x is between 2^(-1022) and 2^(1024) 28 | powermin = 2.0^(-1022); expmin = -1022; 29 | powermax = 2^1024; expmax = 1024; 30 | while (expmax-expmin > 1) 31 | expmiddle = round(Int,(expmax+expmin)/2); 32 | powermiddle = 2.0^expmiddle; 33 | if x >= powermiddle 34 | powermin = powermiddle; 35 | expmin = expmiddle 36 | else 37 | powermax = powermiddle; 38 | expmax = expmiddle 39 | end 40 | end 41 | # now, expmax - expmin = 1 and powermin <= x < powermax, 42 | # powermin = 2^expmin and powermax = 2^expmax, so expmin is the exponent of x 43 | exponent = expmin; 44 | #end; 45 | infmantissa = x*2.0^(52-exponent); 46 | if infmantissa-round(Int,infmantissa) != 0.5 47 | mantissa = round(Int,infmantissa) 48 | else 49 | mantissa = floor(Int,infmantissa); 50 | if reinterpret(UInt64,mantissa) & one(UInt64) == one(UInt64) 51 | mantissa = mantissa+1 52 | end 53 | end 54 | mantissa = mantissa*2.0^(-52); 55 | #end; 56 | end; 57 | end; 58 | sgn,exponent,mantissa; 59 | end 60 | 61 | function nearest(x::BigFloat) 62 | sgn,exponent,mantissa = ieeedouble(x) 63 | mantissa = convert(Float64,mantissa) 64 | sgn>=0 ? ldexp(mantissa,exponent) : -ldexp(mantissa,exponent) 65 | end 66 | 67 | 68 | function nnear(n::Int,x::BigFloat) 69 | bfprec = get_bigfloat_precision() 70 | set_bigfloat_precision(1280) 71 | z = zeros(Float64,n) 72 | z[1] = nearest(x) 73 | rm = x-BigFloat(z[1]) 74 | for i in 2:n 75 | z[i] = nearest(rm) 76 | rm = rm - BigFloat(z[i]) 77 | end 78 | set_bigfloat_precision(bfprec) 79 | z 80 | end 81 | 82 | function nearest12(x::BigFloat) 83 | set_bigfloat_precision(4096) 84 | z = zeros(Float64,12) 85 | a = nnear(6,x) 86 | bfa = BigFloat(a[1])+BigFloat(a[2])+BigFloat(a[3]) 87 | y = x-bfa 88 | b = nnear(6,y) 89 | bfb = BigFloat(b[1])+BigFloat(b[2])+BigFloat(b[3]) 90 | y = x-(bfa+bfb) 91 | c = nnear(6,y) 92 | bfc = BigFloat(c[1])+BigFloat(c[2])+BigFloat(c[3]) 93 | y = x-(bfa+bfb+bfc) 94 | d = nnear(6,y) 95 | 96 | z[1:3] = a[1:3] 97 | z[4:6] = b[1:3] 98 | z[7:9] = c[1:3] 99 | z[10:12] = d[1:3] 100 | z 101 | end 102 | 103 | 104 | function highlow(x::BigFloat) 105 | hi = nearest(x) 106 | lo = nearest(x-BigFloat(hi)) 107 | hi,lo 108 | end 109 | function highlow(x::Real) 110 | if length(fieldnames(x)) == 0 111 | hilo(BigFloat(x)) 112 | elseif length(fieldnames(x)) == 2 113 | hilo(BigFloat(x.hi)+BigFloat(x.lo)) 114 | elseif length(fieldnames(x)) == 3 115 | hilo(BigFloat(x.hi)+BigFloat(x.md)+BigFloat(x.lo)) 116 | else 117 | ErrorException("unsupported type") 118 | end 119 | end 120 | 121 | function highmedlow(x::BigFloat) 122 | hi = nearest(x) 123 | md = nearest(x-BigFloat(hi)) 124 | lo = nearest(x-BigFloat(hi)-BigFloat(md)) 125 | hi,md,lo 126 | end 127 | function highmedlow(x::Real) 128 | if length(fieldnames(x)) == 0 129 | hml(BigFloat(x)) 130 | elseif length(fieldnames(x)) == 2 131 | hml(BigFloat(x.hi)+BigFloat(x.lo)) 132 | elseif length(fieldnames(x)) == 3 133 | hml(BigFloat(x.hi)+BigFloat(x.md)+BigFloat(x.lo)) 134 | else 135 | ErrorException("unsupported type") 136 | end 137 | end 138 | 139 | hilo(x::BigFloat) = DD(highlow(x)) 140 | hml(x::BigFloat) = TD(highmedlow(x)...) 141 | hilo(x::AbstractFloat) = DD(highlow(x)) 142 | hml(x::AbstractFloat) = TD(highmedlow(x)...) 143 | 144 | 145 | besthilo(fn::Function,a::DD) = hilo(fn(BigFloat(convert(Tuple,a)))) 146 | besthml(fn::Function,a::TD) = hml(fn(BigFloat(convert(Tuple,a)))) 147 | besthilo(fn::Function,a::TD) = besthilo(fn,DD(a.hi,a.md)) 148 | besthml(fn::Function,a::DD) = besthml(fn,TD(a.hi,a.lo)) 149 | besthilo(fn::Function,a::AbstractFloat) = besthilo(fn,DD(a)) 150 | besthml(fn::Function,a::AbstractFloat) = besthml(fn,TD(a)) 151 | 152 | 153 | convert(::Type{BigFloat}, a::Tuple{Float64,Float64}) = BigFloat(a[1])+BigFloat(a[2]) 154 | convert(::Type{BigFloat}, a::Tuple{Float64,Float64, Float64}) = BigFloat(a[1])+BigFloat(a[2])+BigFloat(a[3]) 155 | 156 | convert(::Type{BigFloat}, a::DD) = BigFloat(a.hi)+BigFloat(a.lo) 157 | convert(::Type{BigFloat}, a::TD) = BigFloat(a.hi)+BigFloat(a.md)+BigFloat(a.lo) 158 | 159 | convert(::Type{DD}, a::BigFloat) = hilo(a) 160 | convert(::Type{TD}, a::BigFloat) = hml(a) 161 | -------------------------------------------------------------------------------- /src/types.jl: -------------------------------------------------------------------------------- 1 | typealias SignedInt Union{Int128,Int64,Int32,Int16} 2 | typealias SignedFloat Union{Float64,Float32,Float16} 3 | typealias SignedNumber Union{SignedFloat, SignedInt} 4 | 5 | #= 6 | The internal structure is 128 bits given as a magnitude-ordered pair of Float64 values.\\ 7 | The pair are *presumed* to be in cannonical form, where they do not overlap: hi⊕lo ≡ hi.\\ 8 | This representation is known as "double-double" (see refs.md) 9 | =# 10 | 11 | immutable DD <: Real 12 | hi::Float64 13 | lo::Float64 14 | end 15 | 16 | DD(a::Float64) = DD(a,zero(Float64)) 17 | DD{T<:Float64}(a::Tuple{T}) = DD(a[1]) 18 | DD{T<:Float64}(a::Tuple{T,T}) = DD(a[1],a[2]) 19 | 20 | convert(::Type{DD}, a::Float64) = DD(a) 21 | convert(::Type{DD}, a::Float32) = DD(Float64(a)) 22 | convert(::Type{DD}, a::Float16) = DD(Float64(a)) 23 | convert(::Type{DD}, a::Int32) = DD(Float64(a)) 24 | convert(::Type{DD}, a::Int16) = DD(Float64(a)) 25 | function convert(::Type{DD}, a::Int64) 26 | isneg, aa= signbit(a), abs(a) 27 | if aa < 0.0 28 | DD(ldexp(Float64(typemin(Int64)>>11),11),0.0) 29 | elseif aa <= 9007199254740992 30 | DD(convert(Float64,a)) 31 | else 32 | hi = ldexp(convert(Float64,(aa>>11)),11) 33 | lo = convert(Float64, (aa & 4095)) 34 | hi,lo = eftSum2(hi,lo) 35 | isneg ? DD(-hi,-lo) : DD(hi,lo) 36 | end 37 | end 38 | 39 | convert(::Type{Float64}, a::DD) = a.hi 40 | convert{T<:SignedInt}(::Type{DD}, a::T) = DD(convert(Float64,a)) 41 | convert{T<:SignedInt}(::Type{T}, a::DD) = convert(T,floor(a.hi))+convert(T,round(a.lo)) 42 | 43 | convert(::Type{DD}, a::Tuple{Float64}) = DD(a[1]) 44 | convert(::Type{DD}, a::Tuple{Float64,Float64}) = DD(a[1],a[2]) 45 | convert(::Type{Tuple}, a::DD) = (a.hi,a.lo) 46 | convert(::Type{Tuple{Float64,Float64}}, a::DD) = (a.hi,a.lo) 47 | 48 | promote_rule(::Type{DD}, ::Type{Float64}) = DD 49 | promote_rule(::Type{DD}, ::Type{Float32}) = DD 50 | promote_rule(::Type{DD}, ::Type{Int64}) = DD 51 | promote_rule(::Type{DD}, ::Type{Int32}) = DD 52 | 53 | 54 | const epseps1 = eps(eps(1.0)) 55 | 56 | function clean(x::DD) 57 | if (abs(x.hi) <= epseps1) 58 | zero(DD) 59 | elseif (abs(x.lo) <= eps(eps(x.hi))) 60 | DD(x.hi,0.0) 61 | else 62 | x 63 | end 64 | end 65 | 66 | clean(v::Vector{DD}) = [clean(x) for x in v] 67 | clean(m::Matrix{DD}) = reshape([clean(x) for x in m],size(m)) 68 | clean(a::Array{DD}) = reshape([clean(x) for x in a],size(a)) 69 | 70 | 71 | zero(::Type{DD}) = DD(zero(Float64),zero(Float64)) 72 | zero(a::DD) = zero(DD) 73 | one(::Type{DD}) = DD(one(Float64),zero(Float64)) 74 | one(a::DD) = one(DD) 75 | 76 | #= 77 | FL127(a::Float64) = DD(a, zero(Float64)) 78 | 79 | function FL127{T<:Float64}(a::T, b::T) 80 | hi = a + b 81 | lo = x - a 82 | lo = (a - (hi - lo)) + (b - lo) 83 | DD(hi,lo) 84 | end 85 | 86 | for T in (:AbstractFloat, Integer) 87 | @eval begin 88 | FL127(a::($T)) = Float127(convert(Float64,a)) 89 | FL127(a::($T),b::($T)) = Float127(convert(Float64,a),convert(Float64,b)) 90 | end 91 | end 92 | =# 93 | 94 | typealias Float128 DD 95 | 96 | 97 | #= 98 | Some internal computations require higher precision to meet the targeted relative error.\\ 99 | The internal structure is 192 bits given as a magnitude-ordered triple of Float64 values.\\ 100 | The triple are *presumed* to be in cannonical form: hi⊕md ≡ hi, md⊕lo ≡ md\\ 101 | This representation is known as "triple-double" (see refs.md) 102 | =# 103 | 104 | immutable TD <: Real 105 | hi::Float64 106 | md::Float64 107 | lo::Float64 108 | end 109 | 110 | TD(a::Float64) = TD(a,zero(Float64),zero(Float64)) 111 | TD{T<:Float64}(a::T,b::T) = TD(a,b,zero(Float64)) 112 | 113 | TD{T<:Float64}(a::Tuple{T}) = TD(a[1]) 114 | TD{T<:Float64}(a::Tuple{T,T}) = TD(a[1],a[2]) 115 | TD{T<:Float64}(a::Tuple{T,T}) = TD(a[1],a[2],a[3]) 116 | 117 | 118 | zero(::Type{TD}) = TD(zero(Float64),zero(Float64),zero(Float64)) 119 | zero(a::TD) = zero(TD) 120 | one(::Type{TD}) = TD(one(Float64),zero(Float64),zero(Float64)) 121 | one(a::TD) = one(TD) 122 | 123 | convert(::Type{TD}, a::Float64) = TD(a) 124 | convert(::Type{Float64}, a::TD) = a.hi 125 | convert{T<:SignedInt}(::Type{TD}, a::T) = TD(convert(Float64,a)) 126 | convert{T<:SignedInt}(::Type{T}, a::TD) = convert(T,floor(a.hi))+convert(T,floor(a.md))+convert(T,round(a.lo)) 127 | 128 | convert(::Type{TD}, a::DD) = TD(a.hi, a.lo, zero(Float64)) 129 | convert(::Type{DD}, a::TD) = DD(a.hi, a.md) 130 | 131 | 132 | 133 | convert(::Type{TD}, a::Tuple{Float64}) = TD(a[1]) 134 | convert(::Type{TD}, a::Tuple{Float64,Float64}) = TD(a[1],a[2]) 135 | convert(::Type{TD}, a::Tuple{Float64,Float64,Float64}) = TD(a[1],a[2],a[3]) 136 | convert(::Type{Tuple}, a::TD) = (a.hi,a.md,a.lo) 137 | convert(::Type{Tuple{Float64,Float64,Float64}}, a::TD) = (a.hi,a.md,a.lo) 138 | 139 | promote_rule(::Type{TD}, ::Type{Float64}) = TD 140 | promote_rule(::Type{TD}, ::Type{Float32}) = TD 141 | promote_rule(::Type{TD}, ::Type{Int64}) = TD 142 | promote_rule(::Type{TD}, ::Type{Int32}) = TD 143 | 144 | 145 | function clean(x::TD) 146 | ep = eps(eps(1.0)) 147 | if (abs(x.hi) <= ep) 148 | zero(TD) 149 | elseif (abs(x.md) <= eps(eps(x.hi))) 150 | DD(x.hi,0.0,0.0) 151 | elseif (abs(x.lo) <= eps(eps(x.md))) 152 | DD(x.hi,x.md,0.0) 153 | else 154 | x 155 | end 156 | end 157 | 158 | 159 | clean(x::Float32) = abs(x) < eps(eps(one(Float32))) ? zero(Float32) : x 160 | clean(x::Float64) = abs(x) < eps(eps(one(Float64))) ? zero(Float64) : x 161 | clean(x::AbstractFloat) = abs(x) < eps(eps(one(typeof(x)))) ? zero(typeof(x)) : x 162 | clean(x::Complex) = clean(x.re)+clean(x.im)*im 163 | -------------------------------------------------------------------------------- /src/arith/TD.jl: -------------------------------------------------------------------------------- 1 | @inline function renormAs3{T<:Float64}(c0::T, c1::T, c2::T, c3::T) 2 | if isinf(c0) 3 | return c0,zero(Float64),zero(Float64),zero(Float64) 4 | end 5 | 6 | s0,c3 = eftSum2inOrder(c2, c3) 7 | s0,c2 = eftSum2inOrder(c1, s0) 8 | c0,c1 = eftSum2inOrder(c0, s0) 9 | 10 | s0 = c0; s1 = c1; s2 = zero(Float64) 11 | if s1 != zero(Float64) 12 | s1,s2 = eftSum2inOrder(s1, c2) 13 | if s2 != zero(Float64) 14 | s2 += c3 # s2,s3 = eftSum2inOrder(s2, c3) # for renormAs4 15 | else 16 | s1,s2 = eftSum2inOrder(s1, c3) 17 | end 18 | else 19 | s0,s1 = eftSum2inOrder(s0, c2) 20 | if s1 != zero(Float64) 21 | s1,s2 = eftSum2inOrder(s1, c3) 22 | else 23 | s0,s1 = eftSum2inOrder(s0, c3) 24 | end 25 | end 26 | 27 | s0, s1, s2 # s0, s1, s2, s3 # for renormAs4 28 | end 29 | 30 | function renorm{T<:Float64}(c0::T, c1::T, c2::T) 31 | s0=s1=s2=zero(Float64) 32 | 33 | if isinf(c0) 34 | return c0,zero(Float64),zero(Float64) 35 | end 36 | 37 | s0,c2 = eftSum2inOrder(c1, c2) 38 | c0,c1 = eftSum2inOrder(c0, s0) 39 | 40 | s0 = c0 41 | s1 = c1 42 | 43 | if s1 != zero(Float64) 44 | s1,s2 = eftSum2inOrder(s1, c2) 45 | if s2 == zero(Float64) 46 | s1,s2 = eftSum2inOrder(s1, c3) 47 | end 48 | else 49 | s0,s1 = eftSum2inOrder(s0, c2) 50 | end 51 | 52 | s0, s1, s2 53 | end 54 | 55 | function renorm{T<:Float64}(c0::T, c1::T) 56 | eftSum2inOrder(c0,c1) 57 | end 58 | 59 | 60 | @inline function fastRenorm{T<:Float64}(c0::T, c1::T, c2::T) 61 | c1, c2 = eftSum2inOrder(c1,c2) 62 | c0, c1 = eftSum2inOrder(c0,c1) 63 | c0, c1, c2 64 | end 65 | 66 | @inline function fastRenormAs3{T<:Float64}(c0::T, c1::T, c2::T, c3::T) 67 | c2 += c3 68 | c1, c2 = eftSum2inOrder(c1,c2) 69 | c0, c1 = eftSum2inOrder(c0,c1) 70 | c0, c1, c2 71 | end 72 | 73 | 74 | # addition 75 | 76 | # this is less rigorous addition method -- the 77 | # low order bits are dropped converting to DD 78 | 79 | @inline function (+){T<:TD}(a::T,b::T) 80 | s0 = a.hi + b.hi 81 | s1 = a.md + b.md 82 | s2 = a.lo + b.lo 83 | 84 | v0 = s0 - a.hi 85 | v1 = s1 - a.md 86 | v2 = s2 - a.lo 87 | 88 | u0 = s0 - v0 89 | u1 = s1 - v1 90 | u2 = s2 - v2 91 | 92 | w0 = a.hi - u0 93 | w1 = a.md - u1 94 | w2 = a.lo - u2 95 | 96 | u0 = b.hi - v0 97 | u1 = b.md - v1 98 | u2 = b.lo - v2 99 | 100 | t0 = w0 + u0 101 | t1 = w1 + u1 102 | t2 = w2 + u2 103 | 104 | s1,t0 = eftSum2(s1, t0) 105 | s2,t0,t1 = eftSum3(s2, t0, t1) 106 | t0,t2 = eftSum2(t0, t2) 107 | t0 = t0 + t1 108 | 109 | s0,s1,s2 = renormAs3(s0, s1, s2, t0) 110 | TD(s0, s1, s2) 111 | end 112 | 113 | 114 | function (+)(a::TD,b::DD) 115 | 116 | s0 = a.hi + b.hi 117 | s1 = a.md + b.lo 118 | 119 | v0 = s0 - a.hi 120 | v1 = s1 - a.md 121 | 122 | u0 = s0 - v0 123 | u1 = s1 - v1 124 | 125 | w0 = a.hi - u0 126 | w1 = a.md - u1 127 | 128 | u0 = b.hi - v0 129 | u1 = b.lo - v1 130 | 131 | t0 = w0 + u0 132 | t1 = w1 + u1 133 | 134 | s1,t0 = eftSum2(s1, t0) 135 | s2,t0,t1 = eftSum3(a.lo, t0, t1) 136 | t0 += t1 137 | 138 | #s0,s1,s2 = renormAs3(s0, s1, s2, t0) 139 | s2 += t0 140 | s1,s2 = eftSum2inOrder(s1,s2) 141 | s0,s1 = eftSum2inOrder(s0,s1) 142 | 143 | TD(s0, s1, s2) 144 | end 145 | 146 | (+)(a::DD,b::TD) = (+)(b,a) 147 | 148 | 149 | # subtract 150 | 151 | # this is the sloppier subtract, we do not need all the bits 152 | (-)(a::TD,b::TD) = (+)(a,-b) 153 | 154 | (-)(a::TD,b::DD) = (+)(a,-b) 155 | (-)(a::DD,b::TD) = -((-)(b,a)) 156 | 157 | 158 | # multiply 159 | 160 | # square 161 | 162 | function (sqr)(a::TD) 163 | p0,q0 = eftSquare(a.hi) 164 | p1,q1 = eftProd2(2.0*a.hi, a.md) 165 | p2,q2 = eftProd2(2.0*a.hi, a.lo) 166 | p3,q3 = eftSquare(a.md) 167 | 168 | p1,q0 = eftSum2(q0, p1) 169 | 170 | q0,q1 = eftSum2(q0, q1) 171 | p2,p3 = eftSum2(p2, p3) 172 | 173 | s0,t0 = eftSum2(q0, p2) 174 | s1,t1 = eftSum2(q1, p3) 175 | 176 | s1,t0 = eftSum2(s1, t0) 177 | t0 += t1 178 | 179 | s1,t0 = eftSum2inOrder(s1, t0) 180 | p2,t1 = eftSum2inOrder(s0, s1) 181 | p3,q0 = eftSum2inOrder(t1, t0) 182 | 183 | p4 = 2.0 * a.md * a.lo 184 | 185 | q2,q3 = eftSum2(q2, q3) 186 | 187 | t0,t1 = eftSum2(p4, q2) 188 | t1 += q3 189 | 190 | p3,p4 = eftSum2(p3, t0) 191 | p4 = p4 + q0 + t1 192 | 193 | #p0,p1,p2 = renormAs3(p0, p1, p2, p3, p4) 194 | p0,p1,p2 = renormAs3(p0, p1, p2, p3+p4) 195 | 196 | TD(p0,p1,p2) 197 | end 198 | 199 | # this is less rigorous multiply method -- the 200 | # low order bits are dropped converting to DD 201 | 202 | @inline function (*){T<:TD}(a::T,b::T) 203 | p0,q0 = eftProd2(a.hi, b.hi) 204 | p1,q1 = eftProd2(a.hi, b.md) 205 | p2,q2 = eftProd2(a.md, b.hi) 206 | p3,q3 = eftProd2(a.hi, b.lo) 207 | p4,q4 = eftProd2(a.md, b.md) 208 | p5,q5 = eftProd2(a.lo, b.hi) 209 | 210 | # Start Accumulation 211 | p1,p2,q0 = eftSum3(p1, p2, q0) 212 | 213 | # Six-Three Sum of p2, q1, q2, p3, p4, p5 214 | p2,q1,q2 = eftSum3(p2, q1, q2) 215 | p3,p4,p5 = eftSum3(p3, p4, p5) 216 | # compute (s0, s1, s2) = (p2, q1, q2) + (p3, p4, p5) 217 | s0,t0 = eftSum2(p2, p3) 218 | s1,t1 = eftSum2(q1, p4) 219 | s2 = q2 + p5 220 | s1,t0 = eftSum2(s1, t0) 221 | s2 += (t0 + t1) 222 | 223 | # O(eps^3) order terms 224 | s1 += a.md*b.lo + a.lo*b.md + q0 + q3 + q4 + q5 225 | p0,p1,s0 = renormAs3(p0, p1, s0, s1+s2) 226 | TD(p0,p1,s0) 227 | end 228 | 229 | 230 | @inline function (*)(a::TD,b::DD) 231 | p0,q0 = eftProd2(a.hi, b.hi) 232 | p1,q1 = eftProd2(a.hi, b.lo) 233 | p2,q2 = eftProd2(a.md, b.hi) 234 | p4,q4 = eftProd2(a.md, b.lo) 235 | p5,q5 = eftProd2(a.lo, b.hi) 236 | 237 | # Start Accumulation 238 | p1,p2,q0 = eftSum3(p1, p2, q0) 239 | 240 | # Six-Three Sum of p2, q1, q2, p3, p4, p5 241 | p2,q1,q2 = eftSum3(p2, q1, q2) 242 | p3,p4 = eftSum2(p4, p5) 243 | # compute (s0, s1, s2) = (p2, q1, q2) + (p3, p4, p5) 244 | s0,t0 = eftSum2(p2, p3) 245 | s1,t1 = eftSum2(q1, p4) 246 | s2 = q2 247 | s1,t0 = eftSum2(s1, t0) 248 | s2 += (t0 + t1) 249 | 250 | # O(eps^3) order terms 251 | s1 += a.lo*b.lo + q0 + q4 + q5 252 | #p0,p1,s0 = renormAs3(p0, p1, s0, s1+s2) 253 | s1 += s2 254 | s0,s1 = eftSum2inOrder(s0,s1) 255 | p1,s0 = eftSum2inOrder(p1,s0) 256 | p0,p1 = eftSum2inOrder(p0,p1) 257 | 258 | TD(p0,p1,s0) 259 | end 260 | 261 | @inline (*)(a::DD,b::TD) = (*)(b,a) 262 | 263 | 264 | # reciprocation 265 | 266 | function (recip)(b::TD) 267 | a = one(TD) 268 | 269 | q0 = 1.0 / b.hi 270 | r = a - (b * q0) 271 | q1 = r.hi / b.hi 272 | r = r - (b * q1) 273 | q2 = r.hi / b.hi 274 | r = r -(b * q2) 275 | q3 = r.hi / b.hi 276 | r = r - (b * q3) 277 | q3 += r.hi / b.hi 278 | 279 | q0,q1,q2 = renormAs3(q0, q1, q2, q3) 280 | 281 | TD(q0, q1, q2) 282 | end 283 | 284 | #= 285 | # correct, slower 286 | function (rcp)(b::TD)function (recip)(b::TD) 287 | hi,lo = eftRecip(b.hi) 288 | 289 | r = TD(hi,-lo,zero(Float64)) 290 | r = r + (one(TD) - r*b) * r 291 | r = r + (one(TD) - r*b) * r 292 | r = r + (one(TD) - r*b) * r 293 | 294 | r = r + (one(TD) - r*b) * r 295 | end 296 | =# 297 | 298 | # division 299 | 300 | function (/)(a::TD, b::TD) 301 | 302 | q0 = a.hi / b.hi 303 | r = a - (b * q0) 304 | q1 = r.hi / b.hi 305 | r -= (b * q1) 306 | q2 = r.hi / b.hi 307 | r -= (b * q2) 308 | q3 = r.hi / b.hi 309 | r = r - (b * q3) 310 | q3 += r.hi / b.hi 311 | 312 | q0,q1,q2 = renormAs3(q0, q1, q2, q3) 313 | 314 | TD(q0, q1, q2) 315 | end 316 | 317 | 318 | # powers 319 | 320 | 321 | 322 | # roots 323 | 324 | function sqrt(a::TD) 325 | if a.hi <= zero(Float64) 326 | if a.hi == zero(Float64) 327 | return zero(TD) 328 | else 329 | throw(ArgumentError("sqrt expects a nonnegative base")) 330 | end 331 | #elseif (a.hi < 1.0e-18) | (a.hi > 1.0e18) 332 | # throw(ArgumentError("sqrt arg ($a) outside domain")) 333 | end 334 | 335 | if (a.hi < 1.0e-7) # -log2(1.0e-7) < (1/2) Float64 significand bits 336 | return one(TD) / sqrt(one(TD)/a) 337 | end 338 | 339 | # initial approximation to 1/sqrt(a) 340 | r = TD(one(Float64)/sqrt(a.hi), zero(Float64)) 341 | 342 | r = r + divby2( r * (one(TD) - (a*(r*r))) ) 343 | r = r + divby2( r * (one(TD) - (a*(r*r))) ) 344 | r = r + divby2( r * (one(TD) - (a*(r*r))) ) 345 | r = r + divby2( r * (one(TD) - (a*(r*r))) ) 346 | 347 | r = a*r 348 | divby2(r + a/r) 349 | end 350 | 351 | 352 | 353 | function hypot(a::TD, b::TD) 354 | a = abs(a) 355 | b = abs(b) 356 | t, x = min(a,b), max(a,b) 357 | t = t/a 358 | x * sqrt(1.0 + t*t) 359 | end 360 | -------------------------------------------------------------------------------- /src/trig/DD.jl: -------------------------------------------------------------------------------- 1 | @inline function mod2piAsTD(a::DD) 2 | b = TD(a) 3 | b1 = b * td_1_over_twopi 4 | f1 = floor(b1) 5 | chk = floor(b.hi * td_1_over_twopi_part2.hi) 6 | if (chk > zero(Float64)) 7 | throw(ErrorException("arg ($a) is too large")) 8 | end 9 | d1 = f1*td_twopi 10 | d2 = f1*td_twopi_part2 11 | # d3 = f1*td_twopi_part3 12 | 13 | m = b - d1 14 | m = m - d2 15 | # m = m - d3 16 | 17 | m 18 | end 19 | 20 | function mod2pi(a::DD) 21 | DD(mod2piAsTD(a)) 22 | end 23 | 24 | @inline function modPiOver2AsTD(a::DD) 25 | b = TD(a) 26 | b1 = b * td_2_over_pi 27 | f1 = floor(b1) 28 | chk = floor(b.hi * td_2_over_pi_part2.hi) 29 | if (chk > zero(Float64)) 30 | throw(ErrorException("arg ($a) is too large")) 31 | end 32 | d1 = f1*td_pi_over_2 33 | d2 = f1*td_pi_over_2_part2 34 | # d3 = f1*td_pi_over_2_part3 35 | 36 | m = b - d1 37 | m = m - d2 38 | # m = m - d3 39 | 40 | m 41 | end 42 | 43 | # a --> [0 .. p/2) 44 | function modPiOver2(a::DD) 45 | DD(modPiOver2AsTD(a)) 46 | end 47 | 48 | 49 | @inline function modPiOver4AsTD(a::DD) 50 | b = TD(a) 51 | b1 = b * td_4_over_pi 52 | f1 = floor(b1) 53 | chk = floor(b.hi * td_4_over_pi_part2.hi) 54 | if (chk > zero(Float64)) 55 | throw(ErrorException("arg ($a) is too large")) 56 | end 57 | d1 = f1*td_pi_over_4 58 | d2 = f1*td_pi_over_4_part2 59 | # d3 = f1*td_pi_over_4_part3 60 | 61 | m = b - d1 62 | m = m - d2 63 | # m = m - d3 64 | 65 | m 66 | end 67 | 68 | # a --> [0 .. p/2) 69 | function modPiOver4(a::DD) 70 | DD(modPiOver4AsTD(a)) 71 | end 72 | 73 | # a --> [-pi/4 .. p/4) 74 | function modSignedPiOver4(a::DD) 75 | m = modPiOver2AsTD(a) 76 | if (m.hi >= pi/4.0) 77 | m = m - td_pi_over_2 78 | m = m - td_pi_over_2_part2 79 | # m = m - td_pi_over_2_part3 80 | end 81 | 82 | DD(m) 83 | end 84 | #= 85 | more accurate 86 | =# 87 | 88 | function modSignedPiOver4(a::DD) 89 | m = modPiOver2AsTD(a) 90 | if (m.hi >= pi/4.0) 91 | m = m - td_pi_over_2 92 | m = m - td_pi_over_2_part2 93 | # m = m - td_pi_over_2_part3 94 | end 95 | 96 | DD(m) 97 | end 98 | 99 | 100 | # -2pi <= radian < 2pi 101 | function resolveQuadrantInCircle(radian::DD) 102 | isneg, aradian = signbit(radian), abs(radian) 103 | if isneg 104 | aradian = DD(td_twopi - aradian) 105 | end 106 | # octant numbering for trig calcs are rotated by -pi/4 107 | # (see, e.g. Jack Crenshaw, Math Toolkit for Realtime Programming, p106) 108 | octant = trunc(Int, div(radian, dd_pi_over_4).hi) 109 | quadrant = (octant + isodd(octant)) >> 1 110 | quadrant = mod(quadrant,4) 111 | radi = modSignedPiOver4(aradian) 112 | quadrant, radi 113 | end 114 | 115 | 116 | const dd_n_tan_coeff = 16; 117 | const dd_tan_coeff = DD[ 118 | DD(1.0, 0.0), 119 | DD(0.3333333333333333, 1.850371707708594e-17), 120 | DD(0.13333333333333333, 1.8503717077085942e-18), 121 | DD(0.05396825396825397, -2.5552752154071065e-18), 122 | DD(0.021869488536155203, -1.7377829530067485e-19), 123 | DD(0.008863235529902197, -7.63300580171831e-19), 124 | DD(0.003592128036572481, -1.253823608406629e-19), 125 | DD(0.0014558343870513183, -6.214492640136062e-20), 126 | DD(0.000590027440945586, 3.478690842383652e-20), 127 | DD(0.00023912911424355248, 3.564613898329782e-21), 128 | DD(9.691537956929451e-5, -6.2386628755632464e-21), 129 | DD(3.927832388331683e-5, 1.3737015743076767e-21), 130 | DD(1.5918905069328964e-5, 1.0427554807190543e-21), 131 | DD(6.451689215655431e-6, 1.1519922496640058e-22), 132 | DD(2.6147711512907546e-6, -9.313685621299801e-23), 133 | DD(1.0597268320104654e-6, 2.3670525505213632e-24), # 31 134 | ]; 135 | 136 | 137 | function sin_taylor_series(a::DD) 138 | x = a 139 | x2 = x*x 140 | x3 = x*x2 141 | x4 = x2*x2 142 | x5 = x2*x3 143 | x6 = x3*x3 144 | x7 = x3*x4 145 | x8 = x4*x4 146 | x9 = x4*x5 147 | x17 = x8*x9 148 | x25 = x17*x8 149 | 150 | z = TD(x) + x*(-dd_inv_fact[3]*x2 + dd_inv_fact[5]*x4 - dd_inv_fact[7]*x6) 151 | z2 = x9 * (dd_inv_fact[9] - x2*dd_inv_fact[11] + x4*dd_inv_fact[13] - x6*dd_inv_fact[15]) 152 | z3 = x17 * (dd_inv_fact[17] - x2*dd_inv_fact[19] + x4*dd_inv_fact[21] - x6*dd_inv_fact[23]) 153 | z4 = x25 * (dd_inv_fact[25] - x2*dd_inv_fact[27] + x4*dd_inv_fact[29] - x6*dd_inv_fact[31]) 154 | 155 | DD(z + ((z4+z3)+z2)) 156 | end 157 | 158 | function cos_taylor_series(a::DD) 159 | x = a 160 | x2 = x*x 161 | x4 = x2*x2 162 | x6 = x2*x4 163 | x8 = x4*x4 164 | x16 = x8*x8 165 | x24 = x8*x16 166 | 167 | z = (-dd_inv_fact[2]*x2 + dd_inv_fact[4]*x4 - dd_inv_fact[6]*x6) 168 | z2 = x8 * (dd_inv_fact[8] - x2*dd_inv_fact[10] + x4*dd_inv_fact[12] - x6*dd_inv_fact[14]) 169 | z3 = x16 * (dd_inv_fact[16] - x2*dd_inv_fact[18] + x4*dd_inv_fact[20] - x6*dd_inv_fact[22]) 170 | z4 = x24 * (dd_inv_fact[24] - x2*dd_inv_fact[26] + x4*dd_inv_fact[28] - x6*dd_inv_fact[30]) 171 | 172 | ((z4+z3)+z2)+z + 1.0 173 | end 174 | 175 | 176 | 177 | # for a < 9/64 0.140625 178 | function tan_taylor_series(radian::DD) 179 | x = radian 180 | x2 = x*x 181 | x3 = x*x2 182 | x4 = x2*x2 183 | x5 = x2*x3 184 | x6 = x3*x3 185 | x7 = x3*x4 186 | x8 = x4*x4 187 | x9 = x4*x5 188 | x17 = x8*x9 189 | x25 = x17*x8 190 | 191 | z = TD(x) + x*(dd_tan_coeff[2]*x2 + dd_tan_coeff[3]*x4 + dd_tan_coeff[4]*x6) 192 | z2 = x9 * (dd_tan_coeff[5] + x2*dd_tan_coeff[6] + x4*dd_tan_coeff[7] + x6*dd_tan_coeff[8]) 193 | z3 = x17 * (dd_tan_coeff[9] + x2*dd_tan_coeff[10] + x4*dd_tan_coeff[11] + x6*dd_tan_coeff[12]) 194 | z4 = x25 * (dd_tan_coeff[13] + x2*dd_tan_coeff[14] + x4*dd_tan_coeff[15] + x6*dd_tan_coeff[16]) 195 | 196 | DD(z + ((z4+z3)+z2)) 197 | end 198 | 199 | 200 | 201 | function sin_taylor(radian::DD) 202 | hi = radian.hi 203 | if ((hi==zero(Float64)) | (hi==NaN) | (hi==pi/4.0) | (hi==pi/6.0)) 204 | if hi == zero(Float64) 205 | return zero(DD) 206 | elseif hi == NaN 207 | return radian 208 | elseif hi == dd_pi_over_4.hi && radian.lo == dd_pi_over_4.lo 209 | return dd_1_over_sqrt2 210 | elseif hi == dd_pi_over_6.hi && radian.lo == dd_pi_over_6.lo 211 | return dd_half 212 | end 213 | end 214 | sin_taylor_series(radian) 215 | end 216 | 217 | function cos_taylor(radian::DD) 218 | hi = radian.hi 219 | if ((hi==zero(Float64)) | (hi==NaN) | (hi==pi/4.0) | (hi==pi/6.0)) 220 | if hi == zero(Float64) 221 | return one(DD) 222 | elseif hi == NaN 223 | return radian 224 | elseif hi == dd_pi_over_4.hi && radian.lo == dd_pi_over_4.lo 225 | return dd_1_over_sqrt2 226 | elseif hi == dd_pi_over_6.hi && radian.lo == dd_pi_over_6.lo 227 | return dd_sqrt3_over_2 228 | end 229 | end 230 | cos_taylor_series(radian) 231 | end 232 | 233 | 234 | function sincos_taylor(radian::DD) 235 | s = c = zero(DD) 236 | if abs(radian.hi) < 0.39269908169872414 # pi/8 237 | s = sin_taylor(radian) 238 | ts = TD(s) 239 | c = DD(sqrt(one(TD)-ts*ts)) 240 | else 241 | c = cos_taylor(radian) 242 | tc = TD(c) 243 | s = DD(sqrt(one(TD)-tc*tc)) 244 | end 245 | s,c 246 | end 247 | 248 | 249 | # a <= 0.15 250 | function tan_taylor(radian::DD) 251 | hi = radian.hi 252 | if ((hi==zero(Float64)) | (hi==NaN) | (hi==pi/4.0) | (hi==pi/6.0)) 253 | if hi == zero(Float64) 254 | return zero(DD) 255 | elseif hi == NaN 256 | return radian 257 | elseif hi == dd_pi_over_4.hi && radian.lo == dd_pi_over_4.lo 258 | return one(DD) 259 | elseif hi == dd_pi_over_6.hi && radian.lo == dd_pi_over_6.lo 260 | return dd_sqrt3_over_3 261 | end 262 | end 263 | isneg, aradian = signbit(radian), abs(radian) 264 | if (1.0e-15 <= aradian.hi <= 9.0/64.0) 265 | t = tan_taylor_series(aradian) 266 | else 267 | s,c = sincos_taylor(aradian) 268 | t = s/c 269 | end 270 | isneg ? -t : t 271 | end 272 | 273 | 274 | 275 | 276 | #= 277 | for radian in [0,8*pi) 278 | relerr precise sin(radian) ~1.2e-32 (106 bits) 279 | for radian in [0,4096^3 *pi) 280 | relerr precise sin(radian) ~2e-32 (105 bits) 281 | for radian > 4096^3 *pi 282 | relerr 1.5e-29 (95 bits) 283 | =# 284 | 285 | function sinInCircle(radian::DD) 286 | quadrant, radi = resolveQuadrantInCircle(radian) 287 | isneg, aradi = signbit(radi), abs(radi) 288 | if (quadrant == 0) 289 | isneg ? -sin_taylor(aradi) : sin_taylor(aradi) 290 | elseif (quadrant == 1) 291 | cos_taylor(aradi) 292 | elseif (quadrant == 2) 293 | isneg ? sin_taylor(aradi) : -sin_taylor(aradi) 294 | else #if (quadrant == 3) 295 | -cos_taylor(aradi) # isneg ? -cos_taylor(aradi) : -cos_taylor(aradi) 296 | end 297 | end 298 | 299 | function sin(radian::DD) 300 | isneg, aradian = signbit(radian.hi), abs(radian) 301 | if aradian <= dd_pi_over_4 302 | s = sin_taylor(aradian) 303 | elseif aradian < dd_twopi 304 | s = sinInCircle(aradian) 305 | else 306 | r = mod2piAsTD(aradian) 307 | ddr = DD(r.hi,r.md) 308 | s = sinInCircle(ddr)*cos(r.lo)+sin(r.lo)*cos(ddr) 309 | end 310 | isneg ? -s : s 311 | end 312 | 313 | #= 314 | for radian in [0,8*pi) 315 | relerr precise sin(radian) ~1.2e-32 (106 bits) 316 | for radian in [0,4096^3 *pi) 317 | relerr precise sin(radian) ~2e-32 (105 bits) 318 | for radian > 4096^3 *pi 319 | relerr 1.5e-29 (95 bits) 320 | =# 321 | function cosInCircle(radian::DD) 322 | quadrant, radi = resolveQuadrantInCircle(radian) 323 | isneg, aradi = signbit(radi), abs(radi) 324 | if (quadrant == 0) 325 | cos_taylor(aradi) 326 | elseif (quadrant == 1) 327 | isneg ? sin_taylor(aradi) : -sin_taylor(aradi) 328 | elseif (quadrant == 2) 329 | -cos_taylor(aradi) 330 | else #if (quadrant == 3) 331 | isneg ? -sin_taylor(aradi) : sin_taylor(aradi) 332 | end 333 | end 334 | 335 | function cos(radian::DD) 336 | aradian = abs(radian) 337 | if aradian <= dd_pi_over_4 338 | cos_taylor(radian) 339 | elseif aradian < dd_twopi 340 | cosInCircle(aradian) 341 | else 342 | r = mod2piAsTD(aradian) 343 | ddr = DD(r.hi,r.md) 344 | cosInCircle(ddr)*cos(r.lo)-sinInCircle(ddr)*sin(r.lo) 345 | end 346 | end 347 | 348 | 349 | 350 | #= 351 | function sincos(radian::DD) 352 | if abs(radian) <= dd_pi_over_4 353 | s = sin_taylor(radian) 354 | c = DD(sqrt(one(DD)-TD(s)*s)) 355 | elseif abs(radian) < dd_twopi 356 | s = sinInCircle(radian) 357 | c = DD(sqrt(one(DD)-TD(s)*s)) 358 | if (abs(radian) > dd_pi) 359 | c = -c 360 | end 361 | else 362 | r = mod2piAsTD(radian) 363 | ddr = DD(r.hi,r.md) 364 | s = sinInCircle(ddr) 365 | slo = sin(r.lo) 366 | c = cosInCircle(ddr) 367 | clo = cos(r.lo) 368 | s = s*clo + c*slo 369 | c = c*clo - s*slo 370 | if (abs(radian) > dd_pi) 371 | c = -c 372 | end 373 | end 374 | s,c 375 | end 376 | =# 377 | 378 | function sincos(radian::DD) 379 | sin(radian),cos(radian) 380 | end 381 | 382 | 383 | 384 | # good for radian in 0..2pi(quadrants 0,1, 1/2 of q3) 385 | #= 386 | for radian in [0,2*pi) 387 | relerr tan(radian) ~ 5e-3 (106 bits) 388 | =# 389 | function tanInCircle(radian::DD) 390 | quadrant, radi = resolveQuadrantInCircle(radian) 391 | isneg, aradi = signbit(radi), abs(radi) 392 | t = tan_taylor(aradi) 393 | if (quadrant == 0) 394 | isneg ? -t : t 395 | elseif (quadrant == 1) 396 | isneg ? recip(t) : -recip(t) 397 | elseif (quadrant == 2) 398 | isneg ? -t : t 399 | else #if (quadrant == 3) 400 | isneg ? recip(t) : -recip(t) 401 | end 402 | end 403 | 404 | #= 405 | for radian in [-8pi,8pi) 406 | relerr tan(radian) ~4.1e-32 (104 bits) 407 | for radian in [8pi,4096^3 *pi) 408 | relerr tan(radian) ~6.2e-32 (103 bits) 409 | for radian > 4096^3 *pi 410 | relerr 4.2e-29 (94 bits) 411 | =# 412 | #= 413 | function tan(radian::DD) 414 | isneg, aradian = signbit(radian), abs(radian) 415 | if abs(radian.hi) < 9.0/64.0 416 | t = tan_taylor(aradian) 417 | elseif abs(radian < dd_twopi) 418 | t = tanInCircle(aradian) 419 | else 420 | r = mod2piAsTD(aradian) 421 | ddr = DD(r.hi,r.md) 422 | s = TD(sinInCircle(ddr)) 423 | c = TD(cosInCircle(ddr)) 424 | slo,clo = sin(r.lo),cos(r.lo) 425 | s = s*clo+c*slo; c=c*clo-s*slo; 426 | t = DD(s/c) 427 | end 428 | isneg ? -t : t 429 | end 430 | =# 431 | 432 | function tan(radian::DD) 433 | isneg, aradian = signbit(radian.hi), abs(radian) 434 | s = c = zero(DD) 435 | if aradian <= dd_pi_over_4 436 | s = sin_taylor(aradian) 437 | c = cos_taylor(aradian) 438 | elseif aradian < dd_twopi 439 | s = sinInCircle(aradian) 440 | c = cosInCircle(aradian) 441 | else 442 | r = mod2piAsTD(aradian) 443 | ddr = DD(r.hi,r.md) 444 | s = sinInCircle(ddr) 445 | slo = sin(r.lo) 446 | c = cosInCircle(ddr) 447 | clo = cos(r.lo) 448 | s = s*clo+c*slo 449 | c = c*clo-s*slo 450 | end 451 | isneg ? -s/c : s/c 452 | end 453 | 454 | csc(radian::DD) = recip( sin(radian) ) 455 | sec(radian::DD) = recip( cos(radian) ) 456 | cot(radian::DD) = recip( tan(radian) ) 457 | 458 | -------------------------------------------------------------------------------- /src/atrig/DD.jl: -------------------------------------------------------------------------------- 1 | # x=0..0.015 2 | function asinconfrac(x::DD) 3 | x2 = x*x 4 | #x/(1+x2/(-6+x2/(10/17+x2/(-4046/549+x2/(602802/1173833+x2/(-104890816822/12889271025+1207527848162057*x2*(1/573251714022650))))))) 5 | x/(DD(1.0,0.0)+x2/(-DD(6.0,0.0)+x2/(DD(0.5882352941176471, -1.959217102279688e-17)+x2/(-DD(7.36976320582878, -4.044528322860315e-17)+x2/(DD(0.51353301534375, -3.4384261563723567e-17)+x2/(DD(-8.137839340840458, 8.011797547325665e-16)+x2*(DD((2.1064530966484747, 1.1717219329569228e-16))))))))) 6 | end 7 | 8 | 9 | 10 | # |a| <= 0.003 11 | function atan_series(a::DD) 12 | x = a 13 | x2 = x*x 14 | x4 = x2*x2 15 | x6 = x2*x4 16 | x8 = x4*x4 17 | x16 = x8*x8 18 | x24 = x8*x16 19 | 20 | z = -dd_recip_int[3]*x2 + dd_recip_int[5]*x4 - dd_recip_int[7]*x6 21 | z1 = x8*(dd_recip_int[9] - dd_recip_int[11]*x2 + dd_recip_int[14]*x4 - dd_recip_int[15]*x6) 22 | z2 = x16*(dd_recip_int[17] - dd_recip_int[19]*x2 + dd_recip_int[21]*x4 - dd_recip_int[23]*x6) 23 | z3 = x24*(dd_recip_int[25] - dd_recip_int[27]*x2 + dd_recip_int[29]*x4 - dd_recip_int[31]*x6) 24 | 25 | (((z3+z2)+z1)+z+one(DD))*x 26 | end 27 | 28 | 29 | function asin(a::DD) 30 | isneg, abs_a = signbit(a.hi), abs(a) 31 | if abs_a.hi > one(Float64) 32 | throw(ErrorException("asin: Argument out of domain.")) 33 | return dd_NaN 34 | elseif abs_a.hi == one(Float64) && abs_a.lo == zero(Float64) 35 | return (a.hi >= zero(Float64) ? dd_pi_over_2 : -dd_pi_over_2) 36 | end 37 | 38 | if (abs_a.hi <= 0.015) 39 | b = asinconfrac(abs_a) 40 | else 41 | #a = DD(asin(TD(abs_x))) 42 | y = TD(abs_a) 43 | x = y*y 44 | x = one(TD)-x 45 | x = sqrt(x) 46 | x = one(TD) + x 47 | z = atan2(y,x) 48 | z = mulby2(z) 49 | b = DD(z) 50 | end 51 | isneg ? -b : b 52 | end 53 | 54 | function acos(a::DD) 55 | isneg, abs_a = signbit(a.hi), abs(a) 56 | if abs_a.hi > 1.0 57 | throw(ErrorException("acos: Argument out of domain.")) 58 | return dd_NaN 59 | elseif abs_a.hi == one(Float64) && abs_a.lo == zero(Float64) 60 | return (a.hi >= zero(Float64) ? dd_pi : zero(DD)) 61 | elseif abs_a.hi == zero(Float64) && abs.lo == zero(Float64) 62 | return dd_pi_over_2 63 | end 64 | 65 | dd_pi_over_2 - asin(a) 66 | end 67 | 68 | function atan2(y::DD,x::DD) 69 | DD(atan2(TD(y),TD(x))) 70 | end 71 | 72 | function atan(x::DD) 73 | isneg, abs_x = signbit(x), abs(x) 74 | if (abs_x.hi <= 4.19745e-11) 75 | t = abs_x 76 | elseif abs_x.hi <= 0.003 77 | t = atan_series(abs_x) 78 | else 79 | t = atan2(abs_x, one(DD)) 80 | end 81 | isneg ? -t : t 82 | end 83 | 84 | 85 | #= 86 | arctan(x) for x in k/64 .. (k+1)/64 (k in 0..63) 87 | these are minimax results from maple over 88 | k/64 - 1/4096^2 .. (k+1)/64 + 1/4096^2 89 | they are not the best fit to DD coeffs 90 | but they are close enough 91 | =# 92 | 93 | function atan01numer(x::DD) 94 | DD(3.629893017141765e-35, 6.6406679896317375e-52) + 95 | (DD(0.9996754545703865, -4.598817090918266e-17) + 96 | (DD(0.02555812681060226, -9.958411852257287e-20) + 97 | (DD(1.0302585588731008, -7.183792179616217e-17) + 98 | (DD(0.01988046865875826, 7.896880383011565e-19) + 99 | (DD(0.2000869562087623, -8.47084451019246e-18) + 100 | DD(0.0017314342719200748, -7.732543321053218e-20) * x) *x)*x)*x)*x)*x 101 | end 102 | function atan01denom(x::DD) 103 | DD(0.9929146630650226, 1.896947743258429e-18), 104 | (DD(0.12687948850312847, -5.839018909578105e-18), 105 | (DD(1.3614681807580766, -4.280666382785087e-17), 106 | (DD(0.1412487658121559, 6.491929668608193e-18), 107 | (DD(0.4577547489764742, -2.5746404954730867e-18), 108 | (DD(0.03037246208354068, 9.645477620436761e-19), 109 | DD(0.02213623421350611, -1.1027549731601916e-18) * x) *x)*x)*x)*x)*x 110 | end 111 | @inline atan01of64(x::DD) = atan01numer(x) / atan01denom(x) 112 | 113 | function atan12numer(x::DD) 114 | DD(1.6218277873895332e-25, 1.084747206314063e-41) + 115 | (DD(0.9974155586768761, 4.514103898642169e-18) + 116 | (DD(0.0764916212253432, 3.500531525408491e-18) + 117 | (DD(1.0303435035210617, -6.890589883420933e-17) + 118 | (DD(0.05955192232775267, 2.077561630841645e-18) + 119 | (DD(0.20089995784387976, 4.140614508164837e-18) + 120 | DD(0.0051959782853776715, -1.158432657223438e-19)*x) *x)*x)*x)*x)*x 121 | end 122 | function atan12denom(x::DD) 123 | DD(0.9929146630650226, 1.896947743258429e-18) + 124 | (DD(0.12687948850312847, -5.839018909578105e-18) + 125 | (DD(1.3614681807580766, -4.280666382785087e-17) + 126 | (DD(0.1412487658121559, 6.491929668608193e-18) + 127 | (DD(0.4577547489764742, -2.5746404954730867e-18) + 128 | (DD(0.03037246208354068, 9.645477620436761e-19) + 129 | DD(0.02213623421350611, -1.1027549731601916e-18)*x) *x)*x)*x)*x)*x 130 | end 131 | @inline atan12of64(x::DD) = atan12numer(x) / atan12denom(x) 132 | 133 | 134 | function atan2to3numer(x::DD) 135 | DD(1.5746491607703442e-22, -5.35357483834068e-39) + 136 | (DD(0.9929146630650226, 1.8434410645424224e-18) + 137 | (DD(0.12687948850312847, 2.538312664799496e-18) + 138 | (DD(1.0304966264030682, 8.1565115612327e-17) + 139 | (DD(0.09895560297783178, -4.74221417590191e-18) + 140 | (DD(0.20251495466768876, 4.4403079300469404e-18) + 141 | DD(0.00866543793078847, -6.0102146731863325e-19) * x) *x)*x)*x)*x)*x 142 | end 143 | function atan2to3denom(x::DD) 144 | DD(0.9929146630650226, 1.896947743258429e-18) + 145 | (DD(0.12687948850312847, -5.839018909578105e-18) + 146 | (DD(1.3614681807580766, -4.280666382785087e-17) + 147 | (DD(0.1412487658121559, 6.491929668608193e-18) + 148 | (DD(0.4577547489764742, -2.5746404954730867e-18) + 149 | (DD(0.03037246208354068, 9.645477620436761e-19) + 150 | DD(0.02213623421350611, -1.1027549731601916e-18)*x) *x)*x)*x)*x)*x 151 | end 152 | @inline atan2to3of64(x::DD) = atan2to3numer(x) / atan2to3denom(x) 153 | 154 | 155 | function atan3to4numer(x::DD) 156 | DD(1.3187186340364065e-20, -6.470728923559978e-37) + 157 | (DD(0.9862102481582604, 2.7745960767391508e-17) + 158 | (DD(0.17636675197972745, 2.0310811075114496e-18) + 159 | (DD(1.0306848913144344, -2.8475702993687415e-17) + 160 | (DD(0.1379152536552334, -9.407544146202368e-18) + 161 | (DD(0.204910126648868, -5.721917057878642e-18) + 162 | DD(0.012142724623342087, 8.095456557657355e-19) * x) *x)*x)*x)*x)*x 163 | end 164 | function atan3to4denom(x::DD) 165 | DD(0.9862102481582604, 3.091568007464899e-17) + 166 | (DD(0.1763667519797271, 1.1498601703642871e-17) + 167 | (DD(1.359421640700545, -6.950382430252179e-17) + 168 | (DD(0.19670417098071252, 5.430012207236689e-19) + 169 | (DD(0.4608086239537724, -3.5080079009821014e-18) + 170 | (DD(0.04243743032802491, 2.7291468284337927e-18) + 171 | DD(0.022605741241803316, 6.327981810377862e-19)*x) *x)*x)*x)*x)*x 172 | end 173 | @inline atan3to4of64(x::DD) = atan3to4numer(x) / atan3to4denom(x) 174 | 175 | 176 | 177 | function atan4to5numer(x::DD) 178 | DD(3.4986867510923863e-19, -4.80043199494538e-37) + 179 | (DD(0.9773577630727862, 4.222541831019509e-17) + 180 | (DD(0.224611377881578, -1.1083500370099093e-17) + 181 | (DD(1.0308599673016396, 2.2802867037807203e-17) + 182 | (DD(0.17625799155210703, 1.3836582834436884e-17) + 183 | (DD(0.20805322134678086, 6.198168426557029e-18) + 184 | DD(0.015630212957401312, 1.880151741876803e-19)*x) *x)*x)*x)*x)*x 185 | end 186 | function atan4to5denom(x::DD) 187 | DD(0.9773577630727863, -3.6247738309496816e-18) + 188 | (DD(0.2246113778815724, -5.126755876468263e-18) + 189 | (DD(1.3566458883261958, -3.8674444538119656e-17) + 190 | (DD(0.2511284508354467, -2.5250079300540653e-17) + 191 | (DD(0.4647969651117322, 2.5993613189837385e-17) + 192 | (DD(0.05441741583246426, 1.5779355560437385e-18) + 193 | DD(0.023225755314791163, 8.965019269474856e-19)*x) *x)*x)*x)*x)*x 194 | end 195 | @inline atan4to5of64(x::DD) = atan4to5numer(x) / atan4to5denom(x) 196 | 197 | function atan5to6numer(x::DD) 198 | DD(4.724665895731685e-18, 3.197057622132749e-35) + 199 | (DD(0.9664297227423516, 4.7174145325688815e-17) + 200 | (DD(0.27128902188603604, -7.050713460875651e-18) + 201 | (DD(1.0309596465202269, 1.3983478441412103e-17) + 202 | (DD(0.21381562993695888, 7.849093812371462e-20) + 203 | (DD(0.21190211439467507, -1.3818021586137387e-17) + 204 | DD(0.01912954892540732, 1.2767502839033025e-18)*x) *x)*x)*x)*x)*x 205 | end 206 | function atan5to6denom(x::DD) 207 | DD(0.9664297227423524, -1.0951441920954721e-17) + 208 | (DD(0.2712890218859855, 1.419338629146824e-17) + 209 | (DD(1.3531028874365107, 6.755197286060292e-17) + 210 | (DD(0.3042453038355929, 2.6438459401187718e-17) + 211 | (DD(0.46965046699213003, -2.035931360386614e-17) + 212 | (DD(0.06628682504089098, 5.214516757590902e-18) + 213 | DD(0.02399120987040229, -2.370266164091456e-20)*x) *x)*x)*x)*x)*x 214 | end 215 | @inline atan5to6of64(x::DD) = atan5to6numer(x) / atan5to6denom(x) 216 | 217 | #= 218 | function atan6to7numer(x::DD) 219 | DD(4.08258884792285e-17, 1.9801226085996085e-33) + 220 | (DD(0.9535145413823523, -5.236875025807137e-19) + 221 | (DD(0.3160973631452324, 1.2845795833188462e-17) + 222 | (DD(1.0309096536691162, -7.345625130452875e-17) + 223 | (DD(0.25042597049018966, 7.039911798136601e-18) + 224 | (DD(0.21640553613902666, 1.2514546576627358e-18) + 225 | DD(0.022641480101284518, -1.4107627307355407e-18)*x) *x)*x)*x)*x)*x 226 | end 227 | function atan6to7denom(x::DD) 228 | DD(0.9535145413823575, 3.63393809486893e-17) + 229 | (DD(0.31609736314492026, -7.114941540056584e-18) + 230 | (DD(1.3487478341412331, 1.244385774499147e-17) + 231 | (DD(0.35579175792476014, 2.5929154529266115e-17) + 232 | (DD(0.4752852442377697, 1.9402468748279948e-17) + 233 | (DD(0.07801919424133187, -2.3738530590672923e-19) + 234 | DD(0.024895861851288902, -5.072156320295304e-19)*x) *x)*x)*x)*x)*x 235 | end 236 | @inline atan6to7of64(x::DD) = atan6to7numer(x) / atan6to7denom(x) 237 | =# 238 | 239 | function atan6to7numer(x::DD) 240 | DD(-1.0415085111722597e-19, -5.395102486091432e-36) + 241 | (DD(0.9462153358439911, -2.831401300378913e-17) + 242 | (DD(0.36126832267059383, 7.66314484633861e-18) + 243 | (DD(1.2775709776413058, -4.5201332076330683e-17) + 244 | (DD(0.3793593264332555, -1.9726308973556664e-17) + 245 | (DD(0.4252136862797208, 1.5736094412320355e-17) + 246 | (DD(0.07602702590216374, 3.85069313300002e-18) + 247 | DD(0.020647468580854707, 1.5575316780473585e-18)*x) *x)*x)*x)*x)*x)*x 248 | end 249 | function atan6to7denom(x::DD) 250 | DD(0.9462153358439911, -4.3782190107136284e-17) + 251 | (DD(0.3612683226705949, 2.496531220033659e-17) + 252 | (DD(1.5929760895892568, -8.615747353570366e-17) + 253 | (DD(0.4997821006581529, 2.632573078802357e-18) + 254 | (DD(0.7669626489442688, 1.5683319304926968e-17) + 255 | (DD(0.17036739541120313, 1.3669564178288488e-17) + 256 | (DD(0.09288008014809244, -3.2854050411161694e-19) + 257 | DD(0.008442533659821153, -4.3713113100221436e-21)*x) *x)*x)*x)*x)*x)*x 258 | end 259 | @inline atan6to7of64(x::DD) = atan6to7numer(x) / atan6to7denom(x) 260 | 261 | 262 | # for 1 <= |x| < 1+1/320 = 1.003125 263 | function acscNear1(x::DD) 264 | dz = abs(x) - 1.0 265 | sdz = sqrt(dz) 266 | s2 = FLOAT128.dd_sqrt2 267 | p2 = FLOAT128.dd_pi_over_2 268 | a = acscNear1inner(dz) 269 | b = a * sdz 270 | b = b * s2 271 | c = b / 28745297418623385600.0 272 | c = -c 273 | d = c + p2 274 | d 275 | end 276 | 277 | 278 | 279 | function acscNear1inner(z::DD) 280 | 28745297418623385600+(-11977207257759744000+(7725298681255034880+(-5678479512384307200+(4471178803124633600+(-3678333901524172800+(3120230290312396800+(-2707335706710835200+(2390122732757760000+(-2139078913747776000+(1935592642417262400+(-1767382875804546000+1626037491584404899*dz)*dz)*dz)*dz)*dz)*dz)*dz)*dz)*dz)*dz)*dz)*dz 281 | end 282 | 283 | 284 | # recheck for 1.003125 <= |x| < 1.005 285 | function acsc(x::DD) 286 | isneg, abs_x = signbit(x), abs(x) 287 | if abs_x.hi < 1.0 288 | throw(ErrorException("acsc: Argument out of domain.")) 289 | return dd_NaN 290 | end 291 | # if abs_x.hi <= 1.003125 # 1+1/320 292 | # ac = acscNear1(abs_x) 293 | if abs_x.hi > 1.005 294 | ac = asin(1.0/abs_x) 295 | else 296 | ac = acscNear1(abs_x) 297 | end 298 | isneg ? -ac : ac 299 | end 300 | 301 | 302 | function asecNear1(z::DD) 303 | dz = z - one(DD) 304 | v = 1.0+(-DD(5)/DD(12)+(DD(43)/DD(160)+(-DD(177)/DD(896)+(DD(2867)/DD(18432)+(-DD(11531)/DD(90112)+(DD(92479)/DD(851968)+(-DD(74069)/DD(786432)+(DD(11857475)/DD(142606336)+(-DD(47442055)/DD(637534208)+(DD(126527543)/DD(1879048192)+(-DD(1518418695)/DD(24696061952)+(DD(24295375159)/DD(429496729600)-DD(97182800711)*dz*(DD(1.0)/DD(1855425871872.0)))*dz)*dz)*dz)*dz)*dz)*dz)*dz)*dz)*dz)*dz)*dz)*dz 305 | w = v * dd_sqrt2 306 | w = w *sqrt(dz) 307 | w 308 | end 309 | 310 | function asec(x::DD) 311 | isneg, abs_x = signbit(x), abs(x) 312 | if abs_x.hi < 1.0 313 | throw(ErrorException("acsc: Argument out of domain.")) 314 | return dd_NaN 315 | end 316 | if abs_x.hi > 1.005 317 | ac = acos(1.0/abs_x) 318 | else 319 | ac = asecNear1(abs_x) 320 | end 321 | isneg ? DD(td_pi-ac) : ac 322 | end 323 | 324 | 325 | acot(x::DD) = flipsign(dd_pi_over_2,x.hi) - atan(1.0/x) 326 | -------------------------------------------------------------------------------- /src/const/TD.jl: -------------------------------------------------------------------------------- 1 | const td_INF = TD(Inf,NaN,NaN); 2 | const td_NaN = TD(NaN,NaN,NaN); 3 | 4 | const td_zero = TD(0.0,0.0,0.0); 5 | const td_one = TD(1.0,0.0,0.0); 6 | const td_two = TD(2.0,0.0,0.0); 7 | const td_three = TD(3.0,0.0,0.0); 8 | const td_four = TD(4.0,0.0,0.0); 9 | 10 | const td_half = TD(0.5,0.0,0.0); 11 | const td_third = TD(0.3333333333333333, 1.850371707708594e-17, 1.0271626370065257e-33); 12 | const td_qrtr = TD(0.25,0.0,0.0); 13 | 14 | const td_sqrt2 = TD(1.4142135623730951,-9.667293313452913e-17,4.1386753086994136e-33); 15 | const td_sqrt2_over_2 = TD(0.7071067811865476,-4.833646656726457e-17,2.0693376543497068e-33); 16 | 17 | const td_twopi = TD(6.283185307179586,2.4492935982947064e-16,-5.989539619436679e-33); 18 | const td_twopi_part2 = TD(2.2249084417267306e-49,1.1344463959280631e-65,3.489972432270497e-83); 19 | const td_twopi_part3 = TD(1.205874546449908e-99,3.82024709375998e-116,6.0879563306885866e-133); 20 | const td_twopi_part4 = TD(-9.428600061894058e-150,2.0030983388710778e-166,1.242080895683179e-182); 21 | 22 | const td_1_over_twopi = TD(0.15915494309189535,-9.839338337591243e-18,-5.360718141446502e-34); 23 | const td_1_over_twopi_part2 = TD(4.026781963297056e-50,-7.801382953409857e-67,1.4185069655957361e-83); 24 | const td_1_over_twopi_part3 = TD(-7.836906288373592e-100,-1.908123641189411e-116,6.3800543877747325e-133); 25 | const td_1_over_twopi_part4 = TD(-5.782807470788813e-150,-1.9717385086233606e-166,1.3535321672928907e-182); 26 | 27 | const td_pi = TD(3.141592653589793,1.2246467991473532e-16,-2.9947698097183397e-33); 28 | const td_pi_part1 = TD(1.1124542208633653e-49,5.672231979640316e-66,1.7449862161352486e-83); 29 | const td_pi_part2 = TD(6.02937273224954e-100,1.91012354687999e-116,3.0439781653442933e-133); 30 | const td_pi_part3 = TD(-4.714300030947029e-150,1.0015491694355389e-166,6.210404478415895e-183); 31 | 32 | const td_1_over_pi = TD(0.3183098861837907,-1.9678676675182486e-17,-1.0721436282893004e-33); 33 | const td_1_over_pi_part2 = TD(8.053563926594112e-50,-1.5602765906819714e-66,2.8370139311914723e-83); 34 | const td_1_over_pi_part3 = TD(-1.5673812576747183e-99,-3.816247282378822e-116,1.2760108775549465e-132); 35 | const td_1_over_pi_part4 = TD(-1.1565614941577626e-149,-3.943477017246721e-166,2.7070643345857814e-182); 36 | 37 | const td_pi_over_2 = TD(1.5707963267948966,6.123233995736766e-17,-1.4973849048591698e-33); 38 | const td_pi_over_2_part2 = TD(5.562271104316826e-50,2.836115989820158e-66,8.724931080676243e-84); 39 | const td_pi_over_2_part3 = TD(3.01468636612477e-100,9.55061773439995e-117,1.5219890826721466e-133); 40 | const td_pi_over_2_part4 = TD(-2.3571500154735144e-150,5.0077458471776946e-167,3.1052022392079474e-183); 41 | 42 | const td_2_over_pi = TD(0.6366197723675814,-3.935735335036497e-17,-2.1442872565786008e-33); 43 | const td_2_over_pi_part2 = TD(1.6107127853188224e-49,-3.1205531813639427e-66,5.6740278623829445e-83); 44 | const td_2_over_pi_part3 = TD(-3.1347625153494367e-99,-7.632494564757644e-116,2.552021755109893e-132); 45 | const td_2_over_pi_part4 = TD(-2.3131229883155252e-149,-7.886954034493443e-166,5.414128669171563e-182); 46 | 47 | const td_pi_over_4 = TD(0.7853981633974483,3.061616997868383e-17,-7.486924524295849e-34); 48 | const td_pi_over_4_part2 = TD(2.781135552158413e-50,1.418057994910079e-66,4.3624655403381215e-84); 49 | const td_pi_over_4_part3 = TD(1.507343183062385e-100,4.775308867199975e-117,7.609945413360733e-134); 50 | const td_pi_over_4_part4 = TD(-1.1785750077367572e-150,2.5038729235888473e-167,1.5526011196039737e-183); 51 | 52 | const td_4_over_pi = TD(1.2732395447351628,-7.871470670072994e-17,-4.2885745131572016e-33); 53 | const td_4_over_pi_part2 = TD(3.2214255706376448e-49,-6.241106362727885e-66,1.1348055724765889e-82); 54 | const td_4_over_pi_part3 = TD(-6.269525030698873e-99,-1.5264989129515288e-115,5.104043510219786e-132); 55 | const td_4_over_pi_part4 = TD(-4.6262459766310504e-149,-1.5773908068986885e-165,1.0828257338343126e-181); 56 | 57 | const td_pi_over_6 = TD(0.5235987755982989,-5.360408832255455e-17,-4.991283016197232e-34); 58 | const td_pi_over_6_part2 = TD(-3.8478076800910752e-50,9.453719966067193e-67,-4.10175144032351e-83); 59 | const td_pi_over_6_part3 = TD(-5.091037298130543e-100,2.0103151493570977e-116,9.899601237381739e-133); 60 | const td_pi_over_6_part4 = TD(5.731480903641318e-150,1.0713677121117652e-166,1.0350674130693159e-183); 61 | 62 | const td_6_over_pi = TD(1.909859317102744,-7.049757588579267e-18,-2.698859476966472e-34); 63 | const td_6_over_pi_part2 = TD(1.2807246619420275e-50,1.3390820166797071e-67,5.4989930085114005e-84); 64 | const td_6_over_pi_part3 = TD(-2.6038841579011045e-100,2.4819346788835604e-116,-7.969791235122422e-133); 65 | const td_6_over_pi_part4 = TD(-6.939368964946576e-149,1.9752394722400094e-165,-7.856812643514153e-182); 66 | 67 | 68 | #= 69 | julia> show(nearest12((BigFloat(pi)/BigFloat(3)))) 70 | [1.0471975511965979,-1.072081766451091e-16,-9.982566032394464e-34,-7.6956153601821505e-50,1.8907439932134387e-66,-8.20350288064702e-83,-1.0182074596261087e-99,4.0206302987141954e-116,1.9799202474763478e-132,1.1462961807282637e-149,2.1427354242235305e-166,2.0701348261386317e-183] 71 | julia> show(nearest12((BigFloat(3)/BigFloat(pi)))) 72 | [0.954929658551372,-3.524878794289634e-18,-1.349429738483236e-34,6.403623309710137e-51,6.695410083398536e-68,2.7494965042557002e-84,-1.3019420789505522e-100,1.2409673394417802e-116,-3.984895617561211e-133,-3.469684482473288e-149,9.876197361200047e-166,-3.9284063217570764e-182] 73 | julia> show(nearest12((BigFloat(pi)/BigFloat(6)))) 74 | [0.5235987755982989,-5.360408832255455e-17,-4.991283016197232e-34,-3.8478076800910752e-50,9.453719966067193e-67,-4.10175144032351e-83,-5.091037298130543e-100,2.0103151493570977e-116,9.899601237381739e-133,5.731480903641318e-150,1.0713677121117652e-166,1.0350674130693159e-183] 75 | julia> show(nearest12((BigFloat(6)/BigFloat(pi)))) 76 | [1.909859317102744,-7.049757588579267e-18,-2.698859476966472e-34,1.2807246619420275e-50,1.3390820166797071e-67,5.4989930085114005e-84,-2.6038841579011045e-100,2.4819346788835604e-116,-7.969791235122422e-133,-6.939368964946576e-149,1.9752394722400094e-165,-7.856812643514153e-182] 77 | julia> show(nearest12((BigFloat(pi)/BigFloat(5)))) 78 | [0.6283185307179586,2.4492935982947062e-17,1.2499387846680786e-33,-8.038508045027301e-50,-7.646671532238966e-67,-2.2865522425805812e-83,1.5836113154863027e-99,6.473085118933557e-116,-5.574483362587728e-132,-3.0594770653798993e-148,-8.554087239722672e-165,3.68754860323873e-181] 79 | julia> show(nearest12((BigFloat(5)/BigFloat(pi)))) 80 | [1.5915494309189533,6.814007031786105e-17,8.02257680592653e-34,6.056431343790455e-50,1.6941847923499422e-66,-1.2170425202118948e-82,-5.21786984167032e-100,1.2222982866310839e-116,-6.641492695935352e-133,2.0378296197701747e-149,1.9892433267066045e-166,1.4857223474144868e-182] 81 | 82 | julia> show(nearest12((BigFloat(3)*BigFloat(pi)/BigFloat(2)))) 83 | [4.71238898038469,1.8369701987210297e-16,7.8337969295008e-33,-5.173596326540973e-49,-9.872197762993251e-67,2.617479324202873e-83,-9.24373916214209e-100,7.941068994951284e-116,-2.361084738145663e-132,-1.048294136784079e-148,5.30555662348863e-165,3.5574158732616345e-181] 84 | julia> show(nearest12(BigFloat(2)/(BigFloat(3)*BigFloat(pi)))) 85 | [0.2122065907891938,-1.3119117783454992e-17,3.1240021814699226e-34,-1.7583299425164472e-50,-2.48887081641331e-67,-3.0494861737871094e-84,2.1867393413644398e-101,-1.1197059415838415e-117,-2.985153880106913e-134,-1.1932123855859277e-150,8.434387345304554e-168,1.6097156509474174e-184] 86 | julia> show(nearest12((BigFloat(3)*BigFloat(pi)/BigFloat(4)))) 87 | [2.356194490192345,9.184850993605148e-17,3.9168984647504e-33,-2.5867981632704864e-49,-4.9360988814966257e-67,1.3087396621014365e-83,-4.621869581071045e-100,3.970534497475642e-116,-1.1805423690728315e-132,-5.241470683920395e-149,2.652778311744315e-165,1.7787079366308172e-181] 88 | julia> show(nearest12(BigFloat(4)/(BigFloat(3)*BigFloat(pi)))) 89 | [0.4244131815783876,-2.6238235566909983e-17,6.248004362939845e-34,-3.5166598850328943e-50,-4.97774163282662e-67,-6.098972347574219e-84,4.3734786827288795e-101,-2.239411883167683e-117,-5.970307760213826e-134,-2.3864247711718553e-150,1.6868774690609108e-167,3.219431301894835e-184] 90 | 91 | julia> show(nearest12(sqrt(BigFloat(2))/BigFloat(1))) 92 | [1.4142135623730951,-9.667293313452913e-17,4.1386753086994136e-33,4.935546991468351e-50,4.089404286119896e-67,3.1055431288249333e-84,-2.0011002671060812e-100,3.0645041147508584e-117,-1.4729864856186786e-133,1.504917262578619e-150,9.280552860423338e-167,1.3043309260509205e-184] 93 | julia> show(nearest12(sqrt(BigFloat(2))/BigFloat(2))) 94 | [0.7071067811865476,-4.833646656726457e-17,2.0693376543497068e-33,2.4677734957341755e-50,2.044702143059948e-67,1.5527715644124667e-84,-1.0005501335530406e-100,1.5322520573754292e-117,-7.364932428093393e-134,7.524586312893094e-151,4.640276430211669e-167,6.521654630254602e-185] 95 | julia> show(nearest12(BigFloat(1)/sqrt(BigFloat(2)))) 96 | [0.7071067811865476,-4.833646656726457e-17,2.0693376543497068e-33,2.4677734957341755e-50,2.044702143059948e-67,1.5527715644124667e-84,-1.0005501335530406e-100,1.5322520573754292e-117,-7.364932428093393e-134,7.524586312893094e-151,4.640276430211669e-167,6.521654630254602e-185] 97 | julia> show(nearest12(BigFloat(2)/sqrt(BigFloat(2)))) 98 | [1.4142135623730951,-9.667293313452913e-17,4.1386753086994136e-33,4.935546991468351e-50,4.089404286119896e-67,3.1055431288249333e-84,-2.0011002671060812e-100,3.0645041147508584e-117,-1.4729864856186786e-133,1.504917262578619e-150,9.280552860423338e-167,1.3043309260509205e-184] 99 | 100 | julia> show(nearest12(sqrt(BigFloat(3))/BigFloat(1))) 101 | [1.7320508075688772,1.0035084221806903e-16,-1.4959542475733896e-33,5.306147563296169e-50,2.686605845246563e-66,-2.478595051888445e-83,-7.783621362768524e-100,-5.125396118761882e-117,1.4420754924753193e-133,8.009939182654853e-150,2.4065689666180262e-166,-3.9266419386801074e-183] 102 | julia> show(nearest12(sqrt(BigFloat(3))/BigFloat(2))) 103 | [0.8660254037844386,5.0175421109034514e-17,-7.479771237866948e-34,2.6530737816480847e-50,1.3433029226232816e-66,-1.2392975259442224e-83,-3.891810681384262e-100,-2.562698059380941e-117,7.2103774623765965e-134,4.0049695913274265e-150,1.2032844833090131e-166,-1.9633209693400537e-183] 104 | julia> show(nearest12(BigFloat(1)/sqrt(BigFloat(3)))) 105 | [0.5773502691896257,3.3450280739356345e-17,-2.552976689870848e-33,-1.5336978290157996e-49,7.225913778922053e-66,1.6744131554754725e-82,-1.3670506103137645e-98,6.073975755828352e-115,-3.235526764081152e-131,-4.796026408569193e-148,-1.113487238113184e-164,-7.845328368046641e-181] 106 | julia> show(nearest12(BigFloat(2)/sqrt(BigFloat(3)))) 107 | [1.1547005383792515,6.690056147871269e-17,-5.105953379741696e-33,-3.0673956580315993e-49,1.4451827557844107e-65,3.348826310950945e-82,-2.734101220627529e-98,1.2147951511656704e-114,-6.471053528162304e-131,-9.592052817138386e-148,-2.226974476226368e-164,-1.5690656736093281e-180] 108 | 109 | sin(pi) = 0 110 | cos(pi) = -1 111 | 112 | sin(pi/2) = 1 113 | cos(pi/2) = 0 114 | 115 | sin(pi/3) = sqrt(3)/2 116 | cos(pi/3) = 1/2 117 | tan(pi/3) = sqrt(3) 118 | 119 | sin(pi/4) = 1/sqrt(2) 120 | cos(pi/4) = 1/sqrt(2) 121 | tan(pi/4) = 1 122 | 123 | sin(pi/6) = 1/2 124 | cos(pi/6) = sqrt(3)/2 125 | julia> show(nearest12(sqrt(BigFloat(3))/(BigFloat(2)))) 126 | [0.8660254037844386,5.0175421109034514e-17,-7.479771237866948e-34,2.6530737816480847e-50,1.3433029226232816e-66,-1.2392975259442224e-83,-3.891810681384262e-100,-2.562698059380941e-117,7.2103774623765965e-134,4.0049695913274265e-150,1.2032844833090131e-166,-1.9633209693400537e-183] 127 | tan(pi/6) = sqrt(3)/3 128 | julia> show(nearest12(sqrt(BigFloat(3))/(BigFloat(3)))) 129 | [0.5773502691896257,3.3450280739356345e-17,-2.552976689870848e-33,-1.5336978290157996e-49,7.225913778922053e-66,1.6744131554754725e-82,-1.3670506103137645e-98,6.073975755828352e-115,-3.235526764081152e-131,-4.796026408569193e-148,-1.113487238113184e-164,-7.845328368046641e-181] 130 | 131 | 132 | sin(pi/8) 133 | julia> show(nearest12((BigFloat(1)/BigFloat(2)) * sqrt(BigFloat(2)-sqrt(BigFloat(2))))) 134 | [0.3826834323650898,-1.0050772696461588e-17,-2.0605316302806695e-34,-1.2717724698085205e-50,6.07736561771507e-67,-2.1821363367516415e-83,-8.425012284574326e-100,-4.5503869186161457e-116,-5.591112023385709e-133,1.3150133448545305e-149,1.802489770558483e-166,7.111804894055096e-184] 135 | cos(pi/8) 136 | julia> show(nearest12((BigFloat(1)/BigFloat(2)) * sqrt(BigFloat(2)+sqrt(BigFloat(2))))) 137 | [0.9238795325112867,1.7645047084336677e-17,-5.044253732158682e-34,-4.047867771682389e-50,1.3173523970020108e-66,6.543753201571042e-84,-1.427642619125978e-100,-3.887510157422329e-117,-3.021809439424338e-133,1.7591631811711491e-149,-5.34882231789441e-166,1.893065482982587e-182] 138 | tan(pi/8) 139 | julia> show(nearest12((sqrt(BigFloat(2))-(BigFloat(1))))) 140 | [0.41421356237309503,1.4349369327986523e-17,1.0571873976798362e-33,4.935546991468351e-50,4.089404286119896e-67,3.1055431288249333e-84,-2.0011002671060812e-100,3.0645041147508584e-117,-1.4729864856186786e-133,1.504917262578619e-150,9.280552860423338e-167,1.3043309260509205e-184] 141 | 142 | 143 | 144 | sin(pi/16) 145 | julia> show(nearest12((BigFloat(1)/BigFloat(2)) * sqrt(BigFloat(2)-sqrt(BigFloat(2)+sqrt(BigFloat(2)))))) 146 | [0.19509032201612828,-7.991079068461731e-18,6.184627002422071e-34,-3.5840270918032937e-50,-9.074039009264558e-67,-3.410559543738882e-83,9.54337952630623e-100,2.3683460820397133e-117,6.001758402018202e-134,2.894375516755034e-150,2.449106959163259e-166,9.695488080244684e-183] 147 | cos(pi/16) 148 | julia> show(nearest12((BigFloat(1)/BigFloat(2)) * sqrt(BigFloat(2)+sqrt(BigFloat(2)+sqrt(BigFloat(2)))))) 149 | [0.9807852804032304,1.8546939997825006e-17,-1.0696564445530757e-33,6.666817447526496e-50,1.2501990621733019e-66,4.295638407155668e-83,2.4794654864787234e-99,-3.382179249748847e-116,-7.91772466310557e-133,1.0080940625638324e-149,-7.453495384798237e-167,1.932376157412539e-184] 150 | tan(pi/16) 151 | julia> show(nearest12( (sqrt(BigFloat(4)+BigFloat(2)*sqrt(BigFloat(2)))-sqrt(2)-BigFloat(1)) )) 152 | [0.19891236737965792,-1.2567026839878736e-17,1.1978688302191833e-34,5.1778357386963955e-52,-7.396479167882488e-69,3.301252049174257e-85,-2.7452415560193433e-101,-4.375124911861667e-118,3.846662178005746e-134,-2.0591458402781862e-150,1.0473205601807245e-166,-5.902326832216319e-183] 153 | 154 | sin(pi/32) 155 | julia> show(nearest12((BigFloat(1)/BigFloat(2)) * sqrt(BigFloat(2)-sqrt(BigFloat(2)+sqrt(BigFloat(2)+sqrt(BigFloat(2))))))) 156 | [0.0980171403295606,-1.634582362244256e-18,-1.3209238810006454e-35,-3.569106004911794e-52,-2.8087056039524763e-70,-8.565900190239358e-87,6.488423446302344e-103,5.713942397896779e-120,-8.532797727638847e-137,4.826908583968972e-154,1.6328578155478691e-170,6.360887535810713e-187] 157 | cos(pi/32) 158 | julia> show(nearest12((BigFloat(1)/BigFloat(2)) * sqrt(BigFloat(2)+sqrt(BigFloat(2)+sqrt(BigFloat(2)+sqrt(BigFloat(2))))))) 159 | [0.9951847266721969,-4.248691367830441e-17,1.3315510772504614e-33,6.792798741705189e-50,2.6171612305270163e-66,2.5453570401846227e-82,-1.4043434514349089e-98,6.6134846992549765e-115,-2.722831046609068e-132,-1.0786660740504391e-148,4.3149585939657513e-165,-1.2189021450459404e-181] 160 | tan(pi/32) 161 | [0.09849140335716425,5.3100671162822435e-18,4.941260674704094e-35,5.957275980152265e-52,5.686766613520323e-69,-3.7129037063090346e-86,-9.485658360207005e-104,-8.233391132711167e-121,2.634351835390479e-137,-1.345840728141883e-153,-1.3185084435270653e-169,-5.356499339839059e-186] 162 | 163 | =# 164 | 165 | const td_3pi_over_2 = TD((4.71238898038469, 1.8369701987210297e-16, 7.8337969295008e-33)); 166 | const td_2_over_3pi = TD(0.2122065907891938, -1.3119117783454992e-17, 3.1240021814699226e-34); 167 | const td_3pi_over_4 = TD(2.356194490192345,9.184850993605148e-17,3.9168984647504e-33); 168 | const td_4_over_3pi = TD(0.4244131815783876,-2.6238235566909983e-17,6.248004362939845e-34); 169 | 170 | const td_pi_over_1024 = TD(0.0030679615757712823,1.195944139792337e-19,-2.924579892303066e-36); 171 | const td_1024_over_pi = TD(325.94932345220167,-2.0150964915386866e-14,-1.0978750753682436e-30); 172 | 173 | const td_exp1 = TD(2.718281828459045,1.4456468917292502e-16,-2.1277171080381768e-33); 174 | const td_log10 = TD(2.302585092994046,-2.1707562233822494e-16,-9.984262454465777e-33); 175 | 176 | 177 | const td_log2 = TD(0.6931471805599453,2.3190468138462996e-17,5.707708438416212e-34); 178 | const td_log2_part2 = TD(-3.5824322106018114e-50,-1.352169675798863e-66,6.080638740240814e-83); 179 | const td_log2_part3 = TD(2.8955024332347147e-99,2.351386712145641e-116,4.459774417014281e-133); 180 | const td_log2_part4 = TD(-3.069933263232527e-149,-2.0151474461966832e-165,1.618534348863741e-182); 181 | 182 | const td_1_over_log2 = TD(1.4426950408889634,2.0355273740931033e-17,-1.0614659956117258e-33); 183 | const td_1_over_log2_part2 = TD(-1.3836716780181402e-50,9.509563257128724e-67,-6.180554812704206e-83); 184 | const td_1_over_log2_part3 = TD(3.1030020372190077e-99,1.9878535252881986e-115,-1.0831099991141439e-131); 185 | const td_1_over_log2_part4 = TD(-3.203979090649315e-148,-2.9562641491137693e-164,1.8478736774682608e-180); 186 | 187 | 188 | const td_sin_3pi_over_8 = TD(0.9238795325112867, 1.7645047084336677e-17, -5.044253732158682e-34); 189 | const td_cos_3pi_over_8 = TD(0.3826834323650898, -1.0050772696461588e-17, -2.0605316302806695e-34); 190 | -------------------------------------------------------------------------------- /src/exp/DD.jl: -------------------------------------------------------------------------------- 1 | 2 | const dd_n_inv_fact = 32; 3 | const dd_inv_fact = DD[ 4 | DD(1.0,0.0), 5 | DD(0.5,0.0), 6 | DD(0.16666666666666666,9.25185853854297e-18), 7 | DD(0.041666666666666664,2.3129646346357427e-18), 8 | DD(0.008333333333333333,1.1564823173178714e-19), 9 | DD(0.001388888888888889,-5.300543954373577e-20), 10 | DD(0.0001984126984126984,1.7209558293420705e-22), 11 | DD(2.48015873015873e-5,2.1511947866775882e-23), 12 | DD(2.7557319223985893e-6,-1.858393274046472e-22), 13 | DD(2.755731922398589e-7,2.3767714622250297e-23), 14 | DD(2.505210838544172e-8,-1.448814070935912e-24), 15 | DD(2.08767569878681e-9,-1.20734505911326e-25), 16 | DD(1.6059043836821613e-10,1.2585294588752098e-26), 17 | DD(1.1470745597729725e-11,2.0655512752830745e-28), 18 | DD(7.647163731819816e-13,7.03872877733453e-30), 19 | DD(4.779477332387385e-14,4.399205485834081e-31), 20 | DD(2.8114572543455206e-15,1.6508842730861433e-31), 21 | DD(1.5619206968586225e-16,1.1910679660273754e-32), 22 | DD(8.22063524662433e-18,2.2141894119604265e-34), 23 | DD(4.110317623312165e-19,1.4412973378659527e-36), 24 | DD(1.9572941063391263e-20,-1.3643503830087908e-36), 25 | DD(8.896791392450574e-22,-7.911402614872376e-38), 26 | DD(3.868170170630684e-23,-8.843177655482344e-40), 27 | DD(1.6117375710961184e-24,-3.6846573564509766e-41), 28 | DD(6.446950284384474e-26,-1.9330404233703465e-42), 29 | DD(2.4795962632247976e-27,-1.2953730964765229e-43), 30 | DD(9.183689863795546e-29,1.4303150396787322e-45), 31 | DD(3.279889237069838e-30,1.5117542744029879e-46), 32 | DD(1.1309962886447716e-31,1.0498015412959506e-47), 33 | DD(3.7699876288159054e-33,2.5870347832750324e-49), 34 | DD(1.216125041553518e-34,5.586290567888806e-51), 35 | DD(3.8003907548547434e-36,1.7457158024652518e-52) 36 | ]; 37 | 38 | 39 | const dd_n_exp_int = 256; 40 | const dd_exp_int = DD[ 41 | DD(2.718281828459045, 1.4456468917292502e-16), 42 | DD(7.38905609893065, -1.7971139497839148e-16), 43 | DD(20.085536923187668, -1.8275625525512858e-16), 44 | DD(54.598150033144236, 2.8741578015844115e-15), 45 | DD(148.4131591025766, 3.4863514900464198e-15), 46 | DD(403.4287934927351, 1.2359628024450387e-14), 47 | DD(1096.6331584284585, 9.869752640434095e-14), 48 | DD(2980.9579870417283, -2.7103295816873633e-14), 49 | DD(8103.083927575384, -2.1530877621067177e-13), 50 | DD(22026.465794806718, -1.3780134700517372e-12), 51 | DD(59874.14171519782, 1.7895764888916994e-12), 52 | DD(162754.79141900392, 5.30065881322063e-12), 53 | DD(442413.3920089205, 1.2118711752313224e-11), 54 | DD(1.2026042841647768e6, -1.5000525764327354e-11), 55 | DD(3.2690173724721107e6, -3.075806431120808e-11), 56 | DD(8.886110520507872e6, 5.321182483501564e-10), 57 | DD(2.41549527535753e7, -7.203995068362157e-10), 58 | DD(6.565996913733051e7, 1.4165536846555444e-9), 59 | DD(1.7848230096318725e8, 1.333018530234341e-8), 60 | DD(4.851651954097903e8, 4.880277289790406e-10), 61 | DD(1.3188157344832146e9, 8.043448618843281e-8), 62 | DD(3.584912846131592e9, -2.3519384005402157e-7), 63 | DD(9.744803446248903e9, -6.74501500127677e-7), 64 | DD(2.648912212984347e10, 7.670395527778119e-7), 65 | DD(7.200489933738588e10, -6.992440211033874e-6), 66 | DD(1.9572960942883878e11, -1.1364989227123904e-5), 67 | DD(5.3204824060179865e11, -2.8335783945658822e-5), 68 | DD(1.446257064291475e12, 7.602079742299693e-5), 69 | DD(3.931334297144042e12, 8.220112058084352e-5), 70 | DD(1.0686474581524463e13, -0.0007436345313492586), 71 | DD(2.9048849665247426e13, -0.0005501643178883202), 72 | DD(7.896296018268069e13, 0.007660978022635108), 73 | DD(2.1464357978591606e14, 0.002124297761531261), 74 | DD(5.834617425274549e14, 0.006402902734610391), 75 | DD(1.5860134523134308e15, -0.02187035537422534), 76 | DD(4.311231547115195e15, 0.22711342229285691), 77 | DD(1.1719142372802612e16, -0.6912270602088098), 78 | DD(3.1855931757113756e16, 0.22032867170129863), 79 | DD(8.659340042399374e16, 2.953606932719265), 80 | DD(2.3538526683702e17, -14.592100089250966), 81 | DD(6.398434935300549e17, 37.22266340351557), 82 | DD(1.739274941520501e18, 55.394681303611236), 83 | DD(4.727839468229346e18, 257.4744575627443), 84 | DD(1.2851600114359308e19, -12.1907003678569), 85 | DD(3.4934271057485095e19, 436.0347972334061), 86 | DD(9.496119420602448e19, 5929.133649117119), 87 | DD(2.5813128861900675e20, -15192.714199784727), 88 | DD(7.016735912097631e20, 30185.471599886117), 89 | DD(1.9073465724950998e21, -98786.90015904616), 90 | DD(5.184705528587072e21, 419031.45332293346), 91 | DD(1.4093490824269389e22, -614323.8566876298), 92 | DD(3.831008000716577e22, -661524.304512138), 93 | DD(1.0413759433029089e23, -7.520901270665062e6), 94 | DD(2.830753303274694e23, -4.711377645198593e6), 95 | DD(7.694785265142018e23, -3.868399744098706e7), 96 | DD(2.091659496012996e24, 5.079641515721467e7), 97 | DD(5.685719999335932e24, 2.0801558082063326e8), 98 | DD(1.545538935590104e25, 1.2092033491117463e8), 99 | DD(4.2012104037905144e25, -1.7624059056928084e9), 100 | DD(1.1420073898156842e26, 4.912247462314477e9), 101 | DD(3.10429793570192e26, 3.39761293411071e9), 102 | DD(8.438356668741454e26, 6.5719328084037315e10), 103 | DD(2.29378315946961e27, -7.566162968773138e10), 104 | DD(6.235149080811617e27, 1.3899738872492847e11), 105 | DD(1.6948892444103338e28, -6.61940830637628e11), 106 | DD(4.607186634331292e28, -2.37966706696394e12), 107 | DD(1.2523631708422137e29, 8.725173269482437e12), 108 | DD(3.404276049931741e29, -2.3689045745171566e13), 109 | DD(9.253781725587787e29, 4.1335361789492734e13), 110 | DD(2.515438670919167e30, 1.2647645018519611e14), 111 | DD(6.837671229762744e30, -2.8026814130938628e14), 112 | DD(1.8586717452841279e31, 9.331591492068494e14), 113 | DD(5.052393630276104e31, 2.4912292015869455e15), 114 | DD(1.3733829795401761e32, 8.003850355927158e15), 115 | DD(3.7332419967990015e32, 1.5538124781410182e16), 116 | DD(1.0148003881138887e33, -1.8313882415912828e16), 117 | DD(2.7585134545231703e33, -1.1490320660315066e17), 118 | DD(7.498416996990121e33, -4.7233584091570765e17), 119 | DD(2.0382810665126688e34, -5.7128185991424294e17), 120 | DD(5.54062238439351e34, 2.1811937023229343e18), 121 | DD(1.5060973145850306e35, -7.056987941853042e18), 122 | DD(4.0939969621274545e35, 1.852765937250624e19), 123 | DD(1.1128637547917594e36, -2.7961733453775843e19), 124 | DD(3.0250773222011426e36, -2.2396762302858075e20), 125 | DD(8.223012714622913e36, 4.083087026334775e20), 126 | DD(2.235246603734715e37, 7.328168204485786e20), 127 | DD(6.076030225056872e37, 2.4300525977303657e21), 128 | DD(1.6516362549940018e38, 4.5658363808236883e21), 129 | DD(4.4896128191743455e38, -3.034626837469501e22), 130 | DD(1.2204032943178408e39, -3.218018426639282e22), 131 | DD(3.317400098335743e39, -2.0594325391839645e23), 132 | DD(9.017628405034299e39, 4.119507937020878e23), 133 | DD(2.451245542920086e40, -1.809447119103778e24), 134 | DD(6.663176216410896e40, -3.5075886901816454e24), 135 | DD(1.8112390828890233e41, -6.613591371018036e24), 136 | DD(4.923458286012058e41, 1.3869835129739753e25), 137 | DD(1.3383347192042695e42, -3.8243050326463913e25), 138 | DD(3.637970947608805e42, -1.7059216189570308e26), 139 | DD(9.889030319346946e42, 5.152980735736938e26), 140 | DD(2.6881171418161356e43, -1.6101271449201627e27), 141 | DD(7.307059979368067e43, 3.81998468048638e27), 142 | DD(1.9862648361376543e44, -1.7687808052379885e27), 143 | DD(5.399227610580169e44, 1.6694477435363627e28), 144 | DD(1.4676622301554424e45, -5.683445805084399e28), 145 | DD(3.989519570547216e45, -4.528566832709381e28), 146 | DD(1.0844638552900231e46, -5.0737593474148365e29), 147 | DD(2.947878391455509e46, 1.522599815352173e30), 148 | DD(8.013164264000591e46, 4.4255712989469043e30), 149 | DD(2.1782038807290206e47, 6.40943286045652e30), 150 | DD(5.92097202766467e47, 3.6278506451438224e31), 151 | DD(1.609487066961518e48, -3.11348413350283e31), 152 | DD(4.375039447261341e48, 1.035824156236645e32), 153 | DD(1.189259022828201e49, -6.311799972004003e32), 154 | DD(3.2327411910848595e49, -1.6317210762547248e33), 155 | DD(8.787501635837023e49, 4.951878455668192e31), 156 | DD(2.3886906014249913e50, 1.5523479734981885e34), 157 | DD(6.493134255664462e50, 1.417967467778397e33), 158 | DD(1.7650168856917655e51, 3.659435419097009e34), 159 | DD(4.797813327299302e51, -4.832529827928807e34), 160 | DD(1.3041808783936323e52, 2.3598218061815903e35), 161 | DD(3.5451311827611664e52, 4.397256578106813e35), 162 | DD(9.636665673603202e52, -3.923912609184774e36), 163 | DD(2.6195173187490626e53, 9.508437015673215e36), 164 | DD(7.120586326889338e53, -2.2289404495948426e37), 165 | DD(1.9355760420357226e54, -1.8895773015758525e37), 166 | DD(5.261441182666386e54, -2.2391033592780024e38), 167 | DD(1.4302079958348105e55, -4.95219683040473e38), 168 | DD(3.887708405994595e55, 2.707966110366217e39), 169 | DD(1.0567887114362587e56, 1.0147572632726592e40), 170 | DD(2.872649550817832e56, -1.725105418010497e40), 171 | DD(7.808671073519151e56, -3.3393507820354276e39), 172 | DD(2.1226168683560893e57, 9.12124047520486e40), 173 | DD(5.769870862033003e57, 2.54679794252527e41), 174 | DD(1.568413511681964e58, -5.571295095061288e41), 175 | DD(4.263389948314721e58, 9.74205426058927e41), 176 | DD(1.1589095424138854e59, 3.107727800036786e42), 177 | DD(3.150242749971452e59, -9.643637210793454e42), 178 | DD(8.56324762248225e59, -5.908667317844348e43), 179 | DD(2.3277320404788622e60, -1.5410810390283507e44), 180 | DD(6.327431707155585e60, 2.9519976099018483e44), 181 | DD(1.7199742630376623e61, -6.6270661206611855e44), 182 | DD(4.675374784632515e61, 1.2938282778262074e45), 183 | DD(1.2708986318302189e62, -3.042168764740704e44), 184 | DD(3.454660656717546e62, 1.8553902103629043e46), 185 | DD(9.390741286647697e62, 8.372523060245978e46), 186 | DD(2.5526681395254553e63, -1.6889209515414619e47), 187 | DD(6.938871417758404e63, -4.174062699457691e47), 188 | DD(1.886180808490652e64, 8.75753845955151e47), 189 | DD(5.12717101690833e64, -1.848585500693908e47), 190 | DD(1.3937095806663797e65, 7.0244638077530874e47), 191 | DD(3.788495427274696e65, -1.6686420819293392e48), 192 | DD(1.0298198277160991e66, 8.608117819191599e49), 193 | DD(2.799340524267497e66, -8.50129047864975e49), 194 | DD(7.609396478785354e66, -1.2944224384739812e50), 195 | DD(2.0684484173822473e67, -2.743371829892203e50), 196 | DD(5.622625746075033e67, 1.4234908903412887e51), 197 | DD(1.5283881393781746e68, -8.309060391771288e51), 198 | DD(4.154589706104022e68, 2.1030987078913436e52), 199 | DD(1.129334570280557e69, -8.237338292837319e52), 200 | DD(3.0698496406442424e69, 4.375620509828095e52), 201 | DD(8.344716494264775e69, -5.967039946946015e53), 202 | DD(2.2683291210002403e70, 1.4059974118116153e54), 203 | DD(6.165957830579433e70, -5.480338773236432e54), 204 | DD(1.6760811125908828e71, -3.078670967159958e54), 205 | DD(4.556060831379215e71, 4.2683874443891194e55), 206 | DD(1.2384657367292132e72, -1.7417281417483923e55), 207 | DD(3.366498907320164e72, 1.8595557870731098e56), 208 | DD(9.151092805295634e72, 2.9278721984510905e56), 209 | DD(2.487524928317743e73, -2.269951231486326e56), 210 | DD(6.761793810485009e73, 6.044072970031212e57), 211 | DD(1.8380461242828246e74, 6.558763264761503e57), 212 | DD(4.996327379507578e74, 1.2022315866163456e58), 213 | DD(1.358142592474785e75, 6.293920858651693e58), 214 | DD(3.691814329580466e75, 1.5523424954077878e59), 215 | DD(1.0035391806143295e76, -1.600289359022275e59), 216 | DD(2.7279023188106115e76, 6.6492459414351406e59), 217 | DD(7.415207303034179e76, -4.678668371358611e60), 218 | DD(2.0156623266094611e77, 6.4049020966883044e60), 219 | DD(5.47913827473198e77, -3.839583545632845e61), 220 | DD(1.4893842007818383e78, 6.250487712624396e61), 221 | DD(4.048566008579269e78, 1.682018025551642e62), 222 | DD(1.1005143412437996e79, -6.764346497503176e62), 223 | DD(2.991508135761597e79, 1.1738879998058348e63), 224 | DD(8.131762205128143e79, -1.5057074349533377e62), 225 | DD(2.2104421435549888e80, -7.196700457953682e63), 226 | DD(6.008604711685586e80, -3.660345147820277e64), 227 | DD(1.633308100216833e81, -2.1239531351072146e64), 228 | DD(4.4397917290943824e81, -2.882962352721535e65), 229 | DD(1.2068605179340022e82, 7.151662509907955e65), 230 | DD(3.2805870153846705e82, -3.194753619685436e66), 231 | DD(8.917560070598843e82, -8.989668102219982e65), 232 | DD(2.4240441494100796e83, -3.8332753349400205e66), 233 | DD(6.589235162723882e83, -8.709570822927273e66), 234 | DD(1.7911398206275708e84, 5.99708494881663e67), 235 | DD(4.8688228266413195e84, 1.710917432346709e68), 236 | DD(1.3234832615645704e85, -6.425373409956827e68), 237 | DD(3.5976005001806814e85, -2.5813006529759342e69), 238 | DD(9.779292065696318e85, -6.6113382980943924e69), 239 | DD(2.658287191737602e86, 6.120064792143622e69), 240 | DD(7.225973768125749e86, 2.9945383505980016e70), 241 | DD(1.964223318681796e87, -1.0268429875036315e71), 242 | DD(5.339312554208246e87, -2.625028820065693e71), 243 | DD(1.4513756292567526e88, -2.884486923510417e71), 244 | DD(3.945247999276943e88, 7.221484370687266e70), 245 | DD(1.0724295945198918e89, 4.163246302178397e72), 246 | DD(2.9151658790851237e89, 2.656865521036125e73), 247 | DD(7.924242436060931e89, -4.347509662136458e73), 248 | DD(2.1540324218248465e90, 6.568050851363196e73), 249 | DD(5.855267190158109e90, 4.4915902036294956e74), 250 | DD(1.5916266403779241e91, 3.865065123172901e74), 251 | DD(4.326489774230631e91, 3.1789213685539743e74), 252 | DD(1.1760618534305e92, 5.894438850996908e75), 253 | DD(3.196867565323994e92, -1.9538627920591218e76), 254 | DD(8.689987010810322e92, -5.6063024973277287e76), 255 | DD(2.3621833781030834e93, -7.781526569884677e76), 256 | DD(6.421080152185614e93, -1.4034869476251672e77), 257 | DD(1.7454305496765193e94, 9.749159232851838e77), 258 | DD(4.744572146022966e94, -3.2789833020339664e78), 259 | DD(1.2897084248347162e95, 5.438670793036996e78), 260 | DD(3.505790975238748e95, 1.5415362493078123e78), 261 | DD(9.529727902367202e95, 9.833684415222857e78), 262 | DD(2.5904486187163903e96, -2.263041008869737e80), 263 | DD(7.041569407813597e96, -4.0828301614775564e80), 264 | DD(1.9140970165092822e97, -1.497464557916617e81), 265 | DD(5.2030551378848545e97, 4.749190808721398e80), 266 | DD(1.4143370233782872e98, 3.8946526873422757e80), 267 | DD(3.844566629966054e98, 2.2093533915053797e81), 268 | DD(1.0450615608536755e99, -5.337145484954864e82), 269 | DD(2.840771850489593e99, 2.7464976717218177e81), 270 | DD(7.722018499983836e99, -4.0996868440885443e83), 271 | DD(2.0990622567530634e100, 4.153001760319747e83), 272 | DD(5.705842789336087e100, -7.502847960571591e83), 273 | DD(5.705842789336087e100, -7.502847960571591e83), 274 | DD(1.551008877029636e101, -1.1711307176004477e85), 275 | DD(4.216079246208329e101, 3.4845354806957584e84), 276 | DD(1.146049160231141e102, 5.309475346149073e85), 277 | DD(3.115284606777059e102, 1.1305094460701447e86), 278 | DD(8.468221537080262e102, -2.2036277666109673e86), 279 | DD(2.30190127236108e103, -4.663183218411149e86), 280 | DD(6.25721639956588e103, -3.232721480812657e87), 281 | DD(1.700887763567586e104, 1.4773861394382237e88), 282 | DD(4.6234922999541146e104, 6.980490121714062e87), 283 | DD(1.2567955102985587e105, -1.5226136925021163e88), 284 | DD(3.416324397733485e105, -7.894999158901084e86), 285 | DD(9.286532530480224e105, -2.614355089326607e89), 286 | DD(2.5243412626998188e106, 7.770616368141536e88), 287 | DD(6.861870983226278e106, 2.54810635544448e90), 288 | DD(1.8652499202934394e107, 3.8378044485542437e90), 289 | DD(5.070274963868339e107, 1.2106757063676503e90), 290 | DD(1.3782436299574147e108, 8.797324501988005e91), 291 | DD(3.7464546145026734e108, -1.331977416683643e92), 292 | DD(1.0183919499749154e109, 3.760113287049303e92), 293 | DD(2.7682763318657856e109, -4.359593659827271e92), 294 | DD(7.524955249064026e109, 4.590038424351707e93), 295 | DD(2.045494911349825e110, 5.874933608518508e93), 296 | DD(5.5602316477276757e110, -2.3961412490467085e94), 297 | DD(1.5114276650041035e111, 1.4805989167614457e94) 298 | ]; 299 | 300 | function exp_taylor(a::DD) 301 | x = a 302 | x2 = x*x 303 | x3 = x*x2 304 | x4 = x2*x2 305 | x5 = x2*x3 306 | x10 = x5*x5 307 | x15 = x5*x10 308 | x20 = x10*x10 309 | x25 = x10*x15 310 | 311 | z = x + dd_inv_fact[2]*x2 + dd_inv_fact[3]*x3 + dd_inv_fact[4]*x4 312 | z2 = x5 * (dd_inv_fact[5] + x*dd_inv_fact[6] + x2*dd_inv_fact[7] + x3*dd_inv_fact[8] + x4*dd_inv_fact[9]) 313 | z3 = x10 * (dd_inv_fact[10] + x*dd_inv_fact[11] + x2*dd_inv_fact[12] + x3*dd_inv_fact[13] + x4*dd_inv_fact[14]) 314 | z4 = x15 * (dd_inv_fact[15] + x*dd_inv_fact[16] + x2*dd_inv_fact[17] + x3*dd_inv_fact[18] + x4*dd_inv_fact[19]) 315 | z5 = x20 * (dd_inv_fact[20] + x*dd_inv_fact[21] + x2*dd_inv_fact[22] + x3*dd_inv_fact[23] + x4*dd_inv_fact[24]) 316 | z6 = x25 * (dd_inv_fact[25] + x*dd_inv_fact[26] + x2*dd_inv_fact[27]) 317 | 318 | ((((z6+z5)+z4)+z3)+z2)+z + one(DD) 319 | end 320 | 321 | function exp01(a::DD) 322 | if a.hi >= 0.5 323 | sqr(exp_taylor(divby2(a))) 324 | else 325 | exp_taylor(a) 326 | end 327 | end 328 | 329 | function expGT0(a::DD) 330 | if a.hi < 1e-34 331 | return one(DD) 332 | elseif a.hi==1.0 && abs(a.lo) < 1e-34 333 | return dd_exp1 334 | end 335 | 336 | if a.hi > 1.0 337 | if a.hi <= 232.0 338 | ddidx = DD(floor(a.hi)) 339 | idx = floor(Int,a.hi) 340 | expint = dd_exp_int[idx] 341 | dlt = a - ddidx 342 | expdlt = exp01(dlt) 343 | expint*expdlt 344 | else 345 | t = a / 128.0 346 | ipart = floor(t).hi 347 | fpart = t - ipart 348 | fpart = fpart * 128.0 349 | intpart = trunc(Int,ipart) 350 | dd_exp_int[128]^intpart * exp(fpart) 351 | end 352 | else 353 | exp01(a) 354 | end 355 | end 356 | 357 | function exp(a::DD) 358 | isneg, aa = signbit(a.hi), abs(a) 359 | if a.hi == Inf 360 | return sb ? zero(DD) : a 361 | elseif a == zero(DD) 362 | return one(DD) 363 | end 364 | 365 | if aa.hi <= 0.0001220703125 # sqrt(sqrt(eps(1.0))) 366 | DD(exp_taylor(TD(a))) 367 | else 368 | z = expGT0(aa) 369 | isneg ? recip(z) : z 370 | end 371 | end 372 | 373 | 374 | function expm1(a::DD) 375 | u = exp(a) 376 | if (u == one(DD)) 377 | x 378 | elseif (u-1.0 == -one(DD)) 379 | -one(DD) 380 | else 381 | a*(u-1.0) / log(u) 382 | end 383 | end 384 | 385 | dd_n_log_int = 64; 386 | dd_log_int = DD[ 387 | DD(0.0, 0.0), 388 | DD(0.6931471805599453, 2.3190468138462996e-17), 389 | DD(1.0986122886681098, -9.07129723500153e-17), 390 | DD(1.3862943611198906, 4.638093627692599e-17), 391 | DD(1.6094379124341003, 9.280081691085902e-17), 392 | DD(1.791759469228055, 4.349979825096335e-17), 393 | DD(1.9459101490553132, 7.323586207904907e-17), 394 | DD(2.0794415416798357, 1.8059370687790465e-16), 395 | DD(2.1972245773362196, -1.814259447000306e-16), 396 | DD(2.302585092994046, -2.1707562233822494e-16), 397 | DD(2.3978952727983707, -1.253584211423161e-16), 398 | DD(2.4849066497880004, -4.433203607308931e-17), 399 | DD(2.5649493574615367, -2.5580975097208856e-18), 400 | DD(2.6390573296152584, 2.0744863268002772e-16), 401 | DD(2.70805020110221, 2.0878445608437204e-18), 402 | DD(2.772588722239781, 9.276187255385198e-17), 403 | DD(2.833213344056216, -8.500696635386325e-17), 404 | DD(2.8903717578961645, 1.7483143082597936e-16), 405 | DD(2.9444389791664403, 1.9776172119535626e-16), 406 | DD(2.995732273553991, 1.39181753187785e-16), 407 | DD(3.044522437723423, -1.747711027096623e-17), 408 | DD(3.091042453358316, -2.1319025546636875e-16), 409 | DD(3.1354942159291497, 1.5758359867283186e-17), 410 | DD(3.1780538303479458, -1.3216387039714197e-16), 411 | DD(3.2188758248682006, 1.8560163382171803e-16), 412 | DD(3.258096538021482, -9.038993183377354e-17), 413 | DD(3.295836866004329, -5.009431212501459e-17), 414 | DD(3.332204510175204, 1.1961679835597506e-16), 415 | DD(3.367295829986474, -1.1553104240685565e-16), 416 | DD(3.4011973816621555, -8.574398976320894e-17), 417 | DD(3.4339872044851463, -2.5863763694297672e-17), 418 | DD(3.4657359027997265, 4.930038229799327e-18), 419 | DD(3.4965075614664802, 5.973211432699923e-18), 420 | DD(3.5263605246161616, -1.728388006779159e-16), 421 | DD(3.5553480614894135, 1.660366789899081e-16), 422 | DD(3.58351893845611, 8.69995965019267e-17), 423 | DD(3.6109179126442243, 9.643918385970854e-17), 424 | DD(3.6375861597263857, 1.0992988687130361e-16), 425 | DD(3.6635616461296463, 1.2877353506529513e-16), 426 | DD(3.6888794541139363, 5.134991886373236e-17), 427 | DD(3.713572066704308, -1.4628004942704776e-16), 428 | DD(3.7376696182833684, -1.0530894459501889e-16), 429 | DD(3.7612001156935624, 3.879508085699725e-17), 430 | DD(3.784189633918261, 1.4306712005964121e-16), 431 | DD(3.8066624897703196, 1.3341947713585974e-16), 432 | DD(3.828641396489095, -7.207347445676947e-17), 433 | DD(3.8501476017100584, 1.5534199491592608e-16), 434 | DD(3.871201010907891, -2.1999570472119463e-16), 435 | DD(3.8918202981106265, 1.4647172415809814e-16), 436 | DD(3.912023005428146, 9.776979949766539e-17), 437 | DD(3.9318256327243257, 4.632466622115275e-17), 438 | DD(3.9512437185814275, -1.782217661578262e-16), 439 | DD(3.970291913552122, -1.3098078310631424e-16), 440 | DD(3.9889840465642745, -1.3792614644906726e-16), 441 | DD(4.007333185232471, -2.5460220915648837e-16), 442 | DD(4.02535169073515, -4.123042458181402e-16), 443 | DD(4.04305126783455, -1.1499585607969033e-16), 444 | DD(4.060443010546419, 2.4072633311915433e-16), 445 | DD(4.07753744390572, -2.5451232614395796e-16), 446 | DD(4.0943445622221, 2.70513385762801e-16), 447 | DD(4.110873864173311, -1.0515756814070423e-16), 448 | DD(4.127134385045092, -1.1369559801835033e-16), 449 | DD(4.143134726391533, 1.1385452230404978e-16), 450 | DD(4.1588830833596715, 3.611874137558093e-16) 451 | ]; 452 | 453 | const dd_n_recip_int = 36; 454 | const dd_recip_int = DD[ 455 | DD(1.0, 0.0), 456 | DD(0.5, 0.0), 457 | DD(0.3333333333333333, 1.850371707708594e-17), 458 | DD(0.25, 0.0), 459 | DD(0.2, -1.1102230246251566e-17), 460 | DD(0.16666666666666666, 9.25185853854297e-18), 461 | DD(0.14285714285714285, 7.93016446160826e-18), 462 | DD(0.125, 0.0), 463 | DD(0.1111111111111111, 6.1679056923619804e-18), 464 | DD(0.1, -5.551115123125783e-18), 465 | DD(0.09090909090909091, -2.523234146875356e-18), 466 | DD(0.08333333333333333, 4.625929269271485e-18), 467 | DD(0.07692307692307693, -4.270088556250602e-18), 468 | DD(0.07142857142857142, 3.96508223080413e-18), 469 | DD(0.06666666666666667, 9.251858538542971e-19), 470 | DD(0.0625, 0.0), 471 | DD(0.058823529411764705, 8.163404592832033e-19), 472 | DD(0.05555555555555555, 3.0839528461809902e-18), 473 | DD(0.05263157894736842, 2.921639538487254e-18), 474 | DD(0.05, -2.7755575615628915e-18), 475 | DD(0.047619047619047616, 2.64338815386942e-18), 476 | DD(0.045454545454545456, -1.261617073437678e-18), 477 | DD(0.043478260869565216, 1.206764157201257e-18), 478 | DD(0.041666666666666664, 2.3129646346357427e-18), 479 | DD(0.04, -8.326672684688674e-19), 480 | DD(0.038461538461538464, -2.135044278125301e-18), 481 | DD(0.037037037037037035, 2.05596856412066e-18), 482 | DD(0.03571428571428571, 1.982541115402065e-18), 483 | DD(0.034482758620689655, 4.785444071660157e-19), 484 | DD(0.03333333333333333, 4.625929269271486e-19), 485 | DD(0.03225806451612903, 8.953411488912552e-19), 486 | DD(0.03125, 0.0), 487 | DD(0.030303030303030304, -8.410780489584519e-19), 488 | DD(0.029411764705882353, 4.0817022964160166e-19), 489 | DD(0.02857142857142857, 8.921435019309293e-19), 490 | DD(0.027777777777777776, 1.5419764230904951e-18) 491 | ]; 492 | 493 | 494 | function log1p_taylor(a::DD) 495 | x = a 496 | x2 = x*x 497 | x3 = x2*x 498 | x4 = x2*x2 499 | x5 = x2*x3 500 | x10 = x5*x5 501 | x15 = x5*x10 502 | x20 = x10*x10 503 | x25 = x10*x15 504 | x30 = x15*x15 505 | 506 | z = x - dd_recip_int[2]*x2 + dd_recip_int[3]*x3 - dd_recip_int[4]*x4 507 | z2 = x5 * (dd_recip_int[5] - x*dd_recip_int[6] + x2*dd_recip_int[7] - x3*dd_recip_int[8] + x4*dd_recip_int[9]) 508 | z3 = x10 * (-dd_recip_int[10] + x*dd_recip_int[11] - x2*dd_recip_int[12] + x3*dd_recip_int[13] - x4*dd_recip_int[14]) 509 | z4 = x15 * (dd_recip_int[15] - x*dd_recip_int[16] + x2*dd_recip_int[17] - x3*dd_recip_int[18] + x4*dd_recip_int[19]) 510 | z5 = x20 * (-dd_recip_int[20] + x*dd_recip_int[21] - x2*dd_recip_int[22] + x3*dd_recip_int[23] - x4*dd_recip_int[24]) 511 | z6 = x25 * (dd_recip_int[25] - x*dd_recip_int[26] + x2*dd_recip_int[27] - x3*dd_recip_int[28] + x4*dd_recip_int[29]) 512 | z7 = x30 * (-dd_recip_int[30] + x*dd_recip_int[31] - x2*dd_recip_int[32] + x2*dd_recip_int[33]) 513 | 514 | (((((z7+z6)+z5)+z4)+z3)+z2)+z 515 | 516 | end 517 | 518 | function logIter(x::DD) 519 | yy = DD(log(x.hi),0.0) 520 | yy = yy + x * exp(-yy) - 1.0 521 | yy = yy + x * exp(-yy) - 1.0 522 | yy = yy + x * exp(-yy) - 1.0 523 | yy = yy + TD(x) * exp(-yy) - 1.0 524 | DD(yy) 525 | end 526 | 527 | 528 | function logIterThrice(x::DD) 529 | yy = DD(log(x.hi),0.0) 530 | yy = yy + x * exp(-yy) - 1.0 531 | yy = yy + x * exp(-yy) - 1.0 532 | yy = yy + TD(x) * exp(-yy) - 1.0 533 | DD(yy) 534 | end 535 | 536 | 537 | function log(x::DD) 538 | if x.hi == Inf 539 | return x 540 | elseif x.hi <= 1e-324 541 | return -dd_Inf 542 | elseif (x.hi == one(Float64)) && abs(x.lo) <= 1e-34 543 | return DD(x.lo) 544 | end 545 | 546 | if (x.hi < zero(Float64)) 547 | return -log(abs(x)) 548 | end 549 | 550 | if (x.hi < one(Float64)) 551 | -log(recip(x)) 552 | elseif (x.hi < 72.0) 553 | if (x.hi >= 2.718281828459045) 554 | n = floor(log(x.hi)) 555 | y = x / dd_exp_int[trunc(Int,n)] 556 | log(y) + n 557 | elseif (x.hi >= 1.25) # 1.1 .. x .. exp(1) 558 | logIterThrice(x) 559 | elseif (x.hi >= 1.1) 560 | log1p(x) 561 | else # 1.0 .. x .. 1.1 562 | log1p_taylor(x-1.0) 563 | end 564 | else 565 | logIter(x) 566 | end 567 | end 568 | 569 | function log1p(x::DD) 570 | u = 1.0 + x 571 | if u == one(DD) 572 | x 573 | else 574 | log(u)*x/(u-1.0) 575 | end 576 | end 577 | 578 | function log2(x::DD) 579 | log(x) / dd_log2 580 | end 581 | 582 | function log10(x::DD) 583 | log(x) / dd_log10 584 | end 585 | 586 | -------------------------------------------------------------------------------- /src/exp/TD.jl: -------------------------------------------------------------------------------- 1 | const td_inv_fact = TD[ 2 | TD(1.0, 0.0, 0.0), 3 | TD(0.5, 0.0, 0.0), 4 | TD(0.16666666666666666, 9.25185853854297e-18, 5.135813185032629e-34), 5 | TD(0.041666666666666664, 2.3129646346357427e-18, 1.2839532962581572e-34), 6 | TD(0.008333333333333333, 1.1564823173178714e-19, 1.6049416203226965e-36), 7 | TD(0.001388888888888889, -5.300543954373577e-20, -1.7386867553495878e-36), 8 | TD(0.0001984126984126984, 1.7209558293420705e-22, 1.4926912391394127e-40), 9 | TD(2.48015873015873e-5, 2.1511947866775882e-23, 1.865864048924266e-41), 10 | TD(2.7557319223985893e-6, -1.858393274046472e-22, 8.491754604881993e-39), 11 | TD(2.755731922398589e-7, 2.3767714622250297e-23, -3.263188903340883e-40), 12 | TD(2.505210838544172e-8, -1.448814070935912e-24, 2.0426735146714455e-41), 13 | TD(2.08767569878681e-9, -1.20734505911326e-25, 1.702227928892871e-42), 14 | TD(1.6059043836821613e-10, 1.2585294588752098e-26, -5.31334602762985e-43), 15 | TD(1.1470745597729725e-11, 2.0655512752830745e-28, 6.889079232466646e-45), 16 | TD(7.647163731819816e-13, 7.03872877733453e-30, -7.827539277162583e-48), 17 | TD(4.779477332387385e-14, 4.399205485834081e-31, -4.892212048226615e-49), 18 | TD(2.8114572543455206e-15, 1.6508842730861433e-31, -2.877771793074479e-50), 19 | TD(1.5619206968586225e-16, 1.1910679660273754e-32, -4.577506059629983e-49), 20 | TD(8.22063524662433e-18, 2.2141894119604265e-34, -1.508914023774199e-50), 21 | TD(4.110317623312165e-19, 1.4412973378659527e-36, -5.285627548789812e-53), 22 | TD(1.9572941063391263e-20, -1.3643503830087908e-36, 1.3392348251125064e-53), 23 | TD(8.896791392450574e-22, -7.911402614872376e-38, -3.1877976790570933e-54), 24 | TD(3.868170170630684e-23, -8.843177655482344e-40, 3.8718157106173247e-56), 25 | TD(1.6117375710961184e-24, -3.6846573564509766e-41, 1.613256546090552e-57), 26 | TD(6.446950284384474e-26, -1.9330404233703465e-42, -1.5213023807039144e-58), 27 | TD(2.4795962632247976e-27, -1.2953730964765229e-43, 6.403390159849962e-60), 28 | TD(9.183689863795546e-29, 1.4303150396787322e-45, -8.551226774650505e-62), 29 | TD(3.279889237069838e-30, 1.5117542744029879e-46, 8.058517719519716e-63), 30 | TD(1.1309962886447716e-31, 1.0498015412959506e-47, -4.346150929397795e-64), 31 | TD(3.7699876288159054e-33, 2.5870347832750324e-49, 3.23789002742564e-66), 32 | TD(1.216125041553518e-34, 5.586290567888806e-51, 6.615948578082792e-68), 33 | TD(3.8003907548547434e-36, 1.7457158024652518e-52, 2.0674839306508725e-69), 34 | TD(1.151633562077195e-37, -6.09957445788454e-54, -5.3447496196594105e-70), 35 | TD(3.387157535521162e-39, 5.09056148151085e-56, 3.989567349036344e-72), 36 | TD(9.67759295863189e-41, 3.202295548645562e-57, 6.547507205018101e-74), 37 | TD(2.6882202662866363e-42, 5.355061165943334e-59, -1.1290601987449868e-75), 38 | TD(7.265460179153071e-44, -4.364097149354446e-61, 2.5503250121018375e-77), 39 | TD(1.911963205040282e-45, -2.7860822176883126e-62, 2.0347437224101328e-78), 40 | TD(4.902469756513544e-47, -1.213019100517928e-63, -4.4707180011376586e-80), 41 | TD(1.2256174391283858e-48, 6.033927348315605e-68, 4.0762496124582373e-84), 42 | TD(2.9893108271424046e-50, -1.0407247703033156e-66, -1.3761319713775906e-83), 43 | TD(7.117406731291439e-52, 3.1742075384205573e-68, 1.2411289864622588e-84), 44 | TD(1.6552108677421951e-53, 4.147105190494824e-70, 4.321874177581813e-88), 45 | TD(3.7618428812322616e-55, 2.2597135911236184e-71, -1.452551873877095e-87), 46 | TD(8.359650847182804e-57, -5.0402798850883064e-73, -1.971165125943993e-89), 47 | TD(1.817315401561479e-58, 1.365069339879366e-74, 2.5449015040142434e-91), 48 | TD(3.866628513960594e-60, -1.564355005786389e-76, -1.2863855447354847e-92), 49 | TD(8.055476070751236e-62, 8.255818478070949e-78, -2.679969884865593e-94), 50 | TD(1.643974708316579e-63, -4.080880981844294e-80, -3.32913139064192e-96), 51 | TD(3.287949416633158e-65, 5.332251403646481e-82, 8.324193862236773e-99), 52 | TD(6.446959640457172e-67, 2.8542499223476843e-83, -1.3428344869006296e-99), 53 | TD(1.2397999308571486e-68, -2.430377210051421e-85, -8.239318728361721e-102), 54 | TD(2.3392451525606576e-70, 8.161871936085597e-87, 4.847758386854871e-103), 55 | TD(4.331935467704922e-72, -1.0950890458548228e-88, -6.008669702432555e-105), 56 | TD(7.876246304918039e-74, 2.578848742504751e-90, -5.375571071117659e-107), 57 | TD(1.4064725544496498e-75, 1.1618077704898094e-91, -2.9064193324175937e-108), 58 | TD(2.4674957095607893e-77, -4.7567198485936506e-95, -4.498838274048994e-112), 59 | TD(4.254302947518602e-79, 3.3126660495569664e-96, -9.378759508473191e-113), 60 | TD(7.2106829618959365e-81, -4.675660659561278e-97, -2.2732826558679996e-113), 61 | TD(1.2017804936493226e-82, 6.837470842477656e-99, 1.0840439011993803e-115), 62 | TD(1.9701319568021682e-84, 8.210968879386911e-101, 1.3610651106029761e-117), 63 | TD(3.1776321883905942e-86, -1.5561627595804251e-102, 2.834868584973462e-119), 64 | TD(5.043860616493007e-88, -3.178797157619149e-104, 2.613713035752867e-120), 65 | TD(7.881032213270323e-90, -4.96687055877992e-106, 4.0839266183638546e-122) 66 | ]; 67 | 68 | # |a| <= 0.2 69 | function exp_taylor(a::TD) 70 | x = a 71 | x2 = x*x 72 | x3 = x*x2 73 | x4 = x2*x2 74 | x5 = x2*x3 75 | x10 = x5*x5 76 | x15 = x5*x10 77 | x20 = x10*x10 78 | x25 = x10*x15 79 | 80 | z = x + td_inv_fact[2]*x2 + td_inv_fact[3]*x3 + td_inv_fact[4]*x4 81 | z2 = x5 * (td_inv_fact[5] + x*td_inv_fact[6] + x2*td_inv_fact[7] + x3*td_inv_fact[8] + x4*td_inv_fact[9]) 82 | z3 = x10 * (td_inv_fact[10] + x*td_inv_fact[11] + x2*td_inv_fact[12] + x3*td_inv_fact[13] + x4*td_inv_fact[14]) 83 | z4 = x15 * (td_inv_fact[15] + x*td_inv_fact[16] + x2*td_inv_fact[17] + x3*td_inv_fact[18] + x4*td_inv_fact[19]) 84 | z5 = x20 * (td_inv_fact[20] + x*td_inv_fact[21] + x2*td_inv_fact[22] + x3*td_inv_fact[23] + x4*td_inv_fact[24]) 85 | z6 = x25 * (td_inv_fact[25] + x*td_inv_fact[26] + x2*td_inv_fact[27] + x3*td_inv_fact[28]) 86 | 87 | ((((z6+z5)+z4)+z3)+z2)+z + one(DD) 88 | end 89 | 90 | # exp(0 fifths) .. exp(6 fifths) 91 | const td_exp_fifths = TD[ 92 | TD(1.0, 0.0, 0.0), 93 | TD(1.2214027581601699, -2.0740986247316727e-17, -6.426608929993855e-34), 94 | TD(1.4918246976412703, -2.9678597513482695e-17, -1.3156795434672035e-33), 95 | TD(1.8221188003905089, 8.896402286295436e-17, 5.8486273504934125e-33), 96 | TD(2.2255409284924674, 1.7500150972701294e-16, -1.0087607019081632e-32), 97 | TD(2.718281828459045, 1.4456468917292502e-16, -2.1277171080381768e-33), 98 | TD(3.3201169227365477, -1.926181990575462e-16, -9.879307591112402e-33) 99 | ]; 100 | 101 | const td_n_exp_int = 256; 102 | const td_exp_int = TD[ 103 | TD(1.0, 0.0, 0.0), 104 | TD(2.718281828459045, 1.4456468917292502e-16, -2.1277171080381768e-33), 105 | TD(7.38905609893065, -1.7971139497839148e-16, 8.268430555139957e-33), 106 | TD(20.085536923187668, -1.8275625525512858e-16, 1.1213291937709194e-32), 107 | TD(54.598150033144236, 2.8741578015844115e-15, 1.7003104246897037e-31), 108 | TD(148.4131591025766, 3.4863514900464198e-15, -3.811747842562211e-32), 109 | TD(403.4287934927351, 1.2359628024450387e-14, 1.1709520382179646e-31), 110 | TD(1096.6331584284585, 9.869752640434095e-14, -6.125696216224318e-30), 111 | TD(2980.9579870417283, -2.7103295816873633e-14, -1.1372231630220379e-30), 112 | TD(8103.083927575384, -2.1530877621067177e-13, 3.493034785896116e-30), 113 | TD(22026.465794806718, -1.3780134700517372e-12, -3.539114630937125e-29), 114 | TD(59874.14171519782, 1.7895764888916994e-12, -8.815483363882642e-29), 115 | TD(162754.79141900392, 5.30065881322063e-12, 2.466319168695138e-28), 116 | TD(442413.3920089205, 1.2118711752313224e-11, 1.4520080913454788e-28), 117 | TD(1.2026042841647768e6, -1.5000525764327354e-11, -1.0597348307277772e-27), 118 | TD(3.2690173724721107e6, -3.075806431120808e-11, -3.0010656529768048e-27), 119 | TD(8.886110520507872e6, 5.321182483501564e-10, 4.991872015158224e-26), 120 | TD(2.41549527535753e7, -7.203995068362157e-10, -1.2422195607226908e-26), 121 | TD(6.565996913733051e7, 1.4165536846555444e-9, -1.7248998417757113e-26), 122 | TD(1.7848230096318725e8, 1.333018530234341e-8, 4.888990538468543e-25), 123 | TD(4.851651954097903e8, 4.880277289790406e-10, -2.354308077000704e-26), 124 | TD(1.3188157344832146e9, 8.043448618843281e-8, -6.371487773625452e-24), 125 | TD(3.584912846131592e9, -2.3519384005402157e-7, -4.8144679026147915e-24), 126 | TD(9.744803446248903e9, -6.74501500127677e-7, -4.3047722128798514e-23), 127 | TD(2.648912212984347e10, 7.670395527778119e-7, 2.1653676812342498e-23), 128 | TD(7.200489933738588e10, -6.992440211033874e-6, 3.0491941683952344e-22), 129 | TD(1.9572960942883878e11, -1.1364989227123904e-5, -2.3277259364619435e-22), 130 | TD(5.3204824060179865e11, -2.8335783945658822e-5, -8.34700141765522e-22), 131 | TD(1.446257064291475e12, 7.602079742299693e-5, -2.6590406910916902e-21), 132 | TD(3.931334297144042e12, 8.220112058084352e-5, 5.400602628729904e-21), 133 | TD(1.0686474581524463e13, -0.0007436345313492586, 9.460262037429165e-21), 134 | TD(2.9048849665247426e13, -0.0005501643178883202, -1.7689371221606047e-21), 135 | TD(7.896296018268069e13, 0.007660978022635108, 3.1512033963186214e-19), 136 | TD(2.1464357978591606e14, 0.002124297761531261, -1.6486771427095084e-19), 137 | TD(5.834617425274549e14, 0.006402902734610391, 2.5828504022464183e-20), 138 | TD(1.5860134523134308e15, -0.02187035537422534, -6.126063359042446e-19), 139 | TD(4.311231547115195e15, 0.22711342229285691, 1.0760312169033586e-17), 140 | TD(1.1719142372802612e16, -0.6912270602088098, -5.3949122632866115e-17), 141 | TD(3.1855931757113756e16, 0.22032867170129863, 1.2010345536294758e-17), 142 | TD(8.659340042399374e16, 2.953606932719265, -1.7591575006053599e-16), 143 | TD(2.3538526683702e17, -14.592100089250966, 8.263454468543573e-16), 144 | TD(6.398434935300549e17, 37.22266340351557, 2.471122411116742e-15), 145 | TD(1.739274941520501e18, 55.394681303611236, -7.634444032832378e-16), 146 | TD(4.727839468229346e18, 257.4744575627443, -2.5134655743048235e-14), 147 | TD(1.2851600114359308e19, -12.1907003678569, -5.985062012321848e-16), 148 | TD(3.4934271057485095e19, 436.0347972334061, 4.004349215878646e-15), 149 | TD(9.496119420602448e19, 5929.133649117119, -3.704371242840454e-13), 150 | TD(2.5813128861900675e20, -15192.714199784727, -3.1163625504077424e-14), 151 | TD(7.016735912097631e20, 30185.471599886117, -6.848722098545894e-14), 152 | TD(1.9073465724950998e21, -98786.90015904616, 4.197208362517256e-12), 153 | TD(5.184705528587072e21, 419031.45332293346, 2.2470748041381468e-11), 154 | TD(1.4093490824269389e22, -614323.8566876298, -2.981768692273901e-12), 155 | TD(3.831008000716577e22, -661524.304512138, 6.69534599357328e-12), 156 | TD(1.0413759433029089e23, -7.520901270665062e6, -3.754910028167138e-10), 157 | TD(2.830753303274694e23, -4.711377645198593e6, 3.7021605218163874e-10), 158 | TD(7.694785265142018e23, -3.868399744098706e7, -2.6169176485845316e-9), 159 | TD(2.091659496012996e24, 5.079641515721467e7, 2.4047856572771866e-9), 160 | TD(5.685719999335932e24, 2.0801558082063326e8, -9.09248660631395e-9), 161 | TD(1.545538935590104e25, 1.2092033491117463e8, -5.089946219426507e-9), 162 | TD(4.2012104037905144e25, -1.7624059056928084e9, 7.347807408795491e-9), 163 | TD(1.1420073898156842e26, 4.912247462314477e9, -4.0383810556029435e-7), 164 | TD(3.10429793570192e26, 3.39761293411071e9, -1.0683667373232363e-7), 165 | TD(8.438356668741454e26, 6.5719328084037315e10, -3.572644274482033e-6), 166 | TD(2.29378315946961e27, -7.566162968773138e10, -2.122192970659097e-6), 167 | TD(6.235149080811617e27, 1.3899738872492847e11, 2.9479563918462358e-6), 168 | TD(1.6948892444103338e28, -6.61940830637628e11, 2.6706738736225517e-5), 169 | TD(4.607186634331292e28, -2.37966706696394e12, 2.8299599003037097e-5), 170 | TD(1.2523631708422137e29, 8.725173269482437e12, 5.33159885274045e-5), 171 | TD(3.404276049931741e29, -2.3689045745171566e13, 0.0014657873876139946), 172 | TD(9.253781725587787e29, 4.1335361789492734e13, 0.00021234765992072084), 173 | TD(2.515438670919167e30, 1.2647645018519611e14, 0.003586407412973383), 174 | TD(6.837671229762744e30, -2.8026814130938628e14, -0.007794054164068711), 175 | TD(1.8586717452841279e31, 9.331591492068494e14, 0.03694694639669623), 176 | TD(5.052393630276104e31, 2.4912292015869455e15, 0.14648536724497563), 177 | TD(1.3733829795401761e32, 8.003850355927158e15, -0.106842001692075), 178 | TD(3.7332419967990015e32, 1.5538124781410182e16, 0.0143427783686916), 179 | TD(1.0148003881138887e33, -1.8313882415912828e16, 0.9757766648151681), 180 | TD(2.7585134545231703e33, -1.1490320660315066e17, 5.943341520175249), 181 | TD(7.498416996990121e33, -4.7233584091570765e17, -3.545295341022214), 182 | TD(2.0382810665126688e34, -5.7128185991424294e17, 24.374697364861525), 183 | TD(5.54062238439351e34, 2.1811937023229343e18, 68.92485672883268), 184 | TD(1.5060973145850306e35, -7.056987941853042e18, 10.189939649212826), 185 | TD(4.0939969621274545e35, 1.852765937250624e19, -199.67994620780615), 186 | TD(1.1128637547917594e36, -2.7961733453775843e19, 709.7340769207204), 187 | TD(3.0250773222011426e36, -2.2396762302858075e20, 1926.4690322223041), 188 | TD(8.223012714622913e36, 4.083087026334775e20, 17895.486286188476), 189 | TD(2.235246603734715e37, 7.328168204485786e20, -12921.22460748679), 190 | TD(6.076030225056872e37, 2.4300525977303657e21, -68303.38624674038), 191 | TD(1.6516362549940018e38, 4.5658363808236883e21, -260125.0371158), 192 | TD(4.4896128191743455e38, -3.034626837469501e22, 554752.5980586372), 193 | TD(1.2204032943178408e39, -3.218018426639282e22, -1.7368452535789001e6), 194 | TD(3.317400098335743e39, -2.0594325391839645e23, 1.2971230145811823e6), 195 | TD(9.017628405034299e39, 4.119507937020878e23, 2.60947127461132e7), 196 | TD(2.451245542920086e40, -1.809447119103778e24, -4.289318443585035e7), 197 | TD(6.663176216410896e40, -3.5075886901816454e24, -1.116529341124579e8), 198 | TD(1.8112390828890233e41, -6.613591371018036e24, -2.8487633028254557e8), 199 | TD(4.923458286012058e41, 1.3869835129739753e25, -1.8642329204287472e8), 200 | TD(1.3383347192042695e42, -3.8243050326463913e25, 8.969612614572136e8), 201 | TD(3.637970947608805e42, -1.7059216189570308e26, 1.4436385517255863e10), 202 | TD(9.889030319346946e42, 5.152980735736938e26, 1.5421039626071994e9), 203 | TD(2.6881171418161356e43, -1.6101271449201627e27, -1.0138129064122626e11), 204 | TD(7.307059979368067e43, 3.81998468048638e27, 1.7589242949408395e11), 205 | TD(1.9862648361376543e44, -1.7687808052379885e27, -2.8781541988944653e10), 206 | TD(5.399227610580169e44, 1.6694477435363627e28, -5.711187169829366e11), 207 | TD(1.4676622301554424e45, -5.683445805084399e28, -3.9821879815043027e12), 208 | TD(3.989519570547216e45, -4.528566832709381e28, -1.324544028507888e12), 209 | TD(1.0844638552900231e46, -5.0737593474148365e29, 5.128149668201329e12), 210 | TD(2.947878391455509e46, 1.522599815352173e30, 1.4058841019755673e14), 211 | TD(8.013164264000591e46, 4.4255712989469043e30, -1.0731239652864577e14), 212 | TD(2.1782038807290206e47, 6.40943286045652e30, 4.262667389268634e14), 213 | TD(5.92097202766467e47, 3.6278506451438224e31, -1.8673077709586268e15), 214 | TD(1.609487066961518e48, -3.11348413350283e31, -6.980136469693595e14), 215 | TD(4.375039447261341e48, 1.035824156236645e32, 3.7439184111440075e14), 216 | TD(1.189259022828201e49, -6.311799972004003e32, 2.8001767852973828e16), 217 | TD(3.2327411910848595e49, -1.6317210762547248e33, -1.4293720368014344e17), 218 | TD(8.787501635837023e49, 4.951878455668192e31, -3.0729734576366325e15), 219 | TD(2.3886906014249913e50, 1.5523479734981885e34, -2.951509949588213e17), 220 | TD(6.493134255664462e50, 1.417967467778397e33, -1.1115565841105502e17), 221 | TD(1.7650168856917655e51, 3.659435419097009e34, -8.536336063538576e16), 222 | TD(4.797813327299302e51, -4.832529827928807e34, 3.546375057413136e18), 223 | TD(1.3041808783936323e52, 2.3598218061815903e35, 8.088849552127185e17), 224 | TD(3.5451311827611664e52, 4.397256578106813e35, 1.6677167637718272e18), 225 | TD(9.636665673603202e52, -3.923912609184774e36, -2.643344130537555e20), 226 | TD(2.6195173187490626e53, 9.508437015673215e36, 4.903465425299725e20), 227 | TD(7.120586326889338e53, -2.2289404495948426e37, 2.165707551230535e21), 228 | TD(1.9355760420357226e54, -1.8895773015758525e37, -1.1312006802942819e21), 229 | TD(5.261441182666386e54, -2.2391033592780024e38, -1.5567284166783301e22), 230 | TD(1.4302079958348105e55, -4.95219683040473e38, 4.61051227024973e21), 231 | TD(3.887708405994595e55, 2.707966110366217e39, 8.40107669353579e22), 232 | TD(1.0567887114362587e56, 1.0147572632726592e40, 8.174924404317213e22), 233 | TD(2.872649550817832e56, -1.725105418010497e40, -2.6578341119269315e23), 234 | TD(7.808671073519151e56, -3.3393507820354276e39, -2.6676111729938114e23), 235 | TD(2.1226168683560893e57, 9.12124047520486e40, -6.007253710143997e24), 236 | TD(5.769870862033003e57, 2.54679794252527e41, 2.7445496743807577e24), 237 | TD(1.568413511681964e58, -5.571295095061288e41, -3.673797346079441e25), 238 | TD(4.263389948314721e58, 9.74205426058927e41, 6.9314756502460855e25), 239 | TD(1.1589095424138854e59, 3.107727800036786e42, 9.71646756541256e25), 240 | TD(3.150242749971452e59, -9.643637210793454e42, -2.9406195192497175e26), 241 | TD(8.56324762248225e59, -5.908667317844348e43, -1.7405230718552978e27), 242 | TD(2.3277320404788622e60, -1.5410810390283507e44, -2.4913947442828e27), 243 | TD(6.327431707155585e60, 2.9519976099018483e44, -1.1117699126888596e28), 244 | TD(1.7199742630376623e61, -6.6270661206611855e44, -3.7335082280479956e27), 245 | TD(4.675374784632515e61, 1.2938282778262074e45, -2.4885140400989384e28), 246 | TD(1.2708986318302189e62, -3.042168764740704e44, 1.2622264002071768e28), 247 | TD(3.454660656717546e62, 1.8553902103629043e46, 2.5743662868459146e29), 248 | TD(9.390741286647697e62, 8.372523060245978e46, 2.537610862961777e30), 249 | TD(2.5526681395254553e63, -1.6889209515414619e47, -7.484426795815784e30), 250 | TD(6.938871417758404e63, -4.174062699457691e47, 2.4157141035602262e31), 251 | TD(1.886180808490652e64, 8.75753845955151e47, 1.4999486409495774e31), 252 | TD(5.12717101690833e64, -1.848585500693908e47, -8.940294911553923e30), 253 | TD(1.3937095806663797e65, 7.0244638077530874e47, -1.471338870576989e31), 254 | TD(3.788495427274696e65, -1.6686420819293392e48, 1.3653221371939198e32), 255 | TD(1.0298198277160991e66, 8.608117819191599e49, -6.387171108607294e32), 256 | TD(2.799340524267497e66, -8.50129047864975e49, -1.0400371266913997e33), 257 | TD(7.609396478785354e66, -1.2944224384739812e50, -7.883071182081507e33), 258 | TD(2.0684484173822473e67, -2.743371829892203e50, -3.3146200011289803e33), 259 | TD(5.622625746075033e67, 1.4234908903412887e51, 8.207968883270885e34), 260 | TD(1.5283881393781746e68, -8.309060391771288e51, -2.0892527144587264e35), 261 | TD(4.154589706104022e68, 2.1030987078913436e52, -9.488757728213872e35), 262 | TD(1.129334570280557e69, -8.237338292837319e52, 6.801148934606748e35), 263 | TD(3.0698496406442424e69, 4.375620509828095e52, -9.01855287244489e35), 264 | TD(8.344716494264775e69, -5.967039946946015e53, 3.542448397606548e37), 265 | TD(2.2683291210002403e70, 1.4059974118116153e54, 4.083802444122437e36), 266 | TD(6.165957830579433e70, -5.480338773236432e54, 6.805871631769652e37), 267 | TD(1.6760811125908828e71, -3.078670967159958e54, 6.653530993469299e37), 268 | TD(4.556060831379215e71, 4.2683874443891194e55, 2.5603046475883494e39), 269 | TD(1.2384657367292132e72, -1.7417281417483923e55, 4.171665745944932e38), 270 | TD(3.366498907320164e72, 1.8595557870731098e56, 2.430092132939246e39), 271 | TD(9.151092805295634e72, 2.9278721984510905e56, 5.051941818077708e38), 272 | TD(2.487524928317743e73, -2.269951231486326e56, 5.588088411251843e39), 273 | TD(6.761793810485009e73, 6.044072970031212e57, -1.5239530423566517e41), 274 | TD(1.8380461242828246e74, 6.558763264761503e57, -6.2842095497002504e41), 275 | TD(4.996327379507578e74, 1.2022315866163456e58, -4.30439705963749e41), 276 | TD(1.358142592474785e75, 6.293920858651693e58, 2.538001080697679e42), 277 | TD(3.691814329580466e75, 1.5523424954077878e59, 9.102987766276767e42), 278 | TD(1.0035391806143295e76, -1.600289359022275e59, 8.921624694181667e42), 279 | TD(2.7279023188106115e76, 6.6492459414351406e59, -2.952156561715424e43), 280 | TD(7.415207303034179e76, -4.678668371358611e60, -5.344633503211126e43), 281 | TD(2.0156623266094611e77, 6.4049020966883044e60, -1.4870384001958337e44), 282 | TD(5.47913827473198e77, -3.839583545632845e61, -9.356912608779471e44), 283 | TD(1.4893842007818383e78, 6.250487712624396e61, -4.919264913536765e44), 284 | TD(4.048566008579269e78, 1.682018025551642e62, 1.187051587470802e45), 285 | TD(1.1005143412437996e79, -6.764346497503176e62, -1.4326930238358925e46), 286 | TD(2.991508135761597e79, 1.1738879998058348e63, -5.685756925046457e46), 287 | TD(8.131762205128143e79, -1.5057074349533377e62, -6.76542981577317e44), 288 | TD(2.2104421435549888e80, -7.196700457953682e63, -4.59843382846307e47), 289 | TD(6.008604711685586e80, -3.660345147820277e64, 2.677819599177173e48), 290 | TD(1.633308100216833e81, -2.1239531351072146e64, -2.1442930180587127e47), 291 | TD(4.4397917290943824e81, -2.882962352721535e65, -2.7145185615825334e47), 292 | TD(1.2068605179340022e82, 7.151662509907955e65, -4.0011216331943584e49), 293 | TD(3.2805870153846705e82, -3.194753619685436e66, -1.6258192542475755e50), 294 | TD(8.917560070598843e82, -8.989668102219982e65, 5.872088338798872e49), 295 | TD(2.4240441494100796e83, -3.8332753349400205e66, -2.4142368740836784e50), 296 | TD(6.589235162723882e83, -8.709570822927273e66, 4.38393402369277e50), 297 | TD(1.7911398206275708e84, 5.99708494881663e67, -3.898177174687216e50), 298 | TD(4.8688228266413195e84, 1.710917432346709e68, -3.710816434280393e51), 299 | TD(1.3234832615645704e85, -6.425373409956827e68, 2.7202859465247475e52), 300 | TD(3.5976005001806814e85, -2.5813006529759342e69, -4.175155490046978e52), 301 | TD(9.779292065696318e85, -6.6113382980943924e69, -2.4747721494219566e53), 302 | TD(2.658287191737602e86, 6.120064792143622e69, -2.8169558388109244e53), 303 | TD(7.225973768125749e86, 2.9945383505980016e70, -2.4656515449276994e52), 304 | TD(1.964223318681796e87, -1.0268429875036315e71, 5.236639905552299e54), 305 | TD(5.339312554208246e87, -2.625028820065693e71, 2.4083430064717356e55), 306 | TD(1.4513756292567526e88, -2.884486923510417e71, 2.2373717716371445e55), 307 | TD(3.945247999276943e88, 7.221484370687266e70, -2.5602633887737946e54), 308 | TD(1.0724295945198918e89, 4.163246302178397e72, -3.3362467897312186e56), 309 | TD(2.9151658790851237e89, 2.656865521036125e73, -1.2132528701924287e56), 310 | TD(7.924242436060931e89, -4.347509662136458e73, 2.9118839322857488e57), 311 | TD(2.1540324218248465e90, 6.568050851363196e73, 5.687199536689467e56), 312 | TD(5.855267190158109e90, 4.4915902036294956e74, 8.709976552642122e57), 313 | TD(1.5916266403779241e91, 3.865065123172901e74, 1.1362092098744349e58), 314 | TD(4.326489774230631e91, 3.1789213685539743e74, 6.679506996298473e57), 315 | TD(1.1760618534305e92, 5.894438850996908e75, 1.46216982996378e59), 316 | TD(3.196867565323994e92, -1.9538627920591218e76, -1.596248541219925e60), 317 | TD(8.689987010810322e92, -5.6063024973277287e76, -1.039732242539862e60), 318 | TD(2.3621833781030834e93, -7.781526569884677e76, 8.241985687084489e58), 319 | TD(6.421080152185614e93, -1.4034869476251672e77, 8.94340357798147e60), 320 | TD(1.7454305496765193e94, 9.749159232851838e77, 1.3772711407312229e61), 321 | TD(4.744572146022966e94, -3.2789833020339664e78, 1.1145960146026666e62), 322 | TD(1.2897084248347162e95, 5.438670793036996e78, -2.712679566619085e62), 323 | TD(3.505790975238748e95, 1.5415362493078123e78, -5.331771085301626e61), 324 | TD(9.529727902367202e95, 9.833684415222857e78, 2.3224879480754183e62), 325 | TD(2.5904486187163903e96, -2.263041008869737e80, -9.131190514738557e62), 326 | TD(7.041569407813597e96, -4.0828301614775564e80, 5.432549733443377e62), 327 | TD(1.9140970165092822e97, -1.497464557916617e81, 2.4095785563251316e64), 328 | TD(5.2030551378848545e97, 4.749190808721398e80, -7.223986999061391e63), 329 | TD(1.4143370233782872e98, 3.8946526873422757e80, -1.9649170029162572e64), 330 | TD(3.844566629966054e98, 2.2093533915053797e81, -2.3303025309417966e63), 331 | TD(1.0450615608536755e99, -5.337145484954864e82, -7.503673650794132e65), 332 | TD(2.840771850489593e99, 2.7464976717218177e81, 1.7468727661182804e65), 333 | TD(7.722018499983836e99, -4.0996868440885443e83, 7.165169152261782e66), 334 | TD(2.0990622567530634e100, 4.153001760319747e83, -7.009662310297903e66), 335 | TD(5.705842789336087e100, -7.502847960571591e83, -2.4801494557115398e67), 336 | TD(1.551008877029636e101, -1.1711307176004477e85, -5.533742733635353e68), 337 | TD(4.216079246208329e101, 3.4845354806957584e84, -1.462657611650957e68), 338 | TD(1.146049160231141e102, 5.309475346149073e85, 1.5323663978256527e69), 339 | TD(3.115284606777059e102, 1.1305094460701447e86, -1.1160940631374998e69), 340 | TD(8.468221537080262e102, -2.2036277666109673e86, 1.2073850043634683e70), 341 | TD(2.30190127236108e103, -4.663183218411149e86, 2.7194712685695586e70), 342 | TD(6.25721639956588e103, -3.232721480812657e87, -1.412027275389235e71), 343 | TD(1.700887763567586e104, 1.4773861394382237e88, -1.6566552716535912e70), 344 | TD(4.6234922999541146e104, 6.980490121714062e87, -4.178131018909918e71), 345 | TD(1.2567955102985587e105, -1.5226136925021163e88, -3.4070147820917737e71), 346 | TD(3.416324397733485e105, -7.894999158901084e86, 3.685152148214523e70), 347 | TD(9.286532530480224e105, -2.614355089326607e89, -2.5929786669881635e73), 348 | TD(2.5243412626998188e106, 7.770616368141536e88, -4.859484187904238e72), 349 | TD(6.861870983226278e106, 2.54810635544448e90, -2.1180278791034765e74), 350 | TD(1.8652499202934394e107, 3.8378044485542437e90, -1.7069056281222123e74), 351 | TD(5.070274963868339e107, 1.2106757063676503e90, -7.241226422337536e73), 352 | TD(1.3782436299574147e108, 8.797324501988005e91, 1.8741641437570143e75), 353 | TD(3.7464546145026734e108, -1.331977416683643e92, 9.121890396513558e75), 354 | TD(1.0183919499749154e109, 3.760113287049303e92, 3.405230764935433e74), 355 | TD(2.7682763318657856e109, -4.359593659827271e92, -1.2509836751313654e75), 356 | TD(7.524955249064026e109, 4.590038424351707e93, -4.3389309295776495e77), 357 | TD(2.045494911349825e110, 5.874933608518508e93, 1.4602190919301713e77), 358 | TD(5.5602316477276757e110, -2.3961412490467085e94, 7.325348790055507e77), 359 | TD(1.5114276650041035e111, 1.4805989167614457e94, -3.8326245424402867e77) 360 | ]; 361 | 362 | function exp(x::TD) 363 | isneg, abs_x = signbit(x), abs(x) 364 | if abs_x.hi <= 0.2 365 | z = exp_taylor(abs_x) 366 | elseif abs_x.hi <= 256.0 367 | f = floor(abs_x.hi) 368 | i = trunc(Int,f) 369 | d = abs_x - f 370 | expi = td_exp_int[i+1] 371 | dfifths = d / 5.0 372 | f = floor(dfifths.hi) 373 | i = trunc(Int,f) 374 | expi = expi * td_exp_fifths[i+1] 375 | d = d - TD(0.2,0.0,0.0)*f 376 | z = expi * exp_taylor(d) 377 | else 378 | NaN 379 | end 380 | isneg ? recip(z) : z 381 | end 382 | --------------------------------------------------------------------------------