Listing 3: Tracking down performance problems


//complex.cpp:

complex _Cdecl _FARFUNC operator*(complex _FAR & z1,
                               complex _FAR & z2)
{
  double temp_re = z1.re*z2.re - z1.im*z2.im;
  double temp_im = z1.im*z2.re + z1.re*z2.im;
  return complex(temp_re, temp_im);
}

double _Cdecl _FARFUNC norm(complex _FAR & z)
{
/*
  return z.re*z.re + z.im*z.im;
*/
asm LES_  bx, z
asm fld REAL ES_ [bx]
asm fmul  st(0), st(0)
asm fld REAL ES_ [bx+8]
asm fmul  st(0), st(0)
asm fadd
  RETURN_TOS;
}

inline complex _RTLENTRY conj(complex _FAR & __z)
{
  return complex(__z.re, -__z.im);
}

inline complex _RTLENTRY
operator/(complex _FAR & __z1, double __re_val2)
{
  return complex(__z1.re/__re_val2,
                __z1.im/__re_val2);
}

complex _Cdecl _FARFUNC
operator/(complex _FAR & z1, complex _FAR & z2)
{
  return z1 * conj(z2) / norm(z2);
}


//cmplxtst.cpp:

#include    <stdio.h>
#include    <time.h>
#include    <fstream.h>

//#include    "complex.h"
class complex {
// This is essentialy Borland's class stripped down
// to support just mult and div.

public:
  complex(double __re_val, double __im_val=0);
  complex();
friend complex operator* ( const complex &x,
                         const complex &y );
friend complex operator/ ( const complex &x,
                         const complex &y );

public:
    double im,re;
};

/* Prototypes */
complex plex_div(const complex &a,
                const complex &b);
complex plex_mult(const complex &a,
                 const complex &b);

inline complex::complex(double __re_val,
                      double __im_val)
{ // this is Borland's
  re = __re_val;
  im = __im_val;
}

inline complex::complex()
{ // this is Borland's
/* if you want your complex numbers initialized ...
  re = im = 0;
*/
}


inline complex operator* ( const complex &x,
                         const complex &y )
{ // This is mine
    return
    complex(x.re * y.re - x.im * y.im,
        x.re * y.im + x.im * y.re );
}

inline complex operator/ (const complex &a,
                          const complex &b)
// This is mine
    double denom = b.re*b.re + b.im*b.im;
    return complex(
        (a.re * b.re + a.im * b.im) / denom,
        (a.im * b.re - a.re * b.im) / denom );
}


complex plex_div(const complex &a,
                const complex &b)
{ // this is yours
    complex result;

    double denom = b.re*b.re + b.im*b.im;
    result.re = (a.re * b.re + a.im * b.im) / denom;
    result.im = (a.im * b.re - a.re * b.im) / denom;
    return(result);
}
complex plex_mult(const complex &a, const complex &b)
{ // this is yours
complex result;

    result.re = (a.re * b.re - a.im * b.im);
    result.im = (a.re * b.im + a.im * b.re);

    return(result);
}
/* ========================================== */
int main(void)
{
    const long ITER = 200000L;
    cout << endl
         << "Complex number calc comparison for "
         << ITER << " iterations" << endl;

    time_t start_time,end_time,calc_time;
    long i;

    complex a,b,c;
    a = complex(19.45,23.76);
    b = complex(-12.44,7.995);

    start_time = time(NULL);
    /* Do a number of calculations */
    c = a*b;

    for (i=0; i<ITER; i++)
    {
        c = a * c;
        c = a / c;
    }
    end_time = time(NULL);
    calc_time = end_time-start_time;

    cout << "Calc time using overloaded ops: "
        << calc_time << " secs" << endl;
    /* ========================================= */

    start_time = time(NULL);
    c = plex_mult(a,b);
    for (i=0; i<ITER; i++)
    {
        c = plex_mult(a,c);
        c = plex_div(a,c);
    }
    end_time = time(NULL);
    calc_time = end_time-start_time;

    cout << "Calculation time with user functions: "
        << calc_time << " secs" << endl;

    return 0;
}
/* End of File */