#! /usr/bin/perl -w
# XcuteF  <.ccf file> [<count>] [-G] "runs" and [plots] a component behavior.
#
#  The .ccf file may point to either a theory-created file or an executable.
#  If the latter, the theory file is assumed to be available with the proper
#  approximation option.  Default for the optional count is about 5 times 
#  the number of subdomains.
#  If -G option is set, then output is to X11 window in addition to a PostScript file.
#  In any case, five .plt files are made of the graph data
#
use samplingf;
unless (defined($ARGV[0])) {
  die "A .ccf[t] file must be given";
}
$ccf = $ARGV[0];
open(CCF, $ccf) || die "given file ",$ccf," not found";
chop($name = <CCF>);
$count = 0; #to test later for the optional argument
if (defined($ARGV[1])) {
  if ($ARGV[1] eq "-G") {
    $DISPoption = 1;
  } else { #fix this mess TBD
    $count = $ARGV[1];
    if (defined($ARGV[2]) && $ARGV[2] eq "-G") {
      $DISPoption = 1;
    }
  }
}

if ($name !~ /^theory/) {  #regular .ccf, measure
  unless (-x $name) {die "No code file to measure";}
  # BUT: the corresponding xxx.ccft file must also exist 
  $ccftFile = $ccf."t";  #assume it was xxx.ccf, make name xxx.ccft
  unless (-e $ccftFile) {
    die "a `theory' file (.ccft) must exist for the executable";
  }
  $theoryonly = 0;
  #find the extremes of the domain
  $line = <CCF>;
  @vals = split(" ",$line);
  $left = $vals[0];
  $k = 0;
  while ($line) {
    @vals = split(" ",$line);
    $line = <CCF>;
    $k++;
  }
  $numSubd = $k;
  unless ($count) { #no param given
    $count = 5*$numSubd;
  }
  $right = $vals[1];
  #debug
  #print "[$left, $right)  $k $count\n";
  printf "Sampling [%.2f, %.2f) for %d points\n",$left,$right,$count;
  open(M,">meas.plt");
  open(MR,">runmeas.plt");
  $sed = "sed 's/^/out:  /'";  # command to reproduce stdin to stdout with a leading "out:  "
  $y_sqrs = 0;
  $t_sqrs = 0;
  &samplingf::init($left,$right,$count);
  while (($input = &samplingf::next) ne ".") {
    $cmd = "(echo ".$input." | ".$name." | ".$sed.") 2>&1|" ;
    open(PM, $cmd);
    $rmeas = 0;
    while ($line = <PM>) {  #not eof, all output from this system on this input
      # results all come out together, but stdout is preceeded by "out:  "
      @outstrm = split(' ',$line);
      #debug
      #print "$line \n";
      if ($outstrm[0] =~ /out:/) {
        $meas = $outstrm[1];
      }
      else {
        $rmeas += $outstrm[0];
      }
    }
    close(PM);
    $y_sqrs += $meas*$meas;
    $t_sqrs += $rmeas*$rmeas;
    print M "$input $meas \n";
    print MR "$input $rmeas \n";
  } #end loop over inputs
  $yrms = sqrt($y_sqrs/$count);
  $trms = sqrt($t_sqrs/$count);
  close(M);
  close(MR);
  close(CCF);
  open(CCF,"<".$ccftFile) or die "No theory file"; #should never happen; checked above
  $name = <CCF>;
  unless ($name =~ /^theory/) {die "The `theory' file doesn't appear to be one";}
} else { #end dealing with executable file, must be theory only
  $theoryonly = 1;
}

