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
comp
with typedouble
orlong int
.- Replace
sane.h
andmath.h
withfp.h
andfenv.h
.- Replace uses of
extended
withdouble_t
or, 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 typecomp
is a floating-point type with 64 bits of precision. In SANE, typecomp
is automatically converted to extended format whenever an expression is evaluated, just like every other SANE data format. In other words,comp
is a floating-point type disguised as an integer type. In most cases you can replace typecomp
with typedouble
, which provides 53 bits of precision. If yourcomp
variables 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.h
andfenv.h
. The filesfp.h
andfenv.h
replacesane.h
andmath.h
. All of the transcendental functions declared insane.h
are now declared infp.h
, and most of them work exactly the same way in the two environments. If your program includes the header filemath.h
instead ofsane.h
, you should replace it withfp.h
as well. Thefp.h
file declares all of the functions and macros declared in the ANSI header filemath.h
plus some additional ones.Be aware of the differences in function prototypes in the files
sane.h
andfp.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.h
are typeextended
and take typeextended
as 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_t
type changes definition based on which processor the program is run on. For the PowerPC processor,double_t
is defined to be typedouble
. For the 680x0 processor,double_t
is defined to be typeextended
. Therefore, when you change from usingsane.h
to 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_t
type, see "Portable Declarations" on page A-9.In some cases, a numeric function also has a
long double
implementation in MathLib. The declarations of thelong double
implementations are infp.h
and 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 double
implementation. 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 double
implementation 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 asextended
to typedouble_t
. For the 680x0 processor,double_t
is defined asextended
. For the PowerPC processor,double_t
is 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_t
variable 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
copysign
function 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
exp1
function in SANE is namedexpm1
in PowerPC Numerics.- The
ipower
function is replaced with thepow
function in PowerPC Numerics.- The
log1
function in SANE is namedlog1p
in PowerPC Numerics.- The nextafter functions in SANE are
nextfloat
,nextdouble
, andnextextended
. In PowerPC Numerics, they arenexafterf
,nextafterd
, andnextafterl
forfloat
,double
, andlong double
, respectively.- The
nan
function in SANE takes a character parameter, but the PowerPC Numericsnan
function takes a character string parameter.- The SANE
pi
function is replaced with the constantpi
, the SANEinf
function is replaced with the constantINFINITY
, and theNAN
constant remains the same.- The
pow
function 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
remainder
function in SANE takes three parameters, the last one being a return value. The PowerPC Numericsremainder
function takes two parameters. Theremquo
function is analogous to the SANEremainder
function.- The
scalb
function 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.h
are not implemented in MathLib. Instead, MathLib provides a set of macros that perform the same actions.
Table A-1 shows the declarations insane.h
on the left and the corresponding declaration in the MathLib header filefp.h
on the right.
Table A-1 Class and sign inquiries in SANE versus MathLib sane.h
declarationfp.h
declaration
#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.h
declarationfenv.h
declaration#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
pow
function, 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_t
anddouble_t
, in the header fileTypes.h
. If you define a variable to befloat_t
ordouble_t
, it means "use the most efficient floating-point type for this architecture." Table A-3 shows the definitions forfloat_t
anddouble_t
on PowerPC architecture compared with 680x0 architecture.
Table A-3 float_t
anddouble_t
definitionsArchitecture float_t
double_t
PowerPC 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_t
is defined to befloat
(single precision) anddouble_t
is defined to bedouble
for 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_t
anddouble_t
are bothlong double
(extended precision) for the 680x0 architecture.If you declare a variable to be type
double_t
and 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] Thefpclassify
macro returns a long integer.
[69] Thefeholdexcept
function, although it replaces theprocentry
SANE function, affects only the exception flags. It does not affect the rounding direction.