Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 14 Jun 1996 10:30:22 +0200 (MET DST)
From:      Kees Jan Koster <dutchman@spase.nl>
To:        DARREND@novell.com (Darren Davis)
Subject:   Re: 64bit support? - Reply
Message-ID:  <199606140830.KAA00692@phobos.spase.nl>
In-Reply-To: <s1bfed67.038@fromGW> from "Darren Davis" at Jun 13, 96 10:38:09 am

next in thread | previous in thread | raw e-mail | index | archive | help
> 
> Yes, I would be very interested in it.  I actually came to the conclusion
> that moving to C++ was probably my best approach and allready started writing
> a quad class.  It would be nice to see what you did.
> 
Well. Eventually I found it back, I had to rip it from the production source.
I'm sorry, but I made some last-minute changes that I could not test. Someone
had copied the contents of the original quad.h into another file %-(

Anyway, here it is. I am interested in any changes/fixes you may have.

CAVEATS:
  - The multiplication code is flaky. I never needed it ;)
  - Now that I look at the code again, perhaps the passing of 'const quad' as
    'const quad &'. Gee, I really learned some more c++ in the past year ;)
  - There are plenty of details to improve.

  Groetjes,
    Kees Jan    (dutchman@spase.nl)

======- snip -===============================================
//
// quad.h, by Kees Jan Koster.
// Defines two 64-bit types, quad and u_quad.
//
#ifndef QUAD_H
#define QUAD_H

//
// Definitions
//
#include <sys/types.h>

#ifdef __GNUC__
typedef unsigned long long int u_quad;
#else
#ifndef __cplusplus
#error Use c++ to compile classes quad and u_quad.
#endif

class quad
{
  public:
    /* Construction... */
    quad () {}
    quad (const long int low)
    {
      hi = (low < 0L ? -1L : 0L);
      lo = (u_long) low;
    }
    quad (const long int high, const u_long low) {hi = high; lo = low;}

    quad (const quad &q) {hi = q.hi; lo = q.lo;}

     /* Comparing... */
    int operator == (const quad q) {return hi == q.hi && lo == q.lo;}
    int operator != (const quad q) {return hi != q.hi || lo != q.lo;}
    int operator >  (const quad q)
      {return (hi == q.hi ? lo >  q.lo : hi > q.hi);}
    int operator <  (const quad q)
      {return (hi == q.hi ? lo <  q.lo : hi < q.hi);}
    int operator >= (const quad q)
      {return (hi == q.hi ? lo >= q.lo : hi > q.hi);}
    int operator <= (const quad q)
      {return (hi == q.hi ? lo <= q.lo : hi < q.hi);}

/* Logical operations... */
    long int operator & (u_long mask) {return lo & mask;}
    quad operator &  (const quad &mask)
      {return quad (hi &  mask.hi, lo &  mask.lo);}
    quad operator |  (const quad &mask)
      {return quad (hi |  mask.hi, lo |  mask.lo);}
    quad operator ^  (const quad &mask)
      {return quad (hi ^  mask.hi, lo ^  mask.lo);}
    quad operator &= (const quad &mask)
      {return quad (hi &= mask.hi, lo &= mask.lo);}
    quad operator |= (const quad &mask)
      {return quad (hi |= mask.hi, lo |= mask.lo);}

/* Unary operations... */
    quad operator ~ (void) {return quad (~hi, ~lo);}
    quad operator ! (void) {return quad (0L, (hi || lo ? 0L : 1L));}
    quad operator + (void) {return *this;}
    quad operator - (void)
    {
      register u_long low = (~lo) + 1L;
/* If the result (low) is zero, there was carry. */
      return quad (~hi + (lo ? 0L : 1L), low);
     }

/* Shifting... */
    quad operator >> (const int shift)
    {
      return shift > 32 ?
          quad ((hi < 0L ? -1L : 0L), hi >> (shift - 32)) :
        quad (hi >> shift, (lo >> shift) | (hi << (32 - shift)));
    }

