0.2.5 IEEE754tools

This commit is contained in:
Rob Tillaart 2023-11-06 15:19:19 +01:00
parent 3c8e2ae473
commit d36c3b366f
9 changed files with 120 additions and 77 deletions

View File

@ -1,4 +1,4 @@
# Change Log I2CKeyPad8x8
# Change Log IEEE754tools
All notable changes to this project will be documented in this file.
@ -6,12 +6,18 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [0.2.5] - 2023-11-06
- update readme.md
- fix CHANGELOG.md
- renamed IEEE754_VERSION to IEEE754_LIB_VERSION
- minor edits examples.
## [0.2.4] - 2022-11-12
- Add RP2040 support to build-CI.
- Add CHANGELOG.md
- minor edit unit test
## [0.2.3] - 2021-12-20
- update library.json, license, minor edits

View File

@ -2,44 +2,42 @@
//
// FILE: IEEE754tools.h
// AUTHOR: Rob Tillaart
// VERSION: 0.2.4
// VERSION: 0.2.5
// PURPOSE: manipulate IEEE754 float numbers fast
// URL: https://github.com/RobTillaart/IEEE754tools.git
//
// HISTORY: see changelog.md
//
// EXPERIMENTAL ==> USE WITH CARE
// not tested extensively,
#include "Arduino.h"
#define IEEE754_VERSION (F("0.2.4"))
#define IEEE754_LIB_VERSION (F("0.2.5"))
// (un)comment lines to configure functionality / size
//#define IEEE754_ENABLE_MSB // +78 bytes
// #define IEEE754_ENABLE_MSB // +78 bytes
// IEEE754 float layout;
// IEEE754 float layout;
struct IEEEfloat
{
uint32_t m:23;
uint32_t m:23;
uint8_t e:8;
uint8_t s:1;
};
// IEEE754 double layout;
// IEEE754 double layout;
struct IEEEdouble
{
uint64_t m:52;
uint64_t m:52;
uint16_t e:11;
uint8_t s:1;
};
// Arduino UNO double layout:
// Arduino UNO double layout:
// the UNO has no 64 bit double, it is only able to map 23 bits of the mantisse
// a filler is added for the remaining bits. These might be useful in future?
struct _DBL
@ -63,9 +61,9 @@ union _FLOATCONV
// for packing and unpacking a double
union _DBLCONV
{
// IEEEdouble p;
// IEEEdouble p;
_DBL p;
double d; // !! is a 32bit float for UNO.
double d; // !! is a 32bit float for UNO.
byte b[8];
};
@ -82,7 +80,7 @@ void dumpFloat(float number)
Serial.print(x->e, HEX);
Serial.print("\t");
Serial.println(x->m, HEX);
// Serial.print(" sign: "); Serial.print(x->s);
// Serial.print(" exp: "); Serial.print(x->e);
// Serial.print(" mant: "); Serial.println(x->m);
@ -107,7 +105,7 @@ void dumpDBL(struct _DBL dbl)
// converts a float to a packed array of 8 bytes representing a 64 bit double
// restriction exponent and mantissa.
// float; array of 8 bytes; LSBFIRST; MSBFIRST
void float2DoublePacked(float number, byte* bar, int byteOrder = LSBFIRST)
void float2DoublePacked(float number, byte* bar, int byteOrder = LSBFIRST)
{
_FLOATCONV fl;
// prevent warning/error on ESP build
@ -118,9 +116,9 @@ void float2DoublePacked(float number, byte* bar, int byteOrder = LSBFIRST)
_DBLCONV dbl;
dbl.p.filler = 0;
dbl.p.s = fl.p.s;
dbl.p.e = fl.p.e - 127 + 1023; // exponent adjust
dbl.p.e = fl.p.e - 127 + 1023; // exponent adjust
dbl.p.m = fl.p.m;
#ifdef IEEE754_ENABLE_MSB
if (byteOrder == LSBFIRST)
{
@ -149,7 +147,7 @@ float doublePacked2Float(byte* bar, int byteOrder = LSBFIRST)
{
_FLOATCONV fl;
_DBLCONV dbl;
#ifdef IEEE754_ENABLE_MSB
if (byteOrder == LSBFIRST)
{
@ -168,18 +166,18 @@ float doublePacked2Float(byte* bar, int byteOrder = LSBFIRST)
}
}
#endif
int e = dbl.p.e - 1023 + 127; // exponent adjust
// TODO check exponent overflow.
if (e >=0 || e <= 255)
int e = dbl.p.e - 1023 + 127; // e xponent adjust
// TODO check exponent overflow.
if (e >=0 || e <= 255)
{
fl.p.s = dbl.p.s;
fl.p.e = e;
fl.p.m = dbl.p.m; // note this one clips the mantisse
fl.p.e = e;
fl.p.m = dbl.p.m; // note this one clips the mantisse
return fl.f;
}
return NAN; // OR +-INF?
// return (fl.p.s) ? -INFINITY : INFINITY;
return NAN; // OR +-INF?
// return (fl.p.s) ? -INFINITY : INFINITY;
}
@ -188,15 +186,15 @@ float doublePacked2Float(byte* bar, int byteOrder = LSBFIRST)
//
// ~1.7x faster
int IEEE_NAN(float number)
int IEEE_NAN(float number)
{
uint16_t* x = ((uint16_t*) &number + 1);
return ((*x) == 0x7FC0);
return ((*x) == 0x7FC0);
}
// ~3.4x faster
int IEEE_INF(float number)
int IEEE_INF(float number)
{
uint8_t* x = ((uint8_t*) &number);
if (*(x+2) != 0x80) return 0;
@ -207,20 +205,20 @@ int IEEE_INF(float number)
// for the real speed freaks, the next
boolean IEEE_PosINF(float number)
boolean IEEE_PosINF(float number)
{
return (* ((uint16_t*) &number + 1) ) == 0x7F80;
return (* ((uint16_t*) &number + 1) ) == 0x7F80;
}
boolean IEEE_NegINF(float number)
boolean IEEE_NegINF(float number)
{
return (* ((uint16_t*) &number + 1) ) == 0xFF80;
return (* ((uint16_t*) &number + 1) ) == 0xFF80;
}
//
// PROPERTIES
//
//
uint8_t IEEE_Sign(float number)
{
IEEEfloat* x = (IEEEfloat*) ((void*)&number);
@ -293,7 +291,7 @@ bool IEEE_FLOAT_EQ(float &f, float &g)
{
uint16_t *p = (uint16_t *) &f;
uint16_t *q = (uint16_t *) &g;
return (*p++ == *q++) && (*p++ == *q++);
}
@ -315,12 +313,12 @@ bool IEEE_FLOAT_NEQ(float &f, float &g)
//
// get truncated part as separate float.
//
//
void doublePacked2Float2(byte* bar, int byteOrder, float* value, float* error)
{
_FLOATCONV fl;
_DBLCONV dbl;
#ifdef IEEE754_ENABLE_MSB
if (byteOrder == LSBFIRST)
{
@ -339,19 +337,19 @@ void doublePacked2Float2(byte* bar, int byteOrder, float* value, float* error)
}
}
#endif
int e = dbl.p.e - 1023 + 127; // exponent adjust
// TODO check exponent overflow.
if (e >=0 || e <= 255)
int e = dbl.p.e - 1023 + 127; // exponent adjust
// TODO check exponent overflow.
if (e >=0 || e <= 255)
{
fl.p.s = dbl.p.s;
fl.p.e = e;
fl.p.m = dbl.p.m; // note this one clips the mantisse
fl.p.e = e;
fl.p.m = dbl.p.m; // note this one clips the mantisse
*value = fl.f;
fl.p.s = dbl.p.s;
fl.p.e = e-23;
fl.p.m = dbl.p.filler; // note this one clips the mantisse
fl.p.e = e-23;
fl.p.m = dbl.p.filler; // note this one clips the mantisse
*error = fl.f;
}
*value = (dbl.p.s) ? -INFINITY : INFINITY;
@ -372,7 +370,7 @@ float IEEE_FLIP(float number)
/*
// ONELINERS to speed up some specific 32 bit float math
// ONELINERS to speed up some specific 32 bit float math
// *(((byte*) &number)+3) &= 0x7F; // number == fabs(number);
// x = *(((byte*) &number)+3) & 0x7F; // x = fabs(number);
@ -394,11 +392,11 @@ float IEEE_FLIP(float number)
// GAIN = factor 5
// no speed optimize found for
// no speed optimize found for
boolean IEEE_ZERO(float number)
{
return (* ((uint32_t*) &number) ) & 0x7FFFFFFF;
return (* ((uint32_t*) &number) ) & 0x7FFFFFFF;
}
@ -425,5 +423,5 @@ bool IEEE_FLOAT_EQ(float &f, float &g)
// -- END OF FILE --
// -- END OF FILE --

View File

@ -2,8 +2,8 @@
// FILE: FastNegate.ino
// AUTHOR: Rob dot Tillaart at gmail dot com
// PURPOSE: Fast negate for floating points
//
#include "IEEE754tools.h"
volatile float zz = 100;
volatile int x = 3;
@ -14,7 +14,10 @@ uint32_t start, duration1, duration2;
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.println(__FILE__);
Serial.print("IEEE754_LIB_VERSION: ");
Serial.println(IEEE754_LIB_VERSION);
Serial.println();
test_negfabs();
@ -32,7 +35,7 @@ void test_negfabs()
start = micros();
for (int i = 0; i < 30000; i++)
{
*(((byte*) &zz) + 3) |= 0x80; // Force negative == -fabs(zz);
*(((byte*) &zz) + 3) |= 0x80; // Force negative == -fabs(zz);
}
duration1 = micros() - start;
Serial.print("TIME : ");
@ -66,7 +69,7 @@ void test_fabs()
start = micros();
for (int i = 0; i < 30000; i++)
{
*(((byte*) &zz) + 3) &= 0x7F; // force positive == fabs(zz);
*(((byte*) &zz) + 3) &= 0x7F; // force positive == fabs(zz);
}
duration1 = micros() - start;
Serial.print("TIME : ");
@ -131,7 +134,7 @@ void test_less_zero()
start = micros();
for (int i = 0; i < 30000; i++)
{
if ( *(((byte*) &zz) + 3) & 0x80) x = 2; // equals if (zz < 0);
if ( *(((byte*) &zz) + 3) & 0x80) x = 2; // equals if (zz < 0);
}
duration1 = micros() - start;
Serial.print("TIME : ");
@ -188,5 +191,5 @@ void loop()
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -17,7 +17,11 @@ volatile bool b;
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.println(__FILE__);
Serial.print("IEEE754_LIB_VERSION: ");
Serial.println(IEEE754_LIB_VERSION);
Serial.println();
test_FLOAT_EQ_1();
test_FLOAT_EQ_2();
@ -186,5 +190,5 @@ void test_POW2()
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -16,6 +16,11 @@ byte x[8];
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.println(__FILE__);
Serial.print("IEEE754_LIB_VERSION: ");
Serial.println(IEEE754_LIB_VERSION);
Serial.println();
test1();
test2();
@ -49,9 +54,9 @@ void test2()
Serial.println(__FUNCTION__);
Serial.println("\n0.15625");
dumpFloat(0.15625);
// sign = 0
// exponent = 7C
// mantissa = 0020 0000
// sign = 0
// exponent = 7C
// mantissa = 0020 0000
}
@ -79,7 +84,7 @@ void test4()
float2DoublePacked(1.23456789e38, x);
dumpByteArray(x);
float f = doublePacked2Float(x, LSBFIRST);
Serial.println(f / 1e38, 20); // divide prevents ovf in output
Serial.println(f / 1e38, 20); // divide prevents overflow (ovf) in output
dumpFloat(f);
Serial.println();
}
@ -102,5 +107,5 @@ void dumpByteArray(byte *ar)
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -15,9 +15,9 @@
"type": "git",
"url": "https://github.com/RobTillaart/IEEE754tools.git"
},
"version": "0.2.4",
"version": "0.2.5",
"license": "MIT",
"frameworks": "arduino",
"frameworks": "*",
"platforms": "*",
"headers": "IEEE754tools.h"
}

View File

@ -1,9 +1,9 @@
name=IEEE754tools
version=0.2.4
version=0.2.5
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Fast helper functions for IEEE754 floats.
paragraph=
paragraph=
category=Data Processing
url=https://github.com/RobTillaart/IEEE754tools
architectures=*

View File

@ -2,8 +2,11 @@
[![Arduino CI](https://github.com/RobTillaart/IEEE754tools/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci)
[![Arduino-lint](https://github.com/RobTillaart/IEEE754tools/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/IEEE754tools/actions/workflows/arduino-lint.yml)
[![JSON check](https://github.com/RobTillaart/IEEE754tools/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/IEEE754tools/actions/workflows/jsoncheck.yml)
[![GitHub issues](https://img.shields.io/github/issues/RobTillaart/IEEE754tools.svg)](https://github.com/RobTillaart/IEEE754tools/issues)
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/IEEE754tools/blob/master/LICENSE)
[![GitHub release](https://img.shields.io/github/release/RobTillaart/IEEE754tools.svg?maxAge=3600)](https://github.com/RobTillaart/IEEE754tools/releases)
[![PlatformIO Registry](https://badges.registry.platformio.org/packages/robtillaart/library/IEEE754tools.svg)](https://registry.platformio.org/libraries/robtillaart/IEEE754tools)
# IEEE754tools
@ -17,9 +20,12 @@ IEEE754tools.h contains a collection of experimental bit-hacks to speed up
a number of operations on floating point numbers on the **Arduino UNO**.
These bit-hacks started in 2010 (oldest code found), maybe even earlier.
http://en.wikipedia.org/wiki/Double_precision
http://en.wikipedia.org/wiki/Single-precision_floating-point_format
#### Related
- http://en.wikipedia.org/wiki/Double_precision
- http://en.wikipedia.org/wiki/Single-precision_floating-point_format
- https://github.com/RobTillaart/float16
## WARNING
@ -45,6 +51,13 @@ ESP32 - needs investigation as UNO verified code fails.
(something for a long winter)
## Interface
```cpp
#include "IEEE754tools.h"
```
## Operations
See examples
@ -52,19 +65,31 @@ See examples
## Future
#### must
#### Must
- improve documentation
- test with double
- test on ESP23
#### should
- investigate other speed ups
- bring more structure in this library.
#### Should
- investigate other speed ups
- bring more structure in this library
#### Could
#### could
- write more examples
- example binary transfer over Serial
- example binary transfer over Ethernet
- link to float16 in documentation
#### Wont
## Support
If you appreciate my libraries, you can support the development and maintenance.
Improve the quality of the libraries by providing issues and Pull Requests, or
donate through PayPal or GitHub sponsors.
Thank you,

View File

@ -39,7 +39,7 @@
unittest_setup()
{
fprintf(stderr, "IEEE754_VERSION: %s\n", (char*) IEEE754_VERSION);
fprintf(stderr, "IEEE754_LIB_VERSION: %s\n", (char*) IEEE754_LIB_VERSION);
}
@ -58,7 +58,7 @@ unittest(test_all)
assertEqualFloat(p, q, 0.0001);
fprintf(stderr, "IEEE_NAN %f\n", 0.0 / 0.0);
// assertTrue(IEEE_NAN(0.0 / 0.0)); // -nan ?
// assertTrue(IEEE_NAN(0.0 / 0.0)); // -nan ?
fprintf(stderr, "IEEE_INF\n");
assertEqual(1, IEEE_INF(exp(800)));
@ -106,4 +106,6 @@ unittest(test_all)
unittest_main()
// --------
// -- END OF FILE --