Hi! Here's all the messages concerning integer math that I received (via mail or News) and saved. This file is just a simple concatenation of all the messages, 'cause I haven't had time to write any summaries or anything... Anyway, I hope this helps you, it certainly clarified the basic concepts to me! O:) -MiS- /* Mika Saastamoinen */ /* (mikasaas@polaris.utu.fi/msaastamoine@finabo.abo.fi) */ /* Student at Turku School of Economics - Information Systems Science */ #include #define AMIGA_In_an_insane_world_it_is_the_sanest_choice TRUE ----------------... In article <1993Feb12.110623.6317@abo.fi> MSAASTAMOINE@FINABO.ABO.FI (Mika Saastamoinen Tkkk) writes: >Hi ya'all! > >I was wondering if someone could explain to me the basic principles of integer >math. Specifically, I'm thinking of the kind of math one uses in 3D (vector) >graphics programming. Since I'm not so awfully hot on math I thought I'd ask >you Gurus about this! O:) I wouldn't consider myself a guru at it but I should be able to help you. I used an integer scheme on the 6809 for Currilian Cruiser (a game I wrote and tried to sell back in high school) >Let's say I'm thinking of the floating point number '1.234567890': How do I >convert that to integer without losing accuracy too much First let me describe the data structure for what I called fixed point numbers. For this example I am going to assume 16bit integers however this is scalable up or down. your data would look like this (16bit Integer)(16bit Fraction) where the fraction is an integer count of 65536ths. I hope this is clear. Eg (1234)(32768) is 1234.5 Now to answer the question, the representation of the above number 1.234567890 would be (1)(15373) and the translation from fixed point back to decmal is: 1.23457336, this shows your error factor for this number using a 16 bit fraction. How do you convert from/to this format? To convert a number like this 12345.6789 take the integer part and store it in the first 16 bits (12345) take the fractional part and multiply it by 65536, .6789*65536=(44492) To convert a fixed point number like (12345)(44492) to decimal: The integer part is in the first 16bit 12345. The fractional part is obtained by dividing 44492 into 65536: .67889409 Add the two part 12345.+.67889409 = 12345.67889409 This system may appear slower at this point, no it's not. Conversions can be be done at compile time or done with a calculator and entered manually if needed. Youy speedup is obtained in the math. Also the fractional part may be ignored for some applications. > and how would I go >about using that integer number in various calculation (mult,div,add,subs) >with (maybe) one or more of the same kind of integer numbers? The integer numbers are transformed into fixed point numbers by using using the integer and clearing another 16bit value (hopefully behind the 16bit integer). Now you simply preform the integer 32bit operations. If your archetecture doesn't support 32 bit operations use the add with carry schemes. Note an integer over/underflow/zero have the same meanings co compares and condition code side affects can be used for your favorite branching instructions. > >Conversion: Do I multiply the float number by something or do I use 2 variables >(one for the integer part ('1') & one for the fractions ('234567890')) to >describe it or what? Sort of, just remember to do the divide/multiply by the base(in my examples it is 2^16 because I am have a 16bit example) to get your fractions. >Calculation: What if I had this kind of formula: 'y = A*x*x + B*x + C', where >A,B and C are 'converted' integers and x and y 'normal' integers. What do I >have to do get a 'correct' answer out of that formula? If I've multiplied the >floats, do I divide the result of that formula by the number I multiplied the >floats to begin with or if I use that 2-variable-approach... well, I don't >know what I'd do then! It's simple: (y)(Don'tCare)=(A)(0)*(xInt)(xFra)*(xInt)(xFra)+(B)(0) *(xInt)(xFra)+(C)(0) if you want to round off instead of truncating to minimize error, do this: (y)(Don'tCare)=(A)(0)*(xInt)(xFra)*(xInt)(xFra)+(B)(0) *(xInt)(xFra)+(C)(0)+(0)(32768) So this operation on say a MC68000 would take 5 or 6 instructions of in-line code, no subroutine/function calls, lightning fast. >I've already learnt that using lookup-tables for sin and cos values speeds >the (3D vector-) thing up somewhat, but those values are still in floating >point. Now I'd like to know 'How-to-convert' and 'How-to-use-in-calculation'... Use the method I described to convert decmimal numbers to fixed point numbers. Then use the fixed point numbers in the table. Note since you are dealing with sin/cos all of your integer parts of the fixed numbers will be 0. If space is needed the table can be compressed. Since sin and cos share datasets you can also save space by running the sin table from 0 to 250 degrees to get cos X values just use sin X+90 > >Say, does it make much difference (in performance) whether you use integer or >floating point math in any case? That will change from machine to machine. > >BTW, I'm using C, so if you have any bits of integer math code handy in that >language, could you please send me some? > >Thanx for... well, whatever you can tell me! ;) > >/* Mika Saastamoinen */ >/* (mikasaas@polaris.utu.fi/msaastamoine@finabo.abo.fi) */ >/* Student at Turku School of Economics - Information Systems Science */ >#include >#define AMIGA_In_an_insane_world_it_is_the_sanest_choice TRUE > If something isn't clear I'll try to clarify it for you. I don't have much time to proof read this and make is sound better, I cannot slip my schedule. Plus not many people are reading it since it has nothing to do with IBM compatables super VGA graphics or any of that trash. ;) It is such a pain trying to read a newsgroup with so much IBM crap in it all the time, oh well enough complaining. - Brent LaVelle lavelle@convex.com ----------------.... In article <1993Feb12.231906.723@news.eng.convex.com> lavelle@convex.com (Brent LaVelle) writes: >In article <1993Feb12.110623.6317@abo.fi> MSAASTAMOINE@FINABO.ABO.FI (Mika Saastamoinen Tkkk) writes: >>Hi ya'all! >> >>I was wondering if someone could explain to me the basic principles of integer >>math. Specifically, I'm thinking of the kind of math one uses in 3D (vector) >>graphics programming. Since I'm not so awfully hot on math I thought I'd ask >>you Gurus about this! O:) > >I wouldn't consider myself a guru at it but I should be able to help you. I >used an integer scheme on the 6809 for Currilian Cruiser (a game I wrote >and tried to sell back in high school) [long discussion deleted...] I found that discussion to be a little unclear, but what he seemed to be saying (and what I've done), is that you just take your floating point number, and multiply it by some constant to get rid of the fractional part. For example lets take the number 1234.5678 what we might do is multiply it by 10000 to get the integer number 12345678, and then we can do calculations with this integer. Adds and subtracts work normally, you don't have to do anything special. If you multiply two numbers, you have to divide the result by your constant to get the true answer like so: say we got 1.1 and 2.5 converting them we get 11000 and 25000 11000*25000/10000 = 27500 If you convert 27500 back to normal numbers you get 2.75 which is equal to 1.1 * 2.5. Dividing is the same way, accept that you need to multiply the first number by your constant before doing the division. Oh yeah, make sure that when you are multiplying your do the consant division last otherwise you'll lose accuracy. Typically you should use some power of two as your constant, this allows fast conversions just by doing shifts (If you want to find 4*x, you just shift x left twice) What constant should you use? The trade off is that bigger constants give you more accuracy but a smaller range. I think he mentioned 65536 (2^16), I've found that 256 (2^8) is adequate. Well, hopefully that's somewhat clear... -Mike --------------------.... In article <1993Feb12.110623.6317@abo.fi> MSAASTAMOINE@FINABO.ABO.FI (Mika Saastamoinen Tkkk) writes: I was wondering if someone could explain to me the basic principles of integer math. Specifically, I'm thinking of the kind of math one uses in 3D (vector) graphics programming. Since I'm not so awfully hot on math I thought I'd ask you Gurus about this! O:) Let's say I'm thinking of the floating point number '1.234567890': How do I convert that to integer without losing accuracy too much and how would I go about using that integer number in various calculation (mult,div,add,subs) with (maybe) one or more of the same kind of integer numbers? The following is an extract from some technical documentation I started writing for our PC game, Netspace, several months ago. Note that I've set the follow-up to just rec.games.programmer. I apologize for being platform specific, but I assume the general principles should be easily adaptable to the Amiga as well. **** included text Netspace uses a 32-bit fixed-point math library. The basic data type in the library is a scalar stored as a 32-bit integer. A vector ("vect") is an array of three scalars and a viewing coordinate system, a basis, is an array of three orthonormal vect's. Scalars are 32-bit fixed-point numbers. They use 30 bits for the fractional part and two bits for the whole number giving a range for a scalar X from -2 <= X < 2. Scalars are treated in C as long ints. They can be added, subtracted, assigned and compared the same as longs. Multiplying two scalars, however, creates a 64-bit result that must be right-shifted by 30 bits to store back into a 32-bit long. X, Y, Z are fixed-point; x, y, z are floating-point: X == x*2^30 (x + y)*2^30 == (x*2^30) + (y*2^30) X + Y <- X + Y (x * y)*2^30 == (x*2^30) * (y*2^30) / 2^30 X * Y <- X * Y / 2^30 (x / y)*2^30 == (x*2^30) * 2^30 / (y*2^30) X / Y <- X * 2^30 / Y sqrt(x)*2^30 == sqrt((x*2^30) * 2^30) sqrt(X) <- sqrt(X * 2^30) mag(v = (x*2^30, y*2^30, z*2^30)) == sqrt(x*2^30 * x*2^30 + y*2^30 * y*2^30 + z*2^30 * z*2^30) mag(V = (X, Y, Z)) <- sqrt(X * X + Y * Y + Z * Z)) The math library began with a few basic scalar operations, such as multiply, divide, and square root. We later added a 32-bit shift function when we realized that our 16-bit C compiler was performing them as a loop of single bit shift pairs (shift the high word one bit right, shift the low word with carry-in.) Under MS-DOS, the stack is only 16 bits wide. This means that passing a single 32-bit value takes two push operations, one for the high two bytes and another for the low. As a result, calling several 32-bit math routines in succession can be very slow. We have avoided this by converting just about every occurance of two or more consecutive math library calls into a single assembly routine. We now have a routine, for instance, which multiplies a vector by a scalar, adds it to a second vector and stores the result in a third. Converting complicated arithmetic expressions to assembly gave a marked improvement in speed. **** end inclusion Conversion: Do I multiply the float number by something or do I use 2 variables (one for the integer part ('1') & one for the fractions ('234567890')) to describe it or what? Store it in a single int (or long) and simply pretend you know where the radix point is (2.30 in my example above.) The multiply opcode on the 386 generates a 64-bit result which I can easily right-shift to get the radix point back in the correct place. Think back to how you placed the decimal point in long division back in grade school. Say, does it make much difference (in performance) whether you use integer or floating point math in any case? After some recent e-mail conversations I've had, if you were on a 486 with its built-in math coprocessor, I would say save yourself the trouble of dealing with the integer overflows and stick with floating-point. I have no familiarity with Amigas, however, so your mileage may vary. We achieved and extremely noticeable speed up with fixed-point on a 386 which also had a math coprocessor. Try it both ways and find out. BTW, I'm using C, so if you have any bits of integer math code handy in that language, could you please send me some? Sorry, all my math code is in assembly so that it can deal directly with the registers for the extended multiply results and subsequent shifts. Thanx for... well, whatever you can tell me! ;) My pleasure. /* Mika Saastamoinen */ /* (mikasaas@polaris.utu.fi/msaastamoine@finabo.abo.fi) */ /* Student at Turku School of Economics - Information Systems Science */ #include #define AMIGA_In_an_insane_world_it_is_the_sanest_choice TRUE ^^^^^ ^^^^^^ Hee hee. I'm sitting in a room with four rs6000's, four HP 700's, four DECstation 2000's and six Sparc2's. I think I'd rather be insane that suffer on an Amiga. (Sorry, I just liked the contrast.) - Steven Dollins Brown Computer Graphics Group scd@cs.brown.edu -- He was spoiled and had a trust fund that wouldn't fit in a 32-bit int. --------------... By Integer math I take it you mean Fixed Point. In that case, it's easy to do. You define a long value (4 bytes), and use the top two as integer, and the bottom two as fraction. This gives approx. 4 decimal places accuracy, but can be much faster than floating point. When doing math, you typically can only do a FXP by INT function: 0x45555 * 5 This is the same as 4.333 * 5, and the answer yielded is: 0x15AAA9, or 21.6670, where 4.333*5 is 21.665, so it's fairly accurate. You convert from floating point to FXP (fixed point) by doing a simple multiply: fxpvar = floatvar * 65536 and to convert back, it's floatvar = fxpvar/65536 Also, when extracting the integer, doing a: myint = fxp>>16 yeilds a SWAP instruction (using the SAS/C compiler) which is the most efficient way to get the integer value. I hope this helps. -----------... Right, the way I solve this problem is roughly like this: You want to hold the number 1.234567 What I do is to store every number as fixed point ie. every number stored is 1000 times bigger than the real number. ie. I store 1234 (and lose the rest) To add/subtract just add the numbers together To multiply: multiply and then divide the result bu 1000. To divide: multiply one of them by 1000 then divide it by the other one. Nb. be careful or you`ll lose precision when you multiply ie. Multiplying by 1234 rapidly becomes the same as multiplying by 1000. Or bit-wise: I always store my vector stuff in 16 bit words (for speed) the upper 9 bits hold the position of point on screen, the lower 7 hold spare s pace (ie. for the decimals (binerials?)- for accuracy). Multiplying and dividi ng is rather like I suggested for base 10, but more complicated..... Have Fun with life and don`t hesitate to contact me if you have further problem s... Sincere regards Ollie > ----------------------------Original text follows---------------------------- > > Hi ya'all! > > I was wondering if someone could explain to me the basic principles of integer > math. Specifically, I'm thinking of the kind of math one uses in 3D (vector) > graphics programming. Since I'm not so awfully hot on math I thought I'd ask > you Gurus about this! O:) > > Let's say I'm thinking of the floating point number '1.234567890': How do I > convert that to integer without losing accuracy too much and how would I go > about using that integer number in various calculation (mult,div,add,subs) > with (maybe) one or more of the same kind of integer numbers? > > Conversion: Do I multiply the float number by something or do I use 2 variables > (one for the integer part ('1') & one for the fractions ('234567890')) to > describe it or what? > > Calculation: What if I had this kind of formula: 'y = A*x*x + B*x + C', where > A,B and C are 'converted' integers and x and y 'normal' integers. What do I > have to do get a 'correct' answer out of that formula? If I've multiplied the > floats, do I divide the result of that formula by the number I multiplied the > floats to begin with or if I use that 2-variable-approach... well, I don't > know what I'd do then! > > I've already learnt that using lookup-tables for sin and cos values speeds > the (3D vector-) thing up somewhat, but those values are still in floating > point. Now I'd like to know 'How-to-convert' and 'How-to-use-in-calculation'... > > Say, does it make much difference (in performance) whether you use integer or > floating point math in any case? > > BTW, I'm using C, so if you have any bits of integer math code handy in that > language, could you please send me some? > > Thanx for... well, whatever you can tell me! ;) > > /* Mika Saastamoinen */ > /* (mikasaas@polaris.utu.fi/msaastamoine@finabo.abo.fi) */ > /* Student at Turku School of Economics - Information Systems Science */ > #include > #define AMIGA_In_an_insane_world_it_is_the_sanest_choice TRUE > -----------------... Well. I'm not a guru in integer math either, but I did calculations of some fractals which I was quite happy with. What I did was to have some bits in the decimal part and some bits in the integer part. example: 1010,0101 (4 bits integer and 4 bits decimal) Adding and subing is now done in the axactly same way as if it was just an ordinary integer number. add.l d0,d1 or sub.l d0,d1 Muling is done by muling the two numbers and shifting the result n bits to the right. ( n is the number of bits in the decimal part. In our example it is 4.) muls d0,d1 lsr.l #n,d1 Why does it work this way? Well.. think of writing the number in an integer and a decimal part, but with an extra factor. Example: N = I*(2^n)*D , where (2^n) is the extra factor which actually is the number you have to mutiply an integer with to get the same integer in your system. (n is the number of bits for the decimals), I is the integer part and D is the decimal part. When you multiply N1 and N2 you get : I1*I1*(2^n)*(2^n)*D1*d2 , but the number should have just (2^n) as a factor, therefore we divide the result by (2^n). This is the same as shifting the result n bits to the right. Does this clear it up? I hope so, but I think not. Dividing (q/r) is done by shifting q n bits to the left and dividing q by r. lsl.l #n,d0 divs d1,d0 (Hmm... actually I've never tried dividing two integers, but I think this should work.) Well, I don't know if it was this you were looking for, and I don't know if this is the best way of doing it, but it sure helpedalot when I made it in assembly. I hope that it can be of some help. -- /---------------------------------------------------------------------------\ ( 10 rem *** Nice program! *** | Letters: abcdefghijklmnopq ) ) 20 print"Espen Skoglund is my name. "; | rstuwxyzABCDEFGHI ( ( 30 goto 20 | JKLMNOPQRSTUVWXYZ ) \---------------------------------------------------------------------------/ -----------------... In article <1993Feb12.110623.6317@abo.fi> you write: > Hi ya'all! > > I was wondering if someone could explain to me the basic principles of integer > math. Specifically, I'm thinking of the kind of math one uses in 3D (vector) > graphics programming. Since I'm not so awfully hot on math I thought I'd ask > you Gurus about this! O:) > > Let's say I'm thinking of the floating point number '1.234567890': How do I > convert that to integer without losing accuracy too much and how would I go > about using that integer number in various calculation (mult,div,add,subs) > with (maybe) one or more of the same kind of integer numbers? > > Conversion: Do I multiply the float number by something or do I use 2 variables > (one for the integer part ('1') & one for the fractions ('234567890')) to > describe it or what? > The usual approach is to multiply with something. But I suppose this is up to you. By using two variables you will ofcourse get a much more accurate representation. > Calculation: What if I had this kind of formula: 'y = A*x*x + B*x + C', where > A,B and C are 'converted' integers and x and y 'normal' integers. What do I > have to do get a 'correct' answer out of that formula? If I've multiplied the > floats, do I divide the result of that formula by the number I multiplied the > floats to begin with or if I use that 2-variable-approach... well, I don't > know what I'd do then! Well, the first thing I would do was rewrite the formula....=) y = x(A*x+B)+C And to get the right answer you divide by the factor you used above. With the two variable approach, this gets more complicated as you get more multiplications and have to take into accont the state of C(arry)-Flag; > > I've already learnt that using lookup-tables for sin and cos values speeds > the (3D vector-) thing up somewhat, but those values are still in floating > point. Now I'd like to know 'How-to-convert' and 'How-to-use-in-calculation'... HOW TO CONVERT: #define PI 3.141592654 int sintable[256]; float i; for(i=0;i<2*PI;i+=2*PI/256) sintable[i]=(int)30000*sin(i); ----------------------------------------------- TO CALCULATE Y=X*SIN(ANGLE); y=x*sintable[angle]; //Where you would have to represent represent your //angles in values from 0->255 instead of //0->2*PI =) // Now, your y is 30000 times too large, and to make the calculation // correct just divide by 30000, however it might pay off to use some assembly // here as you can gain a lot by using a registers only loop and using // a swap command to correct your calculations. //(BTW: you would have to multiply with 32767 to make this work with // acceptable accuracy ) > > Say, does it make much difference (in performance) whether you use integer or > floating point math in any case? > This depends, on my A4000 you probably wouldn't gain much =) But, on a machine without an FPU this gives a great speed increase FOR THE CALCULATIONS, but usually you'll spend much more time drawing lines than calculating points, so the conclusion is that is you've got a fast FPU, dont bother..... > BTW, I'm using C, so if you have any bits of integer math code handy in that > language, could you please send me some? > I'm coding assembly language, so ehhhhhhh... I don't think so. My routines would be very hard to include in a C program I think. (My calculation loop uses all available registers except the stack pointer =) ) > Thanx for... well, whatever you can tell me! ;) > You are welcome =) ------------------------------------------------------------ INCLUDE "disclaimer.i" Zrouoggathog Olav 'Warp' Kalgraf Cthulhu in '96! internet: olavka@ifi.uio.no Hasoithshuna --------------------... Scaled integers work just fine. Remember your algebra: a = b + c xa = xb + xc a = (xb + xc)/x Basically you can take any algebraic expression and multiply by a constant then divide by the constant and get the same (truncated) answer. 16-bit integers (shorts) only give 4 positions of accuracy whereas 32-bit ints (longs) will give 9. The trade off is speed. You also need to be sure that your integer math won't overflow. Doing things like squares and cubes can make some pretty big numbers in scaled integers. Here's a small example: #define FUNC(b,c) (b*5 + c*10) main() { float af,bf=4.56,cf=7.89; long ai,bi,ci; float factor = 1000; af = FUNC(bf,cf); bi = bf*factor; ci = cf*factor; ai = FUNC(bi,ci); printf("Answers are: %g, %g\n",af,ai/factor); } -- ----------------------------------------------------------------------------- black@beno.CSS.GOV land line: 407-676-2923 | I want a computer real home: Melbourne, FL home line: 407-242-8619 | that does it all! CSI Inc, Computer Software Innovations, Palm Bay, FL ----------------------------------------------------------------------------- -------------.... In article <1993Feb12.110623.6317@abo.fi> MSAASTAMOINE@FINABO.ABO.FI (Mika Saastamoinen Tkkk) writes: > Hi ya'all! > > I was wondering if someone could explain to me the basic principles of integer > math. Specifically, I'm thinking of the kind of math one uses in 3D (vector) > graphics programming. Since I'm not so awfully hot on math I thought I'd ask > you Gurus about this! O:) > > Let's say I'm thinking of the floating point number '1.234567890': How do I > convert that to integer without losing accuracy too much and how would I go > about using that integer number in various calculation (mult,div,add,subs) > with (maybe) one or more of the same kind of integer numbers? You can't convert small FP numbers like that to integer, but consider fixed-point maths, where you arbitrarily create a decimal point somewhere in a 32-bit integer. You still perform "integer" operations on numbers, but you've shifted your range from (say) 2**0 - 2**32-1 to 2**-8 - 2**24-1. Michael Warner (atheist) - Phoenix MicroTechnologies cbmvax.commodore.com!cbmehq!cbmaus!phoenix!michaelw "In the blood of Eden Lie the woman and the man I see the man in the woman And the woman in the man" - Peter Gabriel --------------... lavelle@convex.com (Brent LaVelle) writes: >MSAASTAMOINE@FINABO.ABO.FI (Mika Saastamoinen Tkkk) writes: >>I was wondering if someone could explain to me the basic principles of integer >>math. >>and how would I go >>about using that integer number in various calculation (mult,div,add,subs) >>with (maybe) one or more of the same kind of integer numbers? >The integer numbers are transformed into fixed point numbers by using using >the integer and clearing another 16bit value (hopefully behind the 16bit >integer). Now you simply preform the integer 32bit operations. Just to clarify Brent's description... Say "a" and "b" is your 32-bit value consisting of 16 bits of integer component and 16 bits of fractional component. To ADD a and b, to get c, simply use: c=a+b; BUT, to multiply a by b to get c, you need: c=a*b/65536; Taking whatever precautions to avoid overflow, and whatever advantage of machine instructions your machine requires that your optimising compiler doesn't support... I think it's about time to implement a C++ template for Fixed integers... Anyone interested should contact me. -- Warwick _-_|\ warwick@cs.uq.oz.au /Disclaimer: / * <-- Computer Science Department, / \_.-._/ University of Queensland, / C references are NULL && void* v Brisbane, Australia. / --------------... In article <12083@uqcspe.cs.uq.oz.au> warwick@cs.uq.oz.au writes: >lavelle@convex.com (Brent LaVelle) writes: [Stuff deleted] >Just to clarify Brent's description... > >Say "a" and "b" is your 32-bit value consisting of 16 bits of integer >component and 16 bits of fractional component. To ADD a and b, to get c, >simply use: > > c=a+b; > >BUT, to multiply a by b to get c, you need: > > c=a*b/65536; That is a good point. However, to "fix" the decmal point you simply shift the number by the size of your fraction integer. That's a mouthfull, here is the example, I'll go back to my original notation where fixed point numbers are represented as (IntegerPart)(FractionalPart) This is a long multiplication in base 2^16. (4)(6) * (2)(3) ( 4)( 6) * ( 2)( 3) =========== (12)(18) <- fractional part * whole top number ( 6)(12) <- integer part * whole top number ============ ( 6)(24) <- Your answer. (18) <- error (if >= 2^15 you may want to bump up the answer ^^------------- if this number overflows you have an overflow, inturrupt or set the overflow flag is set, whatever the convention is. Furthermore it can happen after the multiply OR on a carry when you add. Also note if you have 64 bit operations on your processor you can skip a lot of stuff, eg: ( 4)( 6) * ( 2)( 3) =========== (00)( 6)(24) <- Your answer. (18) <- error (if >= 2^15 you may want to bump up the answer ^^------------- if this number is not zero you have an overflow, inturrupt or set the overflow flag is set, whatever the convention is. Furthermore it can happen after the multiply OR on a carry when you add. >Taking whatever precautions to avoid overflow, and whatever advantage of >machine instructions your machine requires that your optimising compiler >doesn't support... > >I think it's about time to implement a C++ template for Fixed integers... >Anyone interested should contact me. Be sure to make it in-line stuff. The call overhead will kill you if you try to use functions. > - Brent LaVelle lavelle@convex.com ---------------... Here's a quick way to do these fixed point integers in 68000 assembly: (assume the two numbers are passed on the stack as usual) xdef _Fixed_mul: _Fixed_mul: move.w 4(a7),d0 mulu.w 10(a7),d0 ; d0 = a1*b2 move.w 6(a7),d1 mulu.w 8(a7),d1 ; d1 = a2*b1 add.l d1,d0 ; d0 = a1*b2+a2*b1 move.w 4(a7),d1 mulu.w 8(a7),d1 ; d1 = a1*b1 sll.l #8,d1 sll.l #8,d1 ; d1 = d1*2^16 add.l d1,d0 rts This will work for unsigned, 32-bit fixed points. If you use 2's complement to represent signed ones, it will work for signed ones, too. Two's complement is also useful for addition/subtraction! Any overflows are ignored (integer part of the result is mod 2^16). It would be easy to modify this function to allow you to signal an overflow. Anyway, this is the ideal which the compiler is striving for. Just use this little routine, and worry no more about sloppy compilers! You can even have it pass the arguments in registers, but this actually will not speed things up much, since it needs to use more registers, and has to save them on the stack anyway. SAS/C allows such register argument passing. For such a simple routine, I'd say assembly code is definitely warranted. The tricky part is printing these numbers out, but hey, who cares how slow that is? The best way is probably to convert them to floating point. -- +----------------------------Ren & Stimpy--------------------------------+ | "Psst. Hey Guido. It's all so clear to me now. I'm the keeper of the | | cheese. And you're the lemon merchant. Get it? And he knows it. That's | | why he's gonna kill us. So we gotta beat it. Yeah. Before he lets | | loose the marmosets on us! Don't worry, little missy! I'll save you!" | +--------------- Quantum Seep -- kopnicky@owlnet.rice.edu ---------------+