
(* Author:  Walid Taha
   Date:    Thu Oct 25 16:32:25 EDT 2001 *)

Trx.init_times ()     (* Initialize a timer library *)


(* Chebyshev approximation, from paper by Robert Glueck et al. *)

let approx n xa xb func =
let k  = ref 0
and j  = ref 0
and xm = ref 0.0
and xp = ref  0.0
and sm = ref 0.0
and c  = Array.create n 0.0
and f  = Array.create (n+1) 0.0
and pi = 3.14
in 
 begin
  xp := (xb+.xa)/. 2.0;
  xm := (xb-.xa)/. 2.0;
  for k = 1 to n do
    f.(k) <- func(!xp+. !xm*.cos(pi*.((float k)-.0.5)/.2.0))
  done;

  for j = 0 to (n-1) do
    sm := 0.0;
    for k = 1 to n do
      sm := !sm +. f.(k)*.cos(pi*.(float j)*.((float k)-.0.5)/. (float n))
    done;
    c.(j) <- (2.0/.(float n))*. !sm
  done;
 c
 end;;

let lift x = .<x>.;;

let approx2 n xa xb func =
let k  = ref 0
and j  = ref 0
and xm = ref 0.0
and xp = ref  0.0
and sm = ref 0.0
and c  = Array.create n 0.0
and f  = Array.create (n+1) 0.0
and pi = 3.14
in 
.<
 begin
  xp := (.~xb+. .~xa)/. 2.0;
  xm := (.~xb-. .~xa)/. 2.0;
  .~(
  let seq = ref .<()>.
  in
  for k = 1 to n do
    seq := .<(.~(!seq);
              f.(k) <- .~func(!xp+. !xm*. .~(lift (cos(pi*.((float k)-.0.5)/.2.0)))))>.
  done;
  !seq
  );
  .~(
  let seq = ref .<()>.
  in
  for j = 0 to (n-1) do
    seq := .<(.~(!seq);
              sm := 0.0;
              .~(
              let seq2 = ref .<()>.
              in
              for k = 1 to n do
                seq2 := .<(.~(!seq2);
                            sm := !sm +. f.(k)*. .~(lift (cos(pi*.(float j)*.((float k)-.0.5)/. (float n)))))>.
              done;
              !seq2
              );
              c.(j) <- .~(lift ((2.0/.(float n))))*. !sm)>.
  done;
  !seq
  ); 
 c
 end
>.;;

let unstagedRunning = 
  Trx.timenew "unstaged running"(fun () -> approx 10 1.0 2.0 (fun x -> x*.x));;

let stage1 = 
  Trx.timenew "stage1"(fun () -> .<fun xa xb f ->
                                                .~(approx2 10 .<xa>. .<xb>. .<f>.)>.);;

let compiled = 
  Trx.timenew "compilation"(fun () -> .! stage1);;

let stage2 = 
  Trx.timenew "stage2"(fun () -> compiled 1.0 2.0 (fun x -> x*.x));;

let base = 
  Trx.timenew "baseline"(fun () -> ());;

let _ = Trx.print_times ()
