Important: The information in this document is obsolete and should not be used for new development.
Porting SANE to PowerPC Numerics
If you have a program that is written to take advantage of SANE features, you might want to port it to the PowerPC processor to take advantage of the increased speed. This section provides tips on how to do so.Perform the following steps to be sure that your program will run on both 680x0-based and PowerPC processor-based Macintosh computers:
The following sections guide you through these four steps.
- Replace all uses of type
compwith typedoubleorlong int.- Replace
sane.handmath.hwithfp.handfenv.h.- Replace uses of
extendedwithdouble_tor, if this is not possible, withlong double.- Replace SANE-specific functions with their MathLib equivalents. SANE-specific functions include the functions listed as implemented differently in MathLib in the section "Differences in Transcendental Functions" on page A-5, all class and sign inquiry functions, and all environmental control functions.
Replacing Variables of Type comp
The first step in porting a SANE program is to remove uses of the data typecomp. The typecompis a floating-point type with 64 bits of precision. In SANE, typecompis automatically converted to extended format whenever an expression is evaluated, just like every other SANE data format. In other words,compis a floating-point type disguised as an integer type. In most cases you can replace typecompwith typedouble, which provides 53 bits of precision. If yourcompvariables require greater than 53 bits of precision, you might need to write your own integer arithmetic package.Using MathLib Instead of the SANE Library
The next step in porting a SANE program is to use the header filesfp.handfenv.h. The filesfp.handfenv.hreplacesane.handmath.h. All of the transcendental functions declared insane.hare now declared infp.h, and most of them work exactly the same way in the two environments. If your program includes the header filemath.hinstead ofsane.h, you should replace it withfp.has well. Thefp.hfile declares all of the functions and macros declared in the ANSI header filemath.hplus some additional ones.Be aware of the differences in function prototypes in the files
sane.handfp.h. If your program currently usessane.h, the declarations for transcendental functions look like this:
extended func_name (extended func_params);In other words, all transcendental functions insane.hare typeextendedand take typeextendedas arguments. These declarations mean that you can pass any floating-point type to a transcendental function without losing precision.In
fp.h, the typical transcendental function declaration has the form
double_t func_name (double_t func_params);Thedouble_ttype changes definition based on which processor the program is run on. For the PowerPC processor,double_tis defined to be typedouble. For the 680x0 processor,double_tis defined to be typeextended. Therefore, when you change from usingsane.hto usingfp.h, your program will compile on both the 680x0 and the PowerPC processors and there will be no change in the way your program runs on the 680x0. For more information on thedouble_ttype, see "Portable Declarations" on page A-9.In some cases, a numeric function also has a
long doubleimplementation in MathLib. The declarations of thelong doubleimplementations are infp.hand have the form
long double func_namel (long double func_params);See the function descriptions in Part 2 of this book to find out if a function you are using has along doubleimplementation. If it does, you should examine the types of the parameters you are passing to that function and you should examine the return values. If a function parameter or return value requires more than 53 bits of precision, you may need to use thelong doubleimplementation of the function when it runs on a PowerPC processor. To do this, you simply add the letter l to the function call.Replacing Extended Format Variables
When changing extended variables, first change all variables that are declared asextendedto typedouble_t. For the 680x0 processor,double_tis defined asextended. For the PowerPC processor,double_tis defined asdouble. Once you make this change, your program runs with no changes on the 680x0 processor but now also runs on the PowerPC processor. Next, you need to examine eachdouble_tvariable to see if it will overflow on the PowerPC processor. If the variable requires more than 53 bits of precision, change its declaration tolong double.Using MathLib Functions
As mentioned previously, PowerPC Numerics (specifically, the MathLib library) provides a superset of the functions that SANE provides. In most cases you don't need to make any changes to your existing calls to the SANE library. However, there are a few transcendental functions that have a different implementation in MathLib. Also, the names have changed for the class and sign inquiries and floating-point environmental controls.Differences in Transcendental Functions
The following transcendental functions are implemented differently in MathLib than in the SANE library:
- The
copysignfunction does not follow the IEEE standard in SANE, which reverses the order of the function's parameters. PowerPC Numerics follows the parameter order described in the IEEE standard.- The
exp1function in SANE is namedexpm1in PowerPC Numerics.- The
ipowerfunction is replaced with thepowfunction in PowerPC Numerics.- The
log1function in SANE is namedlog1pin PowerPC Numerics.- The nextafter functions in SANE are
nextfloat,nextdouble, andnextextended. In PowerPC Numerics, they arenexafterf,nextafterd, andnextafterlforfloat,double, andlong double, respectively.- The
nanfunction in SANE takes a character parameter, but the PowerPC Numericsnanfunction takes a character string parameter.- The SANE
pifunction is replaced with the constantpi, the SANEinffunction is replaced with the constantINFINITY, and theNANconstant remains the same.- The
powfunction behaves differently in the two environments. For example, in SANEpow(NAN,0)returns a NaN, whereas in PowerPC Numerics,pow(NAN,0)returns
a 1.- The
remainderfunction in SANE takes three parameters, the last one being a return value. The PowerPC Numericsremainderfunction takes two parameters. Theremquofunction is analogous to the SANEremainderfunction.- The
scalbfunction does not follow the IEEE standard in SANE, which reverses the order of the function's parameters. PowerPC Numerics follows the parameter order described in the IEEE standard.
Differences in Class and Sign Inquiries
The class and sign inquiry functions declared insane.hare not implemented in MathLib. Instead, MathLib provides a set of macros that perform the same actions.
Table A-1 shows the declarations insane.hon the left and the corresponding declaration in the MathLib header filefp.hon the right.
Table A-1 Class and sign inquiries in SANE versus MathLib sane.hdeclarationfp.hdeclaration
#define SNAN 0
#define QNAN 1
#define INFINITE 2
#define ZERONUM 3
#define NORMALNUM 4
#define DENORMALNUM 5
typedef short numclass;enum NumberKind {
FP_SNAN = 0,
FP_QNAN,
FP_INFINITE,
FP_ZERO,
FP_NORMAL,
FP_SUBNORMAL };numclass classfloat (extended x);
numclass classdouble(extended x);
numclass classcomp(extended x);
numclass classextended(extended x);#define fp_classify(x)[68] long signnum (extended x); #define signbit(x) Differences in Environmental Controls
MathLib's environmental control functions are declared in the header filefenv.h. They affect only rounding direction modes and floating-point exceptions, and they are different from the functions that perform the same tasks in the SANE library.If the SANE program uses rounding precision modes, you must remove this code to run it on the PowerPC processor. The PowerPC processor almost always uses less precision than SANE when evaluating expressions, so this should not be a problem. See Chapter 3, "Expression Evaluation," for details.
If the SANE program uses halts, you need to replace them with your own exception handling routines.
Replace the floating-point environmental access function or macro on the left side of Table A-2 with the corresponding function or macro on the right side. If your compiler supports the environmental access switch described in Appendix D, "FPCE Recommendations for Compilers," you must turn the switch on before using any of the functions or macros from Table A-2.
Table A-2 Environmental access functions in SANE versus MathLib sane.hdeclarationfenv.hdeclaration#define INVALID 1
#define UNDERFLOW 2
#define OVERFLOW 4
#define DIVBYZERO 8
#define INEXACT 16#define FE_INEXACT 0x02000000
#define FE_DIVBYZERO 0x04000000
#define FE_UNDERFLOW 0x08000000
#define FE_OVERFLOW 0x10000000
#define FE_INVALID 0x20000000#define IEEEDEFAULTENV #define FE_DFL_ENV &_FE_DFL_ENV typedef short exception; typedef long int fexcept_t; typedef short environment typedef long int fenv_t; #define TONEAREST 0
#define UPWARD 1
#define DOWNWARD 2
#define TOWARDZERO 3#define FE_TONEAREST 0x00000000
#define FE_TOWARDZERO 0x00000001
#define FE_UPWARD 0x00000002
#define FE_DOWNWARD 0x00000003typedef short rounddir; -- void setexception(exception e,
long s);int fesetexcept(const fexcept_t
*flagp, int excepts);
int feclearexcept(int excepts);
int feraiseexcept(int excepts);long testexception(exception e); int fetestexcept(int excepts); void setround (rounddir r); int fesetround(int round); rounddir getround(void); int fegetround(void); void setenvironment(environment e); void fesetenv(const fenv_t *envp); void getenvironment(environment *e); void fegetenv(fenv_t *envp); void procentry(environment *e); int feholdexcept(fenv_t *envp);[69] void procexit(environment e); void feupdateenv(const fenv_t *envp); Listing A-1 is a C code fragment that runs on both the 680x0 and PowerPC processors. It performs the
powfunction, tests for the occurrence of the inexact exception, and prints the results.Listing A-1 Using environmental controls in SANE and PowerPC Numerics
double_t x, y, result;/* double on PowerPC,extended on 680x0 */ #ifdef __SANE__ /* 680x0 processor */ exception fp_inexact; #else /* PowerPC processor */ fexcept_t fp_inexact; #endif #ifdef __SANE__ /* 680x0 processor */ setenvironment(IEEEDEFAULTENV); #else /* PowerPC processor */ fesetenv(FE_DFL_ENV); #endif result = pow(x, y); #ifdef __SANE__ /* 680x0 processor */ fp_inexact = testexception (INEXACT); #else /* PowerPC processor */ fp_inexact = fetestexcept (FE_INEXACT); #endif printf ("pow(%g,%g) = %g\t", x, y, result); if (fp_inexact) printf ("INEXACT\n");Compatibility Tools in MathLib
This section describes some tools provided in MathLib that help with compatibility between two environments. The tools include type definitions that help you make efficient, portable variable declarations and macros that are defined differently on the two architectures.Portable Declarations
MathLib defines two floating-point type definitions,float_tanddouble_t, in the header fileTypes.h. If you define a variable to befloat_tordouble_t, it means "use the most efficient floating-point type for this architecture." Table A-3 shows the definitions forfloat_tanddouble_ton PowerPC architecture compared with 680x0 architecture.
Table A-3 float_tanddouble_tdefinitionsArchitecture float_tdouble_tPowerPC float double 680x0 long double long double The PowerPC architecture is based on the IEEE double format. The most natural format for computations is double, but the architecture allows computations in single format as well. Therefore,
float_tis defined to befloat(single precision) anddouble_tis defined to bedoublefor the PowerPC architecture. The 680x0 architecture is based on the extended format and performs all computations in extended format regardless of the type of the operands. Therefore,float_tanddouble_tare bothlong double(extended precision) for the 680x0 architecture.If you declare a variable to be type
double_tand you compile the source code as a PowerPC application, the variable is double format. If you recompile the same source code as an 680x0 application, the variable is extended format.If your compiler is FPCE-compliant, it also supports the pragmas that allow the most efficient floating-point type to be used for function return values, parameters, and local variables. See Appendix D, "FPCE Recommendations for Compilers," for more information on these pragmas.
Macros
You might find the following macros useful to isolate 680x0-specific code from PowerPC-specific code:
[68] Thefpclassifymacro returns a long integer.
[69] Thefeholdexceptfunction, although it replaces theprocentrySANE function, affects only the exception flags. It does not affect the rounding direction.