mirror of
https://github.com/RobTillaart/Arduino.git
synced 2024-10-03 18:09:02 -04:00
0.2.5 IEEE754tools
This commit is contained in:
parent
3c8e2ae473
commit
d36c3b366f
@ -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
|
||||
|
||||
|
@ -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 --
|
||||
|
||||
|
@ -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 --
|
||||
|
||||
|
@ -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 --
|
||||
|
||||
|
@ -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 --
|
||||
|
||||
|
@ -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"
|
||||
}
|
||||
|
@ -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=*
|
||||
|
@ -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,
|
||||
|
||||
|
@ -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 --
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user