[comp.sys.mac.programmer] Endless inSANEity...

cjr20670@uxa.cso.uiuc.edu (06/19/89)

  I recently wrote a nifty do-dad program that some of you might have seen.
It's called GDraw; it basically just whipped dots around the screen in
facinating paths.  I'm now working on version 2, but I've run across
a problem that I can't figure a way around. 
   One of the more complicated new features I'm adding is the ability to
switch math modes on the fly, for example from Fixed to SANE.  Presently,
this is all it can do.  I had planned to also add Direct 881 access, BUT
LightSpeed C is giving me qualms.
   All the floating numbers are using this struct at present:

typedef struct
	{
	double	sn;   /* SANE number */
	Fixed	fx;   /* Fixed number */
	} aNum;

   So that's the first big problem, how do I put the 881 "double" in the
same struct?  They're both called double, but one is 12 bytes and the other
is 10 bytes. I can't specify one without the other.  Gggrrrrr.
   If someone can help me with that problem, I've got another one for ya.
Is there anyway I can use both the Math and Math881 libraries in the SAME
project without renaming the needed functions in one of the libraries?
   Anyone with experience in mixing oil and water, please help!

Charlie Reiman
creiman@ncsa.uiuc.edu
cjr20670@uxa.cso.uiuc.edu
 
"My keyboard's busted.  It keeps misspelling words."
                         My boss

siegel@endor.harvard.edu (Rich Siegel) (06/20/89)

In article <227700009@uxa.cso.uiuc.edu> cjr20670@uxa.cso.uiuc.edu writes:

>   All the floating numbers are using this struct at present:
>
>typedef struct
>	{
>	double	sn;   /* SANE number */
>	Fixed	fx;   /* Fixed number */
>	} aNum;
>
>   So that's the first big problem, how do I put the 881 "double" in the
>same struct?  They're both called double, but one is 12 bytes and the other
>is 10 bytes. I can't specify one without the other.  Gggrrrrr.

	You could put 96-bit doubles in your struct by typedef'ing them as
a 12-character array, or three longs. (This is assuming non-881 code
generation.)

>   If someone can help me with that problem, I've got another one for ya.
>Is there anyway I can use both the Math and Math881 libraries in the SAME
>project without renaming the needed functions in one of the libraries?

	Nope. The current design of the linker doesn't allow multiple
or overriding routine definitions, and at any rate, how would you know which
routines to call?

>   Anyone with experience in mixing oil and water, please help!

	Mixing 80- and 96-bit arithmetic in the same program is not
something to be undertake lightly, if at all. You might consider two
copies of your program - one for SANE use, one for direct 881 use.

	In My Humble Opinion, someone Screwed Up when making doubles
to be 80 bits. Motorola has some moderately reasonable reason for making
the IEEE Extended type a 12-byte type, to wit, longword alignment.
I think the SANE interfaces could have been designed this way, but it's
kind of too late....

	GDraw is a nifty program. If you haven't seen it, take a look.

		--Rich



~~~~~~~~~~~~~~~
 Rich Siegel
 Staff Software Developer
 Symantec Corporation, Language Products Group
 Internet: siegel@endor.harvard.edu
 UUCP: ..harvard!endor!siegel

 I classify myself as a real developer because my desk is hip-deep in
 assembly-language listings and I spend more than 50% of my time in TMON.

~~~~~~~~~~~~~~~

earleh@eleazar.dartmouth.edu (Earle R. Horton) (06/20/89)

In article <2089@husc6.harvard.edu> siegel@endor.UUCP (Rich Siegel) writes:
...
>	In My Humble Opinion, someone Screwed Up when making doubles
>to be 80 bits. Motorola has some moderately reasonable reason for making
>the IEEE Extended type a 12-byte type, to wit, longword alignment.
>I think the SANE interfaces could have been designed this way, but it's
>kind of too late....

     Actually, double is 64 bits.  SANE defines four data types:
Single, double, computational, and extended have 32, 64, 64, and 80
bits respectively.  MPW is the only C compiler I know of which lets
you have all four types at the compiler level.  Aztec maps extended to
double, and from what you say TLSC maps double to extended.  (I am
using the SANE definition of double here.  One could argue that the
way C defines double actually implies IEEE Extended.)  One option is
to use SANE single or double for storage, and let SANE or the 881 do
the calculations in extended.  This is kind of rough in a high-level
language, and there is a speed penalty when using non-extended types.

     Actually, since the first Mac had 128k of RAM, I would say that
