/* Profile.c - © '95 by Clemens Marschner */

#include <pragma/timer_lib.h>
#include <pragma/exec_lib.h>
#include <time.h>
#include <string.h>
#include <math.h>
#include <stream.h>

struct Library *OpenTimerLib();
struct Library *TimerBase = OpenTimerLib();
void CloseTimerLib(), InitSinTab();

inline double sintab(double);
double sint[360];
const double pi = 3.141592654;
const double hdpi = 128/pi, pidh = pi/128;
struct timerequest tr;

class Profiler {
  timeval tv1,tv2;
  char *string;
public:
  Profiler(char *desc) {     // Konstruktor
      if(!TimerBase) throw int(1);
      string = new char[strlen(desc)+1];
      if(!string)    throw int(2);
      strcpy(string, desc);  // und kopieren
      GetSysTime(&tv1);  // Zeit in timeval1
  }
  ~Profiler() {
      GetSysTime(&tv2);  // Zeit nach timeval2.
      SubTime(&tv2, &tv1);  // erste davon abzieh.
      cout << string << ": " << double(tv2.tv_secs)*
       1000 +double(tv2.tv_micro) * 1e-3 << " ms\n";
      delete string;
  }
};

void main() {
    if(!TimerBase) return;
    InitSinTab();
    cout << "Profilertest: 1000 mal Sinus.\nEinmal "
            "Systemfunktion, einmal aus Tabelle\n";
    double result;
    try {
        {Profiler p("sin()");
            for(double r = 0; r<2*pi; r+= 2*pi/1000)
                result = sin(r);
        }
        {Profiler p("sintab()");
            for(double r = 0; r<2*pi; r+= 2*pi/1000)
                result = sintab(r);
        }
        {Profiler p("Profiler");
            {Profiler p("leer");  }
        }
    } catch(...) { cout << "Fehler!\n"; }   
    CloseTimerLib();
}

struct Library *OpenTimerLib() {
    int error = OpenDevice(TIMERNAME, UNIT_MICROHZ,
                (struct IORequest*)&tr,0);
    if(error) return 0;
    return (struct Library*)tr.tr_node.io_Device;
}

void CloseTimerLib() {
    CloseDevice((struct IORequest*)&tr);
}

void InitSinTab() {
    for(int i = 0; i < 360; i++)
        sint[i] = sin(double(i)*pidh);
}

inline double sintab(double phi) {      
    return sint[int((phi*hdpi)+0.5)%360];
     // int(x+0.5) rundet richtig, nicht nur ab
}

