module Amethyst.PiecewiseLinear.As.Float where
open import Amethyst.PiecewiseLinear.Base
open import Data.Bool as Bool using (Bool; true; false; if_then_else_; not)
open import Data.Float as Float using (Float; _+_; _*_; _≤ᵇ_)
open import Data.Nat as Nat using (ℕ; suc; zero; NonZero)
open import Data.Vec as Vec using (Vec)
private
variable
pieces : ℕ
lower : Float
step : Float
upper : Float
private
evalLineSegment : (ls : LineSegment lower upper) (x : Float) → Float
evalLineSegment ls x = (x * slope) + intercept
where open LineSegment ls using (slope; intercept)
evalLineSegments : .{{NonZero pieces}} → (pl : LineSegments lower step pieces) → Float → Float
evalLineSegments {_} {lower} {step} (ls ∷ []) x = evalLineSegment ls x
evalLineSegments {_} {lower} {step} (ls ∷ pl@(_ ∷ _)) x =
if x ≤ᵇ lower + step then evalLineSegment ls x else
evalLineSegments pl x
evalOutOfBoundsStrat : OutOfBoundsStrategy → LineSegment lower upper → Bool → Float → Float
evalOutOfBoundsStrat {_} {_} (constant c) _ _ _ = c
evalOutOfBoundsStrat {_} {_} extrapolate ls _ x = evalLineSegment ls x
evalOutOfBoundsStrat {lower} {upper} nearestValue ls below x = evalLineSegment ls (if below then lower else upper)
eval : PiecewiseLinearFn → Float → Float
eval f x = let module F = PiecewiseLinearFn f in
if x ≤ᵇ F.lower then
evalOutOfBoundsStrat F.lowerOOBStrat (first F.lineSegments) true x
else if F.upper ≤ᵇ x then
evalOutOfBoundsStrat F.upperOOBStrat (last F.lineSegments) false x
else
evalLineSegments F.lineSegments x