Skip to main content
gamedev.net
🔒 Locked

Binary degrees

Started by Nice Coder 4 replies 1.2k views
Original Post
Nice Coder
Nice Coder
This topic Near the end, plays with the idea of having a binary degree system. For eg. Having a binary system, Would allow us to use a system, for determining angles and what-not (similar to degrees), using processes that the computer was designed for. And can do well, as well as very fast. My question is: What would this system be? From, Nice coder
Click here to patch the mozilla IDN exploit, or click Here then type in Network.enableidn and set its value to false. Restart the browser for the patches to work.
WhatEver
WhatEver
Didn't id use a system that avoided floats altogether, and instead used long type variables to compute their higher precision math? Is that what you're suggesting?
Nice Coder
Nice Coder
No, what i was thinking of, is that we use a system of units designed for computers, that are easily computable.

For eg. Using binary degrees (which there are exactly 2^32 of), instead of normal degrees. Using things like binary numbers, instead of base 10.

From,
Nice coder.
Click here to patch the mozilla IDN exploit, or click Here then type in Network.enableidn and set its value to false. Restart the browser for the patches to work.
JohnBolton
JohnBolton
That's exactly how it's done when you are using integer or fixed-point math. If you are using floating point, there in not much of an advantage.
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!
Dmytry
Dmytry
Yes, it's exactly how fixed-point math is done.
Some time ago, i posted my little performance test there:
// test#include <iostream>#include <fstream>#include <cmath>#include <vector>#include <assert.h>typedef __int64 INT64;typedef unsigned __int64 UINT64;typedef __int32 INT32;typedef unsigned __int32 UINT32;static const double pi=(3.1415926535897932384626433832795);volatile INT64 frdtsc(){        UINT32 resultL,resultH;        __asm{                push eax                        push edx                        rdtsc                        mov resultL,eax                        mov resultH,edx                        pop edx                        pop eax        };        return resultL+ (((INT64)(resultH))<<32) ;};UINT32 rseed=94564567;inline float random(){    rseed *= 0x08088405;    rseed += 1 ;    return (float)((UINT32)(rseed))/((float)((UINT32)0xFFFFFFFF));}static const int iterations=40*1000*1000;#define test(a) {\           INT64 _startclocks_;\             INT64 _endclocks_;\           for(int _n_=0; _n_<iterations ;_n_++){a;}\           _startclocks_=frdtsc();\           for(_n_=0; _n_<iterations ;_n_++){a;}\           _endclocks_=frdtsc();\           cout<<( ((double)(_endclocks_-_startclocks_))/((double)(iterations)) )<<endl;\   }float SIN_TABLE[256];inline float SinUsingTable(float a){        return SIN_TABLE[255 & int(a*128.0/pi)];};/* array/vector testing */using namespace std;const int size2=14;const int size=1<<size2;vector<float> vec;float array[size];void resetarrays(){        for(int n=0;n<size;n++){array[n]=0.1f;vec.at(n)=0.1f;};}/* -- array/vector testing */int main () {        vec.resize(size,0.1f);        {for(int n=0;n<=255;n++){                SIN_TABLE[n]=sin(n*pi/128.0);}}        /*        rseed^=frdtsc();//randomize        rseed^=frdtsc()<<16;        */        /*        float a;        a=0;        cout<<"testing empty:"<<endl;        test( {a+=20*random();} );        cout<<"I have to write to fool the optimizer:"<<a<<endl;        a=0;        cout<<"testing sin:"<<endl;        test( {a+=sin(20*random());} );        cout<<"I have to write to fool the optimizer:"<<a<<endl;        a=0;        cout<<"testing cos:"<<endl;        test( {a+=cos(20*random());} );        cout<<"I have to write to fool the optimizer:"<<a<<endl;        a=0;        cout<<"testing inverse"<<endl;        test( {a+=1/(20*random());} );        cout<<"I have to write to fool the optimizer:"<<a<<endl;        a=0;        cout<<"testing square root"<<endl;        test( {a+=sqrt(20*random());} );        cout<<"I have to write to fool the optimizer:"<<a<<endl;        a=0;        cout<<"testing sin made using lookup table"<<endl;        test( {a+=SinUsingTable(20*random());} );        cout<<"I have to write to fool the optimizer:"<<a<<endl;        */        int n=0;        n=0;        resetarrays();        cout<<"testing array[]"<<endl;        test( {array[n]+=0.5-random();n=(n+1)&(size-1);} );        n=0;        //resetarrays();        cout<<"testing vector[]"<<endl;        test( {vec[n]+=0.5-random();n=(n+1)&(size-1);} );        n=0;        //resetarrays();        cout<<"testing vector.at"<<endl;        test( {vec.at(n)+=0.5-random();n=(n+1)&(size-1);} );/*      */        // fool advalced optimizers        float b;        for(n=0;n<size;n++){                b+=b*(vec.at(n))*0.0012345;                b+=b*(array[n])*0.001;                b+=array[n];                b+=vec.at(n);                b+=n;        };        cout<<"I have to write that to fool the optimizer:"<<b<<endl;        cout<<"Finished."<<endl;        char c;        cin>>c;        return 0;}

