/* maccomp.c
   comparison between macros, inline functions and functions
*/

#include <stdlib.h>
#include <stdio.h>

#include <unistd.h>
#include <sys/times.h>     

typedef enum
{
  BEGIN,
  END,
  SHOW
} TimerStateType;

typedef struct         
{                      
  long    tps;         
  long    start_time;  
  long    end_time;    
  double  UserTime;    
  double  SystemTime;  
  double  ElapsedTime; 
  double  WaitTime;
  struct  tms start_cpu_time;
  struct  tms end_cpu_time;
} TimerType;           

void                                                                             
CPUTimer ( TimerType * t, TimerStateType state )                                                       
{                                                                                
  if ( state == BEGIN )                                                        
  {                                                                              
    t->tps = sysconf ( _SC_CLK_TCK );                                              
    t->start_time = 0;                                                             
    t->end_time = 0;                                                               
    t->UserTime = 0;                                                               
    t->SystemTime = 0;                                                             
    t->ElapsedTime = 0;
    t->WaitTime = 0;                                                            
    t->start_time = times ( &(t->start_cpu_time) );                              
  }                                                                              
  else if ( state == SHOW )
  {
    printf ( "Process Timer\n"
             "----------------------------------------\n"
             "User CPU Time  : %10.4f s\n"
             "System CPU Time: %10.4f s\n"
             "Wait Time      : %10.4f s\n" 
             "----------------------------------------\n"
             "Elapsed Time   : %10.4f s\n",
             t->UserTime, t->SystemTime, t->WaitTime, t->ElapsedTime );
  }
  else                                                   
  {                                                                              
    t->end_time = times ( &(t->end_cpu_time) );                                  
    t->ElapsedTime = ( (double)( t->end_time - t->start_time ) 
                     / (double) t->tps );                           
    t->UserTime    = ( (double)( t->end_cpu_time.tms_utime - t->start_cpu_time.tms_utime ) 
                     / (double) t->tps );  
    t->SystemTime  = ( (double)( t->end_cpu_time.tms_stime - t->start_cpu_time.tms_stime ) 
                     / (double) t->tps );
    t->WaitTime    = ( t->ElapsedTime - (t->UserTime + t->SystemTime) );
  }                                                                             
}                                                                                

#ifndef TRUE
#define TRUE 1
#endif

#ifndef FALSE
#define FALSE 0
#endif

/* macros */
#define SQR(x)    (x)*(x)
#define ABS(x)    (x < 0 ) ? (x*-1) : (x)
#define MIN(x,y)  ( (x) < (y) ) ? (x) : (y) 
#define MAX(x,y)  ( (x) > (y) ) ? (x) : (y)
#define ISEVEN(x) ( (x % 2) ? FALSE : TRUE )
#define ISODD(x)  ( (x % 2) ? TRUE : FALSE )

/* inline functions */
inline
float
Sqr ( float x )
{
  return ( x*x );
}

inline
float
Abs ( float x )
{
  if ( x < 0 )
    return ( x*-1 );
  else
    return ( x );
}

inline
float
Min ( float x, float y )
{
  if ( x < y )
    return ( x );
  else
    return ( y );
}

inline
float
Max ( float x, float y )
{
  if ( x > y )
    return ( x );
  else
    return ( y );
}

inline
int
Iseven ( int x )
{
  if ( x % 2 )
    return ( FALSE );
  else
    return ( TRUE );
}

inline
int
Isodd ( int x )
{
  if ( x % 2 )
    return ( TRUE );
  else
    return ( FALSE );
}

/* normal functions */
float
sqr ( float x )
{
  return ( x*x );
}

float
absv ( float x )
{
  if ( x < 0 )
    return ( x*-1 );
  else
    return ( x );
}

float
min ( float x, float y )
{
  if ( x < y )
    return ( x );
  else
    return ( y );
}

float
max ( float x, float y )
{
  if ( x > y )
    return ( x );
  else
    return ( y );
}

int
iseven ( int x )
{
  if ( x % 2 )
    return ( FALSE );
  else
    return ( TRUE );
}

int
isodd ( int x )
{
  if ( x % 2 )
    return ( TRUE );
  else
    return ( FALSE );
}

