/////////////////////////////////////////////////////////////////////////////
//       Copyright (C) 1992 MetaWare Incorporated; All Rights Reserved.    //
//                                                                         //
//                        MetaWare's C++ Benchmark                         //
//                               April 1992                                //
//									   //
/////////////////////////////////////////////////////////////////////////////
#if 0

     Redistribution of the source is permitted provided the entire
	    copyright notice and comments are retained.

                        Description of The C++ Benchmark
                        --------------------------------

Notations       Descriptions
---------       ------------
A vvvvv> B      A is virtual base class of B
A -----> B      A is a base class of B
A.v.func        func is a virtual function of A

test #1:
        Constructing a complicated object and call its virtual function,
        5000000 times:

        The object is an instance of a class with two virtual base class
        and one non-virtual base class. The non-virtual base class is again
        a class with two virtual base class and one non-virtual base class
        and so on.

        A.v.func        B
        v               v
        v               v
        vvvvvvvvvvvvvvvvvvvvvvv> C -----+
        v               v               |
        v               v               V
        vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv> D -----+ 
        v               v                      |
        v               v                      V
        vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv> E -----+
        v               v                             |
        v               v                             V
        vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv> F

        (Constructs F and calls F::func(), 5000000 times)


test #2:
        Constructing another complicated object and call its virtual 
        function, 5000000 times:

        The object is an instance of a class with one virtual base 
        class that is derived from another virtual base class and
        so on (5 levels deep).

        A.v.func
        v
        v
        V
        B
        v
        v
        V
        C
        v
        v
        V
        D
        v
        v
        V
        E
        
        (Constructs E and calls E::func(), 5000000 times)

test# 3:
        Assign one complicated object to another, 5000000 times:

        The object is an instance of a class with one non-virtual base 
	class and three virtual base class where one of them is a class 
	with one virtual base class and the other is a class with
        one non-virtual base class and two virtual base class.

        A       C    D          E       F
        v       |    v          |       v
        v       |   v           |       v
        V       |  v            |       v
        B v     | v             |       v
        v  v    |v              |      v
        v   v   V               |     v
        v    v> G               |    v
         v      v               |   v
          v     v               |  v
           v    v               | v
            v   v               |v
             v  v               V
              v vvvvvvvvvvvvvv> H

        (H a, b; assign b to a, 5000000 times).


#endif	/* 0 */

#include <time.h>

// for AT&T C++ on sun4 (This is the value they use -- instead of 60!)
#ifdef _cfront
#ifndef CLOCKS_PER_SEC
#define CLOCKS_PER_SEC	1000000.0
#endif
#endif

extern "C" { long clock(); }
extern "C" { printf(...); }

double second() {
   return (double)(((double)(clock()))/((double)(CLOCKS_PER_SEC)));
   }

// TEST 1
struct a { virtual void foo() {}; int x; };
struct b { int x; };
struct c : 	virtual a, virtual b { int y; };
struct d : c, 	virtual a, virtual b {};
struct e : d,	virtual a, virtual b {};
struct f : e, 	virtual a, virtual b { int z; };

void func1() {
    // Borland C++ (16bit) generates and executes 26 instructions to 
    //   initialize this.
    // Zortech (32bit) generates 24 and executes 18 (with optimization on full).
    //    -- the both with optimization turned on.
    // MetaWare High C++ (32bit) generates and executes 7, with optimization
    //    off, and 6 with optimization on.  So to which compiler would you 
    //    rather trust your execution speed?
    { f z;
      z.foo();
    }
    { f z;
      z.foo();
    }
    { f z;
      z.foo();
    }
    { f z;
      z.foo();
    }
    { f z;
      z.foo();
    }
    }

void test1(int lim, double &start) {
    printf("Construct a complicated object and "
    	   "call a virtual function %ld times:\n",(long)lim*(long)lim*5);
    start = second();
    // Use double loop so 16-bit compilers won't have a fit:
    for (int i = 0; i < lim; i++) 
    	for (int j = 0; j < lim; j++) 
    	    func1(); 
    }


// TEST 2
struct ms1 {
	int ms1f; 
	virtual void foo() {}
	};
struct ms5 : virtual ms1  {int ms5f;} ;
struct ms10: virtual ms5  {int ms10f;};
struct ms15: virtual ms10 {int ms15f;};
struct ms20: virtual ms15 {int ms20f;};
void func2() {
   { ms20 x, *p = &x; p->foo();
   }
   { ms20 x, *p = &x; p->foo();
   }
   { ms20 x, *p = &x; p->foo();
   }
   { ms20 x, *p = &x; p->foo();
   }
   { ms20 x, *p = &x; p->foo();
   }
   }

void test2(int lim, double &start) {
    printf("Construct a different complicated object and "
    	   "call a virt. func. %ld times:\n",(long)lim*(long)lim*5);
    start = second();
    // Use double loop so 16-bit compilers won't have a fit:
    for (int i = 0; i < lim; i++) 
    	for (int j = 0; j < lim; j++) 
    	    func2(); 
    }


// TEST 3
struct s0 { int f0; };
struct s1: virtual s0 { int f; };
struct fill0 { int x; };
struct fill1 { int y; };
struct fill2 { int y; };
struct fill3 { int y; };
struct s2: fill0, virtual s1, fill1 	{ int f2; };
struct s3: fill2, virtual s1, s2, fill3 { int f3; };
void func3(s3&x, s3&y) {  
    x = y;
    x = y;
    x = y;
    x = y;
    x = y;
    }

void test3(int lim, double &start) {
    printf("Assign one complicated object to another "
    	   "%ld times:\n",(long)lim*(long)lim*5);
    start = second();
    // Use double loop so 16-bit compilers won't have a fit:
    for (int i = 0; i < lim; i++) 
    	for (int j = 0; j < lim; j++) {
    	    s3 a,b;
    	    func3(a,b);
    	    }
    }


extern "C" int atoi(...);

// The version of AT&T C-front we have does not allow automatic 
//	initialization of aggregate, so the following is declared global.
void (*funcs[])(int,double&)={test1,test2,test3,0};
void (**p)(int,double&)=funcs;

void main (int argc, char **argv) {
    int lim=0;
    if (argc>1) lim = atoi(argv[1]);
    if (lim < 1000) lim=1000;
    static char *banner[] = {
 "+------------------------------------------------------------------+",
 "|                     MetaWare's C++ Benchmark                     |",
 "|                                                                  |",
 "|   Copyright (C) 1992 MetaWare Incorporated; All Rights Reserved. |",
 "|                            April 1992                            |",
 "+------------------------------------------------------------------+",0};
    for (char **q = banner; *q; q++) printf("  %s\n",*q);
    for (; *p; p++) {
	double clockb;
	printf("\n");
    	(*p)(lim,clockb);
    	double diff = second()-clockb;
    	printf("%f seconds\n",diff);
    	}
    }