Apple had a fairly reasonable reason for storing extended in 80 bits.
Kind of like storing flags in the high bits of master pointers.

Earle R. Horton
"People forget how fast you did a job, but they remember how well you
did it."  Salada Tag Lines

trebor@biar.UUCP (Robert J Woodhead) (06/20/89)

In article <227700009@uxa.cso.uiuc.edu> cjr20670@uxa.cso.uiuc.edu writes:
>  I recently wrote a nifty do-dad program that some of you might have seen.
>It's called GDraw; it basically just whipped dots around the screen in
>facinating paths.

This sounds like it would make a wonderful ``NightLife'' screensaver.  I've
been beta-testing NightLife (it will be, imho, the best screensaver of the
bunch) and it is _very_ easy to write your own screensaver module for the
program.

``NightLife'', in case you don't know, is basically a ScreenSaver ``shell.''
It lets you choose which ``effect'' you want to use, and you can program
your own.  Mine has worms crawling around the screen eating pixels.

-- 
(^;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-;^)
Robert J Woodhead, Biar Games, Inc.   !uunet!biar!trebor | trebor@biar.UUCP
  ``I can read your mind - right now, you're thinking I'm full of it...''

shebanow@apple.com (Andrew Shebanow) (06/21/89)

In article <227700009@uxa.cso.uiuc.edu> cjr20670@uxa.cso.uiuc.edu writes:
>    So that's the first big problem, how do I put the 881 "double" in the
> same struct?  They're both called double, but one is 12 bytes and the 
other
> is 10 bytes. I can't specify one without the other.  Gggrrrrr.

For LSC, I recommend that you use the "short double" type (64 bits) in 
your data structures instead of double. You probably don't need the extra 
precision, and this data type is the same whether you have an 881 or not. 
The only disadvantage is that SANE is slower on 64 bit operations than it 
is on 80 bit (96 for 881) operations, since it has to convert the operands 
to 80 bit before doing its calculations. You can get around this 
limitation by caching the extended versions of your numbers inside of 
complex calculations.

As far as using 881 and non-881 libraries together goes, you are going to 
have a tough job. What I recommend is that you compile everything without 
the 881 option turned on, and that you isolate (and minimize) your 
floating point library calls. For each library call you want to use, write 
a wrapper function like this:

extern Boolean haveFPU;
typedef short double96[6];

double myLibraryCall(double a, double b)
{
   double96 tmpA, tmpB, tmpRes;
   double res;

   if (haveFPU)
     {
       x80tox96(&a,tmpA);
       x80tox96(&b,tmpB);
       asm {
         /*
          * do the whole thing in assembler, using FPU instructions
          * Move tmpA and tmpB into FPU registers, store result in tmpRes
          */
       };
       x96tox80(tmpRes,&res);
       return res;
     }
   else return RealLibraryCall(a,b);
}

You will have to write the routines x80tox96 and x96tox80 yourself, but 
they aren't that tough - just bitshift things around (BTW, MPW 3.0 
includes these routines).

This whole solution is ugly, but it should work. Disclaimer: I've done 
this on a small scale in MPW 3.0, so I know it can be done, but I haven't 
tried it in LSC, so there may be some unexpected problems.

Have fun,

Andrew Shebanow
MacDTS
- Wanna See Something REALLY Scary? -

siegel@endor.harvard.edu (Rich Siegel) (06/21/89)

In article <14001@dartvax.Dartmouth.EDU> earleh@eleazar.dartmouth.edu (Earle R. Horton) writes:

