TweetFollow Us on Twitter

Fixed Math
Volume Number:9
Issue Number:10
Column Tag:C++ Workshop

Related Info: Binary-Dec. Pack.

Fast Fixed-point Math Made Easy

Using C++ to abstract data in an intuitive way

By Brion Sarachan, Albany, New York

Note: Source code files accompanying article are located on MacTech CD-ROM or source code disks.

With the recent release of Symantec C++, a high-quality, low-cost C++ development environment is now available to Macintosh programmers. If used properly, C++ can provide a quantum leap over the representation power of languages like C and Pascal. We often hear about the use of C++ to build object-oriented systems. Even more fundamentally, however, C++ is an excellent language for data abstraction. Using C++, new data types can be defined that can then be used as conveniently as the built-in types like integers, characters, and floating-point numbers.

As an example of C++’s ability to support data abstractions, this article will describe a simple C++ class for fixed-point numbers. Arithmetic operations on fixed-point numbers are much faster than the corresponding operations on floating-point numbers, at the expense of some loss in precision and a smaller range of allowable values. Many computer graphics and animation applications that require high-performance use fixed-point numbers.

Fixed-point numbers are not built into C++. The Mac Toolbox provides its own implementation of fixed-point numbers. However, using the Mac’s fixed-point numbers can be rather awkward for a couple of reasons:

• Arithmetic operators like * and / cannot be used. Instead, calls must be made to Toolbox routines such as FixMul() and FixDiv(). Therefore, code that uses fixed-point numbers must be written differently than other arithmetic expressions.

• ANSI library functions such as sqrt() or printf() cannot use fixed-point numbers directly. A fixed-point number must be converted to a double by using functions like Fix2X() before using the library functions. This is even more complicated because the manner in which fixed-point numbers are converted to doubles may differ depending on the type of floating-point representation being used by the processor or, if there is one, by the floating-point coprocessor.

C++ enables us to solve these problems by allowing us to define a new fixed-point number class. This new class uses the Mac Toolbox internally, but allows the programmer to declare fixed-point numbers and use them in expressions just as easily as built-in types like ints or doubles.

The Macintosh Fixed Data Type and its Operations

The Macintosh Fixed data type is described in Inside Macintosh. A Fixed type is actually a long integer:

typedef long Fixed;

A Fixed number therefore consists of 32 bits: a sign bit, a 15-bit integer part, and a 16-bit fractional part. The value of a Fixed number therefore falls in the range of about + and -32,768.

Fixed numbers can be added and subtracted using the usual + and - operators. However, the * and / operators will not work correctly for multiplication and division. Instead, the Toolbox provides the routines FixMul() and FixDiv(). The Toolbox provides several other routines for conversion to and from other data types and for some math functions. The following Toolbox routines are used in the implementation of the C++ fixed-point number class:

• FixMul() - multiplies two fixed-point numbers

• FixDiv() - divides two fixed-point numbers

• FracSin() - returns the sine of a fixed-point number as a Fract

• FracCos() - returns the cosine of a fixed-point number as a Fract

• Frac2Fix() - converts a Fract to a fixed-point number

• Long2Fix() - converts a long integer to a fixed-point number

• X2Fix() - converts an extended-format floating-point number to a fixed-point number

• Fix2X() - converts a fixed-point number to an extended-format floating-point number

Some of these routines use something called a Fract. A Fract is an alternative fixed-point type provided by the Toolbox. Like a Fixed number, a Fract also consists of 32 bits. However, for the case of a Fract, there is only one integer bit and a 30-bit fractional part.

Normally, one would use fixed-point numbers by declaring Fixed variables and calling the routines listed above directly. Using our new C++ class, we will be able to use floating-point numbers much more easily, while still getting the benefit of fast calculations.

C++ Features that Support Data Abstraction

C++ has several features that make it a good language for data abstraction. These include:

• function overloading

• operator overloading

• user-defined type conversions

These features will be briefly described here, and they are discussed in depth in many reference books on C++. (See the References section at the end of this article.)

Function overloading allows multiple functions having the same name to be defined. As long as each instance of the function has a different argument type list, the compiler is able to determine which instance is being called. Function overloading allows us, for example, to define a sin() function, separate from the sin() function found in the C library, that is specialized for our new fixed-point number class.

Operator overloading allows us to define the meaning of different types of operators as they are applied to user-defined classes. This will allow us, for example, to define the * and / operators for multiplication and division on our new fixed-point number class.

User-defined type conversions are a subtle but very powerful feature of C++. In C (or C++), we can write:

double x = 3;

The compiler automatically converts the integer value of 3 to the double-precision floating-point value of 3.0, which is represented internally in a completely different format. Automatic type conversions save us a lot of work, and eliminate a lot of errors. For example, a library function to calculate a square root may be defined for doubles:

double sqrt(double x);

However, we are generally free to call the sqrt() function with any type of number, such as an integer. The compiler automatically performs any necessary type conversions:

float y = sqrt(3);