    quad operator << (const int shift)
    {
      return shift > 32 ?
        quad (lo << (shift - 32), 0L) :
        quad ((hi << shift) | (lo >> (32 - shift)), lo << shift);
    }

/* Arithmetic operations... */
    quad operator + (const quad q)
    {
      register u_long low = lo + q.lo;
/* If the result (low) is smaller than lo (or q.lo), there was carry. */
      return quad (hi + q.hi + (low < lo ? 1L : 0L), low);
    }
    quad operator - (const quad q)
    {
      register quad r = q;           /* Hack to avoid q being variable... */
      return (*this) + -r;           /* C++ won't accept -q if q is constant */
    }

    quad operator * (quad q)
/*
** Note: This implementation only multiplies the lower long ints
*/
    {
      register const long int a = lo & 0xffffL, b = (lo >> 16) & 0xffffL;
      register const long int c = q.lo & 0xffffL, d = (q.lo >> 16) & 0xffffL;

      register sign = 0;

      if (hi < 0) {sign = !sign; lo = -lo;}
      if (q.hi < 0) {sign = !sign; q.lo = -q.lo;}

      if (sign)
        return -(quad (0L, a*c) + (quad (0L, b*c) << 16) +
                (quad (0L, a*d) << 16) + quad (b*d, 0L));
      else
        return quad (0L, a*c) + (quad (0L, b*c) << 16) +
              (quad (0L, a*d) << 16) + quad (b*d, 0L);
    }

/* Other stuff... */
    void print (FILE *file)
    {
      fprintf (file, "0x%08lx%08lx", hi, lo);
    }

    char* hex(char *s)
    {
      sprintf (s, "0x%08lx%08lx", hi, lo);
      return s;
    }

  private:
    long int hi;
    u_long lo;
}

class u_quad
{
  public:
/* Construction... */
     u_quad (void)
        {hi=0L;lo=0L;}
     u_quad (const u_long low)
        {hi = 0L;lo = low;}
     u_quad (const u_long high, const u_long low)
        {hi = high; lo = low;}
     u_quad (const u_quad& q )
        {hi = q.hi; lo = q.lo;}

/* Comparing... */
     int operator == (const u_quad q) {return hi == q.hi && lo == q.lo;}
     int operator != (const u_quad q) {return hi != q.hi || lo != q.lo;}
     int operator >  (const u_quad q)
        {return (hi == q.hi ? lo >  q.lo : hi > q.hi);}
     int operator <  (const u_quad q)
        {return (hi == q.hi ? lo <  q.lo : hi < q.hi);}
     int operator >= (const u_quad q)
        {return (hi == q.hi ? lo >= q.lo : hi > q.hi);}
     int operator <= (const u_quad q)
        {return (hi == q.hi ? lo <= q.lo : hi < q.hi);}

/* Logical operations... */
     long int operator & (u_long mask) {return lo & mask;}
     u_quad operator &  (const u_quad &mask)
        {return u_quad (hi &  mask.hi, lo &  mask.lo);}
     u_quad operator |  (const u_quad &mask)
        {return u_quad (hi |  mask.hi, lo |  mask.lo);}
     u_quad operator ^  (const u_quad &mask)
        {return u_quad (hi ^  mask.hi, lo ^  mask.lo);}
     u_quad& operator &= (const u_quad &mask)
        {hi &= mask.hi; lo &= mask.lo; return *this;}
     u_quad& operator |= (const u_quad &mask)
        {hi |= mask.hi; lo |= mask.lo; return *this;}

/* Unary operations... */
     u_quad operator ~ (void) {return u_quad (~hi, ~lo);}
     u_quad operator ! (void) {return u_quad (0L, (hi || lo ? 0L : 1L));}
     u_quad operator + (void) {return *this;}
     quad operator - (void)
     {
        register u_long low = (~lo) + 1L;
/* If the result (low) is zero, there was carry. */
        return quad (~hi + (lo ? 0L : 1L), low);
     }

/* Shifting... */
     u_quad operator >> (const int shift)
     {
        return
        (shift == 0) ? u_quad(hi,lo) :
        (
          shift > 32 ?
          u_quad (0L, hi >> (shift - 32) ) :
          u_quad (hi >> shift, (lo >> shift) | (hi << (32 - shift)))
        ) ;
     }

