| 218 SupportProductFirst(ref cut, |
218 SupportProductFirst(ref cut, |
| 219 ref gaussian)) = self; |
219 ref gaussian)) = self; |
| 220 let a = cut.r.value(); |
220 let a = cut.r.value(); |
| 221 let b = ind.r.value(); |
221 let b = ind.r.value(); |
| 222 let σ = gaussian.variance.value().sqrt(); |
222 let σ = gaussian.variance.value().sqrt(); |
| 223 let π = F::PI; |
|
| 224 let t = F::SQRT_2 * σ; |
223 let t = F::SQRT_2 * σ; |
| 225 let c = σ * (8.0/π).sqrt(); |
224 let c = 0.5; // 1/(σ√(2π) * σ√(π/2) = 1/2 |
| 226 |
225 |
| 227 // This is just a product of one-dimensional versions |
226 // This is just a product of one-dimensional versions |
| 228 let unscaled = y.product_map(|x| { |
227 y.product_map(|x| { |
| 229 let c1 = -(a.min(b + x)); //(-a).max(-x-b); |
228 let c1 = -(a.min(b + x)); //(-a).max(-x-b); |
| 230 let c2 = a.min(b - x); |
229 let c2 = a.min(b - x); |
| 231 if c1 >= c2 { |
230 if c1 >= c2 { |
| 232 0.0 |
231 0.0 |
| 233 } else { |
232 } else { |
| 234 let e1 = F::cast_from(erf((c1 / t).as_())); |
233 let e1 = F::cast_from(erf((c1 / t).as_())); |
| 235 let e2 = F::cast_from(erf((c2 / t).as_())); |
234 let e2 = F::cast_from(erf((c2 / t).as_())); |
| 236 debug_assert!(e2 >= e1); |
235 debug_assert!(e2 >= e1); |
| 237 c * (e2 - e1) |
236 c * (e2 - e1) |
| 238 } |
237 } |
| 239 }); |
238 }) |
| 240 |
|
| 241 unscaled / gaussian.scale() |
|
| 242 } |
239 } |
| 243 } |
240 } |
| 244 |
241 |
| 245 impl<F : Float, R, C, S, const N : usize> Apply<Loc<F, N>> |
242 impl<F : Float, R, C, S, const N : usize> Apply<Loc<F, N>> |
| 246 for Convolution<CubeIndicator<R, N>, BasicCutGaussian<C, S, N>> |
243 for Convolution<CubeIndicator<R, N>, BasicCutGaussian<C, S, N>> |
| 274 SupportProductFirst(ref cut, |
271 SupportProductFirst(ref cut, |
| 275 ref gaussian)) = self; |
272 ref gaussian)) = self; |
| 276 let a = cut.r.value(); |
273 let a = cut.r.value(); |
| 277 let b = ind.r.value(); |
274 let b = ind.r.value(); |
| 278 let σ = gaussian.variance.value().sqrt(); |
275 let σ = gaussian.variance.value().sqrt(); |
| 279 let π = F::PI; |
|
| 280 let t = F::SQRT_2 * σ; |
276 let t = F::SQRT_2 * σ; |
| 281 let c = σ * (8.0/π).sqrt(); |
277 let c = 0.5; // 1/(σ√(2π) * σ√(π/2) = 1/2 |
| 282 let cd = (8.0).sqrt(); // σ * (8.0/π).sqrt() / t * (√2/π) |
278 let c_div_t = c / t; |
| 283 |
279 |
| 284 // Calculate the values for all component functions of the |
280 // Calculate the values for all component functions of the |
| 285 // product. This is just the loop from apply above. |
281 // product. This is just the loop from apply above. |
| 286 let unscaled_vs = y.map(|x| { |
282 let unscaled_vs = y.map(|x| { |
| 287 let c1 = -(a.min(b + x)); //(-a).max(-x-b); |
283 let c1 = -(a.min(b + x)); //(-a).max(-x-b); |
| 304 } else { |
300 } else { |
| 305 // erf'(z) = (2/√π)*exp(-z^2), and we get extra factor -1/√(2*σ) = -1/t |
301 // erf'(z) = (2/√π)*exp(-z^2), and we get extra factor -1/√(2*σ) = -1/t |
| 306 // from the chain rule |
302 // from the chain rule |
| 307 let de1 = (-(c1/t).powi(2)).exp(); |
303 let de1 = (-(c1/t).powi(2)).exp(); |
| 308 let de2 = (-(c2/t).powi(2)).exp(); |
304 let de2 = (-(c2/t).powi(2)).exp(); |
| 309 cd * (de1 - de2) |
305 c_div_t * (de1 - de2) |
| 310 } |
306 } |
| 311 }) / gaussian.scale() |
307 }) |
| 312 } |
308 } |
| 313 } |
309 } |
| 314 |
310 |
| 315 impl<F : Float, R, C, S, const N : usize> Differentiable<Loc<F, N>> |
311 impl<F : Float, R, C, S, const N : usize> Differentiable<Loc<F, N>> |
| 316 for Convolution<CubeIndicator<R, N>, BasicCutGaussian<C, S, N>> |
312 for Convolution<CubeIndicator<R, N>, BasicCutGaussian<C, S, N>> |