The example above performs two automatic conversions: The int 3 is converted to a double before calling sqrt(), and then the result of sqrt() is converted to a float. The effect is the same as if we had written:

float y = (float) sqrt( (double) 3 );

But certainly the simpler form of this expression is easier to write, easier to read, and less subject to errors.

C++ allows us to define the valid set of type conversions that the compiler may apply to the new classes that we write. So, in other words, we can tell the compiler how to convert instances of our new fixed-point number class to doubles. We can then apply the sqrt() function to a fixed-point number as easily as any other type of number, and leave the details of the type conversion to the compiler!

Implementation of the C++ Fixed-Point Number Class

Let’s take a look at how our new fixed-point number class is implemented. In order to understand these examples, the reader should know something about C programming. If the reader also has some knowledge of C++, all the better!

Our new C++ class is called simply fix, and recall that the design goal is for fix to be as easily usable as built-in types like float or double. The declaration of fix is structured like this:

/* 1 */

class fix {
private:
 // declarations of friend functions
 Fixed n;
 static fix result;
 // declarations of private member functions
public:
 // declarations of public member functions
};

The fix class has one data member, n. This member is a number whose data type is the Macintosh Toolbox type Fixed, which was described above. The fix class also has a static data member, result, which is shared among all members of the fix class. It was found during development that using this static data member to hold the results of calculations gave better performance than the alternative of declaring local variables within member functions.

The power of the new class comes from its friend and member functions. Examples of these will be described in detail below.

Arithmetic operators

Friend functions are functions that, although external to the class, may access the class’s private data members, which in this case is the Fixed data member, n. One friend function overloads the + operator for addition. This friend function is declared as:

/* 2 */

friend inline fix operator+(const fix, const fix);

and implemented as:

/* 3 */

inline fix operator+(const fix a, const fix b)
{
 fix::result.n = a.n + b.n;
 return fix::result;
}

The inline specifier means that the compiler will substitute the code for the function in place, rather than actually generating a stack frame when the function is called. This speeds execution at the expense of program size.

This friend function allows the + operator to be used for the addition of two numbers of type fix. (The minus operator for subtraction is defined similarly.)

From what we have seen so far, there is not yet much benefit to the fix class; the Toolbox Fixed data type also supports the + and - operators. However, let’s take a look at another friend function:

/* 4 */

inline fix operator*(const fix a, const fix b)
{
 fix::result.n = FixMul(a.n,b.n);
 fix::result.rangecheck();
 return fix::result;
}

Now we begin to see some benefit of C++ data abstraction! This function allows the familiar * operator to be used for multiplication rather than the Toolbox FixMul() function. This seems much more natural. (Division is similarly defined.) Also, friend functions of this form play an important role in user-defined data conversions. Either of the function arguments is subject to implicit, user-defined type conversions. This allows, for example, a fix number to multiply a double.

This function also demonstrates another benefit of C++ classes: that of encapsulation. The function provides a wrapper over fixed-point number multiplication, so that whenever fix numbers are multiplied, the rangecheck() function will be called automatically to ensure that the result is valid.

sin() and cos() functions

Friend functions are also defined for sin() and cos() of fix numbers. For example:

/* 5 */

fix sin(const fix a)
{
 fix result;
 Fract temp = FracSin(a.n);
 result.n = Frac2Fix(temp);
 return result;
}

The calls to the Toolbox functions FracSin() and Frac2Fix() are hidden within the implementation of the friendlier sin() function.

Why is this function defined as a friend function rather than a member function? If it were a member function, it would be called as:

my_fix.sin();

However, as a friend function, it is instead called as:

sin(my_fix);

This matches the normal usage of sin() in the standard ANSI library.

I/O functions

C++ provides the iostream library which may be used in place of the standard C stdio library. Many beginning C++ programmers wonder why an alternative I/O library is provided, and are reluctant to use it since they are already expert in using the stdio library. The benefit of the C++ iostream library is illustrated in the following example.

Suppose we want to print a fix number using stdio. Before doing so, we need to convert the fix to a printable type. (We will assume for now that we may cast a fix to a double. Soon we will take a look at how such user-defined conversions are specified.)

printf("here is the number:  %f \n", (double)my_fix);

Converting the fix to a double before printing is at odds with the notion that user-defined types (such as fix) are supposed to behave analogously to the built-in types (like double). The problem is that stdio is not extensible! We cannot add new data types to the stdio mechanism cleanly. New types must be converted to a built-in type before printing.

In contrast, here is how we print the same thing using the iostream library:

cout << "here is the number:  " << my_fix << endl;

Note that there is no explicit type conversion specified. We would write essentially the same line of code whether we wanted to print a fix, int, or double variable. As we see, the iostream library can be cleanly extended for new data types.

The following friend function implements the above capability by overloading the << operator:

/* 6 */

ostream& operator<<(ostream& os, const fix& f)
{
 os << (double) f;
 return os;
}

The explicit conversion from fix to double is now specified once and for all within the implementation of this method.

The assignment operator and copy constructor