     u_quad operator << (const int shift)
     {
        return
        (shift == 0) ? u_quad(hi,lo) :
        (
          shift > 32 ?
          u_quad ((shift > 63 ? 0L : lo << (shift - 32)), 0L) :
          u_quad ((hi << shift) | (lo >> (32 - shift)), lo << shift)
        );
     }

/* Arithmetic operations... */
     u_quad operator + (const u_quad q)
     {
        u_quad result;

    register u_long low = lo + q.lo;
// If the result (low) is smaller than lo (or q.lo), there was carry.
        return u_quad (hi + q.hi + ((low < lo) || (low < q.lo)), low);
     }

     u_quad operator * (u_quad q);
/*     u_quad operator * (u_quad q)
     {
        // CAUTION CAUTION CAUTION CAUTION CAUTION CAUTION CAUTION CAUTION
        // CAUTION CAUTION CAUTION CAUTION CAUTION CAUTION CAUTION CAUTION
        //
        // SIGNED MULTIPLICATION !!!
        //
        // CAUTION CAUTION CAUTION CAUTION CAUTION CAUTION CAUTION CAUTION
        // CAUTION CAUTION CAUTION CAUTION CAUTION CAUTION CAUTION CAUTION

        // remeber sign
        int sign = !!((hi & 0x80000000L) ^ (q.hi & 0x80000000L));

        u_long a_hi=hi,a_lo=lo;
        u_long b_hi=q.hi,b_lo=q.lo;

        // remove signs
        if (a_hi & 0x80000000L)
        {
            // negate
            //invert
            a_hi=~a_hi;a_lo=~a_lo;
            // add one
            if(a_lo==0xFFFFFFFFL)
            {
                a_hi=a_hi+1L;a_lo=0L;
            }
            else
            {
                a_lo++;
            }
        }
        if (b_hi & 0x80000000L)
        {
            // negate
            // invert
            b_hi=~b_hi;b_lo=~b_lo;
            // add one
            if(b_lo==0xFFFFFFFFL)
            {
                b_hi=b_hi+1L;b_lo=0L;
            }
            else
            {
                b_lo++;
            }
        }

        // multiply
        int i;
        u_long c_hi=0L,c_lo=0L;
        for(i=0;i<32;i++)
        {
            // addition
            if (a_lo & 1)
            {
                // c = c + b
                c_lo = c_lo + b_lo;
                c_hi = c_hi + b_hi + ((c_lo < b_lo) ? 1L : 0L);
            }
            // shift
            // a >> 1
            a_lo >>= 1;
            a_lo |= ((a_hi & 1L)?(0x80000000L):0L);
            a_hi >>= 1;
            // b << 1
            b_hi <<= 1;
            b_hi |= ((b_lo & 0x80000000L)?1L:0L);
            b_lo <<= 1;
        }

        // set sign
        if (sign)
        {
            // c = -c
            //invert
            c_hi=~c_hi;c_lo=~c_lo;
            // add one
            if(c_lo==0xFFFFFFFFL)
            {
                c_hi=c_hi+1L;c_lo=0L;
            }
            else
            {
                c_lo++;
            }
        }

        return u_quad(c_hi,c_lo);
     }
*/

/* Other stuff... */
     void print (FILE *file)
     {
        fprintf (file, "0x%08lx%08lx", hi, lo);
     }

     char* hex(char *s)
     {
        sprintf (s, "0x%08lx%08lx", hi, lo);
        return s;
     }

  private:
     u_long hi;
     u_long lo;
}

#endif // __GNUC__
#endif // QUAD_H
//
// -eof-



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199606140830.KAA00692>