-- | Interpolate between values.
module Numerics.Interpolation (
      lerp

    , lerpDI
    , lerpID
    , lerpII
) where



import Algebra.VectorSpace



-- | Linearly interpolate the interval \([a,b]\) to \([x,y]\). In computer graphics
-- lingo, this is often known as /lerp/.
--
-- \[
-- f(t) = x + \frac{y-x}{b-a} (t-a)
-- \]
--
-- >>> lerp (0,1) (10,20) 0.5
-- 15.0
lerp :: VectorSpace vec => (Double, Double) -> (vec, vec) -> Double -> vec
lerp :: forall vec.
VectorSpace vec =>
(Double, Double) -> (vec, vec) -> Double -> vec
lerp (Double
a, Double
b) (vec
x, vec
y) Double
t = vec
x vec -> vec -> vec
forall v. VectorSpace v => v -> v -> v
+. ((Double
tDouble -> Double -> Double
forall a. Num a => a -> a -> a
-Double
a) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ (Double
bDouble -> Double -> Double
forall a. Num a => a -> a -> a
-Double
a))Double -> vec -> vec
forall v. VectorSpace v => Double -> v -> v
*.(vec
yvec -> vec -> vec
forall v. VectorSpace v => v -> v -> v
-.vec
x)

-- | Linear interpolation from 'Double' to 'Integral' (hence: @DI@).
lerpDI :: Integral int => (Double, Double) -> (int, int) -> Double -> int
lerpDI :: forall int.
Integral int =>
(Double, Double) -> (int, int) -> Double -> int
lerpDI (Double, Double)
ab (int, int)
xy = Double -> int
forall b. Integral b => Double -> b
forall a b. (RealFrac a, Integral b) => a -> b
round (Double -> int) -> (Double -> Double) -> Double -> int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Double, Double) -> (Double, Double) -> Double -> Double
forall vec.
VectorSpace vec =>
(Double, Double) -> (vec, vec) -> Double -> vec
lerp (Double, Double)
ab ((int, int) -> (Double, Double)
forall a. Integral a => (a, a) -> (Double, Double)
doubles (int, int)
xy)

-- | Linear interpolation from 'Integral' to 'Double' (hence: @ID@).
lerpID :: Integral int => (int, int) -> (Double, Double) -> int -> Double
lerpID :: forall int.
Integral int =>
(int, int) -> (Double, Double) -> int -> Double
lerpID (int, int)
ab (Double, Double)
xy int
t = (Double, Double) -> (Double, Double) -> Double -> Double
forall vec.
VectorSpace vec =>
(Double, Double) -> (vec, vec) -> Double -> vec
lerp ((int, int) -> (Double, Double)
forall a. Integral a => (a, a) -> (Double, Double)
doubles (int, int)
ab) (Double, Double)
xy (int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral int
t)

-- | Linear interpolation from 'Integral' to 'Integral' (hence: @II@).
lerpII :: (Integral intA, Integral intB) => (intA, intA) -> (intB, intB) -> intA -> intB
lerpII :: forall intA intB.
(Integral intA, Integral intB) =>
(intA, intA) -> (intB, intB) -> intA -> intB
lerpII (intA, intA)
ab (intB, intB)
xy intA
t = Double -> intB
forall b. Integral b => Double -> b
forall a b. (RealFrac a, Integral b) => a -> b
round ((Double, Double) -> (Double, Double) -> Double -> Double
forall vec.
VectorSpace vec =>
(Double, Double) -> (vec, vec) -> Double -> vec
lerp ((intA, intA) -> (Double, Double)
forall a. Integral a => (a, a) -> (Double, Double)
doubles (intA, intA)
ab) ((intB, intB) -> (Double, Double)
forall a. Integral a => (a, a) -> (Double, Double)
doubles (intB, intB)
xy) (intA -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral intA
t))

doubles :: Integral a => (a, a) -> (Double, Double)
doubles :: forall a. Integral a => (a, a) -> (Double, Double)
doubles (a
a,a
b) = (a -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
a, a -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
b)