Files
microser/mmslib/util/stdtime_quadlib.c
2026-06-15 15:48:16 +08:00

1600 lines
44 KiB
C

/*****************************************************************************/
/* SISCO SOFTWARE MODULE HEADER **********************************************/
/*****************************************************************************/
/* (c) Copyright Systems Integration Specialists Company, Inc., */
/* 2005 All Rights Reserved */
/* */
/* MODULE NAME : QuadLib.c */
/* PRODUCT(S) : Standard Time Management Library */
/* */
/* MODULE DESCRIPTION: */
/* 64-bit Math Simulation Library. */
/* Provided for platforms without native 64-bit support. */
/* */
/* MODIFICATION LOG: */
/* Date Who Rev Comments */
/* -------- --- --- ----------------------------------------------------- */
/* 06/07/06 RLH 02 Numerous features added, see stdtime.doc */
/* 01/18/06 RLH 01 Created */
/*****************************************************************************/
#include "stdtime.h"
#ifdef QUADLIB_ENABLED
int32_t QuadLibU64Cmp (QUADLIB_U64 x, QUADLIB_U64 y)
{
if (x.hi.u < y.hi.u) return -1;
if (x.hi.u > y.hi.u) return 1;
if (x.lo.u < y.lo.u) return -1;
if (x.lo.u > y.lo.u) return 1;
return 0;
}
int32_t QuadLibI64Cmp (QUADLIB_I64 x, QUADLIB_I64 y)
{
if (x.hi.i < y.hi.i) return -1;
if (x.hi.i > y.hi.i) return 1;
/* the unsigned compare on lo.u works correctly if x.hi.i == y.hi.i */
/* in case of negative numbers, when lo increases in unsigned */
/* magnitude, the 64-bit value is less negative, and so is a */
/* greater signed value, so nothing special needs to be done */
if (x.lo.u < y.lo.u) return -1;
if (x.lo.u > y.lo.u) return 1;
return 0;
}
#endif /* QUADLIB_ENABLED */
/*****************************************************************************/
/* GET/SET */
/*****************************************************************************/
#ifndef QUADLIB_ENABLED
/* get hi value of a 64-bit value when host has native support */
QUADLIB_STATIC int32_t QuadLibI64GetHi (QUADLIB_I64 x)
{
return (int32_t) QUADLIB_I64_HI(x);
} /* QuadLibI64GetHi */
QUADLIB_STATIC uint32_t QuadLibU64GetHi (QUADLIB_U64 x)
{
return (uint32_t) QUADLIB_U64_HI(x);
} /* QuadLibU64GetHi */
/* get lo value of a 64-bit value when host has native support */
QUADLIB_STATIC int32_t QuadLibI64GetLo (QUADLIB_I64 x)
{
return (int32_t) QUADLIB_I64_LO(x);
} /* QuadLibI64GetLo */
QUADLIB_STATIC uint32_t QuadLibU64GetLo (QUADLIB_U64 x)
{
return (uint32_t) QUADLIB_U64_LO(x);
} /* QuadLibU64GetLo */
/* set hi value of a 64-bit value when host has native support */
void QuadLibI64SetHi (QUADLIB_I64 *x, int32_t y)
{
(*(QUADLIB_I64_TYPE *)(x)).hi.i = y;
} /* QuadLibI64SetHi */
void QuadLibU64SetHi (QUADLIB_U64 *x, uint32_t y)
{
(*(QUADLIB_I64_TYPE *)(x)).hi.u = y;
} /* QuadLibU64SetHi */
/* set lo value of a 64-bit value when host has native support */
void QuadLibI64SetLo (QUADLIB_I64 *x, int32_t y)
{
(*(QUADLIB_I64_TYPE *)(x)).lo.i = y;
} /* QuadLibI64SetLo */
void QuadLibU64SetLo (QUADLIB_U64 *x, uint32_t y)
{
(*(QUADLIB_I64_TYPE *)(x)).lo.u = y;
} /* QuadLibU64SetLo */
#endif /* not QUADLIB_ENABLED */
/*****************************************************************************/
/* CAST */
/*****************************************************************************/
#ifdef QUADLIB_ENABLED
/* 64-bit to 64-bit conversions */
QUADLIB_STATIC QUADLIB_I64 QuadLibI64CastI64N(void * x, size_t n)
{
QUADLIB_I64 result;
/* determine type of cast based on sizeof(x) */
switch (n)
{
case 8:
QUADLIB_I64_HI(result) = QUADLIB_I64_HI(x);
QUADLIB_I64_LO(result) = QUADLIB_I64_LO(x);
break;
case 2:
QUADLIB_I64_HI(result) =
QUADLIB_I64_LO(result) = (*(short *)(&x));
QUADLIB_I64_HI(result) >>= 31; /* sign propagation */
break;
case 1:
QUADLIB_I64_HI(result) =
QUADLIB_I64_LO(result) = (*(char *)(&x));
QUADLIB_I64_HI(result) >>= 31; /* sign propagation */
break;
default:
/* assume length 4 */
QUADLIB_I64_HI(result) =
QUADLIB_I64_LO(result) = (*(long *)(&x));
QUADLIB_I64_HI(result) >>= 31; /* sign propagation */
break;
}
return result;
} /* QuadLibI64CastI64N */
QUADLIB_STATIC QUADLIB_U64 QuadLibU64CastU64N(void * x, size_t n)
{
QUADLIB_U64 result;
/* determine type of cast based on sizeof(x) */
switch (n)
{
case 8:
QUADLIB_I64_HI(result) = QUADLIB_I64_HI(x);
QUADLIB_I64_LO(result) = QUADLIB_I64_LO(x);
break;
case 2:
QUADLIB_I64_HI(result) = 0;
QUADLIB_I64_LO(result) = (*(unsigned short *)(&x));
break;
case 1:
QUADLIB_I64_HI(result) = 0;
QUADLIB_I64_LO(result) = (*(unsigned char *)(&x));
break;
default:
/* assume length 4 */
QUADLIB_I64_HI(result) = 0;
QUADLIB_I64_LO(result) = (*(unsigned long *)(&x));
break;
}
return result;
} /* QuadLibU64CastU64N */
QUADLIB_STATIC QUADLIB_I64N QuadLibI64NCastI64(QUADLIB_I64 x)
{
QUADLIB_I64N result;
#ifdef QUADLIB_NATIVE64_ENABLED
QUADLIB_I64_HI(result) = QUADLIB_I64_HI(x);
QUADLIB_I64_LO(result) = QUADLIB_I64_LO(x);
#else
/* x is a 32-bit value, so we can only return 32 bits of I64 value */
result = (QUADLIB_I64N) QUADLIB_I64_LO(x);
#endif
return result;
} /* QuadLibI64NCastI64 */
QUADLIB_STATIC QUADLIB_U64N QuadLibU64NCastU64(QUADLIB_U64 x)
{
QUADLIB_U64N result;
#ifdef QUADLIB_NATIVE64_ENABLED
QUADLIB_U64_HI(result) = QUADLIB_U64_HI(x);
QUADLIB_U64_LO(result) = QUADLIB_U64_LO(x);
#else
/* x is a 32-bit value, so we can only return 32 bits of I64 value */
result = (QUADLIB_U64N) QUADLIB_U64_LO(x);
#endif
return result;
} /* QuadLibU64NCastU64 */
/* upsize casts: 32 to 64 bit */
QUADLIB_STATIC QUADLIB_I64 QuadLibI64CastI32 (int32_t x)
{
QUADLIB_I64 result;
result.lo.i = x;
result.hi.i = x;
result.hi.i >>= 31; /* for signed, x propagation */
return result;
} /* QuadLibI64CastI32 */
QUADLIB_STATIC QUADLIB_U64 QuadLibU64CastU32 (uint32_t x)
{
QUADLIB_U64 result;
result.hi.u = 0; /* for unsigned, 0 propagation */
result.lo.u = x;
return result;
} /* QuadLibU64CastU32 */
/* downsize casts: 64 to 32 bit */
QUADLIB_STATIC int32_t QuadLibI32CastI64 (QUADLIB_I64 x)
{
return x.lo.i;
} /* QuadLibI32CastI64 */
QUADLIB_STATIC uint32_t QuadLibU32CastU64 (QUADLIB_U64 x)
{
return x.lo.u;
} /* QuadLibU32CastU64 */
#endif /* QUADLIB_ENABLED */
/*****************************************************************************/
/* QuadLibU64Not */
/* form 1's complement of 64-bit value */
/*****************************************************************************/
#ifdef QUADLIB_ENABLED
QUADLIB_STATIC QUADLIB_U64 QuadLibU64Not (QUADLIB_U64 x)
{
QUADLIB_U64 result;
result.hi.u = ~(x.hi.u);
result.lo.u = ~(x.lo.u);
return result;
}
#endif /* QUADLIB_ENABLED */
/*****************************************************************************/
/* QuadLibU64Neg */
/* form 2's complement of 64-bit value */
/*****************************************************************************/
#ifdef QUADLIB_ENABLED
QUADLIB_STATIC QUADLIB_U64 QuadLibU64Neg (QUADLIB_U64 x)
{
QUADLIB_U64 result;
result.hi.u = ~(x.hi.u);
result.lo.u = (~(x.lo.u)) + 1;
/* if x.lo.u came in as 0, its complement is 0xFFFFFFFF */
/* if we then increment it, it will become 0 again */
/* so, if result.lo.u is zero now, there was a carry */
if (result.lo.u == 0)
{
result.hi.u++;
}
return result;
} /* QuadLibU64Neg */
#endif /* QUADLIB_ENABLED */
/*****************************************************************************/
/* QuadLibU64Abs */
/* form absolute value of 64-bit value */
/*****************************************************************************/
#ifdef QUADLIB_ENABLED
QUADLIB_STATIC QUADLIB_U64 QuadLibU64Abs (QUADLIB_U64 x)
{
if (x.hi.i < 0) /* value is negative */
{
return QUADLIB_U64_NEG (x);
}
return x; /* value is positive, do not negate */
} /* QuadLibU64Abs */
#else /* not QUADLIB_ENABLED */
QUADLIB_STATIC QUADLIB_U64 QuadLibU64Abs (QUADLIB_U64 x)
{
if (x < 0) /* value is negative */
{
return (QUADLIB_U64) (-(QUADLIB_I64) x);
/* negate native I64 value */
}
return x; /* value is positive, do not negate */
} /* QuadLibU64Abs */
#endif /* QUADLIB_ENABLED */
/*****************************************************************************/
/* QuadLibU64Mul */
/* multiply two unsigned 64-bit values. */
/* form partial products from 16-bit values to limit results to 32 bits. */
/* */
/* method: let ABCD mean four 16-bit values with 'one', and WXYZ in 'two' */
/* then, one * two = ABCD * WXYZ. in "long-hand" this means: */
/* */
/* (let xxL mean the Left 16 bits of a word, and xxR the Right 16 bits) */
/* */
/* A B C D */
/* W X Y Z */
/* -------------- */
/* AZ BZ CZ DZ */
/* AY BY CY DY */
/* AX BX CX DX */
/* AW BW CW DW */
/* */
/* express the partial sums as split L/R pairs, and discard partial sums */
/* that exceed the 64-bit result capacity. ("discard" means discard from */
/* the explanation; the discarded values are not actually calculated.) */
/* */
/* A B C D */
/* W X Y Z */
/* -------------- */
/* AZR BZR CZR DZR */
/* BZL CZL DZL */
/* BYR CYR DYR */
/* CYL DYL */
/* CXR DXR */
/* DXL */
/* DWR */
/* */
/* since there is no carry out of the left 32-bit value (the AB column), */
/* there is no need to split the left-most (AB column) 32-bit values into */
/* 16/16. so, we optimize the list of partial sums as follows, (where */
/* (xxL:xxR represents an unsplit 32-bit value), and reorganize the */
/* diagram to show the left/right relationships better: */
/* */
/* A B C D */
/* W X Y Z */
/* -------------- */
/* AZR */
/* bzL:bzR */
/* CZL CZR */
/* DZL DZR */
/* -------------- */
/* BYR */
/* cyL:cyR */
/* DYL DYR */
/* -------------- */
/* CXR */
/* dxL:dxR */
/* -------------- */
/* DWR */
/* */
/* finally, add up the columns, and store the sums in a 64-bit value */
/* */
/*****************************************************************************/
#ifdef QUADLIB_ENABLED
#define QUADLIB_U32_LWORD(x) ( ((uint32_t)(x)) >> 16)
#define QUADLIB_U32_RWORD(x) ((x) & 0xFFFF)
QUADLIB_STATIC QUADLIB_U64 QuadLibU64Mul (
QUADLIB_U64 /*I*/ one,
QUADLIB_U64 /*I*/ two)
{
QUADLIB_U64 result;
uint32_t a, b, c, d, w, x, y, z;
uint32_t ab, bc, cd;
uint32_t az, bz, cz, dz;
uint32_t by, cy, dy;
uint32_t cx, dx;
uint32_t dw;
uint32_t azr, czr, dzr;
uint32_t czl, dzl;
uint32_t byr, dyr;
uint32_t dyl;
uint32_t cxr;
uint32_t dwr;
a = QUADLIB_U32_LWORD(one.hi.u);
b = QUADLIB_U32_RWORD(one.hi.u);
c = QUADLIB_U32_LWORD(one.lo.u);
d = QUADLIB_U32_RWORD(one.lo.u);
w = QUADLIB_U32_LWORD(two.hi.u);
x = QUADLIB_U32_RWORD(two.hi.u);
y = QUADLIB_U32_LWORD(two.lo.u);
z = QUADLIB_U32_RWORD(two.lo.u);
az = a * z; bz = b * z; cz = c * z; dz = d * z;
by = b * y; cy = c * y; dy = d * y;
cx = c * x; dx = d * x;
dw = d * w;
azr = QUADLIB_U32_RWORD(az);
czr = QUADLIB_U32_RWORD(cz);
dzr = QUADLIB_U32_RWORD(dz);
czl = QUADLIB_U32_LWORD(cz);
dzl = QUADLIB_U32_LWORD(dz);
byr = QUADLIB_U32_RWORD(by);
dyr = QUADLIB_U32_RWORD(dy);
dyl = QUADLIB_U32_LWORD(dy);
cxr = QUADLIB_U32_RWORD(cx);
dwr = QUADLIB_U32_RWORD(dw);
bc = czr + dzl + dyr;
ab = bc >> 16;
cd = bc << 16;
result.lo.u = cd + dzr;
result.hi.u = ab + bz + cy + dx
+ czl + dyl
+ ((azr + byr + cxr + dwr) << 16);
return result;
} /* QuadLibU64Mul */
#undef QUADLIB_U32_LWORD
#undef QUADLIB_U32_RWORD
#endif /* QUADLIB_ENABLED */
/*****************************************************************************/
/* QuadLibU64Add */
/* add two unsigned 64-bit values */
/*****************************************************************************/
#ifdef QUADLIB_ENABLED
QUADLIB_STATIC QUADLIB_U64 QuadLibU64Add (
QUADLIB_U64 /*I*/ one,
QUADLIB_U64 /*I*/ two)
{
QUADLIB_U64 sum;
uint32_t carry;
sum.lo.u = one.lo.u + two.lo.u;
sum.hi.u = one.hi.u + two.hi.u;
/* calculate carry using boolean algebra */
carry =
( (one.lo.u & two.lo.u) | ((one.lo.u ^ two.lo.u) & (~sum.lo.u)) ) >> 31;
sum.hi.u += carry;
return sum;
} /* QuadLibU64Add */
#endif /* QUADLIB_ENABLED */
/*****************************************************************************/
/* QuadLibU64Sub */
/* subtract two unsigned 64-bit values */
/* method: negate second operand, and then add values */
/*****************************************************************************/
#ifdef QUADLIB_ENABLED
QUADLIB_STATIC QUADLIB_U64 QuadLibU64Sub (
QUADLIB_U64 /*I*/ one,
QUADLIB_U64 /*I*/ two)
{
return QuadLibU64Add (one, QUADLIB_U64_NEG (two));
} /* QuadLibU64Sub */
#endif /* QUADLIB_ENABLED */
/*****************************************************************************/
/* QuadLibU64Add1 */
/* increment a 64-bit value */
/* method: add a constant 1 to a 64-bit value */
/*****************************************************************************/
#ifdef QUADLIB_ENABLED
QUADLIB_STATIC QUADLIB_U64 QuadLibU64Add1 (
QUADLIB_U64 /*I*/ x)
{
QUADLIB_U64 result;
result.hi.u = x.hi.u;
result.lo.u = x.lo.u + 1;
if (result.lo.u == 0)
{
/* x.lo.u must have had all 1 bits, so a carry occurred */
result.hi.u++;
}
return result;
} /* QuadLibU64Add1 */
#endif /* QUADLIB_ENABLED */
/*****************************************************************************/
/* QuadLibU64Sub1 */
/* decrement a 64-bit value */
/* method: add a constant -1 to a 64-bit value */
/*****************************************************************************/
#ifdef QUADLIB_ENABLED
QUADLIB_STATIC QUADLIB_U64 QuadLibU64Sub1 (
QUADLIB_U64 /*I*/ x)
{
QUADLIB_U64 result;
result.hi.u = x.hi.u;
result.lo.u = x.lo.u - 1;
if (x.lo.u == 0)
{
/* x.lo.u was 0, so a borrow occurred */
result.hi.u--;
}
return result;
} /* QuadLibU64Sub1 */
#endif /* QUADLIB_ENABLED */
/*****************************************************************************/
/* QuadLibU64SHR */
/* shift an unsigned 64-bit value right by n bits */
/*****************************************************************************/
#ifdef QUADLIB_ENABLED
QUADLIB_STATIC QUADLIB_U64 QuadLibU64SHR (
QUADLIB_U64 /*I*/ value,
int32_t /*I*/ shift)
{
QUADLIB_U64 result = QUADLIB_ZERO;
if (shift == 0)
{
return value;
}
if (shift < 0)
{
return QuadLibU64SHL (value, -shift);
}
if (shift > 63)
{
return result; /* all bits shifted out, return 0 */
}
for (result = value; shift > 0; shift--)
{
result.lo.u >>= 1;
if (result.hi.u & 1)
{
/* hi has low-order 1 about to be shifted out */
result.lo.u |= QUADLIB_U32_HIGHBIT;
}
result.hi.u >>= 1; /* unsigned shift right */
}
return result;
} /* QuadLibU64SHR */
#endif /* QUADLIB_ENABLED */
/*****************************************************************************/
/* QuadLibI64SHR */
/* shift a signed 64-bit value right by n bits */
/*****************************************************************************/
#ifdef QUADLIB_ENABLED
QUADLIB_STATIC QUADLIB_I64 QuadLibI64SHR (
QUADLIB_I64 /*I*/ value,
int32_t /*I*/ shift)
{
QUADLIB_I64 result = QUADLIB_ZERO;
if (shift == 0)
{
return value;
}
if (shift < 0)
{
return QuadLibU64SHL (value, -shift);
}
if (shift > 63)
{
return result; /* all bits shifted out return 0 */
}
for (result = value; shift > 0; shift--)
{
result.lo.u >>= 1;
if (result.hi.u & 1)
{
/* hi has low-order 1 about to be shifted out */
result.lo.u |= QUADLIB_U32_HIGHBIT;
}
result.hi.i >>= 1; /* signed shift right */
}
return result;
} /* QuadLibI64SHR */
#endif /* QUADLIB_ENABLED */
/*****************************************************************************/
/* QuadLibU64SHL */
/* shift an unsigned 64-bit value left by n bits */
/*****************************************************************************/
#ifdef QUADLIB_ENABLED
QUADLIB_STATIC QUADLIB_U64 QuadLibU64SHL (
QUADLIB_U64 /*I*/ value,
int32_t /*I*/ shift)
{
QUADLIB_U64 result = QUADLIB_ZERO;
if (shift == 0)
{
return value;
}
if (shift < 0)
{
return QuadLibU64SHR (value, -shift);
}
if (shift > 63)
{
return result; /* all bits shifted out return 0 */
}
for (result = value; shift > 0; shift--)
{
QUADLIB_U64_SHL1_EQ_INLINE (result);
}
return result;
} /* QuadLibU64SHL */
#endif /* QUADLIB_ENABLED */
/*****************************************************************************/
/* QuadLibI64SHR1 */
/* shift a signed 64-bit value right by 1 bit */
/*****************************************************************************/
#ifdef QUADLIB_ENABLED
QUADLIB_STATIC QUADLIB_I64 QuadLibI64SHR1 (
QUADLIB_I64 /*I*/ value)
{
QUADLIB_I64_SHR1_EQ_INLINE (value);
return value;
} /* QuadLibI64SHR1 */
#endif /* QUADLIB_ENABLED */
/*****************************************************************************/
/* QuadLibU64SHR1 */
/* shift an unsigned 64-bit value right by 1 bit */
/*****************************************************************************/
#ifdef QUADLIB_ENABLED
QUADLIB_STATIC QUADLIB_U64 QuadLibU64SHR1 (
QUADLIB_U64 /*I*/ value)
{
QUADLIB_U64_SHR1_EQ_INLINE (value);
return value;
} /* QuadLibU64SHR1 */
#endif /* QUADLIB_ENABLED */
/*****************************************************************************/
/* QuadLibU64SHL1 */
/* shift an unsigned 64-bit value left by 1 bit */
/*****************************************************************************/
#ifdef QUADLIB_ENABLED
QUADLIB_STATIC QUADLIB_U64 QuadLibU64SHL1 (
QUADLIB_U64 /*I*/ value)
{
QUADLIB_U64_SHL1_EQ_INLINE (value);
return value;
} /* QuadLibU64SHL1 */
#endif /* QUADLIB_ENABLED */
/*****************************************************************************/
/* QuadLibI64SHR4 */
/* shift a signed 64-bit value right by 1 bit */
/*****************************************************************************/
#ifdef QUADLIB_ENABLED
QUADLIB_STATIC QUADLIB_I64 QuadLibI64SHR4 (
QUADLIB_I64 /*I*/ value)
{
QUADLIB_I64_SHR4_EQ_INLINE (value);
return value;
} /* QuadLibI64SHR4 */
#endif /* QUADLIB_ENABLED */
/*****************************************************************************/
/* QuadLibU64SHR4 */
/* shift an unsigned 64-bit value right by 1 bit */
/*****************************************************************************/
#ifdef QUADLIB_ENABLED
QUADLIB_STATIC QUADLIB_U64 QuadLibU64SHR4 (
QUADLIB_U64 /*I*/ value)
{
QUADLIB_U64_SHR4_EQ_INLINE (value);
return value;
} /* QuadLibU64SHR4 */
#endif /* QUADLIB_ENABLED */
/*****************************************************************************/
/* QuadLibU64SHL4 */
/* shift an unsigned 64-bit value left by 1 bit */
/*****************************************************************************/
#ifdef QUADLIB_ENABLED
QUADLIB_STATIC QUADLIB_U64 QuadLibU64SHL4 (
QUADLIB_U64 /*I*/ value)
{
QUADLIB_U64_SHL4_EQ_INLINE (value);
return value;
} /* QuadLibU64SHL4 */
#endif /* QUADLIB_ENABLED */
/*****************************************************************************/
/* QuadLibU64Mul10 */
/* multiple an unsigned 64-bit value by 10 */
/* method: get value*2 and value*8 by shifting, and then add them */
/*****************************************************************************/
#ifdef QUADLIB_ENABLED
QUADLIB_STATIC QUADLIB_U64 QuadLibU64Mul10 (
QUADLIB_U64 /*I*/ value)
{
QUADLIB_U64 value2;
QUADLIB_U64 value8;
QUADLIB_U64 result;
value2 = value;
QUADLIB_U64_SHL1_EQ_INLINE (value2);
value8 = value2;
QUADLIB_U64_SHL1_EQ_INLINE (value8);
QUADLIB_U64_SHL1_EQ_INLINE (value8);
result = QuadLibU64Add (value8, value2);
return result;
} /* QuadLibU64Mul10 */
#endif /* QUADLIB_ENABLED */
/*****************************************************************************/
/* StrAToQuadLibU64 */
/* define a portable 64-bit unsigned atoi convervion */
/*****************************************************************************/
/* StrAToQuadLibU64 always defined */
QUADLIB_STATIC QUADLIB_U64 StrAToQuadLibU64 (
char * /*I*/ str)
{
/* extract a decimal string and return unsigned int64 value */
QUADLIB_U64 result = QUADLIB_ZERO;
QUADLIB_U64 digit = QUADLIB_ZERO;
int32_t n;
if (str == NULL)
{
return result;
}
while (isspace (*str))
{
str++; /* skip over whitespace */
}
/* handle hex value if present */
if ( (str[0] == '0') && ((str[1] == 'x') || (str[1] == 'X')) )
{
for (str+=2; *str; str++)
{
n = *str;
if ((n >= '0') && (n <= '9'))
{
n -= '0';
}
else if ((n >= 'A') && (n <= 'F'))
{
n = n - 'A' + 10;
}
else if ((n >= 'a') && (n <= 'f'))
{
n = n - 'a' + 10;
}
else
{
break;
}
QUADLIB_I64_LO(digit) = n;
QUADLIB_U64_SHL1_EQ_INLINE (result);
QUADLIB_U64_ADD_EQ (result, digit);
} /* for */
return result;
}
for (; *str; str++)
{
n = (*str) - '0';
if ((n < 0) || (n > 9))
{
break;
}
QUADLIB_I64_LO(digit) = n;
QUADLIB_U64_MUL10_EQ (result);
QUADLIB_U64_ADD_EQ (result, digit);
}
return result;
} /* StrAToQuadLibU64 */
/* StrAToQuadLibU64 always defined */
/*****************************************************************************/
/* StrAToQuadLibI64 */
/* define a portable 64-bit signed atoi convervion */
/*****************************************************************************/
/* StrAToQuadLibI64 always defined */
QUADLIB_STATIC QUADLIB_I64 StrAToQuadLibI64 (
char * /*I*/ str)
{
/* extract a decimal string and return unsigned int64 value */
QUADLIB_I64 result = QUADLIB_ZERO;
QUADLIB_I64 digit = QUADLIB_ZERO;
char sign = ' ';
int32_t n;
if (str == NULL)
{
return result;
}
while (isspace (*str))
{
str++; /* skip over whitespace */
}
if ((*str == '+') || (*str == '-'))
{
sign = *str;
str++; /* skip over sign */
}
/* handle hex value if present */
if ( (str[0] == '0') && ((str[1] == 'x') || (str[1] == 'X')) )
{
for (str+=2; *str; str++)
{
n = *str;
if ((n >= '0') && (n <= '9'))
{
n -= '0';
}
else if ((n >= 'A') && (n <= 'F'))
{
n = n - 'A' + 10;
}
else if ((n >= 'a') && (n <= 'f'))
{
n = n - 'a' + 10;
}
else
{
break;
}
QUADLIB_I64_LO(digit) = n;
QUADLIB_U64_SHL1_EQ_INLINE (result);
QUADLIB_U64_ADD_EQ (result, digit);
} /* for */
if (sign == '-')
{
result = QUADLIB_I64_NEG (result);
}
return result;
}
for (; *str; str++)
{
n = (*str) - '0';
if ((n < 0) || (n > 9))
{
break;
}
QUADLIB_I64_LO(digit) = n;
QUADLIB_I64_MUL10_EQ (result);
QUADLIB_I64_ADD_EQ (result, digit);
}
if (sign == '-')
{
result = QUADLIB_I64_NEG (result);
}
return result;
} /* StrAToQuadLibI64 */
/* StrAToQuadLibI64 always defined */
/*****************************************************************************/
/* QuadLibU64ToFixedStrA */
/* define a portable 64-bit unsigned itoa convervion */
/*****************************************************************************/
/* QuadLibU64ToFixedStrA always defined */
QUADLIB_STATIC void QuadLibU64ToFixedStrA (
QUADLIB_U64 /*I*/ qValue,
QUADLIB_STRINGA * /*O*/ pString)
{
QUADLIB_U64 value = qValue;
int32_t i;
int32_t n;
int32_t xdigit;
uint8_t sum [QUADLIB_STRING_LEN] = {0};
uint8_t carry;
char * factor;
static char * factor_table[16] =
{
"00000000000000000001",
"00000000000000000016",
"00000000000000000256",
"00000000000000004096",
"00000000000000065536",
"00000000000001048576",
"00000000000016777216",
"00000000000268435456",
"00000000004294967296",
"00000000068719476736",
"00000001099511627776",
"00000017592186044416",
"00000281474976710656",
"00004503599627370496",
"00072057594037927936",
"01152921504606846976",
};
/* grab 16 hex digits one at a time */
/* obtain the decimal factor for a '1' in that position */
/* multiply each decimal digit of the factor by the hex digit */
/* and add to sum */
for (i=0; i < 16; i++)
{
if (QUADLIB_U64_EQ_0 (value))
{
break;
}
xdigit = QUADLIB_U64_LO (value) & 0x0F;
QUADLIB_U64_SHR4_EQ (value);
if (xdigit == 0)
{
continue; /* nothing to do */
}
factor = factor_table [i];
/* highest value in any position is (15*9)+9 = 135+9 = 144 */
/* with a carry in of 9, the highest value is 153 */
/* recall that factor is ASCII when calculating the sum */
carry = 0;
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4244)
/* silence the VC compiler warning message: */
/* "conversion from 'int ' to 'unsigned __int8', possible loss of data" */
#endif
for (n = QUADLIB_STRING_LEN-1; n >= 0; n--)
{
sum[n] += (uint8_t) (((factor[n] & 0x0F) * xdigit) + carry);
carry = sum[n] / 10;
sum[n] %= 10;
}
}
#ifdef _MSC_VER
#pragma warning(pop)
#endif
/* copy sum to output, converting to ASCII */
for (n = 0; n < QUADLIB_STRING_LEN; n++)
{
pString->str[n] = (char) ((sum[n] & 0x0F) + '0');
}
pString->str[QUADLIB_STRING_LEN] = 0;
} /* QuadLibU64ToFixedStrA */
/*****************************************************************************/
/* QuadLibI64ToFixedStrA */
/* define a portable 64-bit signed itoa convervion */
/*****************************************************************************/
/* QuadLibI64ToFixedStrA always defined */
QUADLIB_STATIC void QuadLibI64ToFixedStrA (
QUADLIB_I64 /*I*/ qValue,
QUADLIB_STRINGA * /*O*/ pString)
{
char sign = '0';
if (QUADLIB_I64_LT_0 (qValue))
{
qValue = QUADLIB_I64_NEG (qValue);
sign = '-';
}
QuadLibU64ToFixedStrA (* (QUADLIB_U64 *) &qValue, pString);
pString->str[0] = sign;
} /* QuadLibI64ToFixedStrA */
/*****************************************************************************/
/* QuadLibU64ToStrA */
/* define a portable 64-bit signed itoa convervion, with zero suppression */
/*****************************************************************************/
/* QuadLibU64ToStrA always defined */
QUADLIB_STATIC void QuadLibU64ToStrA (
QUADLIB_U64 /*I*/ qValue,
QUADLIB_STRINGA * /*O*/ pString)
{
QUADLIB_STRINGA s;
int32_t source = 0;
int32_t target = 0;
QuadLibU64ToFixedStrA (qValue, &s);
/* copy back value, suppressing leading zeros */
while (s.str [source] == '0')
{
source++;
}
if (s.str [source] == 0)
{
pString->str [target++] = '0'; /* source is all zero */
}
while (s.str [source])
{
pString->str [target++] = s.str [source++];
}
pString->str [target] = 0;
} /* QuadLibU64ToStrA */
/*****************************************************************************/
/* QuadLibI64ToStrA */
/* define a portable 64-bit signed itoa convervion, with zero suppression */
/*****************************************************************************/
/* QuadLibI64ToStrA always defined */
QUADLIB_STATIC void QuadLibI64ToStrA (
QUADLIB_I64 /*I*/ qValue,
QUADLIB_STRINGA * /*O*/ pString)
{
QUADLIB_STRINGA s;
int32_t source = 0;
int32_t target = 0;
QuadLibI64ToFixedStrA (qValue, &s);
/* copy back value, suppressing leading zeros */
if (s.str [source] == '-')
{
pString->str [target++] = s.str [source++];
}
while (s.str [source] == '0')
{
source++;
}
if (s.str [source] == 0)
{
pString->str [target++] = '0'; /* source is all zero */
}
while (s.str [source])
{
pString->str [target++] = s.str [source++];
}
pString->str [target] = 0;
} /* QuadLibI64ToStrA */
/*****************************************************************************/
/* QuadLibU64DivMod */
/* divide two unsigned 64-bit values to produce a quotient and remainder */
/*****************************************************************************/
#ifdef QUADLIB_ENABLED
QUADLIB_STATIC QUADLIB_U64 QuadLibU64DivMod (
QUADLIB_U64 u64Dividend,
QUADLIB_U64 u64Divisor,
QUADLIB_U64 *pu64Remainder )
{
int32_t Count;
QUADLIB_U64 A_restore;
QUADLIB_U64 A = QUADLIB_ZERO;
QUADLIB_U64 M = u64Divisor;
QUADLIB_U64 Q = u64Dividend;
if ((u64Divisor.hi.u == 0)
&& (u64Divisor.lo.u == 0))
{
*pu64Remainder = A; /* 0 */
return A; /* 0 */
}
for (Count=64; Count; Count--)
{
/* shift A:Q left */
QUADLIB_U64_SHL1_EQ_INLINE (A);
if (Q.hi.i < 0) /* Q has high-order 1 bit */
{
A = QuadLibU64Add1(A); /* A gets low-order 1 bit */
}
QUADLIB_U64_SHL1_EQ_INLINE (Q); /* Q gets low-order 0 bit */
A_restore = A;
A = QuadLibU64Sub(A, M);
if (A.hi.i < 0) /* A has high-order 1 bit */
{
A = A_restore; /* Q has low-order 0 bit */
}
else
{
Q = QuadLibU64Add1(Q); /* Q gets low-order 1 bit */
}
} /* for */
*pu64Remainder = A;
return Q;
} /* QuadLibU64DivMod */
#endif /* QUADLIB_ENABLED */
/*****************************************************************************/
/* QuadLibU64Div */
/* divide two signed 64-bit values to produce an unsigned quotient */
/*****************************************************************************/
#ifdef QUADLIB_ENABLED
QUADLIB_STATIC QUADLIB_U64 QuadLibU64Div (
QUADLIB_U64 u64Dividend,
QUADLIB_U64 u64Divisor)
{
QUADLIB_U64 u64Remainder; /* dummy argument */
return QuadLibU64DivMod (u64Dividend, u64Divisor, &u64Remainder);
} /*QuadLibU64Div */
#endif /* QUADLIB_ENABLED */
/*****************************************************************************/
/* QuadLibU64Mod */
/* divide two signed 64-bit values to produce unsigned remainder (modulus) */
/*****************************************************************************/
#ifdef QUADLIB_ENABLED
QUADLIB_STATIC QUADLIB_U64 QuadLibU64Mod (
QUADLIB_U64 u64Dividend,
QUADLIB_U64 u64Divisor)
{
QUADLIB_U64 u64Remainder;
QuadLibU64DivMod (u64Dividend, u64Divisor, &u64Remainder);
return u64Remainder;
} /*QuadLibU64Mod */
#endif /* QUADLIB_ENABLED */
/*****************************************************************************/
/* QuadLibI64DivMod */
/* divide two signed 64-bit values to produce a quotient and remainder */
/*****************************************************************************/
#ifdef QUADLIB_ENABLED
QUADLIB_STATIC QUADLIB_I64 QuadLibI64DivMod (
QUADLIB_I64 s64Dividend,
QUADLIB_I64 s64Divisor,
QUADLIB_I64 *ps64Remainder )
{
QUADLIB_I64 s64Quotient;
QUADLIB_U64 u64Dividend;
QUADLIB_U64 u64Divisor;
int32_t sign = 0;
if (s64Dividend.hi.i < 0)
{
u64Dividend = QUADLIB_I64_NEG (s64Dividend);
sign = 1;
}
else
{
u64Dividend = s64Dividend;
}
if (s64Divisor.hi.i < 0)
{
u64Divisor = QUADLIB_I64_NEG (s64Divisor);
sign ^= 1;
}
else
{
u64Divisor = s64Divisor;
}
s64Quotient = QuadLibU64DivMod (u64Dividend, u64Divisor, ps64Remainder);
if (sign)
{
/* signs of dividend and divisor are different, result is neg */
s64Quotient = QUADLIB_I64_NEG (s64Quotient);
}
/* remainder takes sign of dividend */
if (s64Dividend.hi.i < 0)
{
*ps64Remainder = QUADLIB_I64_NEG (*ps64Remainder);
}
return s64Quotient;
} /* QuadLibI64DivMod */
#endif /* QUADLIB_ENABLED */
/*****************************************************************************/
/* QuadLibI64Div */
/* divide two signed 64-bit values to produce a signed quotient */
/*****************************************************************************/
#ifdef QUADLIB_ENABLED
QUADLIB_STATIC QUADLIB_I64 QuadLibI64Div (
QUADLIB_I64 s64Dividend,
QUADLIB_I64 s64Divisor)
{
QUADLIB_U64 s64Remainder; /* dummy argument */
return QuadLibI64DivMod (s64Dividend, s64Divisor, &s64Remainder);
} /*QuadLibI64Div */
#endif /* QUADLIB_ENABLED */
/*****************************************************************************/
/* QuadLibI64Mod */
/* divide two signed 64-bit values to produce a signed remainder (modulus) */
/*****************************************************************************/
#ifdef QUADLIB_ENABLED
QUADLIB_STATIC QUADLIB_I64 QuadLibI64Mod (
QUADLIB_I64 s64Dividend,
QUADLIB_I64 s64Divisor)
{
QUADLIB_I64 s64Remainder;
QuadLibI64DivMod (s64Dividend, s64Divisor, &s64Remainder);
return s64Remainder;
} /*QuadLibI64Mod */
#endif /* QUADLIB_ENABLED */
/*****************************************************************************/
/* QuadLibU64DivMod - COMPATIBILITY MODE */
/* QuadLibI64DivMod - COMPATIBILITY MODE */
/* native I64 divide/modulus functions with I64 simulation not in effect */
/*****************************************************************************/
#ifndef QUADLIB_ENABLED
QUADLIB_STATIC QUADLIB_U64 QuadLibU64DivMod (
QUADLIB_U64 u64Dividend,
QUADLIB_U64 u64Divisor,
QUADLIB_U64 *pu64Remainder)
{
if (pu64Remainder != NULL)
{
*pu64Remainder = u64Dividend % u64Divisor;
}
return u64Dividend / u64Divisor;
} /* QuadLibU64DivMod */
QUADLIB_STATIC QUADLIB_I64 QuadLibI64DivMod (
QUADLIB_I64 s64Dividend,
QUADLIB_I64 s64Divisor,
QUADLIB_I64 *ps64Remainder)
{
if (ps64Remainder != NULL)
{
*ps64Remainder = s64Dividend % s64Divisor;
}
return s64Dividend / s64Divisor;
} /* QuadLibI64DivMod */
#endif /* not QUADLIB_ENABLED */
/*****************************************************************************/
/* AND */
/*****************************************************************************/
#ifdef QUADLIB_ENABLED
QUADLIB_STATIC QUADLIB_U64 QuadLibU64And (
QUADLIB_U64 /*I*/ one,
QUADLIB_U64 /*I*/ two)
{
QUADLIB_U64 result;
result.hi.u = one.hi.u & two.hi.u;
result.lo.u = one.lo.u & two.lo.u;
return result;
}
QUADLIB_STATIC QUADLIB_U64 QuadLibU64AndNot (
QUADLIB_U64 /*I*/ one,
QUADLIB_U64 /*I*/ two)
{
QUADLIB_U64 result;
result.hi.u = one.hi.u & (~two.hi.u);
result.lo.u = one.lo.u & (~two.lo.u);
return result;
}
#endif /* QUADLIB_ENABLED */
/*****************************************************************************/
/* OR */
/*****************************************************************************/
#ifdef QUADLIB_ENABLED
QUADLIB_STATIC QUADLIB_U64 QuadLibU64Or (
QUADLIB_U64 /*I*/ one,
QUADLIB_U64 /*I*/ two)
{
QUADLIB_U64 result;
result.hi.u = one.hi.u | two.hi.u;
result.lo.u = one.lo.u | two.lo.u;
return result;
}
QUADLIB_STATIC QUADLIB_U64 QuadLibU64OrNot (
QUADLIB_U64 /*I*/ one,
QUADLIB_U64 /*I*/ two)
{
QUADLIB_U64 result;
result.hi.u = one.hi.u | (~two.hi.u);
result.lo.u = one.lo.u | (~two.lo.u);
return result;
}
#endif /* QUADLIB_ENABLED */
/*****************************************************************************/
/* XOR */
/*****************************************************************************/
#ifdef QUADLIB_ENABLED
QUADLIB_STATIC QUADLIB_U64 QuadLibU64Xor (
QUADLIB_U64 /*I*/ one,
QUADLIB_U64 /*I*/ two)
{
QUADLIB_U64 result;
result.hi.u = one.hi.u ^ two.hi.u;
result.lo.u = one.lo.u ^ two.lo.u;
return result;
}
QUADLIB_STATIC QUADLIB_U64 QuadLibU64XorNot (
QUADLIB_U64 /*I*/ one,
QUADLIB_U64 /*I*/ two)
{
QUADLIB_U64 result;
result.hi.u = one.hi.u ^ (~two.hi.u);
result.lo.u = one.lo.u ^ (~two.lo.u);
return result;
}
#endif /* QUADLIB_ENABLED */