The compiler automatically generates a default assignment operator and copy constructor for each user-defined class. Therefore, the following operations are provided automatically by the compiler:

/* 7 */

fix my_fix;
fix your_fix = my_fix;
fix her_fix(my_fix);

Here, your_fix is assigned to have the same value as my_fix, and her_fix is initialized as being a copy of (having the same value as) my_fix. The default assignment operator and copy constructor perform a memberwise copy of all the data members of the class. For the fix class, the value of the fixed-point number is copied.

Other member functions

A few other member functions are provided, including overloaded operators for increment (++) and decrement (--), as well as the +=, -=, *=, and /= operators. The implementation of these is fairly straightforward.

The last, and most complex, topic in the implementation of the fix class, is that of user-defined type conversions.

User Defined Type Conversions

In the last section, we had assumed that the compiler knew how to convert fix numbers to and from built-in types such as doubles:

double my_double = (fix) my_fix;  // explicit conversion
double another_double = my_fix;   // implicit conversion

These type conversions are specified using C++ member functions. In this section we will examine the details of how this is done.

Whenever an instance of a user-defined class is created, a special function called a constructor is called. A class may have multiple constructors having different argument lists. For example, the fix class has several constructors, one of which is:

fix(const long l) { n = Long2Fix(l); };

This constructor allows a fix to be created from a long integer. The implementation of this constructor calls the Toolbox function Long2Fix() in order to convert the integer to a fixed-point value. The constructor uses the long data type rather than int because the compiler by default casts literal constants to the largest applicable type, so any integer literal has an implicit type of long. Also, the compiler knows how to convert any of the build-in integer types, including int and short, to long.

This constructor allows as to declare fix variables such as:

fix x(36); // initializes the fixed-point number to 36

Less obvious, however, is that this constructor tells the compiler how to implicitly convert between integers and fixed-point numbers. Having defined this constructor, it is valid to write:

int my_int = 38;
fix my_fix = my_int; // implicit conversion

Of course, now that we have the ability to convert integers to fixed-point numbers, it would also be desirable to convert floating-point numbers to fixed-point numbers. The implementation of this constructor is similar:

fix(const long double d) { n = X2Fix(d); };

Now that we can convert numbers of different types (integer and floating-point) to numbers of our new fixed-point class, how do we define the inverse conversion? In this case, we overload the fix cast operator:

/* 8*/

fix::operator long double()
{
 long double result = Fix2X(n);
 return (result);
}

The implementation of this member function is quite analogous to the implementation of the constructor from floating-point numbers, except that the conversion is performed in the reverse direction.

The overloaded cast operator allows us to write the following for an explicit type conversion.

/* 9 */

double d;
fix    f(3.14);
d = (double) f;

Even more importantly, however, the overloaded cast operator tells the compiler how to convert a fix number to a double implicitly.

At this point, we may wonder whether it is valid to write the following:

/* 10 */

fix my_fix, your_fix;
my_fix   = some_value;
your_fix = another_value;
if (my_fix > your_fix)   // Can we compare two fix numbers?
{
 do something...
}

The answer is: yes! Because we have told the compiler how to implicitly convert fixed-point numbers to floating-point numbers, the compiler actually performs the comparison as:

if ( (long double) my_fix > (long double) your_fix )

The compiler implicitly converts the fixed-point numbers to floating-point numbers in order to use the comparison (>) operator.

Using the Fixed-Point Number Class

We’ve already looked at several examples involving the fix class. Let’s study a couple of others in terms of the individual steps -- some explicit and some implicit -- performed by the compiler.

First, let’s consider:

/* 11 */

const double pi = 3.14159;
fix a(0.75);
cout << "sine of 135 degrees is " << sin(a*pi) << endl;

This calculation is performed by executing these steps:

• The overloaded * operator for fixed-point numbers computes a*pi.

• The overloaded sin() function for fixed-point numbers computes the sine of a*pi.

• The overloaded << operator writes the sine value to the output stream.

In contrast, let’s consider this example:

cout << "tangent of 135 degrees is " << tan(a*pi) << endl;

In this case, the calculation consists of these steps:

• The overloaded * operator for fixed numbers computes a*pi.

• The overloaded cast operator implicitly converts a*pi (a fix) to a long double.

• The long double result above is converted implicitly to a double.

• The standard ANSI library tan() function receives the double result from the last step.

• The << operator writes the tangent value to the output stream.

In the first case above, there is a sin() function specialized for fixed-point numbers, so the entire calculation of sin(a*pi) is performed in the domain of fixed-point numbers. In contrast, we have not defined a tan() function for fixed-point numbers. Therefore, the calculation of tan(a*pi) requires an implicit type conversion so that the tangent is actually computed in the domain of floating-point numbers. To the programmer using the fix class, the difference is transparent; fixed-point numbers can be used just like any other numbers. The compiler takes care of the details.

A Benchmark to Measure Performance

In this section we will look at a small sample program that compares the performance of fixed-point and floating-point numbers. To get a fair test, we want to perform the same set of calculations using each type of number. To do this, we will use another C++ feature: templates.

