mirror of
https://github.com/RobTillaart/Arduino.git
synced 2024-10-03 18:09:02 -04:00
0.1.6 Fletcher
This commit is contained in:
parent
3c51c68979
commit
cb1107e950
@ -2,13 +2,13 @@ compile:
|
||||
# Choosing to run compilation tests on 2 different Arduino platforms
|
||||
platforms:
|
||||
- uno
|
||||
- due
|
||||
- zero
|
||||
# - due
|
||||
# - zero
|
||||
- leonardo
|
||||
- m4
|
||||
- esp32
|
||||
- esp8266
|
||||
- mega2560
|
||||
# - mega2560
|
||||
|
||||
libraries:
|
||||
- "printHelpers"
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// FILE: Fletcher.cpp
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.5
|
||||
// VERSION: 0.1.6
|
||||
// DATE: 2022-01-25
|
||||
// PURPOSE: Arduino Library for calculating Fletcher's checksum
|
||||
// URL: https://github.com/RobTillaart/Fletcher
|
||||
@ -17,7 +17,8 @@
|
||||
// fix FLETCHER_LIB_VERSION
|
||||
// 0.1.5 2022-09-08 roll back the optimizations in the standalone functions
|
||||
// conflict with loop optimization already in.
|
||||
// update ketwords.txt
|
||||
// update keywords.txt
|
||||
// 0.1.6 2022-09-10 stabilize optimizations
|
||||
|
||||
|
||||
#include "Fletcher.h"
|
||||
@ -40,10 +41,10 @@ uint16_t fletcher16(uint8_t *data, uint16_t length)
|
||||
s1 += data[i++];
|
||||
s2 += s1;
|
||||
}
|
||||
s1 %= FLETCHER_16;
|
||||
// this optimization does not work due to the above "32-bit" loop.
|
||||
// for all three functions.
|
||||
// s1 = (s1 & 255) + (s1 >> 8);
|
||||
s1 %= FLETCHER_16;
|
||||
s2 %= FLETCHER_16;
|
||||
}
|
||||
return (s2 << 8) | s1;
|
||||
|
@ -2,7 +2,7 @@
|
||||
//
|
||||
// FILE: Fletcher.h
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.5
|
||||
// VERSION: 0.1.6
|
||||
// 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.5"))
|
||||
#define FLETCHER_LIB_VERSION (F("0.1.6"))
|
||||
|
||||
#define FLETCHER_16 255
|
||||
#define FLETCHER_32 65535UL
|
||||
|
@ -1,13 +1,14 @@
|
||||
//
|
||||
// FILE: Fletcher16.cpp
|
||||
// AUTHOR: Rob Tillaart
|
||||
// AUTHOR: Rob Tillaart, Daniel Mohr
|
||||
// PURPOSE: Arduino class for Fletcher16
|
||||
// URL: https://github.com/RobTillaart/Fletcher
|
||||
|
||||
|
||||
#include "Fletcher16.h"
|
||||
|
||||
#define FLETCHER_16 255
|
||||
// UINT8_MAX = 255 = ((((uint16_t) 1) << 8) - 1)
|
||||
#define FLETCHER_16 UINT8_MAX
|
||||
|
||||
|
||||
Fletcher16::Fletcher16()
|
||||
@ -18,8 +19,8 @@ Fletcher16::Fletcher16()
|
||||
|
||||
void Fletcher16::begin(uint8_t s1, uint8_t s2)
|
||||
{
|
||||
_s1 = s1;
|
||||
_s2 = s2;
|
||||
_s1 = (s1 == FLETCHER_16) ? 0 : s1;
|
||||
_s2 = (s2 == FLETCHER_16) ? 0 : s2;
|
||||
_count = 0;
|
||||
}
|
||||
|
||||
@ -27,10 +28,28 @@ void Fletcher16::begin(uint8_t s1, uint8_t s2)
|
||||
void Fletcher16::add(uint8_t value)
|
||||
{
|
||||
_count++;
|
||||
#if defined(ARDUINO_ARCH_AVR)
|
||||
uint8_t t = 0xFF - value;
|
||||
if (t >= _s1) _s1 += value;
|
||||
else _s1 = _s1 + value + 1;
|
||||
|
||||
t = 0xFF - _s1;
|
||||
if (t >= _s2) _s2 += _s1;
|
||||
else _s2 = _s2 + _s1 + 1;
|
||||
|
||||
#elif defined(ARDUINO_ARCH_SAMD) || defined(ESP32) || defined(ESP8266)
|
||||
_s1 += value;
|
||||
_s1 = (_s1 & 255) + (_s1 >> 8);
|
||||
_s1 = (_s1 & FLETCHER_16) + (_s1 >> 8);
|
||||
_s2 += _s1;
|
||||
_s2 = (_s2 & 255) + (_s2 >> 8);
|
||||
_s2 = (_s2 & FLETCHER_16) + (_s2 >> 8);
|
||||
|
||||
#else
|
||||
// REFERENCE
|
||||
_s1 += value;
|
||||
if (_s1 >= FLETCHER_16) _s1 -= FLETCHER_16;
|
||||
_s2 += _s1;
|
||||
if (_s2 >= FLETCHER_16) _s2 -= FLETCHER_16;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -43,5 +62,19 @@ void Fletcher16::add(const uint8_t * array, uint16_t length)
|
||||
}
|
||||
|
||||
|
||||
uint16_t Fletcher16::getFletcher()
|
||||
{
|
||||
if (_s1 >= FLETCHER_16) _s1 -= FLETCHER_16;
|
||||
if (_s2 >= FLETCHER_16) _s2 -= FLETCHER_16;
|
||||
return (((uint16_t)_s2) << 8) | _s1;
|
||||
};
|
||||
|
||||
|
||||
uint32_t Fletcher16::count()
|
||||
{
|
||||
return _count;
|
||||
};
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
//
|
||||
// FILE: Fletcher16.h
|
||||
// AUTHOR: Rob Tillaart
|
||||
// AUTHOR: Rob Tillaart, Daniel Mohr
|
||||
// PURPOSE: Arduino class for Fletcher16
|
||||
// URL: https://github.com/RobTillaart/Fletcher
|
||||
|
||||
@ -20,15 +20,19 @@ public:
|
||||
void add(uint8_t value);
|
||||
void add(const uint8_t * array, uint16_t length);
|
||||
|
||||
uint16_t getFletcher() { return (_s2 << 8) | _s1; };
|
||||
uint32_t count() { return _count; };
|
||||
uint16_t getFletcher();
|
||||
uint32_t count();
|
||||
|
||||
private:
|
||||
#ifdef ARDUINO_ARCH_AVR
|
||||
uint8_t _s1;
|
||||
uint8_t _s2;
|
||||
#else
|
||||
uint16_t _s1;
|
||||
uint16_t _s2;
|
||||
#endif
|
||||
uint32_t _count;
|
||||
};
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
|
||||
|
@ -1,14 +1,14 @@
|
||||
//
|
||||
// FILE: Fletcher32.cpp
|
||||
// AUTHOR: Rob Tillaart
|
||||
// AUTHOR: Rob Tillaart, Daniel Mohr
|
||||
// PURPOSE: Arduino class for Fletcher32
|
||||
// URL: https://github.com/RobTillaart/Fletcher
|
||||
|
||||
|
||||
#include "Fletcher32.h"
|
||||
|
||||
#define FLETCHER_32 65535UL
|
||||
|
||||
// UINT16_MAX = 65535UL = ((((uint32_t) 1) << 16) - 1)
|
||||
#define FLETCHER_32 UINT16_MAX
|
||||
|
||||
|
||||
Fletcher32::Fletcher32()
|
||||
@ -19,8 +19,8 @@ Fletcher32::Fletcher32()
|
||||
|
||||
void Fletcher32::begin(uint16_t s1, uint16_t s2)
|
||||
{
|
||||
_s1 = s1;
|
||||
_s2 = s2;
|
||||
_s1 = (s1 == FLETCHER_32) ? 0 : s1;
|
||||
_s2 = (s2 == FLETCHER_32) ? 0 : s2;
|
||||
_count = 0;
|
||||
}
|
||||
|
||||
@ -28,16 +28,27 @@ void Fletcher32::begin(uint16_t s1, uint16_t s2)
|
||||
void Fletcher32::add(uint16_t value)
|
||||
{
|
||||
_count++;
|
||||
#ifdef ARDUINO_ARCH_AVR
|
||||
unsigned int t = _s1;
|
||||
// Serial.println("__builtin_uadd_overflow");
|
||||
if (__builtin_uadd_overflow(t, value, &t)) {
|
||||
t++;
|
||||
}
|
||||
_s1 = t;
|
||||
t = _s2;
|
||||
if (__builtin_uadd_overflow(t, _s1, &t)) {
|
||||
t++;
|
||||
}
|
||||
_s2 = t;
|
||||
#elif defined(ARDUINO_ARCH_SAMD) || defined(ESP32) || defined(ESP8266)
|
||||
_s1 += value;
|
||||
#if defined(ARDUINO_ARCH_SAMD) || defined(ESP32) || defined(ESP8266)
|
||||
_s1 = (_s1 & 65535UL) + (_s1 >> 16);
|
||||
#else
|
||||
if (_s1 >= FLETCHER_32) _s1 -= FLETCHER_32;
|
||||
#endif
|
||||
_s1 = (_s1 & FLETCHER_32) + (_s1 >> 16);
|
||||
_s2 += _s1;
|
||||
#if defined(ARDUINO_ARCH_SAMD) || defined(ESP32) || defined(ESP8266)
|
||||
_s2 = (_s2 & 65535UL) + (_s2 >> 16);
|
||||
_s2 = (_s2 & FLETCHER_32) + (_s2 >> 16);
|
||||
#else
|
||||
_s1 += value;
|
||||
if (_s1 >= FLETCHER_32) _s1 -= FLETCHER_32;
|
||||
_s2 += _s1;
|
||||
if (_s2 >= FLETCHER_32) _s2 -= FLETCHER_32;
|
||||
#endif
|
||||
}
|
||||
@ -52,6 +63,19 @@ void Fletcher32::add(const uint16_t * array, uint16_t length)
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t Fletcher32::getFletcher()
|
||||
{
|
||||
if (_s1 >= FLETCHER_32) _s1 -= FLETCHER_32;
|
||||
if (_s2 >= FLETCHER_32) _s2 -= FLETCHER_32;
|
||||
return (((uint32_t)_s2) << 16) | _s1;
|
||||
};
|
||||
|
||||
|
||||
uint32_t Fletcher32::count()
|
||||
{
|
||||
return _count;
|
||||
};
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
|
||||
|
@ -20,12 +20,17 @@ public:
|
||||
void add(uint16_t value);
|
||||
void add(const uint16_t * array, uint16_t length);
|
||||
|
||||
uint32_t getFletcher() { return (_s2 << 16) | _s1; };
|
||||
uint32_t count() { return _count; };
|
||||
uint32_t getFletcher();
|
||||
uint32_t count();
|
||||
|
||||
private:
|
||||
#ifdef ARDUINO_ARCH_AVR
|
||||
uint16_t _s1;
|
||||
uint16_t _s2;
|
||||
#else
|
||||
uint32_t _s1;
|
||||
uint32_t _s2;
|
||||
#endif
|
||||
uint32_t _count;
|
||||
};
|
||||
|
||||
|
@ -7,9 +7,8 @@
|
||||
|
||||
#include "Fletcher64.h"
|
||||
|
||||
#define FLETCHER_64 4294967295ULL
|
||||
|
||||
|
||||
// UINT32_MAX = 4294967295ULL = ((((uint64_t) 1) << 32) - 1)
|
||||
#define FLETCHER_64 UINT32_MAX
|
||||
|
||||
Fletcher64::Fletcher64()
|
||||
{
|
||||
@ -19,8 +18,8 @@ Fletcher64::Fletcher64()
|
||||
|
||||
void Fletcher64::begin(uint32_t s1, uint32_t s2)
|
||||
{
|
||||
_s1 = s1;
|
||||
_s2 = s2;
|
||||
_s1 = (s1 == FLETCHER_64) ? 0 : s1;
|
||||
_s2 = (s2 == FLETCHER_64) ? 0 : s2;
|
||||
_count = 0;
|
||||
}
|
||||
|
||||
@ -28,16 +27,23 @@ void Fletcher64::begin(uint32_t s1, uint32_t s2)
|
||||
void Fletcher64::add(uint32_t value)
|
||||
{
|
||||
_count++;
|
||||
#if defined(ARDUINO_ARCH_AVR) || defined(ESP32) || defined(ESP8266)
|
||||
uint32_t t = 0xFFFFFFFF - value;
|
||||
if (t >= _s1) _s1 += value;
|
||||
else _s1 = _s1 + value + 1;
|
||||
|
||||
t = 0xFFFFFFFF - _s1;
|
||||
if (t >= _s2) _s2 += _s1;
|
||||
else _s2 = _s2 + _s1 + 1;
|
||||
#elif defined(ARDUINO_ARCH_SAMD)
|
||||
_s1 += value;
|
||||
#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
|
||||
_s1 = (_s1 & FLETCHER_64) + (_s1 >> 32);
|
||||
_s2 += _s1;
|
||||
#if defined(ARDUINO_ARCH_SAMD) || defined(ESP32) || defined(ESP8266)
|
||||
_s2 = (_s2 & ((((uint64_t) 1) << 32) - 1)) + (_s2 >> 32);
|
||||
_s2 = (_s2 & FLETCHER_64) + (_s2 >> 32);
|
||||
#else
|
||||
_s1 += value;
|
||||
if (_s1 >= FLETCHER_64) _s1 -= FLETCHER_64;
|
||||
_s2 += _s1;
|
||||
if (_s2 >= FLETCHER_64) _s2 -= FLETCHER_64;
|
||||
#endif
|
||||
}
|
||||
@ -52,5 +58,19 @@ void Fletcher64::add(const uint32_t * array, uint16_t length)
|
||||
}
|
||||
|
||||
|
||||
uint64_t Fletcher64::getFletcher()
|
||||
{
|
||||
if (_s1 >= FLETCHER_64) _s1 -= FLETCHER_64;
|
||||
if (_s2 >= FLETCHER_64) _s2 -= FLETCHER_64;
|
||||
return (((uint64_t)_s2) << 32) | _s1;
|
||||
};
|
||||
|
||||
|
||||
uint32_t Fletcher64::count()
|
||||
{
|
||||
return _count;
|
||||
};
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
|
||||
|
@ -20,12 +20,17 @@ public:
|
||||
void add(uint32_t value);
|
||||
void add(const uint32_t * array, uint16_t length);
|
||||
|
||||
uint64_t getFletcher() { return (_s2 << 32) | _s1; };
|
||||
uint32_t count() { return _count; };
|
||||
uint64_t getFletcher();
|
||||
uint32_t count();
|
||||
|
||||
private:
|
||||
#if defined(ARDUINO_ARCH_AVR) || defined(ESP32) || defined(ESP8266)
|
||||
uint32_t _s1;
|
||||
uint32_t _s2;
|
||||
#else
|
||||
uint64_t _s1;
|
||||
uint64_t _s2;
|
||||
#endif
|
||||
uint32_t _count;
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Author: Daniel Mohr
|
||||
Date: 2022-09-08
|
||||
Date: 2022-09-13
|
||||
Purpose: shows stream performance
|
||||
*/
|
||||
#include "Arduino.h"
|
||||
@ -16,65 +16,89 @@
|
||||
#else
|
||||
#define MAX_LEN 16384
|
||||
#endif
|
||||
union main_value_storage {
|
||||
uint8_t uint8[MAX_LEN];
|
||||
uint16_t uint16[MAX_LEN / 2];
|
||||
uint32_t uint32[MAX_LEN / 4];
|
||||
} values;
|
||||
|
||||
#define DO_N 23
|
||||
|
||||
uint32_t myfletcher16(uint8_t *data, const uint16_t length)
|
||||
#if defined(ARDUINO_ARCH_AVR)
|
||||
String float2strn(float value, size_t n) {
|
||||
char strvalout[n];
|
||||
dtostrf(value, n, 2, strvalout);
|
||||
return strvalout;
|
||||
}
|
||||
#else
|
||||
String float2strn(float value, size_t n) {
|
||||
String strval = String(value);
|
||||
while (strval.length() < n) {
|
||||
strval = " " + strval;
|
||||
}
|
||||
return strval;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint16_t myfletcher16(uint8_t *data, const size_t length)
|
||||
{
|
||||
uint8_t s1 = 0;
|
||||
uint8_t s2 = 0;
|
||||
for (size_t i = 0; i < length; i++)
|
||||
{
|
||||
// UINT8_MAX = 255 = ((((uint16_t) 1) << 8) - ((uint16_t) 1))
|
||||
s1 = (uint8_t) (((uint16_t) s1 + (uint16_t) data[i]) % UINT8_MAX);
|
||||
s2 = (uint8_t) (((uint16_t) s2 + (uint16_t) s1) % UINT8_MAX);
|
||||
}
|
||||
return (((uint16_t) s2) << 8) | ((uint16_t) s1);
|
||||
}
|
||||
|
||||
uint32_t myfletcher32(uint16_t *data, const size_t length)
|
||||
{
|
||||
uint16_t s1 = 0;
|
||||
uint16_t s2 = 0;
|
||||
for (uint16_t i = 0; i < length; i++)
|
||||
for (size_t i = 0; i < length; i++)
|
||||
{
|
||||
s1 = (s1 + data[i]) % ((((uint16_t) 1) << 8) - 1);
|
||||
s2 = (s2 + s1) % ((((uint16_t) 1) << 8) - 1);
|
||||
// UINT16_MAX = 65535UL = ((((uint32_t) 1) << 16) - ((uint32_t) 1))
|
||||
s1 = (uint16_t) (((uint32_t) s1 + (uint32_t) data[i]) % UINT16_MAX);
|
||||
s2 = (uint16_t) (((uint32_t) s2 + (uint32_t) s1) % UINT16_MAX);
|
||||
}
|
||||
return (s2 << 8) | s1;
|
||||
return (((uint32_t) s2) << 16) | ((uint32_t) s1);
|
||||
}
|
||||
|
||||
uint32_t myfletcher32(uint16_t *data, const uint16_t length)
|
||||
uint64_t myfletcher64(uint32_t *data, const size_t length)
|
||||
{
|
||||
uint32_t s1 = 0;
|
||||
uint32_t s2 = 0;
|
||||
for (uint16_t i = 0; i < length; i++)
|
||||
for (size_t i = 0; i < length; i++)
|
||||
{
|
||||
s1 = (s1 + data[i]) % ((((uint32_t) 1) << 16) - 1);
|
||||
s2 = (s2 + s1) % ((((uint32_t) 1) << 16) - 1);
|
||||
// UINT32_MAX = 4294967295ULL = ((((uint64_t) 1) << 32) - ((uint64_t) 1))
|
||||
s1 = (uint32_t) (((uint64_t) s1 + (uint64_t) data[i]) % UINT32_MAX);
|
||||
s2 = (uint32_t) (((uint64_t) s2 + (uint64_t) s1) % UINT32_MAX);
|
||||
}
|
||||
return (s2 << 16) | s1;
|
||||
return (((uint64_t) s2) << 32) | ((uint64_t) s1);
|
||||
}
|
||||
|
||||
uint64_t myfletcher64(uint32_t *data, const uint16_t length)
|
||||
{
|
||||
uint64_t s1 = 0;
|
||||
uint64_t s2 = 0;
|
||||
for (uint16_t i = 0; i < length; i++)
|
||||
{
|
||||
s1 = (s1 + data[i]) % ((((uint64_t) 1) << 32) - 1);
|
||||
s2 = (s2 + s1) % ((((uint64_t) 1) << 32) - 1);
|
||||
}
|
||||
return (s2 << 32) | s1;
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial);
|
||||
}
|
||||
|
||||
void test_fletcher16() {
|
||||
Serial.println("Fletcher16");
|
||||
void test_fletcher16(const byte mode) {
|
||||
Serial.print("| 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);
|
||||
if (mode == 0) {
|
||||
t0 = micros();
|
||||
for (uint16_t i = 0; i < max_len; i++) {
|
||||
values.uint8[i] = (uint8_t) random(0, 1 << 8);
|
||||
}
|
||||
t1 = micros();
|
||||
} else {
|
||||
t0 = micros();
|
||||
for (uint16_t i = 0; i < max_len; i++) {
|
||||
values.uint8[i] = 255;
|
||||
}
|
||||
t1 = micros();
|
||||
}
|
||||
t1 = micros();
|
||||
Serial.print("Created random list: ");
|
||||
Serial.print(1024.0 * (t1 - t0) / float(MAX_LEN));
|
||||
Serial.println(" us/kByte.");
|
||||
Serial.print(float2strn(1024.0 * (t1 - t0) / float(MAX_LEN), 8));
|
||||
Serial.print(" us/kByte | ");
|
||||
Fletcher16 checksum_instance;
|
||||
uint16_t checksum;
|
||||
uint32_t totaltime = 0;
|
||||
@ -82,38 +106,47 @@ void test_fletcher16() {
|
||||
t0 = micros();
|
||||
checksum_instance.begin();
|
||||
for (uint16_t i = 0; i < max_len; i++) {
|
||||
checksum_instance.add(values[i]);
|
||||
checksum_instance.add(values.uint8[i]);
|
||||
}
|
||||
checksum = checksum_instance.getFletcher();
|
||||
t1 = micros();
|
||||
totaltime += t1 - t0;
|
||||
}
|
||||
Serial.print("Checksum: ");
|
||||
uint16_t reference_checksum = myfletcher16(values.uint8, max_len);
|
||||
Serial.print(reference_checksum);
|
||||
Serial.print(" | ");
|
||||
Serial.print(checksum);
|
||||
Serial.print(" ( != ");
|
||||
Serial.print(fletcher16(values, max_len));
|
||||
Serial.print(" != ");
|
||||
Serial.print(myfletcher16(values, max_len));
|
||||
Serial.println(" )");
|
||||
Serial.print("Created checksum: ");
|
||||
Serial.print(1024.0 * totaltime / float(DO_N * MAX_LEN));
|
||||
Serial.println(" us/kByte.");
|
||||
Serial.print(" | ");
|
||||
Serial.print(float2strn(1024.0 * totaltime / float(DO_N * MAX_LEN), 8));
|
||||
Serial.print(" us/kByte | ");
|
||||
if (reference_checksum == checksum) {
|
||||
Serial.print(" OK ");
|
||||
} else {
|
||||
Serial.print(" ERROR ");
|
||||
}
|
||||
Serial.println(" |");
|
||||
}
|
||||
|
||||
void test_fletcher32() {
|
||||
Serial.println("Fletcher32");
|
||||
void test_fletcher32(const byte mode) {
|
||||
Serial.print("| 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);
|
||||
if (mode == 0) {
|
||||
t0 = micros();
|
||||
for (uint16_t i = 0; i < max_len; i++) {
|
||||
values.uint16[i] = (uint16_t) random(0, ((uint32_t) 1) << 16);
|
||||
}
|
||||
t1 = micros();
|
||||
} else {
|
||||
t0 = micros();
|
||||
for (uint16_t i = 0; i < max_len; i++) {
|
||||
values.uint16[i] = 65535UL;
|
||||
}
|
||||
t1 = micros();
|
||||
}
|
||||
t1 = micros();
|
||||
Serial.print("Created random list: ");
|
||||
Serial.print(1024.0 * (t1 - t0) / float(MAX_LEN));
|
||||
Serial.println(" us/kByte.");
|
||||
Serial.print(float2strn(1024.0 * (t1 - t0) / float(MAX_LEN), 8));
|
||||
Serial.print(" us/kByte | ");
|
||||
Fletcher32 checksum_instance;
|
||||
uint32_t checksum;
|
||||
uint32_t totaltime = 0;
|
||||
@ -121,38 +154,47 @@ void test_fletcher32() {
|
||||
t0 = micros();
|
||||
checksum_instance.begin();
|
||||
for (uint16_t i = 0; i < max_len; i++) {
|
||||
checksum_instance.add(values[i]);
|
||||
checksum_instance.add(values.uint16[i]);
|
||||
}
|
||||
checksum = checksum_instance.getFletcher();
|
||||
t1 = micros();
|
||||
totaltime += t1 - t0;
|
||||
}
|
||||
Serial.print("Checksum: ");
|
||||
uint32_t reference_checksum = myfletcher32(values.uint16, max_len);
|
||||
Serial.print(reference_checksum);
|
||||
Serial.print(" | ");
|
||||
Serial.print(checksum);
|
||||
Serial.print(" ( != ");
|
||||
Serial.print(fletcher32(values, max_len));
|
||||
Serial.print(" != ");
|
||||
Serial.print(myfletcher32(values, max_len));
|
||||
Serial.println(" )");
|
||||
Serial.print("Created checksum: ");
|
||||
Serial.print(1024.0 * totaltime / float(DO_N * MAX_LEN));
|
||||
Serial.println(" us/kByte.");
|
||||
Serial.print(" | ");
|
||||
Serial.print(float2strn(1024.0 * totaltime / float(DO_N * MAX_LEN), 8));
|
||||
Serial.print(" us/kByte | ");
|
||||
if (reference_checksum == checksum) {
|
||||
Serial.print(" OK ");
|
||||
} else {
|
||||
Serial.print(" ERROR ");
|
||||
}
|
||||
Serial.println(" |");
|
||||
}
|
||||
|
||||
void test_fletcher64() {
|
||||
Serial.println("Fletcher64");
|
||||
void test_fletcher64(const byte mode) {
|
||||
Serial.print("| 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);
|
||||
if (mode == 0) {
|
||||
t0 = micros();
|
||||
for (uint16_t i = 0; i < max_len; i++) {
|
||||
values.uint32[i] = ((uint32_t) random(0, ((uint32_t) 1) << 16)) + (((uint32_t) random(0, ((uint32_t) 1) << 16)) << 16);
|
||||
}
|
||||
t1 = micros();
|
||||
} else {
|
||||
t0 = micros();
|
||||
for (uint16_t i = 0; i < max_len; i++) {
|
||||
values.uint32[i] = 4294967295ULL;
|
||||
}
|
||||
t1 = micros();
|
||||
}
|
||||
t1 = micros();
|
||||
Serial.print("Created random list: ");
|
||||
Serial.print(1024.0 * (t1 - t0) / float(MAX_LEN));
|
||||
Serial.println(" us/kByte.");
|
||||
Serial.print(float2strn(1024.0 * (t1 - t0) / float(MAX_LEN), 8));
|
||||
Serial.print(" us/kByte | ");
|
||||
Fletcher64 checksum_instance;
|
||||
uint64_t checksum;
|
||||
uint32_t totaltime = 0;
|
||||
@ -160,22 +202,31 @@ void test_fletcher64() {
|
||||
t0 = micros();
|
||||
checksum_instance.begin();
|
||||
for (uint16_t i = 0; i < max_len; i++) {
|
||||
checksum_instance.add(values[i]);
|
||||
checksum_instance.add(values.uint32[i]);
|
||||
}
|
||||
checksum = checksum_instance.getFletcher();
|
||||
t1 = micros();
|
||||
totaltime += t1 - t0;
|
||||
}
|
||||
Serial.print("Checksum: ");
|
||||
uint64_t reference_checksum = myfletcher64(values.uint32, max_len);
|
||||
Serial.print(print64(reference_checksum));
|
||||
Serial.print(" | ");
|
||||
Serial.print(print64(checksum));
|
||||
Serial.print(" ( != ");
|
||||
Serial.print(print64(fletcher64(values, max_len)));
|
||||
Serial.print(" != ");
|
||||
Serial.print(print64(myfletcher64(values, max_len)));
|
||||
Serial.println(" )");
|
||||
Serial.print("Created checksum: ");
|
||||
Serial.print(1024.0 * totaltime / float(DO_N * MAX_LEN));
|
||||
Serial.println(" us/kByte.");
|
||||
Serial.print(" | ");
|
||||
Serial.print(float2strn(1024.0 * totaltime / float(DO_N * MAX_LEN), 8));
|
||||
Serial.print(" us/kByte | ");
|
||||
if (reference_checksum == checksum) {
|
||||
Serial.print(" OK ");
|
||||
} else {
|
||||
Serial.print(" ERROR ");
|
||||
}
|
||||
Serial.println(" |");
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
@ -189,14 +240,18 @@ void loop() {
|
||||
Serial.print(MAX_LEN / 4);
|
||||
Serial.println(" elements for Fletcher64");
|
||||
Serial.println("");
|
||||
test_fletcher16();
|
||||
Serial.println("+------------+---------------------+--------------------+----------------------+-------------------+---------+");
|
||||
Serial.println("| alg | created random list | reference checksum | checksum | datarate | correct |");
|
||||
Serial.println("+------------+---------------------+--------------------+----------------------+-------------------+---------+");
|
||||
test_fletcher16(0);
|
||||
test_fletcher16(1);
|
||||
Serial.println("+------------+---------------------+--------------------+----------------------+-------------------+---------+");
|
||||
test_fletcher32(0);
|
||||
test_fletcher32(1);
|
||||
Serial.println("+------------+---------------------+--------------------+----------------------+-------------------+---------+");
|
||||
test_fletcher64(0);
|
||||
test_fletcher64(1);
|
||||
Serial.println("+------------+---------------------+--------------------+----------------------+-------------------+---------+");
|
||||
Serial.println("");
|
||||
delay(1000);
|
||||
test_fletcher32();
|
||||
Serial.println("");
|
||||
delay(1000);
|
||||
test_fletcher64();
|
||||
Serial.println("");
|
||||
delay(1000);
|
||||
Serial.println("");
|
||||
}
|
||||
|
@ -0,0 +1,55 @@
|
||||
#pragma once
|
||||
/*
|
||||
Author: Daniel Mohr
|
||||
Date: 2022-09-09
|
||||
|
||||
Here are implementations with bit shifts instead of modulo.
|
||||
*/
|
||||
|
||||
uint16_t fletcher16_bit_shift(uint8_t *data, const uint16_t length)
|
||||
{
|
||||
uint16_t _s1 = 0;
|
||||
uint16_t _s2 = 0;
|
||||
for (uint16_t i = 0; i < length; i++)
|
||||
{
|
||||
_s1 += data[i];
|
||||
_s1 = (_s1 & 255) + (_s1 >> 8);
|
||||
_s2 += _s1;
|
||||
_s2 = (_s2 & 255) + (_s2 >> 8);
|
||||
}
|
||||
if (_s1 >= 255) _s1 -= 255;
|
||||
if (_s2 >= 255) _s2 -= 255;
|
||||
return (_s2 << 8) | _s1;
|
||||
}
|
||||
|
||||
uint32_t fletcher32_bit_shift(uint16_t *data, const uint16_t length)
|
||||
{
|
||||
uint32_t _s1 = 0;
|
||||
uint32_t _s2 = 0;
|
||||
for (uint16_t i = 0; i < length; i++)
|
||||
{
|
||||
_s1 += data[i];
|
||||
_s1 = (_s1 & 65535UL) + (_s1 >> 16);
|
||||
_s2 += _s1;
|
||||
_s2 = (_s2 & 65535UL) + (_s2 >> 16);
|
||||
}
|
||||
if (_s1 >= 65535UL) _s1 -= 65535UL;
|
||||
if (_s2 >= 65535UL) _s2 -= 65535UL;
|
||||
return (_s2 << 16) | _s1;
|
||||
}
|
||||
|
||||
uint64_t fletcher64_bit_shift(uint32_t *data, const uint16_t length)
|
||||
{
|
||||
uint64_t _s1 = 0;
|
||||
uint64_t _s2 = 0;
|
||||
for (uint16_t i = 0; i < length; i++)
|
||||
{
|
||||
_s1 += data[i];
|
||||
_s1 = (_s1 & ((((uint64_t) 1) << 32) - 1)) + (_s1 >> 32);
|
||||
_s2 += _s1;
|
||||
_s2 = (_s2 & ((((uint64_t) 1) << 32) - 1)) + (_s2 >> 32);
|
||||
}
|
||||
if (_s1 >= 4294967295ULL) _s1 -= 4294967295ULL;
|
||||
if (_s2 >= 4294967295ULL) _s2 -= 4294967295ULL;
|
||||
return (_s2 << 32) | _s1;
|
||||
}
|
@ -0,0 +1,437 @@
|
||||
/*
|
||||
Author: Daniel Mohr
|
||||
Date: 2022-09-10
|
||||
Purpose: shows stream performance for different implementations
|
||||
*/
|
||||
#include "Arduino.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#include "printHelpers.h" // needed for Arduino Nano
|
||||
|
||||
#include "basic.h"
|
||||
#include "Fletcher_v0.1.3.h"
|
||||
#include "Fletcher_v0.1.4.h"
|
||||
#include "Fletcher_v0.1.5.h"
|
||||
#include "Fletcher_v0.1.6.h"
|
||||
#include "Fletcher_next.h"
|
||||
#include "Fletcher_if_statement.h"
|
||||
#include "Fletcher_bit_shift.h"
|
||||
#include "Fletcher_overflow.h"
|
||||
|
||||
#ifdef ARDUINO_ARCH_AVR
|
||||
#define MAX_LEN 500
|
||||
#else
|
||||
#define MAX_LEN 16384
|
||||
#endif
|
||||
union main_value_storage {
|
||||
uint8_t uint8[MAX_LEN];
|
||||
uint16_t uint16[MAX_LEN/2];
|
||||
uint32_t uint32[MAX_LEN/4];
|
||||
} values;
|
||||
|
||||
#define DO_N 23
|
||||
|
||||
#define n_implementations 9
|
||||
|
||||
uint16_t checksum16[n_implementations];
|
||||
uint32_t checksum32[n_implementations];
|
||||
uint64_t checksum64[n_implementations];
|
||||
uint32_t totaltime16[n_implementations];
|
||||
uint32_t totaltime32[n_implementations];
|
||||
uint64_t totaltime64[n_implementations];
|
||||
uint32_t n16 = 0;
|
||||
uint32_t n32 = 0;
|
||||
uint32_t n64 = 0;
|
||||
bool checksum_correct16[n_implementations];
|
||||
bool checksum_correct32[n_implementations];
|
||||
bool checksum_correct64[n_implementations];
|
||||
|
||||
#if defined(ARDUINO_ARCH_AVR)
|
||||
String float2strn(float value, size_t n) {
|
||||
char strvalout[n];
|
||||
dtostrf(value, n, 2, strvalout);
|
||||
return strvalout;
|
||||
}
|
||||
#else
|
||||
String float2strn(float value, size_t n) {
|
||||
String strval = String(value);
|
||||
while (strval.length() < n) {
|
||||
strval = " " + strval;
|
||||
}
|
||||
return strval;
|
||||
}
|
||||
#endif
|
||||
|
||||
void test_fletcher16() {
|
||||
const size_t max_len = MAX_LEN;
|
||||
for (byte mode = 0; mode < 2; mode++) {
|
||||
for (size_t i = 0; i < max_len; i++) {
|
||||
if (mode == 0) {
|
||||
values.uint8[i] = (uint8_t) random(0, 1 << 8);
|
||||
} else {
|
||||
values.uint8[i] = (uint8_t) ((((uint16_t) 1) << 8) - 1);
|
||||
}
|
||||
}
|
||||
uint32_t t0, t1;
|
||||
for (uint16_t j = 0; j < DO_N; j++) {
|
||||
size_t index;
|
||||
/* reference */
|
||||
index = 0;
|
||||
t0 = micros();
|
||||
checksum16[index] = basic_fletcher16(values.uint8, max_len);
|
||||
t1 = micros();
|
||||
totaltime16[index] += t1 - t0;
|
||||
/* 0.1.3 */
|
||||
index = 1;
|
||||
t0 = micros();
|
||||
checksum16[index] = fletcher16_v0_1_3(values.uint8, max_len);
|
||||
t1 = micros();
|
||||
totaltime16[index] += t1 - t0;
|
||||
if (checksum16[index] != checksum16[0]) {
|
||||
checksum_correct16[index] = false;
|
||||
}
|
||||
/* 0.1.4 */
|
||||
index = 2;
|
||||
t0 = micros();
|
||||
checksum16[index] = fletcher16_v0_1_4(values.uint8, max_len);
|
||||
t1 = micros();
|
||||
totaltime16[index] += t1 - t0;
|
||||
if (checksum16[index] != checksum16[0]) {
|
||||
checksum_correct16[index] = false;
|
||||
}
|
||||
/* 0.1.5 */
|
||||
index = 3;
|
||||
t0 = micros();
|
||||
checksum16[index] = fletcher16_v0_1_5(values.uint8, max_len);
|
||||
t1 = micros();
|
||||
totaltime16[index] += t1 - t0;
|
||||
if (checksum16[index] != checksum16[0]) {
|
||||
checksum_correct16[index] = false;
|
||||
}
|
||||
/* 0.1.6 */
|
||||
index = 4;
|
||||
t0 = micros();
|
||||
checksum16[index] = fletcher16_v0_1_6(values.uint8, max_len);
|
||||
t1 = micros();
|
||||
totaltime16[index] += t1 - t0;
|
||||
if (checksum16[index] != checksum16[0]) {
|
||||
checksum_correct16[index] = false;
|
||||
}
|
||||
/* next */
|
||||
index = 5;
|
||||
t0 = micros();
|
||||
checksum16[index] = fletcher16_next(values.uint8, max_len);
|
||||
t1 = micros();
|
||||
totaltime16[index] += t1 - t0;
|
||||
if (checksum16[index] != checksum16[0]) {
|
||||
checksum_correct16[index] = false;
|
||||
}
|
||||
/* if_statement */
|
||||
index = 6;
|
||||
t0 = micros();
|
||||
checksum16[index] = fletcher16_if_statement(values.uint8, max_len);
|
||||
t1 = micros();
|
||||
totaltime16[index] += t1 - t0;
|
||||
if (checksum16[index] != checksum16[0]) {
|
||||
checksum_correct16[index] = false;
|
||||
}
|
||||
/* bit_shift */
|
||||
index = 7;
|
||||
t0 = micros();
|
||||
checksum16[index] = fletcher16_bit_shift(values.uint8, max_len);
|
||||
t1 = micros();
|
||||
totaltime16[index] += t1 - t0;
|
||||
if (checksum16[index] != checksum16[0]) {
|
||||
checksum_correct16[index] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
n16 += DO_N;
|
||||
}
|
||||
|
||||
void test_fletcher32() {
|
||||
const size_t max_len = MAX_LEN / 2;
|
||||
for (byte m = 0; m < 2; m++) {
|
||||
for (size_t i = 0; i < max_len; i++) {
|
||||
if (m == 0) {
|
||||
values.uint16[i] = (uint16_t) random(0, ((uint32_t) 1) << 16);
|
||||
} else {
|
||||
values.uint16[i] = (uint16_t) ((((uint32_t) 1) << 16) - 1);
|
||||
}
|
||||
}
|
||||
uint32_t t0, t1;
|
||||
for (uint16_t j = 0; j < DO_N; j++) {
|
||||
size_t index;
|
||||
/* reference */
|
||||
index = 0;
|
||||
t0 = micros();
|
||||
checksum32[index] = basic_fletcher32(values.uint16, max_len);
|
||||
t1 = micros();
|
||||
totaltime32[index] += t1 - t0;
|
||||
/* 0.1.3 */
|
||||
index = 1;
|
||||
t0 = micros();
|
||||
checksum32[index] = fletcher32_v0_1_3(values.uint16, max_len);
|
||||
t1 = micros();
|
||||
totaltime32[index] += t1 - t0;
|
||||
if (checksum32[index] != checksum32[0]) {
|
||||
checksum_correct32[1] = false;
|
||||
}
|
||||
/* 0.1.4 */
|
||||
index = 2;
|
||||
t0 = micros();
|
||||
checksum32[index] = fletcher32_v0_1_4(values.uint16, max_len);
|
||||
t1 = micros();
|
||||
totaltime32[index] += t1 - t0;
|
||||
if (checksum32[index] != checksum32[0]) {
|
||||
checksum_correct32[1] = false;
|
||||
}
|
||||
/* 0.1.5 */
|
||||
index = 3;
|
||||
t0 = micros();
|
||||
checksum32[index] = fletcher32_v0_1_5(values.uint16, max_len);
|
||||
t1 = micros();
|
||||
totaltime32[index] += t1 - t0;
|
||||
if (checksum32[index] != checksum32[0]) {
|
||||
checksum_correct32[1] = false;
|
||||
}
|
||||
/* 0.1.6 */
|
||||
index = 4;
|
||||
t0 = micros();
|
||||
checksum32[index] = fletcher32_v0_1_6(values.uint16, max_len);
|
||||
t1 = micros();
|
||||
totaltime32[index] += t1 - t0;
|
||||
if (checksum32[index] != checksum32[0]) {
|
||||
checksum_correct32[1] = false;
|
||||
}
|
||||
/* next */
|
||||
index = 5;
|
||||
t0 = micros();
|
||||
checksum32[index] = fletcher32_next(values.uint16, max_len);
|
||||
t1 = micros();
|
||||
totaltime32[index] += t1 - t0;
|
||||
if (checksum32[index] != checksum32[0]) {
|
||||
checksum_correct32[1] = false;
|
||||
}
|
||||
/* if_statement */
|
||||
index = 6;
|
||||
t0 = micros();
|
||||
checksum32[index] = fletcher32_if_statement(values.uint16, max_len);
|
||||
t1 = micros();
|
||||
totaltime32[index] += t1 - t0;
|
||||
if (checksum32[index] != checksum32[0]) {
|
||||
checksum_correct32[1] = false;
|
||||
}
|
||||
/* bit_shift */
|
||||
index = 7;
|
||||
t0 = micros();
|
||||
checksum32[index] = fletcher32_bit_shift(values.uint16, max_len);
|
||||
t1 = micros();
|
||||
totaltime32[index] += t1 - t0;
|
||||
if (checksum32[index] != checksum32[0]) {
|
||||
checksum_correct32[1] = false;
|
||||
}
|
||||
#ifdef ARDUINO_ARCH_AVR
|
||||
/* overflow */
|
||||
index = 8;
|
||||
t0 = micros();
|
||||
checksum32[index] = fletcher32_overflow(values.uint16, max_len);
|
||||
t1 = micros();
|
||||
totaltime32[index] += t1 - t0;
|
||||
if (checksum32[index] != checksum32[0]) {
|
||||
checksum_correct32[1] = false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
n32 += DO_N;
|
||||
}
|
||||
|
||||
void test_fletcher64() {
|
||||
const size_t max_len = MAX_LEN / 4;
|
||||
for (byte m = 0; m < 2; m++) {
|
||||
for (size_t i = 0; i < max_len; i++) {
|
||||
if (m == 0) {
|
||||
values.uint32[i] = ((uint32_t) random(0, ((uint32_t) 1) << 16)) + (((uint32_t) random(0, ((uint32_t) 1) << 16)) << 16);
|
||||
} else {
|
||||
values.uint32[i] = (uint32_t) ((((uint64_t) 1) << 32) - 1);
|
||||
}
|
||||
}
|
||||
uint32_t t0, t1;
|
||||
for (uint16_t j = 0; j < DO_N; j++) {
|
||||
size_t index;
|
||||
/* reference */
|
||||
index = 0;
|
||||
t0 = micros();
|
||||
checksum64[index] = basic_fletcher64(values.uint32, max_len);
|
||||
t1 = micros();
|
||||
totaltime64[index] += t1 - t0;
|
||||
/* 0.1.3 */
|
||||
index = 1;
|
||||
t0 = micros();
|
||||
checksum64[index] = fletcher64_v0_1_3(values.uint32, max_len);
|
||||
t1 = micros();
|
||||
totaltime64[index] += t1 - t0;
|
||||
if (checksum64[index] != checksum64[0]) {
|
||||
checksum_correct64[1] = false;
|
||||
}
|
||||
/* 0.1.4 */
|
||||
index = 2;
|
||||
t0 = micros();
|
||||
checksum64[index] = fletcher64_v0_1_4(values.uint32, max_len);
|
||||
t1 = micros();
|
||||
totaltime64[index] += t1 - t0;
|
||||
if (checksum64[index] != checksum64[0]) {
|
||||
checksum_correct64[1] = false;
|
||||
}
|
||||
/* 0.1.5 */
|
||||
index = 3;
|
||||
t0 = micros();
|
||||
checksum64[index] = fletcher64_v0_1_5(values.uint32, max_len);
|
||||
t1 = micros();
|
||||
totaltime64[index] += t1 - t0;
|
||||
if (checksum64[index] != checksum64[0]) {
|
||||
checksum_correct64[1] = false;
|
||||
}
|
||||
/* 0.1.6 */
|
||||
index = 4;
|
||||
t0 = micros();
|
||||
checksum64[index] = fletcher64_v0_1_6(values.uint32, max_len);
|
||||
t1 = micros();
|
||||
totaltime64[index] += t1 - t0;
|
||||
if (checksum64[index] != checksum64[0]) {
|
||||
checksum_correct64[1] = false;
|
||||
}
|
||||
/* next */
|
||||
index = 5;
|
||||
t0 = micros();
|
||||
checksum64[index] = fletcher64_next(values.uint32, max_len);
|
||||
t1 = micros();
|
||||
totaltime64[index] += t1 - t0;
|
||||
if (checksum64[index] != checksum64[0]) {
|
||||
checksum_correct64[1] = false;
|
||||
}
|
||||
/* if_statement */
|
||||
index = 6;
|
||||
t0 = micros();
|
||||
checksum64[index] = fletcher64_if_statement(values.uint32, max_len);
|
||||
t1 = micros();
|
||||
totaltime64[index] += t1 - t0;
|
||||
if (checksum64[index] != checksum64[0]) {
|
||||
checksum_correct64[1] = false;
|
||||
}
|
||||
/* bit_shift */
|
||||
index = 7;
|
||||
t0 = micros();
|
||||
checksum64[index] = fletcher64_bit_shift(values.uint32, max_len);
|
||||
t1 = micros();
|
||||
totaltime64[index] += t1 - t0;
|
||||
if (checksum64[index] != checksum64[0]) {
|
||||
checksum_correct64[1] = false;
|
||||
}
|
||||
/* overflow */
|
||||
index = 8;
|
||||
t0 = micros();
|
||||
checksum64[index] = fletcher64_overflow(values.uint32, max_len);
|
||||
t1 = micros();
|
||||
totaltime64[index] += t1 - t0;
|
||||
if (checksum64[index] != checksum64[0]) {
|
||||
checksum_correct64[1] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
n64 += DO_N;
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial);
|
||||
for (uint16_t i = 0; i < n_implementations; i++) {
|
||||
checksum16[i] = 0;
|
||||
checksum32[i] = 0;
|
||||
checksum64[i] = 0;
|
||||
totaltime16[i] = 0;
|
||||
totaltime32[i] = 0;
|
||||
totaltime64[i] = 0;
|
||||
checksum_correct16[i] = true;
|
||||
checksum_correct32[i] = true;
|
||||
checksum_correct64[i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
test_fletcher32();
|
||||
test_fletcher64();
|
||||
// generate output
|
||||
Serial.println("data rate in us/kByte:");
|
||||
Serial.println("+------------+----------+----------+----------+----------+----------+----------+----------+----------+----------+");
|
||||
Serial.println("| alg | basic | 0.1.3 | 0.1.4 | 0.1.5 | 0.1.6 | next | if | shift | overflow |");
|
||||
Serial.println("+------------+----------+----------+----------+----------+----------+----------+----------+----------+----------+");
|
||||
Serial.print("| fletcher16 | ");
|
||||
for (uint16_t i = 0; i < n_implementations; i++) {
|
||||
Serial.print(float2strn(1024.0 * totaltime16[i] / float(n16 * MAX_LEN), 8));
|
||||
Serial.print(" | ");
|
||||
}
|
||||
Serial.println("\n+------------+----------+----------+----------+----------+----------+----------+----------+----------+----------+");
|
||||
Serial.print("| fletcher32 | ");
|
||||
for (uint16_t i = 0; i < n_implementations; i++) {
|
||||
Serial.print(float2strn(1024.0 * totaltime32[i] / float(n32 * MAX_LEN), 8));
|
||||
Serial.print(" | ");
|
||||
}
|
||||
Serial.println("\n+------------+----------+----------+----------+----------+----------+----------+----------+----------+----------+");
|
||||
Serial.print("| fletcher64 | ");
|
||||
for (uint16_t i = 0; i < n_implementations; i++) {
|
||||
Serial.print(float2strn(1024.0 * totaltime64[i] / float(n64 * MAX_LEN), 8));
|
||||
Serial.print(" | ");
|
||||
}
|
||||
Serial.println("\n+------------+----------+----------+----------+----------+----------+----------+----------+----------+----------+\n");
|
||||
Serial.println("checksum always OK?");
|
||||
Serial.println("+------------+-------+-------+-------+-------+-------+-------+-------+-------+-------+");
|
||||
Serial.println("| alg | basic | 0.1.3 | 0.1.4 | 0.1.5 | 0.1.6 | next | if | shift | overf |");
|
||||
Serial.println("+------------+-------+-------+-------+-------+-------+-------+-------+-------+-------+");
|
||||
Serial.print("| fletcher16 | ");
|
||||
for (uint16_t i = 0; i < n_implementations; i++) {
|
||||
if (checksum_correct16[i]) {
|
||||
Serial.print(" ");
|
||||
} else {
|
||||
Serial.print("fail ");
|
||||
}
|
||||
Serial.print(" | ");
|
||||
}
|
||||
Serial.println("\n+------------+-------+-------+-------+-------+-------+-------+-------+-------+-------+");
|
||||
Serial.print("| fletcher32 | ");
|
||||
for (uint16_t i = 0; i < n_implementations; i++) {
|
||||
//Serial.print(checksum_correct32[i]);
|
||||
if (checksum_correct32[i]) {
|
||||
Serial.print(" ");
|
||||
} else {
|
||||
Serial.print("fail ");
|
||||
}
|
||||
Serial.print(" | ");
|
||||
}
|
||||
Serial.println("\n+------------+-------+-------+-------+-------+-------+-------+-------+-------+-------+");
|
||||
Serial.print("| fletcher64 | ");
|
||||
for (uint16_t i = 0; i < n_implementations; i++) {
|
||||
//Serial.print(checksum_correct64[i]);
|
||||
if (checksum_correct64[i]) {
|
||||
Serial.print(" ");
|
||||
} else {
|
||||
Serial.print("fail ");
|
||||
}
|
||||
Serial.print(" | ");
|
||||
}
|
||||
Serial.println("\n+------------+-------+-------+-------+-------+-------+-------+-------+-------+-------+\n");
|
||||
Serial.println("");
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
#pragma once
|
||||
/*
|
||||
Author: Daniel Mohr
|
||||
Date: 2022-09-09
|
||||
|
||||
Here are implementations with if statements instead of modulo.
|
||||
*/
|
||||
|
||||
#define FLETCHER_16_if_statement 255
|
||||
#define FLETCHER_32_if_statement 65535UL
|
||||
#define FLETCHER_64_if_statement 4294967295ULL
|
||||
|
||||
uint16_t fletcher16_if_statement(uint8_t *data, const uint16_t length)
|
||||
{
|
||||
uint16_t _s1 = 0;
|
||||
uint16_t _s2 = 0;
|
||||
for (uint16_t i = 0; i < length; i++)
|
||||
{
|
||||
_s1 += data[i];
|
||||
if (_s1 >= FLETCHER_16_if_statement) _s1 -= FLETCHER_16_if_statement;
|
||||
_s2 += _s1;
|
||||
if (_s2 >= FLETCHER_16_if_statement) _s2 -= FLETCHER_16_if_statement;
|
||||
}
|
||||
return (_s2 << 8) | _s1;
|
||||
}
|
||||
|
||||
uint32_t fletcher32_if_statement(uint16_t *data, const uint16_t length)
|
||||
{
|
||||
uint32_t _s1 = 0;
|
||||
uint32_t _s2 = 0;
|
||||
for (uint16_t i = 0; i < length; i++)
|
||||
{
|
||||
_s1 += data[i];
|
||||
if (_s1 >= FLETCHER_32_if_statement) _s1 -= FLETCHER_32_if_statement;
|
||||
_s2 += _s1;
|
||||
if (_s2 >= FLETCHER_32_if_statement) _s2 -= FLETCHER_32_if_statement;
|
||||
}
|
||||
return (_s2 << 16) | _s1;
|
||||
}
|
||||
|
||||
uint64_t fletcher64_if_statement(uint32_t *data, const uint16_t length)
|
||||
{
|
||||
uint64_t _s1 = 0;
|
||||
uint64_t _s2 = 0;
|
||||
for (uint16_t i = 0; i < length; i++)
|
||||
{
|
||||
_s1 += data[i];
|
||||
if (_s1 >= FLETCHER_64_if_statement) _s1 -= FLETCHER_64_if_statement;
|
||||
_s2 += _s1;
|
||||
if (_s2 >= FLETCHER_64_if_statement) _s2 -= FLETCHER_64_if_statement;
|
||||
}
|
||||
return (_s2 << 32) | _s1;
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
/*
|
||||
Author: Daniel Mohr
|
||||
Date: 2022-09-10
|
||||
|
||||
Here are implementations, which could be used in the next release.
|
||||
|
||||
Fletcher16.cpp
|
||||
Fletcher16.h
|
||||
Fletcher32.cpp
|
||||
Fletcher32.h
|
||||
Fletcher64.cpp
|
||||
Fletcher64.h
|
||||
*/
|
||||
|
||||
#include <Fletcher16.h>
|
||||
#include <Fletcher32.h>
|
||||
#include <Fletcher64.h>
|
||||
|
||||
uint16_t fletcher16_next(uint8_t *data, const size_t length)
|
||||
{
|
||||
Fletcher16 checksum_instance;
|
||||
for (size_t i = 0; i < length; i++)
|
||||
{
|
||||
checksum_instance.add(data[i]);
|
||||
}
|
||||
return checksum_instance.getFletcher();
|
||||
}
|
||||
|
||||
uint32_t fletcher32_next(uint16_t *data, const size_t length)
|
||||
{
|
||||
Fletcher32 checksum_instance;
|
||||
for (size_t i = 0; i < length; i++)
|
||||
{
|
||||
checksum_instance.add(data[i]);
|
||||
}
|
||||
return checksum_instance.getFletcher();
|
||||
}
|
||||
|
||||
uint64_t fletcher64_next(uint32_t *data, const size_t length)
|
||||
{
|
||||
Fletcher64 checksum_instance;
|
||||
for (size_t i = 0; i < length; i++)
|
||||
{
|
||||
checksum_instance.add(data[i]);
|
||||
}
|
||||
return checksum_instance.getFletcher();
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
/*
|
||||
Author: Daniel Mohr
|
||||
Date: 2022-09-09
|
||||
|
||||
Here are implementations with testing for overflow instead of modulo.
|
||||
*/
|
||||
|
||||
#define FLETCHER_64_overflow 4294967295ULL
|
||||
|
||||
#ifdef ARDUINO_ARCH_AVR
|
||||
uint32_t fletcher32_overflow(uint16_t *data, const uint16_t length)
|
||||
{
|
||||
uint16_t _s1 = 0;
|
||||
uint16_t _s2 = 0;
|
||||
for (uint16_t i = 0; i < length; i++)
|
||||
{
|
||||
if (__builtin_uadd_overflow(_s1, data[i], &_s1)) {
|
||||
_s1++;
|
||||
}
|
||||
if (__builtin_uadd_overflow(_s2, _s1, &_s2)) {
|
||||
_s2++;
|
||||
}
|
||||
}
|
||||
return (((uint32_t) _s2) << 16) | ((uint32_t) _s1);
|
||||
}
|
||||
#endif
|
||||
|
||||
uint64_t fletcher64_overflow(uint32_t *data, const uint16_t length)
|
||||
{
|
||||
uint32_t _s1 = 0;
|
||||
uint32_t _s2 = 0;
|
||||
for (uint16_t i = 0; i < length; i++)
|
||||
{
|
||||
if (__builtin_uaddl_overflow(_s1, data[i], &_s1)) {
|
||||
_s1++;
|
||||
}
|
||||
if (__builtin_uaddl_overflow(_s2, _s1, &_s2)) {
|
||||
_s2++;
|
||||
}
|
||||
|
||||
}
|
||||
return (((uint64_t) _s2) << 32) | ((uint64_t) _s1);
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
#pragma once
|
||||
/*
|
||||
Author: Daniel Mohr
|
||||
Date: 2022-09-09
|
||||
|
||||
Here are implementations, which were used in release '0.1.3'.
|
||||
|
||||
Fletcher16.cpp
|
||||
Fletcher16.h
|
||||
Fletcher32.cpp
|
||||
Fletcher32.h
|
||||
Fletcher64.cpp
|
||||
Fletcher64.h
|
||||
*/
|
||||
|
||||
#define FLETCHER_16_v0_1_3 255
|
||||
#define FLETCHER_32_v0_1_3 65535UL
|
||||
#define FLETCHER_64_v0_1_3 4294967295ULL
|
||||
|
||||
uint16_t fletcher16_v0_1_3(uint8_t *data, const uint16_t length)
|
||||
{
|
||||
uint16_t _s1 = 0;
|
||||
uint16_t _s2 = 0;
|
||||
for (uint16_t i = 0; i < length; i++)
|
||||
{
|
||||
_s1 += data[i];
|
||||
if (_s1 >= FLETCHER_16_v0_1_3) _s1 -= FLETCHER_16_v0_1_3;
|
||||
_s2 += _s1;
|
||||
if (_s2 >= FLETCHER_16_v0_1_3) _s2 -= FLETCHER_16_v0_1_3;
|
||||
}
|
||||
return (_s2 << 8) | _s1;
|
||||
}
|
||||
|
||||
uint32_t fletcher32_v0_1_3(uint16_t *data, const uint16_t length)
|
||||
{
|
||||
uint32_t _s1 = 0;
|
||||
uint32_t _s2 = 0;
|
||||
for (uint16_t i = 0; i < length; i++)
|
||||
{
|
||||
_s1 += data[i];
|
||||
if (_s1 >= FLETCHER_32_v0_1_3) _s1 -= FLETCHER_32_v0_1_3;
|
||||
_s2 += _s1;
|
||||
if (_s2 >= FLETCHER_32_v0_1_3) _s2 -= FLETCHER_32_v0_1_3;
|
||||
}
|
||||
return (_s2 << 16) | _s1;
|
||||
}
|
||||
|
||||
uint64_t fletcher64_v0_1_3(uint32_t *data, const uint16_t length)
|
||||
{
|
||||
uint64_t _s1 = 0;
|
||||
uint64_t _s2 = 0;
|
||||
for (uint16_t i = 0; i < length; i++)
|
||||
{
|
||||
_s1 += data[i];
|
||||
if (_s1 >= FLETCHER_64_v0_1_3) _s1 -= FLETCHER_64_v0_1_3;
|
||||
_s2 += _s1;
|
||||
if (_s2 >= FLETCHER_64_v0_1_3) _s2 -= FLETCHER_64_v0_1_3;
|
||||
}
|
||||
return (_s2 << 32) | _s1;
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
#pragma once
|
||||
/*
|
||||
Author: Daniel Mohr
|
||||
Date: 2022-09-09
|
||||
|
||||
Here are implementations, which were used in release '0.1.4'.
|
||||
|
||||
Fletcher16.cpp
|
||||
Fletcher16.h
|
||||
Fletcher32.cpp
|
||||
Fletcher32.h
|
||||
Fletcher64.cpp
|
||||
Fletcher64.h
|
||||
*/
|
||||
|
||||
#define FLETCHER_16_v0_1_4 255
|
||||
#define FLETCHER_32_v0_1_4 65535UL
|
||||
#define FLETCHER_64_v0_1_4 4294967295ULL
|
||||
|
||||
uint16_t fletcher16_v0_1_4(uint8_t *data, const uint16_t length)
|
||||
{
|
||||
uint16_t _s1 = 0;
|
||||
uint16_t _s2 = 0;
|
||||
for (uint16_t i = 0; i < length; i++)
|
||||
{
|
||||
_s1 += data[i];
|
||||
_s1 = (_s1 & 255) + (_s1 >> 8);
|
||||
_s2 += _s1;
|
||||
_s2 = (_s2 & 255) + (_s2 >> 8);
|
||||
}
|
||||
return (_s2 << 8) | _s1;
|
||||
}
|
||||
|
||||
uint32_t fletcher32_v0_1_4(uint16_t *data, const uint16_t length)
|
||||
{
|
||||
uint32_t _s1 = 0;
|
||||
uint32_t _s2 = 0;
|
||||
for (uint16_t i = 0; i < length; i++)
|
||||
{
|
||||
_s1 += data[i];
|
||||
#if defined(ARDUINO_ARCH_SAMD) || defined(ESP32) || defined(ESP8266)
|
||||
_s1 = (_s1 & 65535UL) + (_s1 >> 16);
|
||||
#else
|
||||
if (_s1 >= FLETCHER_32_v0_1_4) _s1 -= FLETCHER_32_v0_1_4;
|
||||
#endif
|
||||
_s2 += _s1;
|
||||
#if defined(ARDUINO_ARCH_SAMD) || defined(ESP32) || defined(ESP8266)
|
||||
_s2 = (_s2 & 65535UL) + (_s2 >> 16);
|
||||
#else
|
||||
if (_s2 >= FLETCHER_32_v0_1_4) _s2 -= FLETCHER_32_v0_1_4;
|
||||
#endif
|
||||
}
|
||||
return (_s2 << 16) | _s1;
|
||||
}
|
||||
|
||||
uint64_t fletcher64_v0_1_4(uint32_t *data, const uint16_t length)
|
||||
{
|
||||
uint64_t _s1 = 0;
|
||||
uint64_t _s2 = 0;
|
||||
for (uint16_t i = 0; i < length; i++)
|
||||
{
|
||||
_s1 += data[i];
|
||||
#if defined(ARDUINO_ARCH_SAMD) || defined(ESP32) || defined(ESP8266)
|
||||
_s1 = (_s1 & ((((uint64_t) 1) << 32) - 1)) + (_s1 >> 32);
|
||||
#else
|
||||
if (_s1 >= FLETCHER_64_v0_1_4) _s1 -= FLETCHER_64_v0_1_4;
|
||||
#endif
|
||||
_s2 += _s1;
|
||||
#if defined(ARDUINO_ARCH_SAMD) || defined(ESP32) || defined(ESP8266)
|
||||
_s2 = (_s2 & ((((uint64_t) 1) << 32) - 1)) + (_s2 >> 32);
|
||||
#else
|
||||
if (_s2 >= FLETCHER_64_v0_1_4) _s2 -= FLETCHER_64_v0_1_4;
|
||||
#endif
|
||||
}
|
||||
return (_s2 << 32) | _s1;
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
#pragma once
|
||||
/*
|
||||
Author: Daniel Mohr
|
||||
Date: 2022-09-09
|
||||
|
||||
Here are implementations, which were used in release '0.1.5'.
|
||||
|
||||
Fletcher16.cpp
|
||||
Fletcher16.h
|
||||
Fletcher32.cpp
|
||||
Fletcher32.h
|
||||
Fletcher64.cpp
|
||||
Fletcher64.h
|
||||
*/
|
||||
|
||||
#define FLETCHER_16_v0_1_5 255
|
||||
#define FLETCHER_32_v0_1_5 65535UL
|
||||
#define FLETCHER_64_v0_1_5 4294967295ULL
|
||||
|
||||
uint16_t fletcher16_v0_1_5(uint8_t *data, const uint16_t length)
|
||||
{
|
||||
uint16_t _s1 = 0;
|
||||
uint16_t _s2 = 0;
|
||||
for (uint16_t i = 0; i < length; i++)
|
||||
{
|
||||
_s1 += data[i];
|
||||
_s1 = (_s1 & 255) + (_s1 >> 8);
|
||||
_s2 += _s1;
|
||||
_s2 = (_s2 & 255) + (_s2 >> 8);
|
||||
}
|
||||
return (_s2 << 8) | _s1;
|
||||
}
|
||||
|
||||
uint32_t fletcher32_v0_1_5(uint16_t *data, const uint16_t length)
|
||||
{
|
||||
uint32_t _s1 = 0;
|
||||
uint32_t _s2 = 0;
|
||||
for (uint16_t i = 0; i < length; i++)
|
||||
{
|
||||
_s1 += data[i];
|
||||
#if defined(ARDUINO_ARCH_SAMD) || defined(ESP32) || defined(ESP8266)
|
||||
_s1 = (_s1 & 65535UL) + (_s1 >> 16);
|
||||
#else
|
||||
if (_s1 >= FLETCHER_32_v0_1_5) _s1 -= FLETCHER_32_v0_1_5;
|
||||
#endif
|
||||
_s2 += _s1;
|
||||
#if defined(ARDUINO_ARCH_SAMD) || defined(ESP32) || defined(ESP8266)
|
||||
_s2 = (_s2 & 65535UL) + (_s2 >> 16);
|
||||
#else
|
||||
if (_s2 >= FLETCHER_32_v0_1_5) _s2 -= FLETCHER_32_v0_1_5;
|
||||
#endif
|
||||
}
|
||||
return (_s2 << 16) | _s1;
|
||||
}
|
||||
|
||||
uint64_t fletcher64_v0_1_5(uint32_t *data, const uint16_t length)
|
||||
{
|
||||
uint64_t _s1 = 0;
|
||||
uint64_t _s2 = 0;
|
||||
for (uint16_t i = 0; i < length; i++)
|
||||
{
|
||||
_s1 += data[i];
|
||||
#if defined(ARDUINO_ARCH_SAMD) || defined(ESP32) || defined(ESP8266)
|
||||
_s1 = (_s1 & ((((uint64_t) 1) << 32) - 1)) + (_s1 >> 32);
|
||||
#else
|
||||
if (_s1 >= FLETCHER_64_v0_1_5) _s1 -= FLETCHER_64_v0_1_5;
|
||||
#endif
|
||||
_s2 += _s1;
|
||||
#if defined(ARDUINO_ARCH_SAMD) || defined(ESP32) || defined(ESP8266)
|
||||
_s2 = (_s2 & ((((uint64_t) 1) << 32) - 1)) + (_s2 >> 32);
|
||||
#else
|
||||
if (_s2 >= FLETCHER_64_v0_1_5) _s2 -= FLETCHER_64_v0_1_5;
|
||||
#endif
|
||||
}
|
||||
return (_s2 << 32) | _s1;
|
||||
}
|
@ -0,0 +1,133 @@
|
||||
#pragma once
|
||||
/*
|
||||
Author: Daniel Mohr
|
||||
Date: 2022-09-12
|
||||
|
||||
Here are implementations, which were used in release '0.1.6'.
|
||||
|
||||
Fletcher16.cpp
|
||||
Fletcher16.h
|
||||
Fletcher32.cpp
|
||||
Fletcher32.h
|
||||
Fletcher64.cpp
|
||||
Fletcher64.h
|
||||
*/
|
||||
|
||||
#define FLETCHER_16_v0_1_6 255
|
||||
#define FLETCHER_32_v0_1_6 65535UL
|
||||
#define FLETCHER_64_v0_1_6 4294967295ULL
|
||||
|
||||
uint16_t fletcher16_v0_1_6(uint8_t *data, const uint16_t length)
|
||||
{
|
||||
#ifdef ARDUINO_ARCH_AVR
|
||||
uint8_t _s1 = 0;
|
||||
uint8_t _s2 = 0;
|
||||
#else
|
||||
uint16_t _s1 = 0;
|
||||
uint16_t _s2 = 0;
|
||||
#endif
|
||||
for (uint16_t i = 0; i < length; i++)
|
||||
{
|
||||
#if defined(ARDUINO_ARCH_AVR)
|
||||
uint8_t t = 0xFF - data[i];
|
||||
if (t >= _s1) _s1 += data[i];
|
||||
else _s1 = _s1 + data[i] + 1;
|
||||
|
||||
t = 0xFF - _s1;
|
||||
if (t >= _s2) _s2 += _s1;
|
||||
else _s2 = _s2 + _s1 + 1;
|
||||
|
||||
#elif defined(ARDUINO_ARCH_SAMD) || defined(ESP32) || defined(ESP8266)
|
||||
_s1 += data[i];
|
||||
_s1 = (_s1 & 255) + (_s1 >> 8);
|
||||
_s2 += _s1;
|
||||
_s2 = (_s2 & 255) + (_s2 >> 8);
|
||||
|
||||
#else
|
||||
// REFERENCE
|
||||
_s1 += data[i];
|
||||
if (_s1 >= FLETCHER_16_v0_1_6) _s1 -= FLETCHER_16_v0_1_6;
|
||||
_s2 += _s1;
|
||||
if (_s2 >= FLETCHER_16_v0_1_6) _s2 -= FLETCHER_16_v0_1_6;
|
||||
#endif
|
||||
}
|
||||
if (_s1 >= FLETCHER_16_v0_1_6) _s1 -= FLETCHER_16_v0_1_6;
|
||||
if (_s2 >= FLETCHER_16_v0_1_6) _s2 -= FLETCHER_16_v0_1_6;
|
||||
return (((uint16_t)_s2) << 8) | _s1;
|
||||
}
|
||||
|
||||
uint32_t fletcher32_v0_1_6(uint16_t *data, const uint16_t length)
|
||||
{
|
||||
#ifdef ARDUINO_ARCH_AVR
|
||||
uint16_t _s1 = 0;
|
||||
uint16_t _s2 = 0;
|
||||
#else
|
||||
uint32_t _s1 = 0;
|
||||
uint32_t _s2 = 0;
|
||||
#endif
|
||||
for (uint16_t i = 0; i < length; i++)
|
||||
{
|
||||
#ifdef ARDUINO_ARCH_AVR
|
||||
unsigned int t = _s1;
|
||||
// Serial.println("__builtin_uadd_overflow");
|
||||
if (__builtin_uadd_overflow(t, data[i], &t)) {
|
||||
t++;
|
||||
}
|
||||
_s1 = t;
|
||||
t = _s2;
|
||||
if (__builtin_uadd_overflow(t, _s1, &t)) {
|
||||
t++;
|
||||
}
|
||||
_s2 = t;
|
||||
#elif defined(ARDUINO_ARCH_SAMD) || defined(ESP32) || defined(ESP8266)
|
||||
_s1 += data[i];
|
||||
_s1 = (_s1 & 65535UL) + (_s1 >> 16);
|
||||
_s2 += _s1;
|
||||
_s2 = (_s2 & 65535UL) + (_s2 >> 16);
|
||||
#else
|
||||
_s1 += data[i];
|
||||
if (_s1 >= FLETCHER_32_v0_1_6) _s1 -= FLETCHER_32_v0_1_6;
|
||||
_s2 += _s1;
|
||||
if (_s2 >= FLETCHER_32_v0_1_6) _s2 -= FLETCHER_32_v0_1_6;
|
||||
#endif
|
||||
}
|
||||
if (_s1 >= FLETCHER_32_v0_1_6) _s1 -= FLETCHER_32_v0_1_6;
|
||||
if (_s2 >= FLETCHER_32_v0_1_6) _s2 -= FLETCHER_32_v0_1_6;
|
||||
return (((uint32_t)_s2) << 16) | _s1;
|
||||
}
|
||||
|
||||
uint64_t fletcher64_v0_1_6(uint32_t *data, const uint16_t length)
|
||||
{
|
||||
#if defined(ARDUINO_ARCH_AVR) || defined(ESP32) || defined(ESP8266)
|
||||
uint32_t _s1 = 0;
|
||||
uint32_t _s2 = 0;
|
||||
#else
|
||||
uint64_t _s1 = 0;
|
||||
uint64_t _s2 = 0;
|
||||
#endif
|
||||
for (uint16_t i = 0; i < length; i++)
|
||||
{
|
||||
#if defined(ARDUINO_ARCH_AVR) || defined(ESP32) || defined(ESP8266)
|
||||
uint32_t t = 0xFFFFFFFF - data[i];
|
||||
if (t >= _s1) _s1 += data[i];
|
||||
else _s1 = _s1 + data[i] + 1;
|
||||
|
||||
t = 0xFFFFFFFF - _s1;
|
||||
if (t >= _s2) _s2 += _s1;
|
||||
else _s2 = _s2 + _s1 + 1;
|
||||
#elif defined(ARDUINO_ARCH_SAMD)
|
||||
_s1 += data[i];
|
||||
_s1 = (_s1 & ((((uint64_t) 1) << 32) - 1)) + (_s1 >> 32);
|
||||
_s2 += _s1;
|
||||
_s2 = (_s2 & ((((uint64_t) 1) << 32) - 1)) + (_s2 >> 32);
|
||||
#else
|
||||
_s1 += data[i];
|
||||
if (_s1 >= FLETCHER_64_v0_1_6) _s1 -= FLETCHER_64_v0_1_6;
|
||||
_s2 += _s1;
|
||||
if (_s2 >= FLETCHER_64_v0_1_6) _s2 -= FLETCHER_64_v0_1_6;
|
||||
#endif
|
||||
}
|
||||
if (_s1 >= FLETCHER_64_v0_1_6) _s1 -= FLETCHER_64_v0_1_6;
|
||||
if (_s2 >= FLETCHER_64_v0_1_6) _s2 -= FLETCHER_64_v0_1_6;
|
||||
return (((uint64_t)_s2) << 32) | _s1;
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
/*
|
||||
Author: Daniel Mohr
|
||||
Date: 2022-09-13
|
||||
|
||||
Here are basic implementations which should give reference values.
|
||||
*/
|
||||
|
||||
uint16_t basic_fletcher16(uint8_t *data, const size_t length)
|
||||
{
|
||||
uint8_t s1 = 0;
|
||||
uint8_t s2 = 0;
|
||||
for (size_t i = 0; i < length; i++)
|
||||
{
|
||||
// UINT8_MAX = 255 = ((((uint16_t) 1) << 8) - ((uint16_t) 1))
|
||||
s1 = (uint8_t) (((uint16_t) s1 + (uint16_t) data[i]) % UINT8_MAX);
|
||||
s2 = (uint8_t) (((uint16_t) s2 + (uint16_t) s1) % UINT8_MAX);
|
||||
}
|
||||
return (((uint16_t) s2) << 8) | ((uint16_t) s1);
|
||||
}
|
||||
|
||||
uint32_t basic_fletcher32(uint16_t *data, const size_t length)
|
||||
{
|
||||
uint16_t s1 = 0;
|
||||
uint16_t s2 = 0;
|
||||
for (size_t i = 0; i < length; i++)
|
||||
{
|
||||
// UINT16_MAX = 65535UL = ((((uint32_t) 1) << 16) - ((uint32_t) 1))
|
||||
s1 = (uint16_t) (((uint32_t) s1 + (uint32_t) data[i]) % UINT16_MAX);
|
||||
s2 = (uint16_t) (((uint32_t) s2 + (uint32_t) s1) % UINT16_MAX);
|
||||
}
|
||||
return (((uint32_t) s2) << 16) | ((uint32_t) s1);
|
||||
}
|
||||
|
||||
uint64_t basic_fletcher64(uint32_t *data, const size_t length)
|
||||
{
|
||||
uint32_t s1 = 0;
|
||||
uint32_t s2 = 0;
|
||||
for (size_t i = 0; i < length; i++)
|
||||
{
|
||||
// UINT32_MAX = 4294967295ULL = ((((uint64_t) 1) << 32) - ((uint64_t) 1))
|
||||
s1 = (uint32_t) (((uint64_t) s1 + (uint64_t) data[i]) % UINT32_MAX);
|
||||
s2 = (uint32_t) (((uint64_t) s2 + (uint64_t) s1) % UINT32_MAX);
|
||||
}
|
||||
return (((uint64_t) s2) << 32) | ((uint64_t) s1);
|
||||
}
|
@ -8,6 +8,9 @@
|
||||
"name": "Rob Tillaart",
|
||||
"email": "Rob.Tillaart@gmail.com",
|
||||
"maintainer": true
|
||||
},
|
||||
{
|
||||
"name": "Daniel Mohr"
|
||||
}
|
||||
],
|
||||
"repository":
|
||||
@ -15,7 +18,7 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/Fletcher.git"
|
||||
},
|
||||
"version": "0.1.5",
|
||||
"version": "0.1.6",
|
||||
"license": "MIT",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*",
|
||||
|
@ -1,5 +1,5 @@
|
||||
name=Fletcher
|
||||
version=0.1.5
|
||||
version=0.1.6
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence="Arduino Library for calculating Fletcher's checksum.
|
||||
|
@ -26,6 +26,9 @@
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "Fletcher.h"
|
||||
#include "Fletcher16.h"
|
||||
#include "Fletcher32.h"
|
||||
#include "Fletcher64.h"
|
||||
|
||||
|
||||
|
||||
@ -83,6 +86,56 @@ unittest(test_fletcher64)
|
||||
}
|
||||
|
||||
|
||||
unittest(test_FF_1)
|
||||
{
|
||||
uint8_t x[1] = { 0xFF };
|
||||
uint16_t y[1] = { 0xFFFF };
|
||||
uint32_t z[1] = { 0xFFFFFFFF };
|
||||
|
||||
assertEqual(0, fletcher16(x, 1));
|
||||
assertEqual(0, fletcher32(y, 1));
|
||||
assertEqual(0, fletcher64(z, 1));
|
||||
}
|
||||
|
||||
|
||||
unittest(test_FF_2)
|
||||
{
|
||||
uint8_t x[1] = { 0xFF };
|
||||
uint16_t y[1] = { 0xFFFF };
|
||||
uint32_t z[1] = { 0xFFFFFFFF };
|
||||
|
||||
Fletcher16 FL16;
|
||||
FL16.begin();
|
||||
assertEqual(0, FL16.getFletcher());
|
||||
FL16.begin(0xFF, 0);
|
||||
assertEqual(0, FL16.getFletcher());
|
||||
FL16.add(0xFF);
|
||||
assertEqual(0, FL16.getFletcher());
|
||||
FL16.add(0xFF);
|
||||
assertEqual(0, FL16.getFletcher());
|
||||
|
||||
Fletcher32 FL32;
|
||||
FL32.begin();
|
||||
assertEqual(0, FL32.getFletcher());
|
||||
FL32.begin(0xFFFF, 0);
|
||||
assertEqual(0, FL32.getFletcher());
|
||||
FL32.add(0xFFFF);
|
||||
assertEqual(0, FL32.getFletcher());
|
||||
FL32.add(0xFFFF);
|
||||
assertEqual(0, FL32.getFletcher());
|
||||
|
||||
Fletcher64 FL64;
|
||||
FL64.begin();
|
||||
assertEqual(0, FL64.getFletcher());
|
||||
FL64.begin(0xFFFFFFFF, 0);
|
||||
assertEqual(0, FL64.getFletcher());
|
||||
FL64.add(0xFFFFFFFF);
|
||||
assertEqual(0, FL64.getFletcher());
|
||||
FL64.add(0xFFFFFFFF);
|
||||
assertEqual(0, FL64.getFletcher());
|
||||
}
|
||||
|
||||
|
||||
unittest_main()
|
||||
|
||||
// --------
|
||||
|
Loading…
x
Reference in New Issue
Block a user