1pub fn integrate<F>(f: F, a: f64, b: f64) -> f64
40where
41 F: Fn(f64) -> f64,
42{
43 let c = 0.5 * (b - a);
52 let d = 0.5 * (a + b);
53
54 c * tanhsinh(|t| {
55 let out = f(c * t + d);
56 if out.is_finite() {
57 out
58 } else {
59 0.0
60 }
61 })
62}
63
64fn tanhsinh<F>(f: F) -> f64
66where
67 F: Fn(f64) -> f64,
68{
69 let mut integral = 0.0;
70
71 for i in 0..100 {
72 integral += WEIGHTS[i] * f(ABSCISSAE[i]);
73 }
74
75 integral
76}
77
78pub const ABSCISSAE: [f64; 100] = [
87 -1.0,
88 -1.0,
89 -1.0,
90 -1.0,
91 -1.0,
92 -1.0,
93 -1.0,
94 -1.0,
95 -1.0,
96 -1.0,
97 -1.0,
98 -1.0,
99 -1.0,
100 -1.0,
101 -1.0,
102 -1.0,
103 -0.999_999_999_999_999_999_999_999_92,
104 -0.999_999_999_999_999_999_999_999_95,
105 -0.999_999_999_999_999_999_999_999_98,
106 -0.999_999_999_999_999_999_999_999_91,
107 -0.999_999_999_999_999_999_999_999_95,
108 -0.999_999_999_999_999_999_999_998_77,
109 -0.999_999_999_999_999_999_999_103_26,
110 -0.999_999_999_999_999_999_703_932_4,
111 -0.999_999_999_999_999_950_531_716_2,
112 -0.999_999_999_999_995_4,
113 -0.999_999_999_999_755_4,
114 -0.999_999_999_991_728_4,
115 -0.999_999_999_814_670_3,
116 -0.999_999_997_111_343_6,
117 -0.999_999_967_297_845_9,
118 -0.999_999_720_654_543_6,
119 -0.999_998_137_805_321,
120 -0.999_990_019_143_856_7,
121 -0.999_955_840_978_693_4,
122 -0.999_834_913_162_265,
123 -0.999_467_635_803_999,
124 -0.998_491_938_731_602_9,
125 -0.996_186_771_585_243_7,
126 -0.991_272_560_236_550_9,
127 -0.981_701_565_973_876_9,
128 -0.964_495_379_931_111_4,
129 -0.935_708_688_740_139_8,
130 -0.890_613_153_970_636_9,
131 -0.824_190_972_468_412_2,
132 -0.731_982_954_977_568_5,
133 -0.611_228_933_047_550_6,
134 -0.462_072_342_445_637_1,
135 -0.288_435_163_890_398_6,
136 -0.098_120_697_049_078_77,
137 0.098_120_697_049_078_75,
138 0.288_435_163_890_398_64,
139 0.462_072_342_445_637_19,
140 0.611_228_933_047_550_7,
141 0.731_982_954_977_568_5,
142 0.824_190_972_468_412_2,
143 0.890_613_153_970_636_9,
144 0.935_708_688_740_139_9,
145 0.964_495_379_931_111_5,
146 0.981_701_565_973_876_9,
147 0.991_272_560_236_551,
148 0.996_186_771_585_243_7,
149 0.998_491_938_731_603,
150 0.999_467_635_803_999,
151 0.999_834_913_162_265,
152 0.999_955_840_978_693_5,
153 0.999_990_019_143_856_8,
154 0.999_998_137_805_321_1,
155 0.999_999_720_654_543_7,
156 0.999_999_967_297_846,
157 0.999_999_997_111_343_7,
158 0.999_999_999_814_670_2,
159 0.999_999_999_991_728_4,
160 0.999_999_999_999_755_4,
161 0.999_999_999_999_995_4,
162 0.999_999_999_999_999_950_531_74,
163 0.999_999_999_999_999_999_703_94,
164 0.999_999_999_999_999_999_999_156,
165 0.999_999_999_999_999_999_999_987,
166 0.999_999_999_999_999_999_999_985,
167 0.999_999_999_999_999_999_999_951,
168 0.999_999_999_999_999_999_999_958,
169 0.999_999_999_999_999_999_999_955,
170 0.999_999_999_999_999_999_999_912,
171 1.0,
172 1.0,
173 1.0,
174 1.0,
175 1.0,
176 1.0,
177 1.0,
178 1.0,
179 1.0,
180 1.0,
181 1.0,
182 1.0,
183 1.0,
184 1.0,
185 1.0,
186 1.0,
187];
188
189pub const WEIGHTS: [f64; 100] = [
191 0.0,
192 4.575_617_930_178_338e-295,
193 3.316_994_462_570_346e-260,
194 1.865_212_622_495_173_5e-229,
195 2.479_121_672_052_092e-202,
196 2.081_537_448_295_626e-178,
197 2.628_202_011_356_882_4e-157,
198 1.072_629_885_654_983_3e-138,
199 2.779_482_305_261_637e-122,
200 8.296_418_844_663_515e-108,
201 4.824_667_051_120_648e-95,
202 8.690_880_649_537_159e-84,
203 7.300_384_623_604_137e-74,
204 4.102_662_749_806_205e-65,
205 2.120_927_715_027_845e-57,
206 1.335_824_993_406_033_2e-50,
207 1.313_406_878_320_599_1e-44,
208 2.508_807_816_395_078_6e-39,
209 1.129_193_867_059_432_8e-34,
210 1.419_894_975_881_043_8e-30,
211 5.796_754_421_896_154_4e-27,
212 8.772_732_913_927_396e-24,
213 5.532_447_125_135_289e-21,
214 1.612_026_230_404_078_1e-18,
215 2.377_241_245_744_043_6e-16,
216 1.922_871_877_455_573e-14,
217 9.158_786_378_811_089e-13,
218 2.735_019_685_607_782_3e-11,
219 5.412_036_348_700_474e-10,
220 7.452_095_495_199_113e-9,
221 7.455_643_353_281_056e-8,
222 5.630_935_258_210_419e-7,
223 3.320_892_221_887_424e-6,
224 1.575_869_255_697_420_2e-5,
225 6.178_940_879_197_28e-5,
226 2.049_612_222_935_924_2e-4,
227 5.873_088_850_232_362e-4,
228 0.001_480_856_522_480_776_8,
229 0.003_339_108_906_155_36,
230 0.006_827_704_416_155_456,
231 0.012_809_851_589_261_179,
232 0.022_262_908_367_071_66,
233 0.036_106_623_280_003_48,
234 0.054_935_001_719_810_43,
235 0.078_672_104_392_875_16,
236 0.106_225_018_644_775_54,
237 0.135_274_854_478_869_08,
238 0.162_387_107_725_986_52,
239 0.183_570_841_955_285,
240 0.195_234_233_228_838_65,
241 0.195_234_233_228_838_65,
242 0.183_570_841_955_285,
243 0.162_387_107_725_986_52,
244 0.135_274_854_478_869_08,
245 0.106_225_018_644_775_54,
246 0.078_672_104_392_875_16,
247 0.054_935_001_719_810_43,
248 0.036_106_623_280_003_48,
249 0.022_262_908_367_071_66,
250 0.012_809_851_589_261_179,
251 0.006_827_704_416_155_456,
252 0.003_339_108_906_155_36,
253 0.001_480_856_522_480_776_8,
254 5.873_088_850_232_362e-4,
255 2.049_612_222_935_924_2e-4,
256 6.178_940_879_197_28e-5,
257 1.575_869_255_697_420_2e-5,
258 3.320_892_221_887_424e-6,
259 5.630_935_258_210_419e-7,
260 7.455_643_353_281_056e-8,
261 7.452_095_495_199_113e-9,
262 5.412_036_348_700_474e-10,
263 2.735_019_685_607_782_3e-11,
264 9.158_786_378_811_089e-13,
265 1.922_871_877_455_573e-14,
266 2.377_241_245_744_043_6e-16,
267 1.612_026_230_404_078_1e-18,
268 5.532_447_125_135_289e-21,
269 8.772_732_913_927_396e-24,
270 5.796_754_421_896_154_4e-27,
271 1.419_894_975_881_043_8e-30,
272 1.129_193_867_059_432_8e-34,
273 2.508_807_816_395_078_6e-39,
274 1.313_406_878_320_599_1e-44,
275 1.335_824_993_406_033_2e-50,
276 2.120_927_715_027_845e-57,
277 4.102_662_749_806_205e-65,
278 7.300_384_623_604_137e-74,
279 8.690_880_649_537_159e-84,
280 4.824_667_051_120_648e-95,
281 8.296_418_844_663_515e-108,
282 2.779_482_305_261_637e-122,
283 1.072_629_885_654_983_3e-138,
284 2.628_202_011_356_882_4e-157,
285 2.081_537_448_295_626e-178,
286 2.479_121_672_052_092e-202,
287 1.865_212_622_495_173_5e-229,
288 3.316_994_462_570_346e-260,
289 4.575_617_930_178_338e-295,
290 0.0,
291];
292
293#[cfg(test)]
298mod tests_integration {
299 use super::*;
300
301 use RustQuant_utils::{assert_approx_equal, RUSTQUANT_EPSILON as EPS};
302
303 #[test]
304 fn test_quadrature() {
305 fn f(x: f64) -> f64 {
306 (x.sin()).exp()
307 }
308
309 let integral = integrate(f, 0.0, 5.0);
310
311 assert_approx_equal!(integral, 7.189_119_252_343_784, EPS);
312 }
313}