A new IEEE-754 half precision (16-bit) floating point library in z88dk

190 views
Skip to first unread message

Phillip Stevens

unread,
Jun 15, 2020, 6:18:59 AM6/15/20
to RC2014-Z80
Now not just the whiz-kids promoting Tensor and Deep Learning over at the Nvidia, AMD and ARM camp have access to really fast IEEE-75416-bit half precision maths.
We've just added a 16-bit half precision maths library to the z88dk environment.

For all those times when calculating a full precision floating point number is too slow, the IEEE-754 16-bit option is now available.
Think pixels on a screen, or Deep Learning. Lots of applications.

Through the work of @suborb, the sccz80 C compiler now fully supports the _Float16 type, or as I like to call it the half_t type. If you declare variables as half_t and use the sccz80 compiler, then you can perform normal arithmetic functions (with constants and comparisons, etc) in the 16-bit half_t type. For example, the mandelbrot program in C can be translated to half_t calculations simply by redefining the double_t variables. Using sdcc C compiler (where _Float16 is not native, you have to translate to via called functions), but it works as well.

The math16 library is an adjunct math library. It doesn't support printing directly, so it co-exists with either math32 or math48 to support printing output and input of numbers.
Conversion between float_t and half_t is very straight forward, and quite fast, using the functions provided below.

How to use it? Some command line options below.

zcc +rc2014 -subtype=cpm -clib=new --math16 -lm
zcc
+rc2014 -subtype=cpm -clib=new --math16 --math32

zcc
+hbios -clib=new --math16 -lm
zcc
+hbios -clib=new --math16 --math32

The available functions are currently being expanded. But today we have.

half_t f16_f48(double_t x);
double_t f48_f16
(half_t x);
half_t f16_f32
(float_t x);
float_t f32_f16
(half_t x);

int16_t i16_f16
(half_t x);
uint16_t u16_f16
(half_t x);
int32_t i32_f16
(half_t x);
uint32_t u32_f16
(half_t x);

half_t f16_i8
(int8_t x);
half_t f16_i16
(int16_t x);
half_t f16_i32
(int32_t x);
half_t f16_u8
(uint8_t x);
half_t f16_u16
(uint16_t x);
half_t f16_u32
(uint32_t x);

half_t addf16
(half_t x,half_t y);
half_t subf16
(half_t x,half_t y);
half_t mulf16
(half_t x,half_t y);
half_t divf16
(half_t x,half_t y);
half_t fmaf16
(half_t x,half_t y,half_t z);
half_t hypotf16
(half_t x,half_t y);

half_t invf16
(half_t x);
half_t invsqrtf16
(half_t x);

half_t sqrtf16
(half_t x);

half_t div2f16
(half_t x);
half_t mul2f16
(half_t x);
half_t mul10f16
(half_t x);
half_t frexpf16
(half_t x,int8_t *exp);
half_t ldexpf16
(half_t x,int16_t exp);

half_t fabsf16
(half_t x);
half_t negf16
(half_t x);
half_t ceilf16
(half_t x);
half_t floorf16
(half_t x);

Enjoy, Phillip

Phillip Stevens

unread,
Jun 28, 2020, 6:26:40 AM6/28/20
to RC2014-Z80

Over the past two weeks, we've worked out some issues, and added the basis of trigonometric, logarithmic, and exponential functions.

So to update, I've worked on the n-body benchmark. And the results are pretty good. I'm quite happy with the outcome so far. We're about 6x faster than the standard maths library.

It is pretty easy to use the math16 library. On the command line --math16 needs to be specified, along with one of the other maths libraries -lm if you want to do printing. 

zcc +rc2014 -clib=new -O3 --opt-code-speed=inlineints --math16 -lm myprogram.c -o myprogram -create-app

Because the 16-bit floating point numbers look like integers, inline integer handling really saves a lot of cycles too.

Note that only the sccz80 compiler handles _Float16 (or half_t) numbers natively. sdcc will need to be coaxed by using functions instead of intrinsic C.
To convert any normal program to use 16-bit floats then just do this kind of declaration, and convert all double or float references to DOUBLE.
Remember that your half_t variables will need to be cast to (double) before printing.

#ifdef __MATH_MATH16
    #define DOUBLE          _Float16
#else
    #define DOUBLE          double
#endif

What are the applications for 16-bit floating point? Perhaps if you were trying to build a real-time Startrek game? Or some other game with graphics.

Enjoy, Phillip

Alan Cox

unread,
Jun 28, 2020, 9:24:13 AM6/28/20
to rc201...@googlegroups.com

What are the applications for 16-bit floating point? Perhaps if you were trying to build a real-time Startrek game? Or some other game with graphics.


I don't think we ever used FP in a graphical game. 3D stuff generally used an angle system with 256 'degrees' to a circle and page aligned look up tables for fixed point maths.


Phillip Stevens

unread,
Jun 28, 2020, 8:16:06 PM6/28/20
to RC2014-Z80
On Sunday, 28 June 2020 23:24:13 UTC+10, Alan Cox wrote
I don't think we ever used FP in a graphical game. 3D stuff generally used an angle system with 256 'degrees' to a circle and page aligned look up tables for fixed point maths.

Yes fixed point and table look ups are certainly faster.

The Quake3 inspiration for the inverse square seed only came out around 1999, though credits are for earlier authors back to 1997, so there was probably no drive to use floating point in 3D or 2D graphics prior to that reference frame of SGI Indigos etc. Anyway, happy to have this available now for z80 too.

Phillip Stevens

unread,
Jul 31, 2026, 8:47:05 AM (9 days ago) Jul 31
to RC2014-Z80
In line with the extension to math32 to support Intel 8085, I've also now updated math16 to support the 8085.

Using the sccz80 (or new 80cc) compiler, it it is possible to declare variables as _Float16 or half, and then calculations will naturally happen with 16-bit floating point.

Why use 16-bit floating point? The range is greater than 16-bit fixed point in 8.8 format, as it can reach from 65504 down to 6.1x10-5 whereas fixed point is limited to maximum 255.
The performance for 16-bit IEEE754 _Float16 library math16 is between 2x and 3x that of the fastest 32-bit IEEE754, or similar Microsoft 32-bit, floating point libraries.


Cheers, Phillip

Reply all
Reply to author
Forward
0 new messages