A C++ matrix template

Templates allow functions or classes to be written once for multiple data types. For example, our benchmark program will use a simple template class for matrices. This template class definition defines a simple 4x4 matrix of any type of number:

/* 12 */

template <class Number>
class matrix {
private:
 Number m[4][4];
 friend ostream& 
 operator<<(ostream&, const matrix<Number>&);
public:
 matrix();
 inline Number& operator()(const int,const int);
 matrix<Number> operator*(const matrix<Number>);
};

This is not an exhaustive definition for a matrix class by any means. If we were building a matrix class as part of a general-purpose class library, there are many other matrix functions that we would probably want to provide. However, this definition will suffice for the purpose of benchmarking the fix class.

As we can see, the definition of the matrix class includes:

• a 4x4 matrix of numbers

• an overloaded << operator for writing the matrix to an output stream

• a constructor for initializing a matrix

• an overloaded () operator that is used for indexing the elements of the matrix

• an overloaded * operator for multiplying matrices

Let’s take a look at the implementation of the * (matrix multiplication) operator:

/* 13 */

template <class Number>
matrix<Number> 
matrix<Number>::operator*(const matrix<Number> mat)
{
 matrix<Number> result;
 int i,j,k;
 
 for(i=0;i<4;i++)
   for(j=0;j<4;j++)
     for(k=0;k<4;k++)
       result[i][j] += m[i][k] * mat.m[k][j];
 return result;
}

This template function implements the traditional algorithm for multiplying two 4x4 matrices. Note that the multiplication of pairs of numbers is performed using the * operator. Of course this is the usual way of multiplying built-in number types like ints and doubles. Because we also defined the fix class to use the * operator for multiplication, this function can multiply matrices of fix numbers, as well.

Matrices for different types of numbers can now be declared as:

/* 14 */

matrix<double> double_matrix;
matrix<fix>    fix_matrix;

The benchmark() function

The benchmark() function is itself defined as a template, so that it can be applied to a matrix of any type of numbers. The benchmark() function:

• sets the input matrix to be an identity matrix,

• creates a three dimensional rotation matrix corresponding to a 2 degree rotation about the Z axis,

• premultiplies the input matrix 1000 times by the rotation matrix, and counts the number of seconds that this takes, and finally

• prints the resulting matrix (resulting from the 1000 multiplications).

Matrix operations like those listed above, and their use for three-dimensional computer graphics, are described in many standard textbooks, such as those listed in the References section.

It’s interesting to look at the line of code within the benchmark() function that performs the matrix multiplication:

m = rotation * m;

Because we overloaded the * operator for the matrix class to perform matrix multiplication, this line of code can be written in an extremely simple fashion! At this level of detail we do not have to be concerned with the fact that multiplication of two 4x4 matrices actually involves 64 multiplications of numbers, 48 additions, and so forth. The matrix C++ class is a high-level abstract data type that hides the details of the low-level matrix operations.

The main() routine calls the benchmark() function for both a matrix of fix numbers and a matrix of doubles. The results are summarized in the next section.

Benchmark Results

After the initial identity matrix:

10 0 0
01 0 0
00 1 0
00 0 1

was premultiplied 1000 times by the rotation matrix:

cos(Π/90) -sin(Π/90) 0 0

sin(Π/90) cos(Π/90) 0 0

0 0 1 0

0 0 0 1

the result, using fix numbers, was the matrix:

-0.93808 0.338715 0 0

-0.338715 -0.93808 0 0

0 0 1 0

0 0 0 1

And using doubles, the result was:

-0.939703 0.341992 0 0

-0.341992 -0.939703 0 0

0 0 1 0

0 0 0 1

It can be seen that the difference in precision between fix numbers and doubles in this case is less than 1% for 1000 calculations. This difference is certainly tolerable for many types of graphics applications where the numbers correspond to screen positions or orientations of geometric objects. For these cases, an infinitesimal difference in some quantity will most likely not even be noticeable.

The benchmark was run on a Powerbook 145 running at 16 MHz. The 1000 matrix multiplications took about 4 seconds for fix numbers and about 13 seconds for doubles. Therefore, the fix numbers executed about 3 times faster!

We might wonder whether a significant portion of the time for the fix number calculations was due to overhead introduced by the fix number class, as compared to the time required by the fixed-point math routines themselves. To find out, the profiler was used to take statistics during the 1000 matrix multiplications for fix numbers. The results were:

Function Min Max Avg % Entries

matrix<fix>::operator * 0 3 0 28 1000

operator * 0 1 0 33 64000

fix::operator += 0 1 0 16 64000

fix::rangecheck 0 1 0 8 64000

operator + 0 1 0 11 64000

matrix<fix>::__PT6matrix3fix 0 1 0 0 1000

fix::fix 0 1 0 0 1000

fix::fix 0 1 0 2 16000

