diff --git a/src/bin/flat/main.rs b/src/bin/flat/main.rs index 98db0bc..ab7ff31 100644 --- a/src/bin/flat/main.rs +++ b/src/bin/flat/main.rs @@ -573,18 +573,26 @@ mod fns { pub external: f32, } + /// Продолжает функцию f с [-lim, lim] линейно в предположении f(±lim) = ±val, f'(±lim) = 1. + fn extend_linear(t: f32, f: impl FnOnce(f32) -> f32, lim: f32, val: f32) -> f32 { + if t.abs() <= lim { f(t) } else { t + t.signum() * (val - lim) } + } + + /// Продолжает функцию f с [-lim, lim] константой в предположении f(±lim) = val, f'(±lim) = 0. + fn extend_const(t: f32, f: impl FnOnce(f32) -> f32, lim: f32, val: f32) -> f32 { + if t.abs() <= lim { f(t) } else { val } + } + impl RectY { fn a(&self) -> f32 { -(self.external - self.internal) / self.internal.powi(2) } fn b(&self) -> f32 { 2.0 * self.external / self.internal - 1.0 } fn root(&self, x: f32) -> f32 { (self.b().powi(2) + 4.0 * self.a() * x.abs()).sqrt() } - pub fn x(&self, u: f32) -> f32 { (self.a() * u.abs() + self.b()) * u } - pub fn u(&self, x: f32) -> f32 { 0.5 * x.signum() * (-self.b() + self.root(x)) / self.a() } - pub fn dx(&self, u: f32) -> f32 { 2.0 * self.a() * u.abs() + self.b() } - pub fn du(&self, x: f32) -> f32 { 1.0 / self.root(x) } - - pub fn value(&self, x: f32) -> f32 { if x.abs() <= self.external { 1.0 / self.root(x) } else { 1.0 } } - pub fn derivative(&self, x: f32) -> f32 { if x.abs() <= self.external { -2.0 * x.signum() * self.a() * self.root(x).powi(-3) } else { 0.0 } } + pub fn x(&self, u: f32) -> f32 { extend_linear(u, |u| (self.a() * u.abs() + self.b()) * u, self.internal, self.external) } + pub fn u(&self, x: f32) -> f32 { extend_linear(x, |x| 0.5 * x.signum() * (-self.b() + self.root(x)) / self.a(), self.external, self.internal) } + pub fn dx(&self, u: f32) -> f32 { extend_const(u, |u| 2.0 * self.a() * u.abs() + self.b(), self.internal, 1.0) } + pub fn du(&self, x: f32) -> f32 { extend_const(x, |x| 1.0 / self.root(x), self.external, 1.0) } + pub fn d2u(&self, x: f32) -> f32 { extend_const(x, |x| -2.0 * x.signum() * self.a() * self.root(x).powi(-3), self.external, 0.0) } } } @@ -637,7 +645,7 @@ impl FloatExt2 for (f32, f32) { impl Metric for Rect { fn sqrt_at(&self, pos: Vec2) -> Decomp2 { let sx = self.fx().value(pos.x); - let sy = self.fy().value(pos.y); + let sy = self.fy().du(pos.y); let s = sx + sy - sx * sy; assert!(sx.is_finite()); assert!(sy.is_finite()); @@ -650,10 +658,10 @@ impl Metric for Rect { fn part_derivs_at(&self, pos: Vec2) -> Tens2 { let sx = self.fx().value(pos.x); - let sy = self.fy().value(pos.y); + let sy = self.fy().du(pos.y); let s = sx + sy - sx * sy; let dsx_dx = self.fx().derivative(pos.x); - let dsy_dy = self.fy().derivative(pos.y); + let dsy_dy = self.fy().d2u(pos.y); let ds2_dx = 2.0 * s * (1.0 - sy) * dsx_dx; let ds2_dy = 2.0 * s * (1.0 - sx) * dsy_dy; [