Source

papl / src / PaplInterpolate.ml

(*
  Copyright (c) 2012 Anders Lau Olsen.
  See LICENSE file for terms and conditions.
*)

type 'a t = 'a -> 'a -> float -> 'a

type 'a option_t = 'a -> 'a -> float -> 'a option

type 'a intermediary_t = 'a -> 'a -> 'a BatEnum.t

let stop () = raise BatEnum.No_more_elements

let intermediary_steps interpolate (metric, eps) = (); fun a b ->
  let ip = interpolate a b in
  let len = metric a b in
  let step = eps /. len in
  let pos = ref step in
  let next () =
    if !pos < 1.0 then
      let q = ip !pos in
        pos := !pos +. step;
        q
    else
      stop ()
  in
    BatEnum.from next

(* See also this alternative implementation that accepts a looser connection
   between the metric and the interpolation.

let intermediary_steps interpolate (metric, eps) start goal =
  let pos = ref start in
  let next () =
    let d = metric !pos goal in
      if d < eps then
        stop ()
      else
        let pos' = interpolate (eps /. d) !pos goal in
          pos := pos';
          pos'
  in
    BatEnum.from next
*)

module Float = struct
  let interpolate a b s = a +. (b -. a) *. s
end

module Int = struct
  let round v = int_of_float (v +. 0.5)

  let interpolate x y s =
    round (Float.interpolate (float_of_int x) (float_of_int y) s)
end

module Tuple2 = struct
  let interpolate ipa ipb (a0, b0) (a1, b1) =
    let ip1 = ipa a0 a1 in
    let ip2 = ipb b0 b1 in
      fun s -> ip1 s, ip2 s
end

module Tuple3 = struct
  let interpolate ipa ipb ipc (a0, b0, c0) (a1, b1, c1) =
    let ip1 = ipa a0 a1 in
    let ip2 = ipb b0 b1 in
    let ip3 = ipc c0 c1 in
      fun s -> ip1 s, ip2 s, ip3 s
end

let flip_interpolate ip s = (); fun a b -> ip a b s

module List = struct
  let interpolate ip xs ys s =
    List.map2 (flip_interpolate ip s) xs ys
end

module Array = struct
  let interpolate ip xs ys s =
    BatArray.map2 (flip_interpolate ip s) xs ys
end