0.1.4 Fletcher

This commit is contained in:
rob tillaart 2022-09-08 13:31:39 +02:00
parent 196397b8ca
commit 7aa3c626ab
18 changed files with 336 additions and 49 deletions

View File

@ -2,13 +2,13 @@ compile:
# Choosing to run compilation tests on 2 different Arduino platforms
platforms:
- uno
# - due
# - zero
# - leonardo
- due
- zero
- leonardo
- m4
- esp32
# - esp8266
# - mega2560
- esp8266
- mega2560
libraries:
- "printHelpers"

View File

@ -1,7 +1,7 @@
//
// FILE: Fletcher.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.1.3
// VERSION: 0.1.4
// DATE: 2022-01-25
// PURPOSE: Arduino Library for calculating Fletcher's checksum
// URL: https://github.com/RobTillaart/Fletcher
@ -12,16 +12,12 @@
// 0.1.1 2022-01-26 optimize % math variation based upon to Anastase Nakassis (wikipedia)
// 0.1.2 2022-01-26 add class implementation e.g. for streaming
// 0.1.3 2022-04-15 fix #4 split .h in .h and .cpp
// 0.1.4 2022-09-08 performance optimization (Kudos to Daniel Mohr).
// affects SAMD, ESP32 and ESP8266
// fix FLETCHER_LIB_VERSION
#include "Arduino.h"
#define FLETCHER_LIB_VERSION (F("0.1.2"))
#define FLETCHER_16 255
#define FLETCHER_32 65535UL
#define FLETCHER_64 4294967295ULL
#include "Fletcher.h"
//
@ -42,7 +38,10 @@ uint16_t fletcher16(uint8_t *data, uint16_t length)
s2 += s1;
}
s1 %= FLETCHER_16;
// does not work due to the above "32-bit" loop.
// s1 = (s1 & 255) + (s1 >> 8);
s2 %= FLETCHER_16;
// s2 = (s2 & 255) + (s2 >> 8);
}
return (s2 << 8) | s1;
}
@ -60,8 +59,11 @@ uint32_t fletcher32(uint16_t *data, uint16_t length)
s1 += data[i++];
s2 += s1;
}
s1 %= FLETCHER_32;
s2 %= FLETCHER_32;
// s1 %= FLETCHER_32;
s1 = (s1 & 65535UL) + (s1 >> 16);
// s2 %= FLETCHER_32;
s2 = (s2 & 65535UL) + (s2 >> 16);
}
return (s2 << 16) | s1;
}
@ -79,8 +81,10 @@ uint64_t fletcher64(uint32_t *data, uint16_t length)
s1 += data[i++];
s2 += s1;
}
s1 %= FLETCHER_64;
s2 %= FLETCHER_64;
// s1 %= FLETCHER_64;
s1 = (s1 & ((((uint64_t) 1) << 32) - 1)) + (s1 >> 32);
// s2 %= FLETCHER_64;
s2 = (s2 & ((((uint64_t) 1) << 32) - 1)) + (s2 >> 32);
}
return (s2 << 32) | s1;
}

View File

@ -2,7 +2,7 @@
//
// FILE: Fletcher.h
// AUTHOR: Rob Tillaart
// VERSION: 0.1.3
// VERSION: 0.1.4
// DATE: 2022-01-25
// PURPOSE: Arduino Library for calculating Fletcher's checksum
// URL: https://github.com/RobTillaart/Fletcher
@ -12,7 +12,7 @@
#include "Arduino.h"
#define FLETCHER_LIB_VERSION (F("0.1.3"))
#define FLETCHER_LIB_VERSION (F("0.1.4"))
#define FLETCHER_16 255
#define FLETCHER_32 65535UL

View File

@ -28,9 +28,9 @@ void Fletcher16::add(uint8_t value)
{
_count++;
_s1 += value;
if (_s1 >= FLETCHER_16) _s1 -= FLETCHER_16;
_s1 = (_s1 & 255) + (_s1 >> 8);
_s2 += _s1;
if (_s2 >= FLETCHER_16) _s2 -= FLETCHER_16;
_s2 = (_s2 & 255) + (_s2 >> 8);
}

View File