(note that sin-using-lookup-tables convert input from radians to "computer degrees" in range 0..255) You can use it to test if something is really faster[grin]. But you have to use it with maximal compiler optimization.

The most significant problem with fixed point is that intermediate results in expressions will have bad precision. That is, let x is in range 0..1 ,
So, x2 is in range 0..1 too. Let x have some discrecy.
For example,
0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1 (or, if you wish, 0,1/256,2/256....)
Plot a graph of x2. You'll see that x2 can have values
0,0.01,0.04,0.09,0.16,0.25,0.36,0.48,0.64,0.81,1
If we will store it with same discrecy again, we get
0,0,0,0.1,0.2,0.2,0.4,0.5,0.6,0.8,1
, that is, result of discretization is especially bad at smaller values.

As you know, floating point have bigger accuracy for smaller values. What i wrote is reason why it is useful.
Floating point calculations can be done in parallel using SSE, so i doubt you'll accelerate something by using integers all the time.

As about lookup tables: Just try to do something with lookup table of 2048 floats (that is, 8192 bytes), and measure performance [grin]. I'd like to look how "insanely fast" it will be.

Also, i can bet that if you use sine and cosine, your code is either highly-inoptimal (you use atan/asin/acos/atan2 to find angle, then use sin and cos to do rotation), or you are doing that once per some screen drawing. And that it consumes something like 0.001% of computer time.

***************************
(PS: for record: note that our dear "mature-nonoptimization zealots" never post their cut-n-pasted argumentation to such low-level fixed point & lookup tables-related topics, where their argumentation is atleast somewhat related. But when somebody(e.g. me) simplifies some mathematical equation(that is, replaces more mathematical operations by less operations without doing something like fixedpoint math or lookup tables or anything similar) and therefore optimizes it, they always post some totally offtopic blabla about cache behavior, lookup tables, float to int and int to float conversion, etc.)

[Edited by - Dmytry on January 11, 2005 4:35:10 AM]
Nice Coder
Nice Coder
What i was thinking, is if you have say a 32 bit number, (fixed point), and you wanted to do sin/cosin/ect.

What you could do, is you could have, for eg.
Table[0-255] then you liniarly interpolate off that (lowish precision, because it only uses the first 8 bits as a guide (those are the most significant bits, so the rest can only change the entire number by 1/256 which is 0.00390625 of a revolution. Which is good accurisy, without the cost of remaking the table more then once.

You can simply make a bigger table, with
o(n) Memory Copies (n is the current size of the table) And
o(n) Sins/cosins/ect. (where n is still the current size of the table).
This is because 1110 is = 111.
This means that you replace half of the operations, with (much faster) memory copies.

Now 32 bit fixed point has a resolution of 23283064365386963 * 10^-10 Which should be more then enough for games (or most things, rather).

The reson i was thinking about this, is that you could have 32 bits to play with, but you could always use less, and make things faster.

From,
Nice coder
Click here to patch the mozilla IDN exploit, or click Here then type in Network.enableidn and set its value to false. Restart the browser for the patches to work.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.