>     Actually, double is 64 bits.  SANE defines four data types:
>Single, double, computational, and extended have 32, 64, 64, and 80
>bits respectively.  MPW is the only C compiler I know of which lets
>you have all four types at the compiler level.  Aztec maps extended to
>double, and from what you say TLSC maps double to extended.  (I am

	Sorry about that - I meant 'extended', but my fingers were still
thinking C. In TLSC, the 'double' data type is 80-bit (or 96-bit, depending
on options) SANE Extended, and 'short double' is the 64-bit IEEE
double-precision data type. 

>     Actually, since the first Mac had 128k of RAM, I would say that
>Apple had a fairly reasonable reason for storing extended in 80 bits.
>Kind of like storing flags in the high bits of master pointers.

	What does that have to do with the price of tea in China?
I don't follow the correlation.

		-R.



~~~~~~~~~~~~~~~
 Rich Siegel
 Staff Software Developer
 Symantec Corporation, Language Products Group
 Internet: siegel@endor.harvard.edu
 UUCP: ..harvard!endor!siegel

 I classify myself as a real developer because my desk is hip-deep in
 assembly-language listings and I spend more than 50% of my time in TMON.

~~~~~~~~~~~~~~~

lippin@spam.berkeley.edu (The Apathist) (06/21/89)

Recently cjr20670@uxa.cso.uiuc.edu wrote:
[...]
>  I recently wrote a nifty do-dad program that some of you might have seen.
>It's called GDraw; it basically just whipped dots around the screen in
>facinating paths.  I'm now working on version 2, but I've run across
>a problem that I can't figure a way around. 
>   One of the more complicated new features I'm adding is the ability to
>switch math modes on the fly, for example from Fixed to SANE.  Presently,
>this is all it can do.  I had planned to also add Direct 881 access, BUT
>LightSpeed C is giving me qualms.

Types are pretty easy -- since you don't need to see the inside of a
number, you can declare a struct of the appropriate length to be the
extended size you don't have.

As for the math library, I say ditch it.  It isn't really doing much,
and it's going to get in your way.  Instead, get to the SANE routines
through fp68k() and elems68k().  There's a header file <sane.h> in LSC
that contains most of what you need; the Apple Numerics manual will
tell you how to use it, sort of.  To get you started, here are some
sample uses:

Given extended a,b,
b+=a		fp68k(&a,&b,FOADD|FFEXT)
a=sin(a)	elems68k(&a,FOSIN|FFEXT)

(This is from memory; you can check me against the source for the math
library.) 

It may be handy to make a set of macro definitions for these calls.

Once you understand how to use SANE, you have two options.  The "no
guts" way is to use the Math881 library for the 881 calls; there's no
insurmountable problem with this now that you don't use the regular
math library.  But you will have to live with double being 96 bits and
convert as necessary.  Also, be careful not to use any of the C
operators for +-/*=<> on floating point numbers in places where you
might be running without an FPU.  Finally, this will add a subroutine
jump/return to each operation, which may be noticeable when you're
running on the FPU.

The "guts" way is to write the assembler for elementary operations
yourself, and probably include them as macros, like this:

#ifdef useFPU
#define sin(a)		asm{ fsin a }
#else
#define sin(a)		elems68k(&a,FOSIN,FFEXT)
#endif

Then you can stick your floating point intensive routines in a
separate file, and make two copies, one defining useFPU and one not.
Of course, you'll still have to use two different names, and convert
any floating point numbers where these modules communicate with the
main program.

Good luck, and may the source be with you,

					--Tom Lippincott
					  lippin@math.berkeley.edu

		"You've got to know when to code it,
			       know when to log out,
			       know when to single step,
			       know when to run..."
					--The Hacker

earleh@eleazar.dartmouth.edu (Earle R. Horton) (06/21/89)

In article <2092@husc6.harvard.edu> siegel@endor.UUCP (Rich Siegel) writes:
>In article <14001@dartvax.Dartmouth.EDU> earleh@eleazar.dartmouth.edu
	(Earle R. Horton) writes:
...
>>     Actually, since the first Mac had 128k of RAM, I would say that
>>Apple had a fairly reasonable reason for storing extended in 80 bits.
>>Kind of like storing flags in the high bits of master pointers.
>
>	What does that have to do with the price of tea in China?
>I don't follow the correlation.

     Well, by storing extended in 80 bits versus 96 bits, you save 16
bits per floating point quantity.  By storing flags in the high bits of
master pointers, you save at least 16 bits over doing it the right
way.  I suppose it is a weak correlation, at that.

Earle R. Horton
"People forget how fast you did a job, but they remember how well you
did it."  Salada Tag Lines

siegel@endor.harvard.edu (Rich Siegel) (06/21/89)

In article <14017@dartvax.Dartmouth.EDU> earleh@eleazar.dartmouth.edu (Earle R. Horton) writes:

>     Well, by storing extended in 80 bits versus 96 bits, you save 16
>bits per floating point quantity.  By storing flags in the high bits of

	You're technicaly correct, but it's a pretty weak reason to have
made the size what it was (if, in fact, that WAS the reason). If you're
that concerned about space, store  your results as single, and use
extendeds for temps (which most compilers do for calculations).

		--R.

~~~~~~~~~~~~~~~
 Rich Siegel
 Staff Software Developer
 Symantec Corporation, Language Products Group
 Internet: siegel@endor.harvard.edu
 UUCP: ..harvard!endor!siegel

 I classify myself as a real developer because my desk is hip-deep in
 assembly-language listings and I spend more than 50% of my time in TMON.

~~~~~~~~~~~~~~~