# In either case, CCF is now open to the "theory" file, 1st line in $name
@codes = split(" ",$name);
$rely = 0; #  assume it is run time in the theory file
if (defined($codes[3]) && $codes[2] eq "r") { #reliability instead of run time
  $rely = 1;
  $conf = $codes[3];
}
$k = 0;
$line = <CCF>;
@subd = split(" ",$line);
open(B,">subd.plt"); #for marking boundaries
open(C,">pred.plt"); #calculation values
open(CR,">runpred.plt"); #calc runtimes
$WtdVerr = 0;
$WtdRerr = 0;
unless ($theoryonly) {
  if ($rely) { #reliability
    print "normalized rms func error	$conf-% confidence\n";
    print "interval	func		reliability\n";
  } else { #run time
    print "normalized rms errors\n";
    print "interval	func	run\n";
  }
}
while ($line) { #read and store boundaries, plot theory.
  @subd = split(" ",$line);
  $LB[$k] = $subd[0];
  print B "$subd[0] 0\n";
  $UB[$k] = $subd[1];
    $slope = $subd[2];
    $intcpt = $subd[3];
    $rslope = $subd[4];
    $rintcpt = $subd[5];
    $v1 = $slope*$LB[$k] + $intcpt;
    $v2 = $slope*$UB[$k] + $intcpt;
    $r1 = $rslope*$LB[$k] + $rintcpt;
    $r2 = $rslope*$UB[$k] + $rintcpt;
    print C "$LB[$k] $v1\n";
    print C "$UB[$k] $v2\n";
    print CR "$LB[$k] $r1\n";
    print CR "$UB[$k] $r2\n";
    unless ($theoryonly) {
      $verr = 100*($subd[6]/$yrms);
      $rerr = 100*$subd[7]/$trms;
    }
    $fform = "%3.2f";
    if ($rely) { #relability, correct "run time" error to reliability value
      $rerr = $rintcpt;
      $fform = "	%5.4f";
    }
    
  unless ($theoryonly) {
    $WtdVerr += $verr*($UB[$k] - $LB[$k]);
    $WtdRerr += $rerr*($UB[$k] - $LB[$k]);
    printf "[%.2f, %.2f):	%3.2f%%	$fform%%\n",$LB[$k], $UB[$k], $verr, $rerr;
  }
  $line = <CCF>;
  $k++;
}
unless ($theoryonly) {
  $WtdVerr /= $UB[$k-1] - $LB[0];
  $WtdRerr /= $UB[$k-1] - $LB[0];
  printf "Weighted average:	%3.2f%%	$fform%%\n", $WtdVerr, $WtdRerr;
}
close(C);
close(CR);
print B "$UB[$k-1] 0\n";
close(B);


open(PF,">complot");  #put postscript plot in plot.ps
print PF "set terminal postscript color\n";
print PF qq(set output "plot.ps"\n);
if ($theoryonly) {
  print PF "plot ";
} else {
  print PF qq(plot "meas.plt", "runmeas.plt", ); #plot runtime even though it's reliability
}
print PF qq("subd.plt" with points pt 2 pointsize 3, "pred.plt" with lines, "runpred.plt" with lines\n);
close(PF);
system("gnuplot complot");

if ($DISPoption) {
  $meastring = qq("meas.plt" axes x1y1 with lines lt 4,);
  $runmeastring = qq("runmeas.plt" axes x1y2 with lines lt 5,);
  if ($rely) {
    $runmeastring = "";
  }
  if ($theoryonly) {
    $meastring = "";
    $runmeastring = "";
  }
  open(PF,">complot");  
  print PF "set terminal x11\n";
  print PF "set nokey\n";
  #print PF "set size 1.3,1.3\n";
  print PF qq(set nox2tics\n);
  print PF qq(set border 11\n);
  print PF qq(set xlabel "Input showing subdomains" font "Helvetica,16"\n);
  print PF qq(set ylabel "Functional output values" font "Helvetica,16"\n);
  print PF qq(set xtics nomirror font "Helvetica,14"\n);
  print PF qq(set ytics nomirror font "Helvetica,14"\n);
  print PF qq(set y2tics font "Helvetica,14"\n);
  if ($rely) {
    print PF qq(set y2label "$conf%-confidence reliability bound" font "Helvetica,16"\n);
  } else {
    print PF qq(set y2label "Run time values" font "Helvitica,16"\n);
  }
  print PF qq(plot "runpred.plt" axes x1y2 with lines lt 3,"subd.plt" axes x1y1 with points pointsize 3,$meastring $runmeastring "pred.plt" axes x1y1 with lines lt -1\n);
  close(PF);
  system("gnuplot -persist complot");
}