As we see, 33% of the execution time was due to fixed-point number multiplication (performed in the operator *). 28% was due to the matrix multiplication routine, consisting of the nested for loops and assignment statements. Only 11% of the execution time was due to the addition of fixed-point numbers, although a surprising 16% of time was due to the += operator. We also note that 8% was due to the rangecheck() function. We could of course abstain from calling this function at the expense of some safety. It certainly seems as though the bulk of the execution time was due to the mathematical operations themselves, rather than overhead introduced by the class definition.

Conclusions

We have looked in detail at the design of a new C++ class that allows fixed-point numbers to be used as easily as floating-point numbers, with about a 3 times improvement in performance. The loss in precision was found to be less than 1%, even after a large number of calculations. The values of the fix numbers span the range of about + and - 32,768. The fix class should only be used for applications where values will remain within this range.

Modular design and consistent interfaces are extremely important for well-designed C++ classes. The fix class, although simple, was designed using an extremely powerful idea. By providing the same standard interface as the built-in number types, fix numbers can be used interchangeably with floats or doubles.

We could, for example, develop an application using doubles, and then easily “plug in” fix numbers for increased performance, simply by changing the types of variables. Conversely, if we develop an application using fix numbers, and then find that we need to use doubles after all, we could just “plug in” doubles.

The implementation of the fix class could be easily extended in a modular way. For example, if we want, in the future, to provide a fast square root function optimized for fixed-point numbers, we could easily “plug in” such a function. In the interim, fixed-point square roots are easily calculated by the compiler by implicitly converting fix numbers to doubles, and then calling the standard C sqrt() function. A programmer can use the fix class effectively without being concerned with these details.

Looking to the Future

There are many other examples where the power of C++ could greatly simplify Macintosh programming. Large, commercial class libraries such as the THINK Class Library (TCL), MacApp, and, soon, Bedrock, provide us with general-purpose application frameworks. However, we can still improve the design of our own specialized applications by developing appropriate, application-specific class definitions that work along with the larger application frameworks.

For example, suppose we wanted to create a class library to support a variety of three-dimensional graphics and animation applications. Using the modest foundation developed in this article, we could:

• extend the simple, initial matrix class introduced here to include other matrix functions,

• derive specialized types of matrices for geometric transformations, perspective projections, and so forth,

• design additional classes for such things as points, lines, and planes, using the fast fix class for calculations, and even

• derive a new type of TCL pane class that uses transformations, projections, and so forth, to support three-dimensional geometry.

The only limit is our imagination!

References

C++

The Symantec C++ User’s Guide lists many of the good references on C++. Two others will be mentioned here.

The following book was just recently published and contains a good introduction to C++, the Symantec programming environment, and the THINK Class Library:

Rhodes and McKeehan, Symantec C++ Programming for the Macintosh, Brady, 1993.

The following book has a detailed discussion of the C++ data abstraction capabilities discussed in this article.

K.E. Gorlen, et. al., Data Abstraction and Object-Oriented Programming in C++, Wiley, 1990.

[And don’t forget Dave Mark’s Learn C++ on the Macintosh published by Addison-Wesley. - Ed.]

Macintosh Toolbox

The Fixed data type and its operations are documented in Volumes I and IV of Inside Macintosh.

Graphics and Animation

There are many standard textbooks that cover the graphics and animation topics mentioned in this article. Two of the best are:

Foley, et. al., Computer Graphics, Principles and Practice, 2nd ed., Addison-Wesley, 1990.

Rogers, Mathematical Elements for Computer Graphics, 2nd ed., McGraw-Hill, 1990.

Listing: fix.h
/***************************************
* fix.h
* fixed-point number class interface
***************************************/

#pragma once

#include <FixMath.h>
#include <iostream.h>
#include <assert.h>

const Fixed fixed_zero = Long2Fix((long) 0);

class fix {
private:
// arithmetic operators
 friend inline fix operator+(const fix, const fix);
 friend inline fix operator-(const fix, const fix);
 friend inline fix operator*(const fix, const fix);
 friend inline fix operator/(const fix, const fix);
// I/O operators
 friend ostream& operator<<(ostream&, const fix&);
 friend istream& operator>>(istream&, fix&);
// transcendental functions that are optimized 
// for fixed-point numbers
 friend fix sin(const fix);
 friend fix cos(const fix);
// data value
 Fixed n;
// static data member for computation results
 static fix result;
// private range check member function
 inline void rangecheck();
public:
// constructors
 fix() { n = fixed_zero; };
 fix(const long l) { n = Long2Fix(l); };
 fix(const long double d) { n = X2Fix(d); };
// incremant and decrement operators
 fix operator++()   { n += Long2Fix(1); return *this; }; 
// prefix
 fix operator--()    { n -= Long2Fix(1); return *this; };
 fix operator++(int) { n += Long2Fix(1); return *this; }; 
// postfix
 fix operator--(int) { n -= Long2Fix(1); return *this; };
// cast operators
 operator long double();
// other operators...
 fix operator+=(const fix f) 
 { *this = *this + f; return *this; }; 
 fix operator-=(const fix f) 
 { *this = *this - f; return *this; }; 
 fix operator*=(const fix f) 
 { *this = *this * f; return *this; }; 
 fix operator/=(const fix f) 
 { *this = *this / f; return *this; }; 
};
 
