Technical Notes
OverviewAny variable declared as a quad or uquad in a C++ program can be used with either the operators provided by the class or the functions provided in the integer math unit.
The following table shows numeric types which are supported by the operators in the quad and uquad classes:
Numeric Type Size Range unsigned char (inline only)8-bit integer 0 to 255 char (inline only) 8-bit integer -128 to 127 unsigned int 16-bit integer 0 to 65,535 int 16-bit integer -32,768 to 32,767 unsigned long 32-bit integer 0 to 4,294,967,295 long 32-bit integer -2,147,483,648 to 2,147,483,647 uquad 64-bit integer 0 to 264-1 quad 64-bit integer -263 to 263-1Because C does not supply defined types for 64-bit integers, the following integer classes are provided to simplify the use of 64-bit integers in C++ applications: uquad for unsigned 64-bit integers and quad for signed 64-bit integers. When compiling a C program, the quad and uquad types are defined using typedef, as follows:
typedef signed char quad[8];
typedef unsigned char uquad[8];
When using C++, quad and uquad are defined as classes. There are no additional coding requirements when using the quad or uquad classes in C++ programs. The standard quad and uquad integer math functions work in both C and C++.
64-bit integers should be declared by using uquad for unsigned values and quad for signed values, as in the following example:
...
uquad num1, num2; /* declare two unsigned quads */
quad num3, num4; /* declare two signed quads */
...
An extensive set of routines is provided for mixed-type operations (quad-quad, quad-long, and quad-int). The programmer should choose carefully from among these routines to avoid proliferation of code.
For example, in monetary-type operations, floating point types often lose accuracy over time due to the imprecise representation of base ten values. Furthermore, emulated floating point operations execute roughly 4 to 7 times more slowly than 64-bit integer calculations. Financial operations may be performed with the quad class by counting pennies instead of fractions of dollars; there is no loss of precision and the calculations are much faster. The fixed-point data conversion functions are ideal for input and output of values of this type (see the Data Conversion technical notes).
The code size difference between quad functions and floating point functions is striking. If a program is compiled with floating-point emulation support, the .EXE size increases by 10K to 20K. By contrast, all of the Spontaneous Assembly integer math functions and their C binders occupy less than 3.2K, including every variation of every function (i.e., functions which perform mixed-type operations). The actual memory usage for quad functions is, however, usually less than 800 bytes since only the required Spontaneous Assembly functions are linked into the final program and a limited number of functions is required for most applications.
Unary Operators:
++ Increment (pre or post) -- Decrement (pre or post) Binary Operators: + Add - Subtract * Multiply / Divide = Assign to % Remainder < Less than <= Less than or equal to > Greater than >= Greater than or equal to == Equal to != Not equal += Assign sum -= Assign difference *= Assign product /= Assign quotient %= Assign remainder (mod)Operators for the quad and uquad classes are defined in QUAD.HPP, which is automatically included in IMATH.H if the file is being compiled as a C++ file.
Whenever possible, use assignment operators (+=,*=) in place of straight arithmetic operators (+,þ,*). For example, use
num *= 3; // generates more efficient code
instead of
num = num * 3; // generates less efficient code.
The compiler generates more efficient code for assignment operators because they do not require the creation of a temporary quad or uquad to hold the result.
quad Class:
int-to-quad (includes char type) long-to-quad quad-to-quad uquad Class: int-to-uquad (includes char type) unsigned int-to-uquad (includes unsigned char type) long-to-uquad unsigned long-to-uquad uquad-to-uquadWARNING! The operators for the uquad class are overloaded for int and long types to allow the use of immediate values. DO NOT use signed values with uquad operators, or the result will be incorrect. For example, if -1 is added to a uquad with a value of 30, the result will be 65565 instead of 29.
The compiler may occasionally become confused as to which overloaded operator to use for a given situation. For example, the following code generates an "ambiguity between operators" error in Borland C++:
char x;
quad y;
...
if (x == y)
return (1);
This error can be fixed as follows by adding a type cast to resolve any ambiguity:
char x;
quad y;
...
if (x == (char)y)
return (1);
#include
#include
#include
#include
int test_quad (void);
int test_float (void);
int test_double (void);
int test_ldouble (void);
#define LOOPS 1000
void main (void)
{
int lloop = 0;
std_time time;
_tmr_reset ();
printf ("\nQUAD class: ");
for (lloop = 0; lloop < LOOPS; lloop++)
test_quad ();
_tmr_read (&time);
printf ("%d minutes %d.%02d seconds\n", time.minutes, time.seconds, time.hseconds);
_tmr_reset ();
printf ("FLOAT type: ");
for (lloop = 0; lloop < LOOPS; lloop++)
test_float ();
_tmr_read (&time);
printf ("%d minutes %d.%02d seconds\n", time.minutes, time.seconds, time.hseconds);
_tmr_reset ();
printf ("DOUBLE type: ");
for (lloop = 0; lloop < LOOPS; lloop++)
test_double ();
_tmr_read (&time);
printf ("%d minutes %d.%02d seconds\n", time.minutes, time.seconds, time.hseconds);
_tmr_reset ();
printf ("LONG DOUBLE type: ");
for (lloop = 0; lloop < LOOPS; lloop++)
test_ldouble ();
_tmr_read (&time);
printf ("%d minutes %d.%02d seconds\n", time.minutes, time.seconds, time.hseconds);
}
// The following macro defines the functions called above
#define FUNC(FUNC_NAME,TYPE) \
int FUNC_NAME (void)\
{\
TYPE a = 10, b = 2, c = 3;\
b++;\
a--;\
b+=a;\
a=b*c;\
b=a/c;\
b+=a+c;\
a-=b-c;\
a=b/c;\
a*=b;\
b/=c;\
if (a != 867)\
return (1);\
if (!(b == 17))\
return (1);\
if (b == c)\
return (1);\
if (!(b != c))\
return (1);\
if (c != b - 14)\
return (1);\
if (c >= b || b < c)\
return (1);\
if (c > b || b <= c)\
return (1);\
return (0);\
}
FUNC (test_quad, quad);
FUNC (test_float, float);
FUNC (test_double, double);
FUNC (test_ldouble, long double);
The sample program shown above (QUAD.CPP) is provided on the distribution diskettes and may be compiled and linked using the following Microsoft C and Borland C command lines:
Microsoft C:
cl /c /I\msc\include /I\sa\include quad.cpp
link quad,quad,,\sa\lib\_sas \msc\lib\slibce
Borland C:
bcc /c /ms /I\bc\include /I\sa\include quad.cpp
tlink \bc\lib\c0s quad,quad,,\sa\lib\_sas \bc\lib\cs