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>