inline void fix::rangecheck()
{
 assert((n != 0x7FFFFFFF) && (n != 0x80000000));
}

inline fix operator+(const fix a, const fix b)
{
 fix::result.n = a.n + b.n;
 return fix::result;
}
 
inline fix operator-(const fix a, const fix b)
{
 fix::result.n = a.n - b.n;
 return fix::result;
}
 
inline fix operator*(const fix a, const fix b)
{
 fix::result.n = FixMul(a.n,b.n);
 fix::result.rangecheck();
 return fix::result;
}
 
inline fix operator/(const fix a, const fix b)
{
 fix::result.n = FixDiv(a.n,b.n);
 fix::result.rangecheck();
 return fix::result;
}
Listing: fix.cp
/***************************************
* fix.cp
* fixed-point number class implementation
***************************************/

#include "fix.h"
#include <math.h>
#include <SANE.h>

fix fix::result; // initialize static data member

fix::operator long double()
{
 long double result = Fix2X(n);
 return (result);
}

ostream& operator<<(ostream& os, const fix& f)
{
 os << (double) f;
 return os;
}

istream& operator>>(istream& is, fix& f)
{
 double temp;
 
 is >> temp;
 // Since this routine reads a floating-point number, 
 // and then converts it, errors are handled in the same 
 // way as for reading floating-point numbers.  The 
 // iostream library includes functions for testing 
 // and reseting the error state.
 if (is.good())
 f = (fix) temp;
 return is;
}

fix sin(const fix a)
{
 fix result;
 Fract temp = FracSin(a.n);
 result.n = Frac2Fix(temp);
 return result;
}

fix cos(const fix a)
{
 fix result;
 Fract temp = FracCos(a.n);
 result.n = Frac2Fix(temp);
 return result;
}
Listing: matrix.h
/***************************************
* matrix.h
* matrix template class interface
***************************************/

#pragma once

#include <iostream.h>
#include <assert.h>

template <class Number>
class matrix {
private:
 Number m[4][4];
 friend ostream& operator<<(ostream&, const matrix<Number>&);
public:
 matrix();
 inline Number& operator()(const int,const int); 
// for matrix indexing 
 matrix<Number> operator*(const matrix<Number>);
};

template <class Number>
inline Number& matrix<Number>::operator()(const int row, 
 const int col)
{
 assert(row >=0 && row <= 3 && col >=0 && col <= 3);
 return m[row][col];
}
Listing: matrix.cp
/***************************************
* matrix.cp
* matrix template class implementations
***************************************/

#include "matrix.h"
#include <iomanip.h>

template <class Number>
matrix<Number>::matrix()
{
 int i,j;
 Number zero(0); // initialize any type of Number to zero
 
 for(i=0;i<4;i++)
 for(j=0;j<4;j++)
 m[i][j] = zero;
}

template <class Number>
matrix<Number> matrix<Number>::operator*(
 const matrix<Number> mat)
{
 matrix<Number> result;
 int i,j,k;
 
 for(i=0;i<4;i++)
 for(j=0;j<4;j++)
 for(k=0;k<4;k++)
 result.m[i][j] += m[i][k] * mat.m[k][j];
 return result;
}

template <class Number>
ostream& operator<<(ostream& os, const matrix<Number>& mat)
{
 int i,j;
 
 for(i=0;i<4;i++)
 {
 for(j=0;j<4;j++)
 os << setw(10) << mat(i,j);
 os << endl;
 }
 return os;
}
Listing: matrix<double>.cp
/***************************************
* matrix<double>.cp
* pragmas to create public double matrix
***************************************/

#include "matrix.cp"
#pragma template matrix<double>
#pragma template_access public
Listing: matrix<fix>.cp
/***************************************
* matrix<fix>.cp
* pragmas to create public fix matrix
***************************************/

#include "fix.h"
#include "matrix.cp"
#pragma template matrix<fix>
#pragma template_access public
Listing: benchmark.cp
/***************************************
* benchmark.cp
* benchmark template function and main routine
***************************************/

#include "fix.h"
#include "matrix.h"
#include <math.h>
#include <iostream.h>
#include <console.h>
#include <profile.h>

 // Change the 0 below to a 1 to use the profiler.
 // Also turn on the following C++ compiler options:
 //    "Generate profiler calls"
 //    "Always generate stack frames"
 //    "Use function call for inlines"
const int use_profiler = 0;

const double pi = 3.14159;
const int num_iterations = 1000;