int
main ( int argc, char ** argv )
{

  float x = 3.33;
  float y = -4.23;
  int z = 3;
  int count = 10000000;
  int i = 0;
  int value = 0;

  /* timer setup */
  TimerType t;

  if ( argc > 1 )
  {
    count = atoi ( argv[1] );
    if ( count < 0 )
    {
      count = 10000000;
    }
  }

  printf ( "Comparison of macro, inline and functions\n\n" );

  printf ( "\nmacro\n" );
  printf ( "SQR (%.2f)       = %.2f\n", x, SQR(x) );
  printf ( "ABS (%.2f)      = %.2f\n", y, ABS(y) );
  printf ( "MAX (%.2f,%.2f) = %.2f\n", x, y, MAX(x,y) );
  printf ( "MIN (%.2f,%.2f) = %.2f\n", x, y, MIN(x,y) );
  printf ( "ISEVEN (%d)       = %d\n", z, ISEVEN(z) );
  printf ( "ISODD (%d)        = %d\n", z, ISODD(z) );

  printf ( "\ninline function\n" );
  printf ( "Sqr (%.2f)       = %.2f\n", x, Sqr(x) );
  printf ( "Abs (%.2f)      = %.2f\n", y, Abs(y) );
  printf ( "Max (%.2f,%.2f) = %.2f\n", x, y, Max(x,y) );
  printf ( "Min (%.2f,%.2f) = %.2f\n", x, y, Min(x,y) );
  printf ( "Iseven (%d)       = %d\n", z, Iseven(z) );
  printf ( "Isodd (%d)        = %d\n", z, Isodd(z) );  
     
  printf ( "\nfunction\n" );
  printf ( "%s\n","----------------------------------------" );
  printf ( "sqr (%.2f)       = %.2f\n", x, sqr(x) );
  printf ( "abs (%.2f)      = %.2f\n", y, absv(y) );
  printf ( "max (%.2f,%.2f) = %.2f\n", x, y, max(x,y) );
  printf ( "min (%.2f,%.2f) = %.2f\n", x, y, min(x,y) );
  printf ( "iseven (%d)       = %d\n", z, iseven(z) );
  printf ( "isodd (%d)        = %d\n", z, isodd(z) );  

  printf ( "\nTiming %d Min Macros\n\n", count );
  CPUTimer ( &t, BEGIN ); /* begin */
  for ( i=0; i<count; i++ )
  {
    value = MIN(x,y);
  }
  CPUTimer ( &t, END );
  CPUTimer ( &t, SHOW );

  printf ( "\nTiming %d Min inline Functions\n\n", count );
  CPUTimer ( &t, BEGIN ); /* begin */
  for ( i=0; i<count; i++ )
  {
    value = Min(x,y);
  }

  CPUTimer ( &t, END );
  CPUTimer ( &t, SHOW );
  printf ( "\nTiming %d min Functions\n\n", count );
  CPUTimer ( &t, BEGIN ); /* begin */
  for ( i=0; i<count; i++ )
  {
    value = min(x,y);
  }
  CPUTimer ( &t, END );
  CPUTimer ( &t, SHOW );

  return (1);
}

/* Example OutPut 
Comparison of macro, inline and functions


macro
SQR (3.33)       = 11.09
ABS (-4.23)      = 4.23
MAX (3.33,-4.23) = 3.33
MIN (3.33,-4.23) = -4.23
ISEVEN (3)       = 0
ISODD (3)        = 1

inline function
Sqr (3.33)       = 11.09
Abs (-4.23)      = 4.23
Max (3.33,-4.23) = 3.33
Min (3.33,-4.23) = -4.23
Iseven (3)       = 0
Isodd (3)        = 1

function
----------------------------------------
sqr (3.33)       = 11.09
abs (-4.23)      = 4.23
max (3.33,-4.23) = 3.33
min (3.33,-4.23) = -4.23
iseven (3)       = 0
isodd (3)        = 1

Timing 10000000 Min Macros

Process Timer
----------------------------------------
User CPU Time  :     3.2500 s
System CPU Time:     0.0000 s
Wait Time      :     0.0800 s
----------------------------------------
Elapsed Time   :     3.3300 s

Timing 10000000 Min inline Functions

Process Timer
----------------------------------------
User CPU Time  :     4.6700 s
System CPU Time:     0.0100 s
Wait Time      :     0.1100 s
----------------------------------------
Elapsed Time   :     4.7900 s

Timing 10000000 min Functions

Process Timer
----------------------------------------
User CPU Time  :     5.1700 s
System CPU Time:     0.0000 s
Wait Time      :     0.3900 s
----------------------------------------
Elapsed Time   :     5.5600 s

*/
