0.1.0 float16ext

This commit is contained in:
Rob Tillaart 2024-03-06 20:05:07 +01:00
parent 917571e880
commit 55152137f2
21 changed files with 1246 additions and 0 deletions

View 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"

View File

@ -0,0 +1,4 @@
# These are supported funding model platforms
github: RobTillaart

View 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

View 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

View 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$"

View 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

View 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.

View 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 E8 | 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,

View 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"

View File

@ -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 --

View 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"

View File

@ -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 --

View 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"

View File

@ -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 --

View 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 --

View 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 --

View 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 --

View 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

View 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"
}

View 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=

View 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 --