@ -29,9 +29,17 @@ void Fletcher32::add(uint16_t value)
{
_count++;
_s1 += value;
if (_s1 >= FLETCHER_32) _s1 -= FLETCHER_32;
#if defined(ARDUINO_ARCH_SAMD) || defined(ESP32) || defined(ESP8266)
_s1 = (_s1 & 65535UL) + (_s1 >> 16);
#else
if (_s1 >= FLETCHER_32) _s1 -= FLETCHER_32;
#endif
_s2 += _s1;
if (_s2 >= FLETCHER_32) _s2 -= FLETCHER_32;
#if defined(ARDUINO_ARCH_SAMD) || defined(ESP32) || defined(ESP8266)
_s2 = (_s2 & 65535UL) + (_s2 >> 16);
#else
if (_s2 >= FLETCHER_32) _s2 -= FLETCHER_32;
#endif
}
// NOTE: padding with zero's error

View File

@ -29,9 +29,17 @@ void Fletcher64::add(uint32_t value)
{
_count++;
_s1 += value;
if (_s1 >= FLETCHER_64) _s1 -= FLETCHER_64;
#if defined(ARDUINO_ARCH_SAMD) || defined(ESP32) || defined(ESP8266)
_s1 = (_s1 & ((((uint64_t) 1) << 32) - 1)) + (_s1 >> 32);
#else
if (_s1 >= FLETCHER_64) _s1 -= FLETCHER_64;
#endif
_s2 += _s1;
if (_s2 >= FLETCHER_64) _s2 -= FLETCHER_64;
#if defined(ARDUINO_ARCH_SAMD) || defined(ESP32) || defined(ESP8266)
_s2 = (_s2 & ((((uint64_t) 1) << 32) - 1)) + (_s2 >> 32);
#else
if (_s2 >= FLETCHER_64) _s2 -= FLETCHER_64;
#endif
}

View File

@ -23,7 +23,7 @@ Relates to https://github.com/RobTillaart/CRC
Use https://github.com/RobTillaart/printHelpers to print the Fletcher64().
Tested on Arduino UNO only.
Tested on Arduino UNO + ESP32 + SAMD (See PR #7).
## Interface
@ -47,19 +47,6 @@ The checksum from **getFletcher()** can be split into a high and a low part
to be used to "feed" **begin()** again. See restart example.
#### Performance
Not tested ESP32 (and many other platforms) yet.
First numbers of **.add(value)** measured with test sketch shows the following timing.
| Checksum | UNO 16 MHz | ESP32 240 MHz |
|:------------|:-----------:|:-------------:|
| Fletcher16 | 3.8 us | 0.22 us |
| Fletcher32 | 5.6 us | 0.23 us |
| Fletcher64 | 10.1 us | 0.26 us |
| Average | 6.5 us | 0.24 us |
## Interface static functions
The functions are straightforward, however one should define **length**
@ -74,14 +61,28 @@ Use **\#include "Fletcher.h"**
- **uint64_t fletcher64(uint32_t \*data, uint16_t length)** length in units of 4 bytes = 32 bits.
#### Performance
#### Performance I
Not tested ESP32 (and many other platforms) yet.
First numbers of **.add(value)** measured with test sketch shows the following timing.
| Checksum | UNO 16 MHz | ESP32 240 MHz |
|:------------|:-----------:|:-------------:|
| Fletcher16 | 3.8 us | 0.22 us |
| Fletcher32 | 5.6 us | 0.23 us |
| Fletcher64 | 10.1 us | 0.26 us |
| Average | 6.5 us | 0.24 us |
#### Performance II
Not tested extensively, first numbers of **.add(array, length)**
measured with **Fletcher_performance.ino** sketch shows the following timing.
Lorem Ipsum text = 868 bytes.
Version 0.1.3.
| Checksum | UNO 16 MHz | ESP32 240 MHz | Notes |
|:------------|:-----------:|:-------------:|:-------------------|
| Fletcher16 | 1120 us | 62 us | first run slower ? |
@ -91,6 +92,9 @@ Lorem Ipsum text = 868 bytes.
| Avg / char | 1.46 us | 0.0495 us | 868 bytes |
Note 0.1.4 has improved the performance. See PR #7 for some numbers.
## Operation
See examples.
@ -99,6 +103,7 @@ See examples.
## Future ideas
- improve documentation
- update performance figures.
- test other platforms
- others e.g. Fletcher24?
- generic FletcherN(). for N = 1..32

View File

@ -24,7 +24,7 @@ void setup()
start = micros();
for (uint16_t x = 0; x < 10000; x++)
{
z = random(255);
z = random(256);
}
stop = micros();
randomtime = stop - start;
@ -36,7 +36,7 @@ void setup()
start = micros();
for (uint16_t x = 0; x < 10000; x++)
{
z = random(255);
z = random(256);
fl.add(z);
}
stop = micros();

View File

@ -24,7 +24,7 @@ void setup()
start = micros();
for (uint16_t x = 0; x < 10000; x++)
{
z = random(255);
z = random(256);
}
stop = micros();
randomtime = stop - start;
@ -36,7 +36,7 @@ void setup()
start = micros();
for (uint16_t x = 0; x < 10000; x++)
{
z = random(255);
z = random(256);
fl.add(z);
}
stop = micros();

View File

@ -0,0 +1,11 @@
Tested on ESP32 (240 MHz)
IDE 1.18
FLETCHER_LIB_VERSION: 0.1.3
Fletcher32_performance
randomtime: 6945
total: 9275
1e4 x add: 2330
checksum: 430995902

View File

@ -0,0 +1,26 @@
Tested on ESP32 (240 MHz)
IDE 1.18
FLETCHER_LIB_VERSION: 0.1.3
Fletcher32_performance
randomtime: 6945
total: 9275
1e4 x add: 2330
checksum: 430995902
FLETCHER_LIB_VERSION: 0.1.4
Fletcher32_performance (old method)
randomtime: 6945
total: 9274
1e4 x add: 2329
checksum: 886350356 (as we add random values this happens).
Fletcher32_performance (optimized modulo)
randomtime: 6947
total: 8577
1e4 x add: 1630
checksum: 233217780

View File

@ -24,7 +24,7 @@ void setup()
start = micros();
for (uint16_t x = 0; x < 10000; x++)
{
z = random(255);
z = random(256);
}
stop = micros();
randomtime = stop - start;
@ -36,7 +36,7 @@ void setup()
start = micros();
for (uint16_t x = 0; x < 10000; x++)
{
z = random(255);
z = random(256);
fl.add(z);
}
stop = micros();

View File

@ -0,0 +1,21 @@
Tested on ESP32 (240 MHz)
IDE 1.18.19
(included for comparison Arduino UNO)
FLETCHER_LIB_VERSION: 0.1.1
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ae...
LENGTH STR: 868
FLETCHER16: 1120 53705
FLETCHER32: 728 1196447857
FLETCHER64: 1952 10053561395214921491
FLETCHER_LIB_VERSION: 0.1.3
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ae...
LENGTH STR: 868
FLETCHER16: 61 53705
FLETCHER32: 33 1196447857
FLETCHER64: 34 10053561395214921491

View File

@ -0,0 +1,23 @@
Tested on Arduino UNO
IDE 1.18.19
(included for comparison)
FLETCHER_LIB_VERSION: 0.1.1
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ae...
LENGTH STR: 868
FLETCHER16: 1120 53705
FLETCHER32: 728 1196447857
FLETCHER64: 1952 10053561395214921491
FLETCHER_LIB_VERSION: 0.1.4
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ae...
LENGTH STR: 868
FLETCHER16: 1120 53705
FLETCHER32: 552 1196447857
FLETCHER64: 1960 10053561395214921491

View File

@ -0,0 +1,31 @@
Tested on ESP32 (240 MHz)
IDE 1.18.19
(included for comparison Arduino UNO)
FLETCHER_LIB_VERSION: 0.1.1
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ae...
LENGTH STR: 868
FLETCHER16: 1120 53705
FLETCHER32: 728 1196447857
FLETCHER64: 1952 10053561395214921491
FLETCHER_LIB_VERSION: 0.1.3
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ae...
LENGTH STR: 868
FLETCHER16: 61 53705
FLETCHER32: 33 1196447857
FLETCHER64: 34 10053561395214921491
FLETCHER_LIB_VERSION: 0.1.4
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ae...
LENGTH STR: 868
FLETCHER16: 60 53705
FLETCHER32: 34 1196447857
FLETCHER64: 31 10053561395214921491

View File

@ -0,0 +1,150 @@
/*
Author: Daniel Mohr
Date: 2022-09-07
Purpose: shows stream performance
*/
#include "Arduino.h"
#include "printHelpers.h" // needed for Arduino Nano
#include <Fletcher16.h>
#include <Fletcher32.h>
#include <Fletcher64.h>
#ifdef ARDUINO_ARCH_AVR
#define MAX_LEN 1024
#else
#define MAX_LEN 16384
#endif
#define DO_N 23
void setup()
{
Serial.begin(115200);
while (!Serial);
}
void test_fletcher16() {
Serial.println("Fletcher16");
const uint16_t max_len = MAX_LEN;
uint8_t values[max_len];
uint32_t t0, t1;
delay(100);
t0 = micros();
for (uint16_t i = 0; i < max_len; i++) {
values[i] = (uint8_t) random(0, 1 << 8);
}
t1 = micros();
Serial.print("Created random list: ");
Serial.print(1024.0 * (t1 - t0) / float(MAX_LEN));
Serial.println(" us/kByte.");
Fletcher16 checksum_instance;
uint16_t checksum;
uint32_t totaltime = 0;
for (uint16_t j = 0; j < DO_N; j++) {
t0 = micros();
checksum_instance.begin();
for (uint16_t i = 0; i < max_len; i++) {
checksum_instance.add(values[i]);
}
checksum = checksum_instance.getFletcher();
t1 = micros();
totaltime += t1 - t0;
}
Serial.print("Checksum: ");
Serial.println(checksum);
Serial.print("Created checksum: ");
Serial.print(1024.0 * totaltime / float(DO_N * MAX_LEN));
Serial.println(" us/kByte.");
}
void test_fletcher32() {
Serial.println("Fletcher32");
const uint16_t max_len = MAX_LEN / 2;
uint16_t values[max_len];
uint32_t t0, t1;
delay(100);
t0 = micros();
for (uint16_t i = 0; i < max_len; i++) {
values[i] = (uint16_t) random(0, ((uint32_t) 1) << 16);
}
t1 = micros();
Serial.print("Created random list: ");
Serial.print(1024.0 * (t1 - t0) / float(MAX_LEN));
Serial.println(" us/kByte.");
Fletcher32 checksum_instance;
uint32_t checksum;
uint32_t totaltime = 0;
for (uint16_t j = 0; j < DO_N; j++) {
t0 = micros();
checksum_instance.begin();
for (uint16_t i = 0; i < max_len; i++) {
checksum_instance.add(values[i]);
}
checksum = checksum_instance.getFletcher();
t1 = micros();
totaltime += t1 - t0;
}
Serial.print("Checksum: ");
Serial.println(checksum);
Serial.print("Created checksum: ");
Serial.print(1024.0 * totaltime / float(DO_N * MAX_LEN));
Serial.println(" us/kByte.");
}
void test_fletcher64() {
Serial.println("Fletcher64");
const uint16_t max_len = MAX_LEN / 4;
uint32_t values[max_len];
uint32_t t0, t1;
delay(100);
t0 = micros();
for (uint16_t i = 0; i < max_len; i++) {
values[i] = ((uint32_t) random(0, ((uint32_t) 1) << 16)) + (((uint32_t) random(0, ((uint32_t) 1) << 16)) << 16);
}
t1 = micros();
Serial.print("Created random list: ");
Serial.print(1024.0 * (t1 - t0) / float(MAX_LEN));
Serial.println(" us/kByte.");
Fletcher64 checksum_instance;
uint64_t checksum;
uint32_t totaltime = 0;
for (uint16_t j = 0; j < DO_N; j++) {
t0 = micros();
checksum_instance.begin();
for (uint16_t i = 0; i < max_len; i++) {
checksum_instance.add(values[i]);
}
checksum = checksum_instance.getFletcher();
t1 = micros();
totaltime += t1 - t0;
}
Serial.print("Checksum: ");
Serial.println(print64(checksum));
Serial.print("Created checksum: ");
Serial.print(1024.0 * totaltime / float(DO_N * MAX_LEN));
Serial.println(" us/kByte.");
}
void loop() {
Serial.print("Using list of ");
Serial.print(MAX_LEN);
Serial.println(" elements for Fletcher16");
Serial.print("Using list of ");
Serial.print(MAX_LEN/2);
Serial.println(" elements for Fletcher32");
Serial.print("Using list of ");
Serial.print(MAX_LEN/4);
Serial.println(" elements for Fletcher64");
Serial.println("");
test_fletcher16();
Serial.println("");
delay(1000);
test_fletcher32();
Serial.println("");
delay(1000);
test_fletcher64();
Serial.println("");
delay(1000);
Serial.println("");
}

View File

@ -15,7 +15,7 @@
"type": "git",
"url": "https://github.com/RobTillaart/Fletcher.git"
},
"version": "0.1.3",
"version": "0.1.4",
"license": "MIT",
"frameworks": "arduino",
"platforms": "*",

View File

@ -1,5 +1,5 @@
name=Fletcher
version=0.1.3
version=0.1.4
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence="Arduino Library for calculating Fletcher's checksum.