Closed GoogleCodeExporter closed 9 years ago
Very well spotted, I'm going to put that error down to my retarded state of
mind late at night and the fact that I've never tested this. It seems that I
forgot I was doing fixed point and mixed in some integer maths there, the
correct code for those lines is:
tempOut = (fix16_one + fix16_mul(inValue, inValue));
tempOut = (fix16_one + fix16_sqrt(tempOut));
tempOut = fix16_div(inValue, tempOut);
tempOut = _fix16_atan(tempOut);
return (tempOut << 1);
The reason that if statement is there is because the approximation is quite
wrong for numbers over that value. As for the inaccuracy of the numbers below
that threshold, I may need to lower the threshold or improve the accuracy of
the algorithm. I did work out what accuracy should be needed but my maths was
clearly very sketchy at the point when I wrote this specific function.
I'll commit it when I get home and get a chance to which may be later this
week, in the mean time you seem quite interested in this project and have a
good level of understanding, so your welcome to committer access if you want to
join the project (don't worry I won't expect anything off you but it just means
that you can fix any bugs that you may find).
Original comment by Flatmush@googlemail.com
on 22 Feb 2011 at 5:26
I've just noticed a similar set of problems in asin, this should be:
fix16_t fix16_asin(fix16_t inValue) {
if((inValue > fix16_one) || (inValue < -fix16_one))
return 0; // Should cause error case.
fix16_t tempOut;
tempOut = (fix16_one - fix16_mul(inValue, inValue));
tempOut = fix16_div(inValue, fix16_sqrt(tempOut));
tempOut = fix16_atan(tempOut);
return tempOut;
}
Original comment by Flatmush@googlemail.com
on 22 Feb 2011 at 5:37
Looking at it, it might make sense for me to do the atan function in 64-bit
(32.32) format to maintain accuracy unless I can find a faster way to get
accurate results.
Original comment by Flatmush@googlemail.com
on 22 Feb 2011 at 5:41
Ok, so I tried out a approximation I found at
http://www.dspguru.com/dsp/tricks/fixed-point-atan2-with-self-normalization
I have attached both implementations, the simple one which is <.08 radians off
~ 4 degrees
the complex one which is < .01 radians off ~ .057 degrees
They need some optimization obviously but the idea is there.
We could use half angle approximations to find asin and acos?
http://en.wikipedia.org/wiki/Inverse_trigonometric_functions
let me know what you think.
Original comment by joe.scha...@gmail.com
on 23 Feb 2011 at 12:44
Attachments:
So I did some tests on my ARM Cortex-M0
Attached is my code
With neither FLOAT_TEST or FIXED_TEST defined code size is 1741 Bytes
With FLOAT_TEST defined code size is 13176 Bytes
With FIXED_TEST defined code size is 3764 Bytes ( this is with the 4KB array
removed, and the associated if)
With FLOAT_TEST and FIXED_TEST defined code size 13624 Bytes
to add the floating point sin it takes 11500 Bytes
to add the fixed point sin it takes ~2000 bytes
so a ~9500 Bytes savings.
to compute the floating point sine it took "Conversion Took 9210 ticks"
to compute the fixed point sine it took "Conversion Took 2562"
Original comment by joe.scha...@gmail.com
on 23 Feb 2011 at 2:36
Attachments:
Nice work, we should put these results on the wiki.
I hadn't thought of using this in such an embedded environment, I put in the 4K
(16KiB) caches for speed because I was using this for games/3d on a less
embedded environment, but it's clear that we should have some macros to disable
them on smaller environments.
As for your code we should look into committing it, a few quick things to note:
You should work out the constants using other constants which can be reduced at
compile time or using a calculator rather than using fix16_from_dbl, for
example:
3 * (pi / 4) = (fix16_pi * 3) >> 2
or
3 * (pi / 4) = 3 * (3.1415926535897932384626433832795 * 65536) / 4 = 154415
Original comment by Flatmush@googlemail.com
on 23 Feb 2011 at 9:31
Ok, I've committed the above changes to the code tree.
As for the complex atan2, I've made some changes to your code, tell me what you
think. But I consider this to be your work and your contribution so since you
now have committer access you should add this change in since it's you who
deserves the credit for it.
A few things that I changed:
1. Use fix16_sdiv (saturated divide) so you don't have to worry about divide by
zero, sdiv will simply return fix16_max if you do a divide by zero so it works
well with most functions.
2. Like I said above, the code will be more accurate and faster if you use the
proper constants for pi, so I replaced all the constants.
3. Made the code a bit more concise and inkeeping with the current code, though
I kept your variable names the same since they're much nicer than the naming
scheme I originally used. I'm no longer such a fan of putting temp infront of
every local variable.
Original comment by Flatmush@googlemail.com
on 23 Feb 2011 at 10:09
Attachments:
Original comment by Flatmush@googlemail.com
on 23 Feb 2011 at 10:10
Ok, my code had an error (the >> 16 in a constant).
I've run your test code with your version of the code and the version with a
few small updates, and I can confirm that the updated version is very slightly
more accurate. Included is the test with both versions of the code for
comparison, the updated version is now fixed.
Original comment by Flatmush@googlemail.com
on 23 Feb 2011 at 10:23
Attachments:
Hi,
Can you please upload the latest libfixmath after all the above fixes.
BR,
Original comment by birdla...@gmail.com
on 23 Feb 2011 at 12:49
Latest revision is uploaded.
Original comment by Flatmush@googlemail.com
on 23 Feb 2011 at 2:31
It seems that the uploaded version does not contain the correct version on
atan2. Can you plz check if I am not wrong.
Original comment by birdla...@gmail.com
on 23 Feb 2011 at 4:55
I was going to let joe commit that change since it was his algorithm, but since
you want it now I've uploaded a version which I've implemented in fixed point
with no external calls, it's tested across the full range of fixed point
numbers for accuracy though there may be some room for me to optimize it by
removing some of the rounding that is required due to the dynamic range.
Original comment by Flatmush@googlemail.com
on 23 Feb 2011 at 5:15
No problem with commiting I you seem to have improved it too. It also seems
that we are in far different timezones...
I will get a chance to test it in a little bit. However It looks good, I like
the no external calls part of it, also the low usage of division operations.
The only part I personally dont like is the 64bit numbers, mainly because I
don't know how well GCC handles 64bit numbers on a 32bit system, I assume it
would handle them very well.
But I will run a test when I get home using my "complex_atan2.c" and your
updated atan2, and check codesize, conversion time differences, and size
comparisons to the math.h atan2.
Flatmush if you want to start the wiki, I could add an embedded section to it.
Also is their a mailing list so I dont have to reply to the issue every time?
Original comment by joe.scha...@gmail.com
on 23 Feb 2011 at 8:09
Not yet, I only just updated the project and it's not my only project. I
actually didn't expect that many people to be interested in it really so that's
a nice surprise. I guess I should look at sorting out a mailing list but I'm a
bit rubbish at these admin things which is why I like googlecode.
Yeah the 64-bit integer arithmetic could be a problem, but without doing
specific assembler for each platform (could do with gcc macros) there's no way
of making it platform independent.
The real thing is that despite doing a lot of embedded stuff, this maths code
has never really been the bottleneck of any of my projects, with graphics stuff
it's almost always the triangle filler, etc. I'll have a look into benchmarking
and optimizing it but if you beat me to the punch with that then be sure to
commit it.
My timezone is GMT (UTC + 0), I'm guessing you're in America?
Original comment by Flatmush@googlemail.com
on 23 Feb 2011 at 8:15
Mailing list created.
Original comment by Flatmush@googlemail.com
on 23 Feb 2011 at 8:28
hi
The latest version is more accurate. It is working fine with gcc but only one
problem is that one of the compilers I use does not support int64. Is there any
way around.
Any benchmarking results for the library?
Original comment by birdla...@gmail.com
on 24 Feb 2011 at 9:57
I'm going to make an issue ticket for 64-bit support, it's possible we can make
some speed gains with it at the same time.
Original comment by Flatmush@googlemail.com
on 24 Feb 2011 at 12:52
Original issue reported on code.google.com by
joe.scha...@gmail.com
on 22 Feb 2011 at 5:28