I'm still learning how to work with GitHub/git, but you can help or access the code for this project here.

The library of "single precision" floats (they don't conform to IEEE standards Sad ) needs a lot of work using my newer knowledge. However, it does have abs, add, sub, rsub, negate, arithmetic mean, square root, geometric mean, Borschardt-Gauss, compare, 1/x, division, multiplication, e^x, 2^x, 10^x, x^y, ln(x), log2(x), log10(x), log_y(x), atanh, acosh, asinh, atan, asin, acos, rand, float→TI float, float→str, str→float.

The extended precision floats (15-bit exponent, 64-bit mantissa) are not as compete yet, but I have implemented: add, sub, rsub, arithmetic mean, multiplication, division, square roots, geometric mean, Borschardt-Gauss, acos, asin, atan, acosh, asinh, atanh, ln(x), and float→str.

I am particularly proud of the fact that square roots average under 6600cc, about 13 times faster than TI's (and to about 5 digits more precision).

Later when I am home I'll come up with screen shots. I hope these are useful ! There is a lot more work to be done. Maybe even make eZ80 versions ! This has been kind of exhausting, honestly.
EDIT: Screenshot:

For 64-bit floats, results are only good to about 19 digits, though 20 digits are displayed. With that in mind, the biggest error is less than half a digit so I'm calling it rounding error, both of the inputs (constants are only stored to 64 bits precision) and during intermediate calculations. Razz

EDIT: 14 Jan 2019
Here is a screenshot of some of the single-precision routines!
Fantastic work as always Xeda!

Will you be incorporating this library into KnightOS?
As awesome as that would be, I don't think I'm up to that task. If somebody else wants to, I encourage it!
I have been focusing on the single-precision floats this past week or so. I rewrote or re-worked a lot of routines. I got rid of most of the tables by switching to a polynomial approximation for the 2^x routine (thanks to the Sollya program!) and using the B-G algorithm to compute lnSingle. It turned out to be faster this way, anyways.

I implemented sine, cosine, and tangent, the first two, again, using minimax polynomial approximation. I optimized the square-root routine (much faster but a few bytes bigger). I re-implemented the B-G algorithm using math optimizations I came up with a few months ago. I opted for two B-G implementations-- one for lnSingle which requires only 1 iteration for single precision, and one for the inverse trig and hyperbolic functions which needs 2 iterations. For anybody looking to save on size, you can just use the second B-G routine for natural logarithm. It will be a little slower, but it'll work just fine (maybe even give you an extra half-bit of precision Razz).

I included the Python program that I use for converting numbers to my single precision format. You can use it to convert a single float or a bunch of them. I also included a Python tool I made for computing more efficient coefficients in the B-G algorithm, but that'll only be useful to me and maybe a handful of other people. It's there on the off chance somebody stumbles across my project looking for a B-G implementation.


The single precision floats are largely complete in that I can't think of any other functions that I want to add. There is still work to be done on range reduction and verification, as well as bug fixes and more extensive testing.

Here is a current screenshot of some of the routines and their outputs:


The current list of single-precision routines:

Code:

Basic arithmetic:
  absSingle     |x| -> z       Computes the absolute value
  addSingle     x+y -> z
  ameanSingle   (x+y)/2 -> z.  Arithmetic mean of two numbers.
  cmpSingle     cmp(x,y)       Compare two numbers. Output is in the flags register!
  rsubSingle    y-x -> z
  subSingle     x-y -> z
  divSingle     x/y -> z
  invSingle     1/x -> z
  mulSingle     x*y -> z
  negSingle     -x  -> z
  sqrtSingle    sqrt(x*y) -> z
  geomeanSingle sqrt(x*y) -> z

Logs, Exponentials, Powers
  expSingle    e^x -> z
  pow2Single   2^x -> z
  pow10Single  10^x-> z
  powSingle    y^x -> z
  lgSingle     log2(x)  -> z
  lnSingle     ln(x)    -> z
  log10Single  log10(x) -> z
  logSingle    log_y(x) -> z

Trig, Hyperbolic, and their Inverses
  acoshSingle   acosh(x) -> z
  acosSingle    acos(x)  -> z
  asinhSingle   asinh(x) -> z
  asinSingle    asin(x)  -> z
  atanhSingle   atanh(x) -> z
  atanSingle    atan(x)  -> z
  coshSingle    cosh(x)  -> z
  cosSingle     cos(x)   -> z
  sinhSingle    sinh(x)  -> z
  sinSingle     sin(x)   -> z
  tanhSingle    tanh(x)  -> z
  tanSingle     tan(x)   -> z

Special-Purpose    Used by various internal functions, or optimized for special cases
  bg2iSingle     1/BG(x,y) -> z   Fewer iterations, but enough to be suitable for ln(x). Kind of a special-purpose routine
  bgiSingle      1/BG(x,y) -> z   More iterations, general-purpose, needed for the inverse trig and hyperbolics
  div255Single   x/255 -> z
  div85Single    x/85  -> z
  div51Single    x/51  -> z
  div17Single    x/17  -> z
  div15Single    x/15  -> z
  div5Single     x/5   -> z
  div3Single     x/3   -> z
  mul10Single    x*10  -> z
  mulSingle_p375         x*0.375  -> z      Used in bg2iSingle.  x*(3/8)
  mulSingle_p34375       x*0.34375-> z      Used in bgiSingle.   x*(11/32)
  mulSingle_p041015625   x*0.041015625-> z  Used in bgiSingle.   x*(21/512)

Miscellaneous and Utility
  randSingle    rand   -> z
  single2str    str(x) -> z           Convert a single to a null-terminated string, with formatting
  single2TI     tifloat(x) -> z       Converts a single to a TI-float. Useful for interacting with the TI-OS
  ti2single     single(tifloat x)->z  Converts a TI-float to a single. Useful for interacting with the TI-OS
  single2char   Honestly, I forgot what it does, but I use it in some string routines. probably converts to a uint8
  pushpop       pushes the main registers to the stack and sets up a routine so that when your code exits, it restores registers. Replaces manually surrounding code with push...pop
Update:
For the extended-precision floats, I added:

Code:

xcmp     for comparing two numbers
xneg     -x -> z
xabs     |x|-> z
xinv     1/x -> z   Observed a bug in 1/pi !
xpow     x^y -> z
xpow2    2^x
xpow10   10^x
xlog     log_y(x)   It's failing miserably
xlg      log2(x)
xlog10   log10(x)   Observed a bug in log10(pi)

I made the str->single routine better (it had been quickly thrown together and failed on many/most cases due to lost precision). Now it appears that digits get swapped in some cases! Sad I have to look into this.

To Do:
Look into the string->single routine and figure out what is wrong
I still have to look into the bugs observed in the single-precision Mandelbrot set program
Look into the errors in xinv, xlog, and xlog10 (these might all be related, or maybe I accidentally a byte in the built-in constants).
Have to make xsin, xcos, xtan, xsinh, xcosh, xtanh, xtoTI (x-float to TI float), TItox (TI float to x-float), and strtox (string --> x-float).
For all of the trig routines, I still need to apply range-reduction Neutral

Once these are done, it's just finding and fixing bugs and optimizing, and the project is as complete as what I wanted to do. BCD floats were a cute idea, but I'm a bit more realistic now Razz Maybe I'll be motivated to add in stuff like gamma / log-gamma ?
Updates!

There are still bugs that I have to locate and fix, but this project is almost complete!
Every routine that I had planned to implement is now implemented Smile
Cosine and sine now have range reduction. It isn't perfect, but it works for now.
The extended precision floats now have sin/cos/tan along with range reduction.
I had to add a routine for mod 1 in order to implement range reduction.
I now have all of the conversion routines done between strings, floats, and TI floats.

^~^

Combining the single- and extended-precision floats into one app (removing duplicated routines), the extended-precision routines total 7980 bytes, and single-precision routines total 4906 bytes, for a total of 12886 bytes.

EDIT: I had five bugs that needed fixing and I fixed them this morning! Four of them were solved by fixing two issues in the division routine, and the other was xtanh which I rewrote and now it works Smile (I was pretty sure it was variable juggling issues).
I'm posting to announce a new addition to the library: 24-bit floats! I basically wrote all of these in the last 48 hours and I'm pretty burned-out:
https://github.com/Zeda/z80float/tree/master/f24

These floats are a fantastic balance of speed and usefulness on the Z80, and I think all of the routines fit into about 2500 bytes, so they are compact, too. I think I handled 0/inf/NaN a lot better with these routines (in that I made sure each routine handled them)

I still need to write conversion routines, but that can wait for another time, maybe next year if someone else doesn't get to it first Razz
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 1
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement