Skip to content
theZiz edited this page May 15, 2013 · 9 revisions

Welcome to the third tutorial of sparrow3d about sparrowMath. This tutorial will be a bit dryer, because you will not see any fancy pictures or learn anything about 3d pony rainbow animations. No, this tutorial is about mathematics.

Table of Contents

Introduction

So, why inventing the wheel again and making my own fancy mathematics? Most ARM devices sparrow3d runs on don't have an FPU. That means, that floating point operations are slow like hell. Another approach are fixed point numbers. I will not go to deep, but the main idea is to think of all integers as divided by 65536. That means 65536 is 1.0, 1 is 1/65536 is ~0.00001526 or 123456 is 123456/65536 = 1.8838.

Divisions are slow as hell, too, but, if we divide by a power of 2, we can use bit shifting, which is much faster. With this idea multiplication, addition and subtraction is as fast as normal integer operations. However keep in mind: We loose some precision!

First of all you need to init sparrowMath with spInitMath. However, this is called by spInitCore at start.

Conversion

First of all the type you will work with is Sint32. This type is defined in SDL and is (obviously) a 32 bit signed integer value. To convert a int to this fixed point number use spIntToFixed. This function only makes:

 value << SP_ACCURACY

which is in fact a multiplication with 65536. However spIntToFixed is in fact a define, so it is at fast as doing

 value << SP_ACCURACY

by yourself - but looks much better. Similar and intuitive functions are spFixedToFloat, spFloatToFixed, spFixedToInt and spFixedRoundInt. See Here for more details.

Basic Arithmetic Operations

Now you now, how to create and set a fixed point value. But how do calculate with it? Addition and Subtraction are easy: You can use handle the fixed point values like normal numbers, e.g:

 Sint32 foo = spIntToFixed(123);
 Sint32 bar = spFloatToFixed(12.3);
 Sint32 meow = foo + bar;
 printf("%f\n",spFixedToFloat(meow)); //Will print 135.3

If you want to multiplicate or divide two fixed point numbers you can't use the normal * or / operator! You have to use one of these self-explaining functions:

  • spMul(a,b) multiplies the fixed point numbers a and b with the default accuracy on the system
  • spMulHigh(a,b) multiplies the fixed point numbers a and b with high accuracy
  • spMulLow(a,b) multiplies the fixed point numbers a and b with low accuracy
Especially very small numbers can get zero, if multiplied with low accuracy. High accuracy works better, but needs more time because of fancy 64 Bit arithmetics. However, it is still much faster than FPU emulation. I use it e.g. for light calculation on every device, otherwise the light would flicker.

The function for the division work in the same manner, see Here.

You can also square (spSquare) or extract a root of number. (spSqrt).

If you want to multiply a normal int with a fixed point number, you can use multiply them btw.:

 Sint32 foo = spIntToFixed(123);
 int bar = 5;
 Sint32 meow = foo * bar; // will be 615 as fixed point number

The division of a fixed point number and an int works similar, but the dividend has to be the fixed point number and the divisor the normal int.

Constants

Furthermore I definied some usefull constants. SP_ONE is the same as spIntToFixed(1) and SP_PI is pi as fixed pointer numbers needs for trigonometric functions.

Trigonometric functions

sparrowMath also provides trigonometric functions like sinus and cosinus. The "normal" FPU sinus and cosinus are very accurate, but slow as hell, so I do the oldest trick in computer science: I use precalculated lookup tables. SP_MATH_ACCURACY defines, how much values shall be saved. As higher the number is, as fewer values are stored. At the moment e.g. 25736 values are saved for sinus and cosinus. At all ~1MB is used for all lookup tables. The functions themself are self-explaining again: spSin, spCos, spTan, spAsin and. spAcos.

Little helpers

Furthermore you have spMax and spMin to get the biggest or smallest of two numbers (doesn't matter, whether fixed point number or net). To get the biggest or smallest out of three or more numbers, use a tree-like call structure:

 Sint32 smallest = spMin( spMin( number1, number2), number3);

Furthermore similar to atof, we have spAtof for directly converting a string to a fixed point number

That's all about fixed point numbers! You see, you don't have to understand everything, just calling the functions should be enough, just don't forget to use them. ;) The next Tutorial will be about a very important a high optimized part of sparrow3d: Drawing stuff with sparrowPrimitives

Clone this wiki locally