/* * Article 633 of net.micro.amiga: * ion: version B 2.10.2 9/17/84 chuqui version 1.9 3/12/85; site unisoft.UUCP * Posting-Version: version B 2.10.3 4.3bsd-beta 6/6/85; site amiga.amiga.UUCP * Path: unisoft!dual!lll-crg!ucdavis!ucbvax!decvax!decwrl!pyramid!amiga!bobp * From: bobp@amiga.UUCP (Robert S. Pariseau) * Newsgroups: net.micro.amiga * Subject: LatFFP program SOURCE (LONG!) * Message-ID: <192@amiga.amiga.UUCP> * Date: 6 Nov 85 03:53:01 GMT * Date-Received: 17 Nov 85 21:40:30 GMT * Reply-To: bobp@snake.UUCP (Robert S. Pariseau) * Organization: Commodore-Amiga Inc., 983 University Ave #D, Los Gatos CA 95030 * Lines: 749 * * TITLE: LatFFP program SOURCE (LONG!) * * The program below shows how to access the Motorola Fast Floating Point * libraries from V1.0 release Lattice C for the Amiga. As you will see * when you run it, the performance improvement gained by using the * FFP routines (even in this kludgey fashion) is generally around a * factor of 10! * * Part of that improvement is just the difference in precision. The * Lattice stuff provides a 64 bit software implementation of the IEEE * format. The FFP stuff provides a 32 bit implementation of the * Motorola format. * * The variables used for FFP math are defined as ints. You can't use * FLOATs because V1.0 Lattice C converts FLOAT to DOUBLE during * expression evaluation and when passing arguments. * */ /* * ------------------------Program Notes: * * The program will compile and link cleanly using the stuff on the * standard V1.0 Lattice C for Amiga disk. The Make script in the * examples directory will do all the work for you. Since my C disk * is rather full, and since I like the dramatic increase in speed, * I usually do my work in ram disk as follows: * * 1> cd df1: [my C disk] * 1> copy examples/Make to : [more convenient in root] * * 1> copy LatFFP.c to ram: * 1> execute Make ram:LatFFP * 1> copy ram:LatFFP to df1: * * I've also added a "stack 20000" command in my startup script * (s/startup-sequence) to make sure I don't have to worry about stack * overflows. * * The program shows 3 bugs in the V1.0 stuff and includes one kludge. * The bugs and kludge are maked in the source. Bug (1): V1.0 Lattice * C doesn't properly handle successive assignments of constants. Use * expressions. Bug (2): V1.0 FFP doesn't correctly return a result * from SPCmp(). Fake it with subtraction and SPTst() or write your * own compare for now. Bug (3): V1.0 FFP doesn't correctly return * the cosine result from SPSincos(). Use SPCos() instead. * * The kludge is the set of union definitions so that we can use the * same variables for related Lattice and FFP expressions and for * the conversions in and out of IEEE format. Note that we use * the Lattice IEEE based routines in printf() to get our output. * * Note however, that the conversion routines are in the RAM based * MathTrans library. Therefore, if you only want to use the WCS * based MathFFP library, you are on your own for conversion. * *------------------------Program Source Follows: * */ /*********************************************************************** * LatFFP -- Program to show the use of Motorola Fast Floating Point * math libraries with V1.0 Lattice C for the Amiga in * comparison to the DOUBLE precision IEEE floating point * math which is built in to the C. The FFP format is * a 32 bit format. * * Larry Hildenbrand -- Nov. 4, 1985 * Bob Pariseau -- Nov. 4, 1985 (minor editorial corrections) * ***********************************************************************/ #include #include /* ??? #define E 2.718281828459045 */ /* V1.0 Lattice C BUG! See */ #define PIME 0.423310826 /* below. PIME == PI - E. */ /**** MAY BE BROKEN OUT INTO SEPARATE #include FILE ****/ extern int SPFix(); extern int SPFlt(); extern int SPCmp(); extern int SPTst(); extern int SPAbs(); extern int SPNeg(); extern int SPAdd(); extern int SPSub(); extern int SPMul(); extern int SPDiv(); extern int SPAtan(); extern int SPSin(); extern int SPCos(); extern int SPTan(); extern int SPSincos(); extern int SPSinh(); extern int SPCosh(); extern int SPTanh(); extern int SPExp(); extern int SPLog(); extern int SPPow(); extern int SPSqrt(); extern int SPTieee(); extern int SPFieee(); /********************************************************/ char st1[80] = "3.1415926535897"; char st2[80] = "2.718281828459045"; int MathBase; /* Basic FFP lib pointer */ int MathTransBase; /* Transcendental FFP lib pointer */ int dots_good = 0; union kludge1 /* Can't use FLOAT directly for FFP stuff */ { /* because V1.0 Lattice converts FLOAT to */ FLOAT num1; /* DOUBLE in expressions and when passing */ int i1; /* parameters. */ } k1; union kludge2 { FLOAT num2; int i2; } k2; union kludge3 { FLOAT num3; int i3; } k3; union kludge4 { FLOAT num4; int i4; } k4; union kludge5 { FLOAT num5; int i5; } k5; union kludge6 { FLOAT num6; int i6; } k6; show_dot() { if( ++dots_good == 1000) { dots_good = 0; printf(".");} } show_result( num ) FLOAT num; { printf("\nResult = %f", num); } show_result_ffp(in_val) /* Convert to IEEE and display */ int in_val; { union kludge_sr { FLOAT new_iv_f; int new_iv_i; } k; k.new_iv_i = SPTieee(in_val); show_result(k.new_iv_f); } main() /* Lattice/FFP test code */ { UWORD i; int i3; printf("C-ROM & Shared RAM Library Test Facility for the Amiga-Lattice Basic/Trans Math Libraries"); /*****************************************/ /*****************************************/ /*** ***/ /*** OPEN ROM AND RAM FFP LIBRARIES ***/ /*** ***/ /*****************************************/ /*****************************************/ if((MathBase = OpenLibrary("mathffp.library", 0)) < 1 ) { printf("\n\n*** ERROR *** Can't open mathffp.library: vector = %lx\n", MathBase); exit(); } else { printf("\n\nSuccessfully opened mathffp.library: vector = %lx\n", MathBase); } if((MathTransBase = OpenLibrary("mathtrans.library", 0)) < 1 ) { printf("\n\n*** ERROR *** Can't open mathtrans.library: vector = %lx\n", MathTransBase); CloseLibrary(MathBase); exit(); } else { printf("\n\nSuccessfully opened mathtrans.library: vector = %lx\n", MathTransBase); } /*****************************************/ /*****************************************/ /*** ***/ /*** COMPILER & FFP S.P. ADDITION ***/ /*** ***/ /*****************************************/ /*****************************************/ k1.num1 = PI; /* V1.0 Lattice C BUG! Can't have two */ k2.num2 = k1.num1 - PIME; /* constant assignments in a row. Fake */ /* it by making the second be an */ /* expression! */ printf("\n\n50,000 additions of %s to %s (Compiler Interface)\n", st1, st2); for( dots_good = 0, i= 1; i < 50000; i++ ) { k3.num3 = k1.num1 + k2.num2; show_dot(); } show_result( k3.num3 ); k1.i1 = SPFieee(k1.i1); k2.i2 = SPFieee(k2.i2); printf("\n\n50,000 additions of %s to %s (Function Interface)\n", st1, st2 ); for( dots_good = 0, i= 1; i < 50000; i++ ) { k3.i3 = SPAdd(k2.i2, k1.i1); show_dot(); } show_result_ffp( k3.i3 ); /*****************************************/ /*****************************************/ /*** ***/ /*** COMPILER & FFP S.P. SUBTRACTION ***/ /*** ***/ /*****************************************/ /*****************************************/ k1.num1 = PI; k2.num2 = k1.num1 - PIME; printf("\n\n50,000 subtractions of %s from %s (Compiler Interface)\n", st1, st2 ); for( dots_good = 0, i= 1; i < 50000; i++ ) { k3.num3 = k2.num2 - k1.num1; show_dot(); } show_result( k3.num3 ); k1.i1 = SPFieee(k1.i1); k2.i2 = SPFieee(k2.i2); printf("\n\n50,000 subtractions of %s from %s (Function Interface)\n", st1, st2 ); for( dots_good = 0, i= 1; i < 50000; i++ ) { k3.i3 = SPSub(k1.i1, k2.i2); show_dot(); } show_result_ffp( k3.i3 ); /*****************************************/ /*****************************************/ /*** ***/ /*** COMPILER & FFP S.P. MULTIPLYS ***/ /*** ***/ /*****************************************/ /*****************************************/ k1.num1 = PI; k2.num2 = k1.num1 - PIME; printf("\n\n50,000 multiplies of %s by %s (Compiler Interface)\n", st1, st2 ); for( dots_good = 0, i= 1; i < 50000; i++ ) { k3.num3 = k1.num1 * k2.num2; show_dot(); } show_result( k3.num3 ); k1.i1 = SPFieee(k1.i1); k2.i2 = SPFieee(k2.i2); printf("\n\n50,000 multiplies of %s by %s (Function Interface)\n", st1, st2 ); for( dots_good = 0, i= 1; i < 50000; i++ ) { k3.i3 = SPMul(k2.i2, k1.i1); show_dot(); } show_result_ffp( k3.i3 ); /*****************************************/ /*****************************************/ /*** ***/ /*** COMPILER & FFP S.P. DIVISION ***/ /*** ***/ /*****************************************/ /*****************************************/ k1.num1 = PI; k2.num2 = k1.num1 - PIME; printf("\n\n50,000 divides of %s by %s (Compiler Interface)\n", st1, st2 ); for( dots_good = 0, i= 1; i < 50000; i++ ) { k3.num3 = k1.num1 / k2.num2; show_dot(); } show_result( k3.num3 ); k1.i1 = SPFieee(k1.i1); k2.i2 = SPFieee(k2.i2); printf("\n\n50,000 divides of %s by %s (Function Interface)\n", st1, st2 ); for( dots_good = 0, i= 1; i < 50000; i++ ) { k3.i3 = SPDiv(k2.i2, k1.i1); show_dot(); } show_result_ffp( k3.i3 ); /*****************************************/ /*****************************************/ /*** ***/ /*** COMPILER & FFP S.P. TRUNCATION ***/ /*** ***/ /*****************************************/ /*****************************************/ k1.num1 = PI; k2.num2 = k1.num1 - PIME; printf("\n\n50,000 fixes of %s (Compiler Interface)\n", st1 ); for( dots_good = 0, i= 1; i < 50000; i++ ) { i3 = (int) k1.num1; if( ++dots_good == 1000) { dots_good = 0; printf(".");} } printf("\nResult = %d", i3 ); k1.i1 = SPFieee(k1.i1); k2.i2 = SPFieee(k2.i2); printf("\n\n50,000 fixes of %s (Function Interface)\n", st1 ); for( dots_good = 0, i= 1; i < 50000; i++ ) { i3 = SPFix(k1.i1); if( ++dots_good == 1000) { dots_good = 0; printf(".");} } printf("\nResult = %d", i3); /*****************************************/ /*****************************************/ /*** ***/ /*** COMPILER & FFP S.P. FLOATATION ***/ /*** ***/ /*****************************************/ /*****************************************/ i3 = 5; printf("\n\n50,000 floats of %d (Compiler Interface)\n", i3 ); for( dots_good = 0, i= 1; i < 50000; i++ ) { k4.num4 = (FLOAT) i3; show_dot(); } show_result( k4.num4 ); printf("\n\n50,000 floats of %d (Function Interface)\n", i3 ); for( dots_good = 0, i= 1; i < 50000; i++ ) { k4.i4 = SPFlt(i3); show_dot(); } show_result_ffp( k4.i4 ); /*****************************************/ /*****************************************/ /*** ***/ /*** COMPILER & FFP S.P. NEGATION ***/ /*** ***/ /*****************************************/ /*****************************************/ k1.num1 = PI; k2.num2 = k1.num1 - PIME; printf("\n\n50,000 negates of %s (Compiler Interface)\n", st2 ); for( dots_good = 0, i= 1; i < 50000; i++ ) { k4.num4 = -k2.num2; show_dot(); } show_result( k4.num4 ); k1.i1 = SPFieee(k1.i1); k2.i2 = SPFieee(k2.i2); printf("\n\n50,000 negates of %s (Function Interface)\n", st2 ); for( dots_good = 0, i= 1; i < 50000; i++ ) { k4.i4 = SPNeg(k2.i2); show_dot(); } show_result_ffp( k4.i4 ); /*****************************************/ /*****************************************/ /*** ***/ /*** COMPILER & FFP S.P. ABSOLUTE VAL ***/ /*** ***/ /*****************************************/ /*****************************************/ k1.num1 = PI; k4.num4 = PIME - k1.num1; printf("\n\n50,000 absolute values of %f (Compiler Interface)\n", k4.num4 ); for( dots_good = 0, i= 1; i < 50000; i++ ) { k5.num5 = fabs(k4.num4); show_dot(); } show_result( k5.num5 ); printf("\n\n50,000 absolute values of %f (Function Interface)\n", k4.num4 ); k4.i4 = SPFieee(k4.i4); for( dots_good = 0, i= 1; i < 50000; i++ ) { k5.i5 = SPAbs(k4.i4); show_dot(); } show_result_ffp( k5.i5 ); printf("\n\n*** HIT RETURN TO CONTINUE ***"); getch(); /*****************************************/ /*****************************************/ /*** ***/ /*** COMPILER & FFP S.P. COMPARE ***/ /*** ***/ /*****************************************/ /*****************************************/ k1.num1 = PI; k2.num2 = k1.num1 - PIME; if (k2.num2 >= k1.num1) printf("\n\n%f is greater than or equal to %f (Compiler Interface)\n", k2.num2, k1.num1); else printf("\n\n%f is less than %f (Compiler Interface)\n", k2.num2, k1.num1); k1.i1 = SPFieee(k1.i1); k2.i2 = SPFieee(k2.i2); printf("\n*** SPCmp(k2.i2, k1.i1) returned %d ***", SPCmp(k2.i2, k1.i1)); if (SPCmp(k2.i2, k1.i1)) /* V1.0 FFP Bug. SPCmp() broken. */ { k1.num1 = PI; k2.num2 = k1.num1 - PIME; printf("\n\n%f is greater than or equal to %f (Function Interface)\n", k2.num2, k1.num1); } else { k1.num1 = PI; k2.num2 = k1.num1 - PIME; printf("\n\n%f is less than %f (Function Interface)\n", k2.num2, k1.num1); } if (k1.num1 >= k2.num2) printf("\n\n%f is greater than or equal to %f (Compiler Interface)\n", k1.num1, k2.num2); else printf("\n\n%f is less than %f (Compiler Interface)\n", k1.num1, k2.num2); k1.i1 = SPFieee(k1.i1); k2.i2 = SPFieee(k2.i2); if (SPCmp(k1.i1, k2.i2)) { k1.num1 = PI; k2.num2 = k1.num1 - PIME; printf("\n\n%f is greater than or equal to %f (Function Interface)\n", k1.num1, k2.num2); } else { k1.num1 = PI; k2.num2 = k1.num1 - PIME; printf("\n\n%f is less than %f (Function Interface)\n", k1.num1, k2.num2); } /*****************************************/ /*****************************************/ /*** ***/ /*** COMPILER & FFP S.P. TEST ***/ /*** ***/ /*****************************************/ /*****************************************/ if (k2.num2) printf("\n\n%f is not equal to 0.0 (Compiler Interface)\n", k2.num2); else printf("\n\n%f is equal to 0.0 (Compiler Interface)\n", k2.num2); k2.i2 = SPFieee(k2.i2); if (SPTst(k2.i2)) { k1.num1 = PI; k2.num2 = k1.num1 - PIME; printf("\n\n%f is not equal to 0.0 (Function Interface)\n", k2.num2); } else { k1.num1 = PI; k2.num2 = k1.num1 - PIME; printf("\n\n%f is equal to 0.0 (Function Interface)\n", k2.num2); } k2.num2 = 0.0; if (k2.num2) printf("\n\n%f is not equal to 0.0 (Compiler Interface)\n", k2.num2); else printf("\n\n%f is equal to 0.0 (Compiler Interface)\n", k2.num2); k2.i2 = SPFieee(k2.i2); if (SPTst(k2.i2)) { k2.num2 = 0.0; printf("\n\n%f is not equal to 0.0 (Function Interface)\n", k2.i2); } else { k2.num2 = 0.0; printf("\n\n%f is equal to 0.0 (Function Interface)\n", k2.i2); } /*****************************************/ /*****************************************/ /*** ***/ /*** FFP S.P. SQUARE ROOT ***/ /*** ***/ /*****************************************/ /*****************************************/ k1.num1 = PI; k2.num2 = k1.num1 - PIME; printf("\n\n50,000 square roots of %f\n", k2.num2); k1.i1 = SPFieee(k1.i1); k2.i2 = SPFieee(k2.i2); for( dots_good = 0, i= 1; i < 50000; i++ ) { k3.i3 = SPSqrt( k2.i2 ); show_dot(); } show_result_ffp( k3.i3 ); /*****************************************/ /*****************************************/ /*** ***/ /*** FFP S.P. NATURAL LOGARITHM ***/ /*** ***/ /*****************************************/ /*****************************************/ printf("\n\n40,000 logarithms of %s\n", st1 ); for( dots_good = 0, i= 1; i < 40000; i++ ) { k3.i3 = SPLog( k1.i1 ); show_dot(); } show_result_ffp( k3.i3 ); /*****************************************/ /*****************************************/ /*** ***/ /*** FFP S.P. EXPONENT (BASE e) ***/ /*** ***/ /*****************************************/ /*****************************************/ printf("\n\n40,000 exponents of %s\n", st1 ); for( dots_good = 0, i= 1; i < 40000; i++ ) { k3.i3 = SPExp( k1.i1 ); show_dot(); } show_result_ffp( k3.i3 ); /*****************************************/ /*****************************************/ /*** ***/ /*** FFP S.P. SINE, COSINE & TANGENT ***/ /*** ***/ /*****************************************/ /*****************************************/ k1.num1 = PI; k2.num2 = k1.num1 - PIME; k1.num1 = k1.num1 / 6.0; k1.i1 = SPFieee(k1.i1); k2.i2 = SPFieee(k2.i2); printf("\n\n20,000 sines, cosines and tangents of %s / 6 radians\n", st1 ); for( dots_good = 0, i= 1; i < 20000; i++ ) { k2.i2 = SPSin(k1.i1); k3.i3 = SPCos(k1.i1); k4.i4 = SPTan(k1.i1); k5.i5 = SPSincos(&k6.i6, k1.i1); /* V1.0 FFP BUG! Cosine return */ /* value (k6.i6) of SPSincos is */ /* broken. Function result */ /* (sine -- k5.i5) is OK. */ show_dot(); } show_result_ffp( k2.i2 ); show_result_ffp( k3.i3 ); show_result_ffp( k4.i4 ); show_result_ffp( k5.i5 ); show_result_ffp( k6.i6 ); /*****************************************/ /*****************************************/ /*** ***/ /*** FFP S.P. ARCTANGENT ***/ /*** ***/ /*****************************************/ /*****************************************/ printf("\n\n20,000 arctangents of the tangent of %s / 6 radians\n", st1 ); for( dots_good = 0, i= 1; i < 20000; i++ ) { k2.i2 = SPAtan(k4.i4); show_dot(); } show_result_ffp( k2.i2 ); /***************************************************/ /***************************************************/ /*** ***/ /*** FFP S.P. HYPERBOLIC SINE, COSINE & TANGENT ***/ /*** ***/ /***************************************************/ /***************************************************/ k1.num1 = PI; k2.num2 = k1.num1 - PIME; k1.i1 = SPFieee(k1.i1); k2.i2 = SPFieee(k2.i2); printf("\n\n20,000 hyperbolic sines, cosines and tangents of %s radians\n", st1 ); for( dots_good = 0, i= 1; i < 20000; i++ ) { k2.i2 = SPSinh( k1.i1 ); k3.i3 = SPCosh( k1.i1 ); k4.i4 = SPTanh( k1.i1 ); show_dot(); } show_result_ffp( k2.i2 ); show_result_ffp( k3.i3 ); show_result_ffp( k4.i4 ); /*****************************************/ /*****************************************/ /*** ***/ /*** FFP S.P. POWER FUNCTION ***/ /*** ***/ /*****************************************/ /*****************************************/ k1.num1 = PI; k2.num2 = k1.num1 - PIME; k1.i1 = SPFieee(k1.i1); k2.i2 = SPFieee(k2.i2); printf("\n\n10,000 %s raised to the %s power\n", st1, st2 ); for( dots_good = 0, i= 1; i < 10000; i++ ) { k3.i3 = SPPow( k2.i2, k1.i1 ); show_dot(); } show_result_ffp( k3.i3 ); /*****************************************/ /*****************************************/ /*** ***/ /*** CLOSE ROM AND RAM FFP LIBRARIES ***/ /*** ***/ /*****************************************/ /*****************************************/ RemLibrary(MathTransBase); /* Mark lib for Expunge() from RAM upon */ /* CloseLibrary() by last opener. Else */ /* lib stays in RAM for others to use */ /* quickly (no need to go to disk) until */ /* AllocMem() finds it needs the memory */ /* for some other purpose. */ CloseLibrary(MathTransBase); /* Close transcendental math RAM library */ CloseLibrary(MathBase); /* Close basic math ROM library */ printf("\n\nEnd C-ROM & Shared RAM Library Test (LATTICE) \n"); }