home *** CD-ROM | disk | FTP | other *** search
- 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 <stddisclaimer.h>
- #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 <stddisclaimer.h>
- >#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 <stddisclaimer.h>
- #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 <stddisclaimer.h>
- > #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 ---------------+
-