@@ -131,9 +131,63 @@ The implementation ensures `logcosh(-x) = logcosh(x)`.
131
131
"""
132
132
function logcosh (x:: Real )
133
133
abs_x = abs (x)
134
+ if (x isa Union{Float32, Float64}) && (abs_x < oftype (x, 0.7373046875 ))
135
+ return logcosh_ker (x)
136
+ end
134
137
return abs_x + log1pexp (- 2 * abs_x) - IrrationalConstants. logtwo
135
138
end
136
139
140
+ """
141
+ logcosh_ker(x::Union{Float32, Float64})
142
+
143
+ The kernel of `logcosh`.
144
+
145
+ The polynomial coefficients were found using Sollya:
146
+
147
+ ```sollya
148
+ prec = 500!;
149
+ points = 50001!;
150
+ accurate = log(cosh(x));
151
+ domain = [-0.125, 0.7373046875];
152
+ constrained_part = (x^2) / 2;
153
+ free_monomials_32 = [|4, 6, 8, 10, 12|];
154
+ free_monomials_64 = [|4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24|];
155
+ polynomial_32 = fpminimax(accurate, free_monomials_32, [|single...|], domain, constrained_part);
156
+ polynomial_64 = fpminimax(accurate, free_monomials_64, [|double...|], domain, constrained_part);
157
+ polynomial_32;
158
+ polynomial_64;
159
+ ```
160
+ """
161
+ function logcosh_ker (x:: Union{Float32, Float64} )
162
+ x² = x * x
163
+ if x isa Float32
164
+ p = (
165
+ 5f-1 ,
166
+ - 0.083333164f0 ,
167
+ 0.022217678f0 ,
168
+ - 0.0067060017f0 ,
169
+ 0.0020296266f0 ,
170
+ - 0.00044135848f0 ,
171
+ )
172
+ elseif x isa Float64
173
+ p = (
174
+ 5e-1 ,
175
+ - 0.08333333333332801 ,
176
+ 0.02222222222164912 ,
177
+ - 0.0067460317245250445 ,
178
+ 0.0021869484500251714 ,
179
+ - 0.0007385985435311435 ,
180
+ 0.0002565500026777061 ,
181
+ - 9.084985367586575e-5 ,
182
+ 3.2348259905568986e-5 ,
183
+ - 1.1058814347469105e-5 ,
184
+ 3.16293199955507e-6 ,
185
+ - 5.312230207322749e-7 ,
186
+ )
187
+ end
188
+ evalpoly (x², p) * x²
189
+ end
190
+
137
191
"""
138
192
$(SIGNATURES)
139
193
0 commit comments