Has anyone any idea where I can get a double precision maths library which will work with the Keil C51 compiler.
Hello Dave Have never used the forum before, but I have been driven here by the same need... my project required greater precision than 'float' & I have discovered the hard way that the Keil tools (otherwise very good) ignore the 'double' declaration. You can get a double precision maths library that Keil claim will do the job... it's called GoFast from microdigital (see http://www.smxinfo.com) but it costs around $5,000. I cannot justify the cost as all I need is the four basic functions (+ - / and *). I have had a quick look at the problem & it seems this could be done as C functions (using a union to create the data type & writing functions to do the maths) - if this is all you need, do you want to collaborate on writing & testing these? BR Paul
Hi Paul I see what you mean about the price - how on earth do they justify that! We have decided that we can just about do the job by using 64 bit integers providing we put some code in place to stop the the numbers overflowing so we will not need to do anything more, but thanks for the offer! I wish you well with your task and if I can help in any way don't hesitate to contact me. Dave
(if the Keil tools had supported ANSI C we would hvave been happy) rather than missing "tools had supported" I think you missed "time to process using a slow 8 bitter". Alas, that is water under the bridge. If you do a bit of paper calculations, you will see that fixed point with scaling really is not that big a deal. in most cases you can, simply by knowing possible ranges, scale by fixed values. If not, there always is the "floating fixed point" method. let us have a look at x = ((a * b)/c) you need one variable "fudge" set to zero before the calculation. here we go (syntaxically incorrect)
if (a > one_half_max) { a /= 2; fudge--; } if (b > one_half_max) { b /= 2; fudge--; } temp = a*b while (temp < one_half_max) { temp *= 2; fudge ++; } x = temp/c
Hello Erik Many thanks for he code ideas (gives me food for thought). I am now in the throws of coding functions with double precision floats... handling NaN, zero, +INF & -INF conditions for each variable & combination like +IN+ + -INF seems to take up most of the effort!. best regards - Paul
I think you missed "time to process using a slow 8 bitter".<p> Time is not an issue in some applications. Not having the double datatype is probably just a way not to lead clueless programmers into the temptation of actually using them - which will then make them complain that their stuff does not work (especially when they try to cram heavy double crunching into ISRs).
Hello Christoph You are right (& all the other contributors to this duscussion)... it is slow doing this on an 8-bitter. I have just started to test my first attempt & adds go from around 30us with floats to 300us for doubles (10 times slower!!). I hadn't expected such a big impact, but I am writing it in C rather than assembler (I thought C was supposed to be just about as fast as assembler!). Back to the fun of testing... thanks - Paul.
"I hadn't expected such a big impact..." Maybe the $5000 is sounding a bit less unreasonable...? "I thought C was supposed to be just about as fast as assembler!" That does, of course, depend very largely upon your skill... And there are some tasks for which 'C' is particularly unsuited - I guess this could well be one of them?
Hello Paul Many thanks for the offer and I would welcome a copy when you get it all sorted. We are doing polynomial calculations linearising a 24 bit sensor input on some micro balances (scale). Speed is a secondary requirement, well, no requirement at all really, the most important thing is accuracy. best regards Dave
Hello David If you send me your contact details (to paul.bramley@metrosol-ltd.co.uk), I will get in touch & send you the results of my efforts. Best Regards - Paul
I hadn't expected such a big impact, but I am writing it in C rather than assembler (I thought C was supposed to be just about as fast as assembler!).<p> This is one of the cases where hand-coded assembler will beat any kind of high-level language (even C) hands down. Having access to the CPUs overflow- and carry-flag alone will speed up the calculations significantly since it makes checking for these conditions by doing actual comparisons unnecessary. You can, of course, access these flags in C code ... however, this is an ugly hack at best (when you know exactly what you are doing and double-check the resulting compiler output, since the actual behavior of the compiler is pretty much undefined in this case), but much more likely it is a sure-fire way to make the program a horrible, bug-infested nightmare. (Read: Don't do it unless you're really willing to verify that the compiler output does what you want it to do, and don't expect anyone after you to do any maintenance on the code.) If you need speed, it might be worth your while to familiarize yourself with '51 assembler (which, due to the simplicity of the CPU, isn't too bad, as you don't have to deal with pipelines and other things that make an assembler programmers life hard on more modern architectures) to optimize your double arithmetic routines.
We are doing polynomial calculations linearising a 24 bit sensor input on some micro balances (scale). Have you considered (and discarded) other approaches for doing this (e.g. lookup-table with interpolation) ?
"Yes - this one had me perplexed. 10 decades would be enough for me, but since the IEEE format calls for 8 bytes with a 53-bit mantissa (including the assumed leading 1) I don't know why ANSI C only calls for 10 decades." I don't think ANSI requires IEEE754 to be used. The explanation for the seemingly 'easy' requirements is most likely to avoid making old implementations non-conforming. ANSI have always seem to have adopted a policy of formalising existing popular implementations rather than pushing the boundaries forward.
"Maybe the $5000 is sounding a bit less unreasonable...?" Have you seen how little of the standard math library you actually get for your $5000?
" ... double-check the resulting compiler output ... " Of course, by the time you've done that, you might as well have writted it in assembler in the first place! :-0
The problem here is not just C.
The float implementation of C51 uses registers for float operations. It can do this because there are eight 1-byte registers and each float only uses 4 bytes. So, C51's implementation is actually pretty fast.
When you start to implement double operations, you need 8 bytes for each operand and 16 bytes for both. So, you can't do everything in registers. Assuming that you could do everything in registers, I'd expect most operations to be at least 4 times slower. Since you'll have to swap registers out to memory, a factor of 10x is probably not too bad.
Jon
We have considered using interpolation and thats the way we are now doing it. We have succeeded in using 64bit integer maths with that so there is no need to go to f.p.
Hello Jon Thanks for the explanation - that makes perfect sense. Coding now complete... into testing. best regards - Paul
View all questions in Keil forum