template <class Number>
unsigned long benchmark(matrix<Number> m,const int use_prof=0)
{
 unsigned long time1, time2, total;

 // Make the matrix an identity matrix, and print.
 m(0,0) = m(1,1) = m(2,2) = m(3,3) = 1;
 cout << "identity matrix:" << endl << m;
 
 // Create a rotation matrix, and print.
 matrix<Number> rotation;
 rotation(0,0) = rotation(1,1) = cos(pi/90);  
 // 2 degree rotation
 rotation(0,1) = rotation(1,0) = sin(pi/90);
 rotation(0,1) *= -1;
 rotation(2,2) = rotation(3,3) = 1;
 cout << "rotation matrix:" << endl << rotation;
 
 // Premultiply the matrix by the rotation 
 // matrix 1000 times.
 GetDateTime(&time1);
 if (use_prof) InitProfile(200,200);
 for (int i=0; i<num_iterations; i++)
 m = rotation * m;
 if (use_prof) DumpProfile();
 GetDateTime(&time2);

 // Print results.
 cout << "result of " << num_iterations << 
 " multiplications:" << endl << m;
 total = time2-time1;
 cout << "duration: " << total << " seconds" << endl;
 return total;
}

void main(int argc, char *argv[])
{
 unsigned long double_time, fix_time;
 double   ratio;

 // The ccommand() function allows results to be 
 // easily saved to a file.
 argc = ccommand(&argv);

 cout << 
 "calling the benchmark function on a double matrix..." 
 << endl;
 matrix<double> double_matrix;
 double_time = benchmark(double_matrix);
 
 cout << "calling the benchmark function on a fix matrix..." 
 << endl;
 matrix<fix> fix_matrix;
 fix_time = benchmark(fix_matrix,use_profiler);
 
 if (!use_profiler)
 if (fix_time > 0)
 {
 ratio = (double)double_time/(double)fix_time;     
 cout << "fixed-point calculations were about " 
 << ratio << " times faster!" << endl;
 }
 else
 cout << 
 "fixed-point calculations completed in less than 1 second!" 
 << endl;
}

 
AAPL
$117.60
Apple Inc.
-1.03
MSFT
$47.47
Microsoft Corpora
-0.12
GOOG
$541.08
Google Inc.
+1.81

MacTech Search:
Community Search:

Software Updates via MacUpdate

