mirror of
https://github.com/RobTillaart/Arduino.git
synced 2024-09-19 16:46:11 -04:00
0.1.0 float16ext
This commit is contained in:
parent
917571e880
commit
55152137f2
30
libraries/float16ext/.arduino-ci.yml
Normal file
30
libraries/float16ext/.arduino-ci.yml
Normal file
@ -0,0 +1,30 @@
|
||||
platforms:
|
||||
rpipico:
|
||||
board: rp2040:rp2040:rpipico
|
||||
package: rp2040:rp2040
|
||||
gcc:
|
||||
features:
|
||||
defines:
|
||||
- ARDUINO_ARCH_RP2040
|
||||
warnings:
|
||||
flags:
|
||||
|
||||
packages:
|
||||
rp2040:rp2040:
|
||||
url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
|
||||
|
||||
compile:
|
||||
# Choosing to run compilation tests on 2 different Arduino platforms
|
||||
platforms:
|
||||
- uno
|
||||
# - due
|
||||
# - zero
|
||||
# - leonardo
|
||||
- m4
|
||||
- esp32
|
||||
# - esp8266
|
||||
# - mega2560
|
||||
- rpipico
|
||||
|
||||
libraries:
|
||||
- "printHelpers"
|
4
libraries/float16ext/.github/FUNDING.yml
vendored
Normal file
4
libraries/float16ext/.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: RobTillaart
|
||||
|
13
libraries/float16ext/.github/workflows/arduino-lint.yml
vendored
Normal file
13
libraries/float16ext/.github/workflows/arduino-lint.yml
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
|
||||
name: Arduino-lint
|
||||
|
||||
on: [push, pull_request]
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: arduino/arduino-lint-action@v1
|
||||
with:
|
||||
library-manager: update
|
||||
compliance: strict
|
17
libraries/float16ext/.github/workflows/arduino_test_runner.yml
vendored
Normal file
17
libraries/float16ext/.github/workflows/arduino_test_runner.yml
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
---
|
||||
name: Arduino CI
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
runTest:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: 2.6
|
||||
- run: |
|
||||
gem install arduino_ci
|
||||
arduino_ci.rb
|
18
libraries/float16ext/.github/workflows/jsoncheck.yml
vendored
Normal file
18
libraries/float16ext/.github/workflows/jsoncheck.yml
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
name: JSON check
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- '**.json'
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: json-syntax-check
|
||||
uses: limitusus/json-syntax-check@v1
|
||||
with:
|
||||
pattern: "\\.json$"
|
||||
|
11
libraries/float16ext/CHANGELOG.md
Normal file
11
libraries/float16ext/CHANGELOG.md
Normal file
@ -0,0 +1,11 @@
|
||||
# Change Log Float16ext
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
||||
and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
|
||||
## [0.1.0] - 2024-03-06
|
||||
- initial version based upon float16
|
||||
|
21
libraries/float16ext/LICENSE
Normal file
21
libraries/float16ext/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024-2024 Rob Tillaart
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
156
libraries/float16ext/README.md
Normal file
156
libraries/float16ext/README.md
Normal file
@ -0,0 +1,156 @@
|
||||
|
||||
[![Arduino CI](https://github.com/RobTillaart/float16ext/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci)
|
||||
[![Arduino-lint](https://github.com/RobTillaart/float16ext/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/float16ext/actions/workflows/arduino-lint.yml)
|
||||
[![JSON check](https://github.com/RobTillaart/float16ext/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/float16ext/actions/workflows/jsoncheck.yml)
|
||||
[![GitHub issues](https://img.shields.io/github/issues/RobTillaart/float16ext.svg)](https://github.com/RobTillaart/float16ext/issues)
|
||||
|
||||
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/float16ext/blob/master/LICENSE)
|
||||
[![GitHub release](https://img.shields.io/github/release/RobTillaart/float16ext.svg?maxAge=3600)](https://github.com/RobTillaart/float16ext/releases)
|
||||
[![PlatformIO Registry](https://badges.registry.platformio.org/packages/robtillaart/library/float16ext.svg)](https://registry.platformio.org/libraries/robtillaart/float16ext)
|
||||
|
||||
# float16ext
|
||||
|
||||
Arduino library to implement float16ext data type.
|
||||
|
||||
|
||||
## Description
|
||||
|
||||
This **experimental** library defines the float16ext (2 byte) data type, including conversion
|
||||
function to and from float32 type. It is an extension to the float16 library.
|
||||
Reference -https://en.wikipedia.org/wiki/Half-precision_floating-point_format#ARM_alternative_half-precision
|
||||
|
||||
The library implements the **Printable** interface so one can directly print the
|
||||
float16ext values in any stream e.g. Serial.
|
||||
|
||||
The primary usage of the float16ext data type is to efficiently store and transport
|
||||
a floating point number. As it uses only 2 bytes where float and double have typical
|
||||
4 and 8 bytes, gains can be made at the price of range and precision.
|
||||
|
||||
Note that float16ext only has ~3 significant digits.
|
||||
|
||||
|
||||
#### Difference with float16
|
||||
|
||||
The float16ext library has an extended range as it supports values from +- 65504
|
||||
to +- 131008.
|
||||
|
||||
The float16ext does not support INF, -INF and NAN. These values are mapped upon
|
||||
the largest positive, the largest negative and the largest positive number.
|
||||
|
||||
The -0 and 0 values will both exist.
|
||||
|
||||
|
||||
Although they share a lot of code float16 and float16ext should not be mixed.
|
||||
In the future these libraries might merge / derive one from the other.
|
||||
|
||||
|
||||
## Specifications
|
||||
|
||||
layout is same as float16.
|
||||
|
||||
| attribute | value | notes |
|
||||
|:----------|:-------------|:--------|
|
||||
| size | 2 bytes | layout s eeeee mmmmmmmmmm (1, 5, 10)
|
||||
| sign | 1 bit |
|
||||
| exponent | 5 bit |
|
||||
| mantissa | 10 bit | ~ 3 digits
|
||||
| minimum | 5.96046 E−8 | smallest positive number.
|
||||
| | 1.0009765625 | 1 + 2^−10 = smallest number larger than 1.
|
||||
| maximum | 131008 |
|
||||
| | |
|
||||
|
||||
|
||||
#### Related
|
||||
|
||||
- https://github.com/RobTillaart/float16
|
||||
- https://en.wikipedia.org/wiki/Half-precision_floating-point_format
|
||||
|
||||
|
||||
## Interface
|
||||
|
||||
```cpp
|
||||
#include "float16ext.h"
|
||||
```
|
||||
|
||||
#### Constructors
|
||||
|
||||
- **float16ext(void)** defaults to zero.
|
||||
- **float16ext(double f)** constructor.
|
||||
- **float16ext(const float16ext &f)** copy constructor.
|
||||
|
||||
|
||||
#### Conversion
|
||||
|
||||
- **double toDouble(void)** convert to double (or float).
|
||||
- **uint16_t getBinary()** get the 2 byte binary representation.
|
||||
- **void setBinary(uint16_t u)** set the 2 bytes binary representation.
|
||||
- **size_t printTo(Print& p) const** Printable interface.
|
||||
- **void setDecimals(uint8_t d)** idem, used for printTo.
|
||||
- **uint8_t getDecimals()** idem.
|
||||
|
||||
Note the setDecimals takes one byte per object which is not efficient for arrays of float16ext.
|
||||
See array example for efficient storage using set/getBinary() functions.
|
||||
|
||||
|
||||
#### Compare
|
||||
|
||||
Standard compare functions. Since 0.1.5 these are quite optimized,
|
||||
so it is fast to compare e.g. 2 measurements.
|
||||
|
||||
- **bool operator == (const float16ext& f)**
|
||||
- **bool operator != (const float16ext& f)**
|
||||
- **bool operator > (const float16ext& f)**
|
||||
- **bool operator >= (const float16ext& f)**
|
||||
- **bool operator < (const float16ext& f)**
|
||||
- **bool operator <= (const float16ext& f)**
|
||||
|
||||
|
||||
#### Math (basic)
|
||||
|
||||
Math is done by converting to double, do the math and convert back.
|
||||
These operators are added for convenience only.
|
||||
Not planned to optimize these.
|
||||
|
||||
- **float16ext operator + (const float16ext& f)**
|
||||
- **float16ext operator - (const float16ext& f)**
|
||||
- **float16ext operator \* (const float16ext& f)**
|
||||
- **float16ext operator / (const float16ext& f)**
|
||||
- **float16ext& operator += (const float16ext& f)**
|
||||
- **float16ext& operator -= (const float16ext& f)**
|
||||
- **float16ext& operator \*= (const float16ext& f)**
|
||||
- **float16ext& operator /= (const float16ext& f)**
|
||||
|
||||
negation operator.
|
||||
- **float16ext operator - ()** fast negation.
|
||||
|
||||
- **int sign()** returns 1 == positive, 0 == zero, -1 == negative.
|
||||
- **bool isZero()** returns true if zero. slightly faster than **sign()**.
|
||||
|
||||
|
||||
## Notes
|
||||
|
||||
|
||||
## Future
|
||||
|
||||
#### Must
|
||||
|
||||
- update documentation.
|
||||
- keep in sync with float16 lib
|
||||
|
||||
#### Should
|
||||
|
||||
|
||||
#### Could
|
||||
|
||||
|
||||
#### 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,
|
||||
|
@ -0,0 +1,30 @@
|
||||
platforms:
|
||||
rpipico:
|
||||
board: rp2040:rp2040:rpipico
|
||||
package: rp2040:rp2040
|
||||
gcc:
|
||||
features:
|
||||
defines:
|
||||
- ARDUINO_ARCH_RP2040
|
||||
warnings:
|
||||
flags:
|
||||
|
||||
packages:
|
||||
rp2040:rp2040:
|
||||
url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
|
||||
|
||||
compile:
|
||||
# Choosing to run compilation tests on 2 different Arduino platforms
|
||||
platforms:
|
||||
- uno
|
||||
# - due
|
||||
# - zero
|
||||
# - leonardo
|
||||
- m4
|
||||
- esp32
|
||||
# - esp8266
|
||||
# - mega2560
|
||||
- rpipico
|
||||
|
||||
libraries:
|
||||
- "printHelpers"
|
@ -0,0 +1,51 @@
|
||||
//
|
||||
// FILE: float16ext_plotter.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: test float16ext
|
||||
// URL: https://github.com/RobTillaart/float16ext
|
||||
|
||||
|
||||
#include "float16ext.h"
|
||||
|
||||
|
||||
float16ext f16;
|
||||
|
||||
void setup()
|
||||
{
|
||||
delay(500);
|
||||
Serial.begin(115200);
|
||||
while (!Serial) delay(1);
|
||||
|
||||
// Serial.println();
|
||||
// Serial.println(__FILE__);
|
||||
// Serial.print("FLOAT16EXT_LIB_VERSION: ");
|
||||
// Serial.println(FLOAT16EXT_LIB_VERSION);
|
||||
|
||||
f16.setDecimals(10);
|
||||
|
||||
print_all();
|
||||
|
||||
Serial.println("\ndone");
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void print_all()
|
||||
{
|
||||
Serial.println("X\tF(X)");
|
||||
// plot numbers to fit into serial plotter
|
||||
for (uint32_t x = 0x0000; x <= 0xFFFF; x += 128)
|
||||
{
|
||||
f16.setBinary(x);
|
||||
Serial.print(x);
|
||||
Serial.print("\t");
|
||||
Serial.print(f16);
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
@ -0,0 +1,30 @@
|
||||
platforms:
|
||||
rpipico:
|
||||
board: rp2040:rp2040:rpipico
|
||||
package: rp2040:rp2040
|
||||
gcc:
|
||||
features:
|
||||
defines:
|
||||
- ARDUINO_ARCH_RP2040
|
||||
warnings:
|
||||
flags:
|
||||
|
||||
packages:
|
||||
rp2040:rp2040:
|
||||
url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
|
||||
|
||||
compile:
|
||||
# Choosing to run compilation tests on 2 different Arduino platforms
|
||||
platforms:
|
||||
- uno
|
||||
# - due
|
||||
# - zero
|
||||
# - leonardo
|
||||
- m4
|
||||
- esp32
|
||||
# - esp8266
|
||||
# - mega2560
|
||||
- rpipico
|
||||
|
||||
libraries:
|
||||
- "printHelpers"
|
@ -0,0 +1,67 @@
|
||||
//
|
||||
// FILE: float16ext_print_all.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: test float16ext
|
||||
// URL: https://github.com/RobTillaart/float16ext
|
||||
|
||||
|
||||
#include "float16ext.h"
|
||||
|
||||
|
||||
float16ext f16;
|
||||
|
||||
void setup()
|
||||
{
|
||||
delay(500);
|
||||
Serial.begin(115200);
|
||||
while (!Serial) delay(1);
|
||||
|
||||
Serial.println();
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("FLOAT16EXT_LIB_VERSION: ");
|
||||
Serial.println(FLOAT16EXT_LIB_VERSION);
|
||||
|
||||
f16.setDecimals(10);
|
||||
|
||||
print_all();
|
||||
|
||||
Serial.println("\ndone");
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void print_all()
|
||||
{
|
||||
Serial.println(__FUNCTION__);
|
||||
|
||||
// test all positive patterns
|
||||
// test both the conversion to and from float.
|
||||
for (uint32_t x = 0x0000; x <= 0x7FFF; x++)
|
||||
{
|
||||
f16.setBinary(x);
|
||||
Serial.print(x);
|
||||
Serial.print("\t");
|
||||
Serial.print(f16.toDouble(), 10);
|
||||
Serial.print("\t");
|
||||
Serial.print(f16);
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
// test all negative patterns
|
||||
for (uint32_t x = 0x8000; x <= 0xFFFF; x++)
|
||||
{
|
||||
f16.setBinary(x);
|
||||
Serial.print(x);
|
||||
Serial.print("\t");
|
||||
Serial.print(f16.toDouble(), 10);
|
||||
Serial.print("\t");
|
||||
Serial.print(f16);
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
@ -0,0 +1,30 @@
|
||||
platforms:
|
||||
rpipico:
|
||||
board: rp2040:rp2040:rpipico
|
||||
package: rp2040:rp2040
|
||||
gcc:
|
||||
features:
|
||||
defines:
|
||||
- ARDUINO_ARCH_RP2040
|
||||
warnings:
|
||||
flags:
|
||||
|
||||
packages:
|
||||
rp2040:rp2040:
|
||||
url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
|
||||
|
||||
compile:
|
||||
# Choosing to run compilation tests on 2 different Arduino platforms
|
||||
platforms:
|
||||
- uno
|
||||
# - due
|
||||
# - zero
|
||||
# - leonardo
|
||||
- m4
|
||||
- esp32
|
||||
# - esp8266
|
||||
# - mega2560
|
||||
- rpipico
|
||||
|
||||
libraries:
|
||||
- "printHelpers"
|
@ -0,0 +1,62 @@
|
||||
//
|
||||
// FILE: float16ext_print_all_sci.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: test float16ext
|
||||
// URL: https://github.com/RobTillaart/float16ext
|
||||
|
||||
|
||||
#include "float16ext.h"
|
||||
#include "printHelpers.h" // for scientific notation
|
||||
|
||||
|
||||
float16ext f16, f17;
|
||||
|
||||
void setup()
|
||||
{
|
||||
delay(500);
|
||||
Serial.begin(115200);
|
||||
while (!Serial) delay(1);
|
||||
|
||||
Serial.println();
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("FLOAT16EXT_LIB_VERSION: ");
|
||||
Serial.println(FLOAT16EXT_LIB_VERSION);
|
||||
|
||||
print_all();
|
||||
|
||||
Serial.println("\ndone");
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void print_all()
|
||||
{
|
||||
Serial.println(__FUNCTION__);
|
||||
|
||||
// test all positive patterns
|
||||
// test both the conversion to and from float.
|
||||
for (uint32_t x = 0x0000; x <= 0x7FFF; x++)
|
||||
{
|
||||
f16.setBinary(x);
|
||||
Serial.print(x);
|
||||
Serial.print("\t");
|
||||
Serial.print(sci(f16.toDouble(), 4));
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
// test all negative patterns
|
||||
for (uint32_t x = 0x8000; x <= 0xFFFF; x++)
|
||||
{
|
||||
f16.setBinary(x);
|
||||
Serial.print(x);
|
||||
Serial.print("\t");
|
||||
Serial.print(sci(f16.toDouble(), 4));
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
|
||||
// -- END OF FILE --
|
@ -0,0 +1,86 @@
|
||||
//
|
||||
// FILE: float16ext_test_all_2.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: test float16ext
|
||||
// URL: https://github.com/RobTillaart/float16ext
|
||||
|
||||
|
||||
#include "float16ext.h"
|
||||
|
||||
|
||||
float16ext f16, f17;
|
||||
|
||||
void setup()
|
||||
{
|
||||
delay(500);
|
||||
Serial.begin(115200);
|
||||
while (!Serial) delay(1);
|
||||
|
||||
Serial.println();
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("FLOAT16EXT_LIB_VERSION: ");
|
||||
Serial.println(FLOAT16EXT_LIB_VERSION);
|
||||
|
||||
f16.setDecimals(6);
|
||||
|
||||
test_all();
|
||||
|
||||
Serial.println("\ndone");
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void test_all()
|
||||
{
|
||||
Serial.println(__FUNCTION__);
|
||||
|
||||
// test all positive patterns
|
||||
// test both the conversion to and from float.
|
||||
for (uint32_t x = 0x0000; x <= 0x7FFF; x++)
|
||||
{
|
||||
f16.setBinary(x);
|
||||
f17 = f16.toDouble();
|
||||
|
||||
// internal format should be equal. Except for -0 and 0.
|
||||
if (x - f17.getBinary() != 0)
|
||||
{
|
||||
Serial.print(f16.toDouble(), 10);
|
||||
Serial.print("\t");
|
||||
Serial.print(f16.getBinary(), HEX);
|
||||
Serial.print("\t");
|
||||
Serial.print(f17.getBinary(), HEX);
|
||||
Serial.print("\t");
|
||||
Serial.print(x - f17.getBinary(), HEX);
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
|
||||
// test all negative patterns
|
||||
for (uint32_t x = 0x8000; x <= 0xFFFF; x++)
|
||||
{
|
||||
f16.setBinary(x);
|
||||
f17 = f16.toDouble();
|
||||
|
||||
if (x - f17.getBinary() != 0)
|
||||
{
|
||||
Serial.print(f16.toDouble(), 10);
|
||||
Serial.print("\t");
|
||||
Serial.print(f16.getBinary(), HEX);
|
||||
Serial.print("\t");
|
||||
Serial.print(f17.getBinary(), HEX);
|
||||
Serial.print("\t");
|
||||
Serial.print(x - f17.getBinary(), HEX);
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
280
libraries/float16ext/float16ext.cpp
Normal file
280
libraries/float16ext/float16ext.cpp
Normal file
@ -0,0 +1,280 @@
|
||||
//
|
||||
// FILE: float16ext.cpp
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.0
|
||||
// PURPOSE: library for Float16s for Arduino
|
||||
// URL: http://en.wikipedia.org/wiki/Half-precision_floating-point_format
|
||||
|
||||
|
||||
#include "float16ext.h"
|
||||
|
||||
|
||||
// CONSTRUCTOR
|
||||
float16ext::float16ext(double f)
|
||||
{
|
||||
_value = f32tof16(f);
|
||||
}
|
||||
|
||||
// PRINTING
|
||||
size_t float16ext::printTo(Print& p) const
|
||||
{
|
||||
double d = this->f16tof32(_value);
|
||||
return p.print(d, _decimals);
|
||||
}
|
||||
|
||||
double float16ext::toDouble() const
|
||||
{
|
||||
return f16tof32(_value);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
//
|
||||
// EQUALITIES
|
||||
//
|
||||
bool float16ext::operator == (const float16ext &f)
|
||||
{
|
||||
return (_value == f._value);
|
||||
}
|
||||
|
||||
bool float16ext::operator != (const float16ext &f)
|
||||
{
|
||||
return (_value != f._value);
|
||||
}
|
||||
|
||||
bool float16ext::operator > (const float16ext &f)
|
||||
{
|
||||
if ((_value & 0x8000) && ( f._value & 0x8000)) return _value < f._value;
|
||||
if (_value & 0x8000) return false;
|
||||
if (f._value & 0x8000) return true;
|
||||
return _value > f._value;
|
||||
}
|
||||
|
||||
bool float16ext::operator >= (const float16ext &f)
|
||||
{
|
||||
if ((_value & 0x8000) && (f._value & 0x8000)) return _value <= f._value;
|
||||
if (_value & 0x8000) return false;
|
||||
if (f._value & 0x8000) return true;
|
||||
return _value >= f._value;
|
||||
}
|
||||
|
||||
bool float16ext::operator < (const float16ext &f)
|
||||
{
|
||||
if ((_value & 0x8000) && (f._value & 0x8000)) return _value > f._value;
|
||||
if (_value & 0x8000) return true;
|
||||
if (f._value & 0x8000) return false;
|
||||
return _value < f._value;
|
||||
}
|
||||
|
||||
bool float16ext::operator <= (const float16ext &f)
|
||||
{
|
||||
if ((_value & 0x8000) && (f._value & 0x8000)) return _value >= f._value;
|
||||
if (_value & 0x8000) return true;
|
||||
if (f._value & 0x8000) return false;
|
||||
return _value <= f._value;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
//
|
||||
// NEGATION
|
||||
//
|
||||
float16ext float16ext::operator - ()
|
||||
{
|
||||
float16ext f16;
|
||||
f16.setBinary(_value ^ 0x8000);
|
||||
return f16;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
//
|
||||
// MATH
|
||||
//
|
||||
float16ext float16ext::operator + (const float16ext &f)
|
||||
{
|
||||
return float16ext(this->toDouble() + f.toDouble());
|
||||
}
|
||||
|
||||
float16ext float16ext::operator - (const float16ext &f)
|
||||
{
|
||||
return float16ext(this->toDouble() - f.toDouble());
|
||||
}
|
||||
|
||||
float16ext float16ext::operator * (const float16ext &f)
|
||||
{
|
||||
return float16ext(this->toDouble() * f.toDouble());
|
||||
}
|
||||
|
||||
float16ext float16ext::operator / (const float16ext &f)
|
||||
{
|
||||
return float16ext(this->toDouble() / f.toDouble());
|
||||
}
|
||||
|
||||
float16ext& float16ext::operator += (const float16ext &f)
|
||||
{
|
||||
*this = this->toDouble() + f.toDouble();
|
||||
return *this;
|
||||
}
|
||||
|
||||
float16ext& float16ext::operator -= (const float16ext &f)
|
||||
{
|
||||
*this = this->toDouble() - f.toDouble();
|
||||
return *this;
|
||||
}
|
||||
|
||||
float16ext& float16ext::operator *= (const float16ext &f)
|
||||
{
|
||||
*this = this->toDouble() * f.toDouble();
|
||||
return *this;
|
||||
}
|
||||
|
||||
float16ext& float16ext::operator /= (const float16ext &f)
|
||||
{
|
||||
*this = this->toDouble() / f.toDouble();
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
//
|
||||
// MATH HELPER FUNCTIONS
|
||||
//
|
||||
int float16ext::sign()
|
||||
{
|
||||
if (_value & 0x8000) return -1;
|
||||
if (_value & 0xFFFF) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool float16ext::isZero()
|
||||
{
|
||||
return ((_value & 0x7FFF) == 0x0000);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
//
|
||||
// CORE CONVERSION
|
||||
//
|
||||
float float16ext::f16tof32(uint16_t _value) const
|
||||
{
|
||||
uint16_t sgn, man;
|
||||
int exp;
|
||||
double f;
|
||||
|
||||
sgn = (_value & 0x8000) > 0;
|
||||
exp = (_value & 0x7C00) >> 10;
|
||||
man = (_value & 0x03FF);
|
||||
|
||||
// ZERO
|
||||
if ((_value & 0x7FFF) == 0)
|
||||
{
|
||||
return sgn ? -0 : 0;
|
||||
}
|
||||
// NAN & INF
|
||||
// if (exp == 0x001F)
|
||||
// {
|
||||
// if (man == 0) return sgn ? -INFINITY : INFINITY;
|
||||
// else return NAN;
|
||||
// }
|
||||
|
||||
// NORMAL
|
||||
if (exp > 0)
|
||||
{
|
||||
f = pow(2.0, exp - 15) * (1 + man * 0.0009765625);
|
||||
return sgn ? -f : f;
|
||||
}
|
||||
// SUBNORMAL
|
||||
// exp == 0;
|
||||
f = pow(2.0, -24) * man;
|
||||
return sgn ? -f : f;
|
||||
}
|
||||
|
||||
|
||||
uint16_t float16ext::f32tof16(float f) const
|
||||
{
|
||||
uint32_t t = *(uint32_t *) &f;
|
||||
// man bits = 10; but we keep 11 for rounding
|
||||
uint16_t man = (t & 0x007FFFFF) >> 12;
|
||||
int16_t exp = (t & 0x7F800000) >> 23;
|
||||
bool sgn = (t & 0x80000000);
|
||||
|
||||
// Serial.print("BEFOR:\t ");
|
||||
// Serial.print(sgn, HEX);
|
||||
// Serial.print(" ");
|
||||
// Serial.print(man, HEX);
|
||||
// Serial.print(" ");
|
||||
// Serial.println(exp, HEX);
|
||||
|
||||
// handle 0
|
||||
if ((t & 0x7FFFFFFF) == 0)
|
||||
{
|
||||
return sgn ? 0x8000 : 0x0000;
|
||||
}
|
||||
|
||||
// denormalized float32 does not fit in float16ext
|
||||
if (exp == 0x00)
|
||||
{
|
||||
return sgn ? 0x8000 : 0x0000;
|
||||
}
|
||||
|
||||
// handle INF and NAN == infinity and not a number
|
||||
// map these to most positive and most negative numbers.
|
||||
if (exp == 0x00FF)
|
||||
{
|
||||
if (man) return 0x7FFF; // sort of NAN
|
||||
return sgn ? 0xFFFF : 0x7FFF; // sort of -INF : INF
|
||||
}
|
||||
|
||||
// rescale exponent
|
||||
exp = exp - 127 + 15;
|
||||
|
||||
// overflow does not fit => INF (infinity)
|
||||
if (exp > 31)
|
||||
{
|
||||
return sgn ? 0xFFFF : 0x7FFF; // sort of -INF : INF
|
||||
}
|
||||
|
||||
// subnormal numbers out of range => 0.
|
||||
if (exp < -9)
|
||||
{
|
||||
return sgn ? 0x8000 : 0x0000; // -0 or 0 ? just 0 ?
|
||||
}
|
||||
|
||||
// subnormal numbers
|
||||
if (exp <= 0)
|
||||
{
|
||||
exp = 0;
|
||||
man = abs(f) * 16777216; // pow(2.0, 24);
|
||||
if (sgn) return 0x8000 | man;
|
||||
return man;
|
||||
}
|
||||
|
||||
|
||||
// normal numbers
|
||||
// rounding
|
||||
man++;
|
||||
man >>= 1;
|
||||
// correction mantissa overflow issue #10 float16
|
||||
if (man == 0x0400)
|
||||
{
|
||||
exp++;
|
||||
man = 0;
|
||||
}
|
||||
exp <<= 10;
|
||||
|
||||
// Serial.print("AFTER:\t ");
|
||||
// Serial.print(sgn, HEX);
|
||||
// Serial.print(" ");
|
||||
// Serial.print(man, HEX);
|
||||
// Serial.print(" ");
|
||||
// Serial.println(exp, HEX);
|
||||
|
||||
if (sgn) return 0x8000 | exp | man;
|
||||
return exp | man;
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
|
78
libraries/float16ext/float16ext.h
Normal file
78
libraries/float16ext/float16ext.h
Normal file
@ -0,0 +1,78 @@
|
||||
#pragma once
|
||||
//
|
||||
// FILE: float16ext.h
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.0
|
||||
// PURPOSE: Arduino library to implement float16ext data type.
|
||||
// half-precision floating point format,
|
||||
// used for efficient storage and transport.
|
||||
// URL: https://github.com/RobTillaart/float16ext
|
||||
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
#define FLOAT16EXT_LIB_VERSION (F("0.1.0"))
|
||||
|
||||
|
||||
class float16ext: public Printable
|
||||
{
|
||||
public:
|
||||
// Constructors
|
||||
float16ext(void) { _value = 0x0000; };
|
||||
float16ext(double f);
|
||||
float16ext(const float16ext &f) { _value = f._value; };
|
||||
|
||||
// Conversion
|
||||
double toDouble(void) const;
|
||||
// access the 2 byte representation.
|
||||
uint16_t getBinary() { return _value; };
|
||||
void setBinary(uint16_t u) { _value = u; };
|
||||
|
||||
// Printable
|
||||
size_t printTo(Print& p) const;
|
||||
void setDecimals(uint8_t d) { _decimals = d; };
|
||||
uint8_t getDecimals() { return _decimals; };
|
||||
|
||||
// equalities
|
||||
bool operator == (const float16ext& f);
|
||||
bool operator != (const float16ext& f);
|
||||
|
||||
bool operator > (const float16ext& f);
|
||||
bool operator >= (const float16ext& f);
|
||||
bool operator < (const float16ext& f);
|
||||
bool operator <= (const float16ext& f);
|
||||
|
||||
// negation
|
||||
float16ext operator - ();
|
||||
|
||||
// basic math
|
||||
float16ext operator + (const float16ext& f);
|
||||
float16ext operator - (const float16ext& f);
|
||||
float16ext operator * (const float16ext& f);
|
||||
float16ext operator / (const float16ext& f);
|
||||
|
||||
float16ext& operator += (const float16ext& f);
|
||||
float16ext& operator -= (const float16ext& f);
|
||||
float16ext& operator *= (const float16ext& f);
|
||||
float16ext& operator /= (const float16ext& f);
|
||||
|
||||
// math helper functions
|
||||
int sign(); // 1 = positive 0 = zero -1 = negative.
|
||||
bool isZero();
|
||||
|
||||
|
||||
// CORE CONVERSION
|
||||
// should be private but for testing...
|
||||
float f16tof32(uint16_t) const;
|
||||
uint16_t f32tof16(float) const;
|
||||
|
||||
|
||||
private:
|
||||
uint8_t _decimals = 4;
|
||||
uint16_t _value;
|
||||
|
||||
};
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
|
22
libraries/float16ext/keywords.txt
Normal file
22
libraries/float16ext/keywords.txt
Normal file
@ -0,0 +1,22 @@
|
||||
# Syntax Colouring Map For float16
|
||||
|
||||
|
||||
# Data types (KEYWORD1)
|
||||
float16ext KEYWORD1
|
||||
|
||||
|
||||
# Methods and Functions (KEYWORD2)
|
||||
toDouble KEYWORD2
|
||||
getBinary KEYWORD2
|
||||
setBinary KEYWORD2
|
||||
|
||||
setDecimals KEYWORD2
|
||||
getDecimals KEYWORD2
|
||||
|
||||
sign KEYWORD2
|
||||
isZero KEYWORD2
|
||||
|
||||
|
||||
# Constants (LITERAL1)
|
||||
FLOAT16EXT_LIB_VERSION LITERAL1
|
||||
|
23
libraries/float16ext/library.json
Normal file
23
libraries/float16ext/library.json
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "float16ext",
|
||||
"keywords": "float16, float16ext",
|
||||
"description": "Arduino library to implement float16ext data type.",
|
||||
"authors":
|
||||
[
|
||||
{
|
||||
"name": "Rob Tillaart",
|
||||
"email": "Rob.Tillaart@gmail.com",
|
||||
"maintainer": true
|
||||
}
|
||||
],
|
||||
"repository":
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/float16ext.git"
|
||||
},
|
||||
"version": "0.1.0",
|
||||
"license": "MIT",
|
||||
"frameworks": "*",
|
||||
"platforms": "*",
|
||||
"headers": "float16ext.h"
|
||||
}
|
11
libraries/float16ext/library.properties
Normal file
11
libraries/float16ext/library.properties
Normal file
@ -0,0 +1,11 @@
|
||||
name=float16ext
|
||||
version=0.1.0
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence=Arduino library to implement float16ext data type.
|
||||
paragraph=
|
||||
category=Data Processing
|
||||
url=https://github.com/RobTillaart/float16ext
|
||||
architectures=*
|
||||
includes=float16ext.h
|
||||
depends=
|
206
libraries/float16ext/test/unit_test_001.cpp
Normal file
206
libraries/float16ext/test/unit_test_001.cpp
Normal file
@ -0,0 +1,206 @@
|
||||
//
|
||||
// FILE: unit_test_001.cpp
|
||||
// AUTHOR: Rob Tillaart
|
||||
// DATE: 2021-11-26
|
||||
// PURPOSE: unit tests for the float16 data type
|
||||
// https://github.com/RobTillaart/float16
|
||||
// https://github.com/Arduino-CI/arduino_ci/blob/master/REFERENCE.md
|
||||
//
|
||||
|
||||
// supported assertions
|
||||
// ----------------------------
|
||||
// assertEqual(expected, actual); // a == b
|
||||
// assertNotEqual(unwanted, actual); // a != b
|
||||
// assertComparativeEquivalent(expected, actual); // abs(a - b) == 0 or (!(a > b) && !(a < b))
|
||||
// assertComparativeNotEquivalent(unwanted, actual); // abs(a - b) > 0 or ((a > b) || (a < b))
|
||||
// assertLess(upperBound, actual); // a < b
|
||||
// assertMore(lowerBound, actual); // a > b
|
||||
// assertLessOrEqual(upperBound, actual); // a <= b
|
||||
// assertMoreOrEqual(lowerBound, actual); // a >= b
|
||||
// assertTrue(actual);
|
||||
// assertFalse(actual);
|
||||
// assertNull(actual);
|
||||
|
||||
// // special cases for floats
|
||||
// assertEqualFloat(expected, actual, epsilon); // fabs(a - b) <= epsilon
|
||||
// assertNotEqualFloat(unwanted, actual, epsilon); // fabs(a - b) >= epsilon
|
||||
// assertInfinity(actual); // isinf(a)
|
||||
// assertNotInfinity(actual); // !isinf(a)
|
||||
// assertNAN(arg); // isnan(a)
|
||||
// assertNotNAN(arg); // !isnan(a)
|
||||
|
||||
|
||||
#include <ArduinoUnitTests.h>
|
||||
|
||||
#include "float16ext.h"
|
||||
|
||||
|
||||
unittest_setup()
|
||||
{
|
||||
fprintf(stderr, "FLOAT16EXT_LIB_VERSION: %s\n", (char*) FLOAT16EXT_LIB_VERSION);
|
||||
}
|
||||
|
||||
|
||||
unittest_teardown()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
unittest(test_constructor)
|
||||
{
|
||||
float16ext zero;
|
||||
assertEqualFloat(0.000, zero.toDouble(), 1e-3);
|
||||
float16ext one(1);
|
||||
assertEqualFloat(1.000, one.toDouble(), 1e-3);
|
||||
|
||||
float16ext e(exp(1));
|
||||
assertEqualFloat(1.000, ( 2.7183 / e.toDouble()), 1e-3);
|
||||
float16ext pie(PI);
|
||||
assertEqualFloat(1.000, (3.142 / pie.toDouble()), 1e-3);
|
||||
|
||||
float goldenRatio = 1.61803398875;
|
||||
float16ext gr(goldenRatio);
|
||||
assertEqualFloat(1.000, (goldenRatio / gr.toDouble()), 1e-3);
|
||||
|
||||
float16ext minusOne(-1);
|
||||
// fprintf(stderr, "MINUSONE: %f\n", minusOne.toDouble());
|
||||
assertEqualFloat(1.000, (-1 / minusOne.toDouble()), 1e-3);
|
||||
|
||||
// TODO
|
||||
// NAN constructor how to test
|
||||
// float16ext nanny(1.0/0.0);
|
||||
// assertNAN(nanny.toDouble());
|
||||
|
||||
// Overflow constructor
|
||||
float16ext big(1e6);
|
||||
assertEqualFloat(131008, big.toDouble(), 1);
|
||||
|
||||
float16ext bag(-1e6);
|
||||
assertEqualFloat(-131008, bag.toDouble(), 1);
|
||||
|
||||
float16ext small(1e-30);
|
||||
assertEqualFloat(0.0, small.toDouble(), 1e-3);
|
||||
float16ext smaller(-1e-30);
|
||||
assertEqualFloat(0.0, smaller.toDouble(), 1e-3);
|
||||
}
|
||||
|
||||
|
||||
unittest(test_compare_equal)
|
||||
{
|
||||
float16ext a(1);
|
||||
float16ext b(1);
|
||||
float16ext c(2);
|
||||
float16ext d(-1);
|
||||
|
||||
assertTrue(a == a);
|
||||
assertTrue(a == b);
|
||||
assertFalse(a == c);
|
||||
assertFalse(a == d);
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
assertFalse(a != a);
|
||||
assertFalse(a != b);
|
||||
assertTrue(a != c);
|
||||
assertTrue(a != d);
|
||||
}
|
||||
|
||||
|
||||
unittest(test_compare_1nequal)
|
||||
{
|
||||
float16ext a(1);
|
||||
float16ext b(1);
|
||||
float16ext c(2);
|
||||
float16ext d(-2);
|
||||
|
||||
assertFalse(a < a);
|
||||
assertTrue(a <= b);
|
||||
assertFalse(a > b);
|
||||
assertTrue(a >= a);
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
assertTrue(a < c);
|
||||
assertTrue(a <= c);
|
||||
assertFalse(a > c);
|
||||
assertFalse(a >= c);
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
assertFalse(a < d);
|
||||
assertFalse(a <= d);
|
||||
assertTrue(a > d);
|
||||
assertTrue(a >= d);
|
||||
}
|
||||
|
||||
|
||||
unittest(test_negation)
|
||||
{
|
||||
float16ext f16(123.456);
|
||||
float16ext f17(-f16);
|
||||
float16ext f18 = -f16;
|
||||
|
||||
assertEqualFloat(-123.456, f17.toDouble(), 1e-1);
|
||||
assertEqualFloat(-123.456, f18.toDouble(), 1e-1);
|
||||
}
|
||||
|
||||
|
||||
unittest(test_conversion)
|
||||
{
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
float f = random(60000000) * 0.001;
|
||||
float16ext f16(f);
|
||||
assertEqualFloat(1, (f / f16.toDouble()), 1e-3);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unittest(test_printable)
|
||||
{
|
||||
float16ext f16(123.456);
|
||||
// test default value.
|
||||
assertEqual(4, f16.getDecimals());
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
f16.setDecimals(i);
|
||||
assertEqual(i, f16.getDecimals());
|
||||
}
|
||||
|
||||
// TODO
|
||||
// printable? how to test?
|
||||
}
|
||||
|
||||
|
||||
unittest(test_all_values)
|
||||
{
|
||||
float16ext a;
|
||||
float16ext b;
|
||||
|
||||
// test both the conversion to and from float.
|
||||
// internal format should be equal. Except for -0 and 0.
|
||||
|
||||
fprintf(stderr, "test all positive patterns\n");
|
||||
for (uint32_t x = 0x0000; x < 0x7FFF; x++)
|
||||
{
|
||||
a.setBinary(x);
|
||||
b = a.toDouble();
|
||||
if (x != b.getBinary()) // assert would give 65K lines output!
|
||||
{
|
||||
fprintf(stderr, "fail at %d\n", x);
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "test all negative patterns\n");
|
||||
for (uint32_t x = 0x8000; x < 0xFFFF; x++)
|
||||
{
|
||||
a.setBinary(x);
|
||||
b = a.toDouble();
|
||||
if (x != b.getBinary())
|
||||
{
|
||||
fprintf(stderr, "fail at %d\n", x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unittest_main()
|
||||
|
||||
|
||||
// -- END OF FILE --
|
Loading…
Reference in New Issue
Block a user