MacUpdate Desktop 6.0.3 - Discover and i...
MacUpdate Desktop 6 brings seamless 1-click installs and version updates to your Mac. With a free MacUpdate account and MacUpdate Desktop 6, Mac users can now install almost any Mac app on macupdate.... Read more
SteerMouse 4.2.2 - Powerful third-party...
SteerMouse is an advanced driver for USB and Bluetooth mice. It also supports Apple Mighty Mouse very well. SteerMouse can assign various functions to buttons that Apple's software does not allow,... Read more
iMazing 1.1 - Complete iOS device manage...
iMazing (was DiskAid) is the ultimate iOS device manager with capabilities far beyond what iTunes offers. With iMazing and your iOS device (iPhone, iPad, or iPod), you can: Copy music to and from... Read more
PopChar X 7.0 - Floating window shows av...
PopChar X helps you get the most out of your font collection. With its crystal-clear interface, PopChar X provides a frustration-free way to access any font's special characters. Expanded... Read more
Carbon Copy Cloner 4.0.3 - Easy-to-use b...
Carbon Copy Cloner backups are better than ordinary backups. Suppose the unthinkable happens while you're under deadline to finish a project: your Mac is unresponsive and all you hear is an ominous,... Read more
ForeverSave 2.1.3 - Universal auto-save...
ForeverSave auto-saves all documents you're working on while simultaneously doing backup versioning in the background. Lost data can be quickly restored at any time. Losing data, caused by... Read more
Voila 3.8.1 - Capture, annotate, organiz...
Voila is a screen-capture, recording, and annotation tool that is a full-featured replacement for Mac's screen-capture and screen-recording capabilities. It has a large and robust set of editing,... Read more
SyncTwoFolders 2.0.6 - Syncs two user-sp...
SyncTwoFolders simply synchronizes two folders. It supports synchronization across mounted network drives and it is a possibility to run a simulation showing in a log what will be done. Please visit... Read more
Duplicate Annihilator 5.1.1 - Find and d...
Duplicate Annihilator takes on the time-consuming task of comparing the images in your iPhoto library using effective algorithms to make sure that no duplicate escapes. Duplicate Annihilator detects... Read more
HandBrake 0.10.0 - Versatile video encod...
HandBrake is a tool for converting video from nearly any format to a selection of modern, widely supported codecs. Supported Sources: VIDEO_TS folder, DVD image or real DVD (unencrypted -- CSS is... Read more

Latest Forum Discussions

See All

Screeny (Utilities)
Screeny 1.0 Device: iOS iPhone Category: Utilities Price: $.99, Version: 1.0 (iTunes) Description: Screeny is an utility app that helps you save space consumed by screenshots. It screens your camera roll and helps you to filter and... | Read more »
Tilt to Live Bundle Set to Arrive This T...
Tilt to Live Bundle Set to Arrive This Thanksgiving Posted by Ellis Spice on November 25th, 2014 [ permalink ] One Man Left has unveiled an upcoming Tilt to Live bundle, allowing players to get the series for a di | Read more »
BattleLore: Command (Entertainment)
BattleLore: Command 1.0 Device: iOS Universal Category: Entertainment Price: $9.99, Version: 1.0 (iTunes) Description: ***NOTE: Compatible with iPad 2/iPad mini, iPod touch 5 and up and iPhone 4S and up – WILL NOT RUN ON EARLIER... | Read more »
Weather Or Not Review
Weather Or Not Review By Jennifer Allen on November 25th, 2014 Our Rating: :: STYLISH WEATHER REPORTINGiPhone App - Designed for the iPhone, compatible with the iPad Check the weather quickly and conveniently with Weather or Not... | Read more »
The All-New Football Manager Handheld 20...
The All-New Football Manager Handheld 2015 is Available Now Posted by Jessica Fisher on November 25th, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Six iOS Games to Get You Ready for Thank...
Image Source: Friends Wiki At this point in the month, you or at least a few people you know are probably getting ready to scramble around (or are already scrambling around) for Thanksgiving Dinner. It’s a hectic day of precise oven utilization, but... | Read more »
Call of Duty: Heroes: Tips, Tricks, and...
Hello Heroes: What’d we think of Call of Duty‘s take on Clash of Clans? Check out our Call of Duty: Heroes review to find out! Just downloaded Call of Duty: Heroes and need some handy tips and tricks on how to get ahead of the rest? As we often do,... | Read more »
Call of Duty: Heroes Review
Call of Duty: Heroes Review By Jennifer Allen on November 25th, 2014 Our Rating: :: CLASH OF FRANCHISESUniversal App - Designed for iPhone and iPad Mix Clash of Clans with Call of Duty, and this is what you get.   | Read more »
Slider Review
Slider Review By Jordan Minor on November 25th, 2014 Our Rating: :: SLIDE TO PLAYUniversal App - Designed for iPhone and iPad Slider has all the excitement of unlocking your phone screen.   | Read more »
oh my giraffe (Games)
oh my giraffe 1.0.0 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0.0 (iTunes) Description: Eat fruits while being chased by lions. Cut the vines to send fruit plummeting onto the lions. Don't worry, your flexible... | Read more »

Price Scanner via MacPrices.net

Early Black Friday MacBook Pro sale: 15-inch...
 Best Buy has posted early Black Friday prices on 15″ Retina MacBook Pros, with models on sale for $300 off MSRP on their online store for a limited time. Choose free local store pickup (if available... Read more
A9 Chips Already?
It’s barely more than a couple of months since Apple got the first A8 systems-on-chip into consumer hands, but rumor and news focus is already turning to the next-generation A9 SoC. Apple Daily... Read more
NewerTech Announces NuGuard KXs Impact X-Orbi...
NewerTech has announced updates to its family of Impact X-Orbing Screen Armor bringing military grade, triple layer protection to Apple’s new iPhone 6 and 6 Plus. Like all models in the NuGuard KXs... Read more
13-inch 1.4GHz MacBook Air on sale for $889,...
 B&H Photo has the 13″ 1.4GHz/128GB MacBook Air on sale for $889 including free shipping plus NY tax only. Their price is $110 off MSRP. B&H will also include free copies of Parallels Desktop... Read more
Save up to $300 on Macs and iPads with your A...
Purchase a new Mac or iPad at The Apple Store for Education and take up to $300 off MSRP. All teachers, students, and staff of any educational institution qualify for the discount. Shipping is free,... Read more
Apple refurbished Mac Pros available for up t...
The Apple Store is offering Apple Certified Refurbished Mac Pros for up to $600 off the cost of new models. An Apple one-year warranty is included with each Mac Pro, and shipping is free. The... Read more
Jumptuit Launches One-Tap Windows 8.1 iTunes...
Jumptuit has launched Windows 8.1 support for One-Tap iTunes Sync. with which Windows 8.1 users can now easily sync their iTunes libraries with Microsoft OneDrive. Jumptuit provides easy access from... Read more
Apple restocks refurbished 13-inch 2014 Retin...
The Apple Store has restocked Apple Certified Refurbished 2014 13″ 2.6GHz Retina MacBook Pros for up to $230 off the cost of new models. An Apple one-year warranty is included with each model, and... Read more
CEA Study Finds More People Recycling Electro...
A new study by the Consumer Electronics Association (CEA) finds that electronics recycling receives the continued and growing support of consumers. According to the CEA,s Recycling and Reuse Study,... Read more
15″ 2.2GHz Retina MacBook Pro on sale for $17...
 B&H Photo has the 2014 15″ 2.2GHz Retina MacBook Pro on sale today for $1749. Shipping is free, and B&H charges NY sales tax only. B&H will also include free copies of Parallels Desktop... Read more

Jobs Board

*Apple* Solutions Consultant (ASC) - Apple (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
Senior Event Manager, *Apple* Retail Market...
…This senior level position is responsible for leading and imagining the Apple Retail Team's global event strategy. Delivering an overarching brand story; in-store, Read more
*Apple* Retail - Multiple Positions (US) - A...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
*Apple* Solutions Consultant (ASC) - Apple (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
*Apple* Solutions Consultant (ASC) - Apple (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.