diff --git a/libraries/Adler/Adler.cpp b/libraries/Adler/Adler.cpp index 81c50516..0b411639 100644 --- a/libraries/Adler/Adler.cpp +++ b/libraries/Adler/Adler.cpp @@ -1,7 +1,7 @@ // // FILE: Adler.cpp // AUTHOR: Rob Tillaart -// VERSION: 0.2.0 +// VERSION: 0.2.1 // DATE: 2022-01-27 // PURPOSE: Arduino Library for calculating Adler checksum // URL: https://github.com/RobTillaart/Adler diff --git a/libraries/Adler/Adler.h b/libraries/Adler/Adler.h index 7257b8fb..063e4f84 100644 --- a/libraries/Adler/Adler.h +++ b/libraries/Adler/Adler.h @@ -2,7 +2,7 @@ // // FILE: Adler.h // AUTHOR: Rob Tillaart -// VERSION: 0.2.0 +// VERSION: 0.2.1 // DATE: 2022-01-27 // PURPOSE: Arduino Library for calculating Adler checksum // URL: https://github.com/RobTillaart/Adler @@ -12,7 +12,7 @@ #include "Arduino.h" -#define ADLER_LIB_VERSION (F("0.2.0")) +#define ADLER_LIB_VERSION (F("0.2.1")) const uint32_t ADLER32_MOD_PRIME = 65521; diff --git a/libraries/Adler/Adler16.cpp b/libraries/Adler/Adler16.cpp index 1d8d397b..6c482b0c 100644 --- a/libraries/Adler/Adler16.cpp +++ b/libraries/Adler/Adler16.cpp @@ -1,7 +1,7 @@ // // FILE: Adler16.cpp // AUTHOR: Rob Tillaart -// VERSION: 0.2.0 +// VERSION: 0.2.1 // DATE: 2022-06-14 // PURPOSE: Arduino Library for calculating Adler-16 checksum // URL: https://github.com/RobTillaart/Adler @@ -56,13 +56,14 @@ void Adler16::add(uint8_t value) // straightforward going through the array. // small footprint -void Adler16::add(uint8_t * array, uint16_t length) +// returns current Adler value +uint16_t Adler16::add(uint8_t * array, uint16_t length) { while (length--) { add(*array++); } - return; + return (_s2 << 8) | _s1; } @@ -71,7 +72,8 @@ void Adler16::add(uint8_t * array, uint16_t length) // S2 grows quadratic // only do modulo when S2 reaches halfway uint16_t // and at the end of the loop. -void Adler16::addFast(uint8_t * array, uint16_t length) +// returns current Adler value +uint16_t Adler16::addFast(uint8_t * array, uint16_t length) { _count += length; uint16_t s1 = _s1; @@ -92,6 +94,7 @@ void Adler16::addFast(uint8_t * array, uint16_t length) } _s1 = s1; _s2 = s2; + return (s2 << 8) | s1; } @@ -101,6 +104,12 @@ uint16_t Adler16::getAdler() }; +uint16_t Adler16::count() +{ + return _count; +}; + + ////////////////////////////////////////////////////////////// // // wrappers for strings. @@ -111,15 +120,15 @@ void Adler16::add(char value) } -void Adler16::add(char * array, uint16_t length) +uint16_t Adler16::add(char * array, uint16_t length) { - add((uint8_t *) array, length); + return add((uint8_t *) array, length); } -void Adler16::addFast(char * array, uint16_t length) +uint16_t Adler16::addFast(char * array, uint16_t length) { - addFast((uint8_t *) array, length); + return addFast((uint8_t *) array, length); } diff --git a/libraries/Adler/Adler16.h b/libraries/Adler/Adler16.h index 26326de1..3743bef1 100644 --- a/libraries/Adler/Adler16.h +++ b/libraries/Adler/Adler16.h @@ -2,7 +2,7 @@ // // FILE: Adler16.cpp // AUTHOR: Rob Tillaart -// VERSION: 0.2.0 +// VERSION: 0.2.1 // DATE: 2022-06-15 // PURPOSE: Arduino Library for calculating Adler-16 checksum // URL: https://github.com/RobTillaart/Adler @@ -13,7 +13,7 @@ #include "Arduino.h" -#define ADLER16_LIB_VERSION (F("0.2.0")) +#define ADLER16_LIB_VERSION (F("0.2.1")) // largest prime below 2^8 @@ -24,21 +24,25 @@ class Adler16 public: Adler16(); - void begin(uint16_t s1 = 1, uint16_t s2 = 0); + void begin(uint16_t s1 = 1, uint16_t s2 = 0); - void add(uint8_t value); - void add(uint8_t * array, uint16_t length); + void add(uint8_t value); + // returns current Adler value + uint16_t add(uint8_t * array, uint16_t length); // trade PROGMEM for speed - void addFast(uint8_t * array, uint16_t length); + // returns current Adler value + uint16_t addFast(uint8_t * array, uint16_t length); // wrappers for strings - void add(char value); - void add(char * array, uint16_t length); - void addFast(char * array, uint16_t length); - + void add(char value); + // returns current Adler value + uint16_t add(char * array, uint16_t length); + // returns current Adler value + uint16_t addFast(char * array, uint16_t length); + // returns current Adler value uint16_t getAdler(); - uint16_t count() { return _count; }; + uint16_t count(); private: uint16_t _s1; diff --git a/libraries/Adler/Adler32.cpp b/libraries/Adler/Adler32.cpp index 5ca98bcc..91535c14 100644 --- a/libraries/Adler/Adler32.cpp +++ b/libraries/Adler/Adler32.cpp @@ -1,7 +1,7 @@ // // FILE: Adler32.cpp // AUTHOR: Rob Tillaart -// VERSION: 0.2.0 +// VERSION: 0.2.1 // DATE: 2022-01-27 // PURPOSE: Arduino Library for calculating Adler-32 checksum // URL: https://github.com/RobTillaart/Adler @@ -55,13 +55,14 @@ void Adler32::add(uint8_t value) // straightforward going through the array. // small footprint. -void Adler32::add(uint8_t * array, uint16_t length) +// returns current Adler value +uint32_t Adler32::add(uint8_t * array, uint16_t length) { while (length--) { add(*array++); } - return; + return (_s2 << 16) | _s1; } @@ -70,7 +71,8 @@ void Adler32::add(uint8_t * array, uint16_t length) // S2 grows quadratic // only do modulo when S2 reaches halfway uint32_t // and at the end of the loop. -void Adler32::addFast(uint8_t * array, uint16_t length) +// returns current Adler value +uint32_t Adler32::addFast(uint8_t * array, uint16_t length) { _count += length; uint32_t s1 = _s1; @@ -91,6 +93,7 @@ void Adler32::addFast(uint8_t * array, uint16_t length) } _s1 = s1; _s2 = s2; + return (s2 << 16) | s1; } @@ -100,6 +103,11 @@ uint32_t Adler32::getAdler() }; +uint32_t Adler32::count() +{ + return _count; +}; + ////////////////////////////////////////////////////////////// // @@ -111,15 +119,15 @@ void Adler32::add(char value) } -void Adler32::add(char * array, uint16_t length) +uint32_t Adler32::add(char * array, uint16_t length) { - add((uint8_t *) array, length); + return add((uint8_t *) array, length); } -void Adler32::addFast(char * array, uint16_t length) +uint32_t Adler32::addFast(char * array, uint16_t length) { - addFast((uint8_t *) array, length); + return addFast((uint8_t *) array, length); } diff --git a/libraries/Adler/Adler32.h b/libraries/Adler/Adler32.h index aebb0181..7953ec02 100644 --- a/libraries/Adler/Adler32.h +++ b/libraries/Adler/Adler32.h @@ -2,7 +2,7 @@ // // FILE: Adler.h // AUTHOR: Rob Tillaart -// VERSION: 0.2.0 +// VERSION: 0.2.1 // DATE: 2022-01-27 // PURPOSE: Arduino Library for calculating Adler-32 checksum // URL: https://github.com/RobTillaart/Adler @@ -12,7 +12,7 @@ #include "Arduino.h" -#define ADLER32_LIB_VERSION (F("0.2.0")) +#define ADLER32_LIB_VERSION (F("0.2.1")) // largest prime below 2^16 @@ -24,21 +24,25 @@ class Adler32 public: Adler32(); - void begin(uint32_t s1 = 1, uint32_t s2 = 0); + void begin(uint32_t s1 = 1, uint32_t s2 = 0); - void add(uint8_t value); - void add(uint8_t * array, uint16_t length); + void add(uint8_t value); + // returns current Adler value + uint32_t add(uint8_t * array, uint16_t length); // trade PROGMEM for speed - void addFast(uint8_t * array, uint16_t length); + // returns current Adler value + uint32_t addFast(uint8_t * array, uint16_t length); // wrappers for strings - void add(char value); - void add(char * array, uint16_t length); - void addFast(char * array, uint16_t length); + void add(char value); + // returns current Adler value + uint32_t add(char * array, uint16_t length); + // returns current Adler value + uint32_t addFast(char * array, uint16_t length); uint32_t getAdler(); - uint32_t count() { return _count; }; + uint32_t count(); private: uint32_t _s1; diff --git a/libraries/Adler/CHANGELOG.md b/libraries/Adler/CHANGELOG.md index 8505120e..c3b7ab2f 100644 --- a/libraries/Adler/CHANGELOG.md +++ b/libraries/Adler/CHANGELOG.md @@ -5,6 +5,13 @@ 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.2.1] - 2022-09-20 + +- return value added to **add(array)** +- return value added to **addFast(array, length)** +- update documentation (e.g. timing table). +- moved count() to .cpp + ## [0.2.0] - 2022-06-15 - breaking change diff --git a/libraries/Adler/README.md b/libraries/Adler/README.md index d21f7748..42c74fbc 100644 --- a/libraries/Adler/README.md +++ b/libraries/Adler/README.md @@ -15,9 +15,9 @@ Arduino Library for Adler-32 and experimental Adler-16 checksum. This library provides a Adler32 checksum of a data array. Furthermore since 0.2.0 an experimental Adler-16 implementation is added. -This one is often faster as it uses a smaller checksum than the Adler32, -and the price is that it is less sensitive than the Adler32. -Still it might have its niches where it will be useful. +This one is often faster as it uses a smaller checksum than the Adler32. +The price is that Adler16 is less sensitive than the Adler32. +Still it will have its niches where it will be useful. Relates to https://github.com/RobTillaart/CRC @@ -46,10 +46,14 @@ The interface for the Adler16 is very similar. optional setting start values for s1 and s2. Note this is not part of the standard. This allows a restart from a specific index in a buffer. - **void add(uint8_t value)** add a single value to the checksum. -- **void add(const uint8_t \* array, uint8_t length)** add an array of values to the checksum. -- **void addFast(const uint8_t \* array, uint8_t length)** add an array of values to the checksum. Is faster by trading PROGMEM for performance. +- **uint32_t add(const uint8_t \* array, uint8_t length)** add an array of values to the checksum. +Returns the current checksum. +- **uint32_t addFast(const uint8_t \* array, uint8_t length)** add an array of values to the checksum. +Is faster by trading PROGMEM for performance. +Returns the current checksum. - **uint32_t getAdler()** get the current checksum. -- **uint32_t count()** get the number of items added. Merely a debugging feature, can overflow without affecting checksum. +- **uint32_t count()** get the number of items added. Merely a debugging feature, +can overflow without affecting checksum. The class is typically used for streaming very large blocks of data, optional with intermediate checksum tests. @@ -57,7 +61,8 @@ optional with intermediate checksum tests. ## Performance Adler32 -Not tested ESP32 (and many other platforms) yet. +Only tested on UNO and ESP32 yet. +If you have data of other platforms, please let me know. Numbers measured with **Adler32_performance.ino**. @@ -69,9 +74,9 @@ instead of a modulo. | Version | Function | UNO 16 MHz | ESP32 240 MHz | |:-------:|:---------|:----------:|:-------------:| -| 0.1.0 | add | 5.6 us | | -| 0.1.2 | add | 6.6 us | | -| 0.2.0 | add | 5.9 us | | +| 0.1.0 | add | 5.6 us | | +| 0.1.2 | add | 6.6 us | | +| 0.2.0 | add | 5.9 us | 1.7 us | ### add(lorem) 868 chars @@ -81,9 +86,10 @@ over the array and has a small footprint. | Version | Function | UNO 16 MHz | ESP32 240 MHz | |:-------:|:---------|:----------:|:-------------:| -| 0.1.0 | add | | | -| 0.1.2 | add | 6392 us | | -| 0.2.0 | add | 5748 us | | +| 0.1.0 | add | | | +| 0.1.2 | add | 6392 us | | +| 0.2.0 | add | 5748 us | 145 us | + Note: **add()** is about 6.6 us per byte. @@ -91,7 +97,7 @@ Note: **add()** is about 6.6 us per byte. ### addFast(lorem) 868 chars The **addFast(array, length)** is faster than the -reference **add(array, length)** and uses 108 bytes more. +reference **add(array, length)** and uses 108 bytes more (UNO). So the function has a larger footprint. Depending on your needs, choose performance or footprint. @@ -102,15 +108,15 @@ See **Adler32_performance_addFast.ino** |:-------:|:---------|:----------:|:-------------:| | 0.1.0 | addFast | | | | 0.1.2 | addFast | 1348 us | | -| 0.2.0 | addFast | 1348 us | | +| 0.2.0 | addFast | 1348 us | 66 us | Note: **addFast()** is less than 2 us per byte. - ## Performance Adler16 -Not tested ESP32 (and many other platforms) yet. +Only tested on UNO and ESP32 yet. +If you have data of other platforms, please let me know. Numbers measured with **Adler16_performance.ino**. @@ -122,7 +128,7 @@ instead of a modulo. | Version | Function | UNO 16 MHz | ESP32 240 MHz | |:-------:|:---------|:----------:|:-------------:| -| 0.2.0 | add | 4.0 us | | +| 0.2.0 | add | 4.0 us | 1.8 us | The per byte performance of the Adler16 (on UNO) is faster than the Adler32 **add(value)**. The reason is that a 16 bit @@ -136,7 +142,7 @@ over the array and has a small footprint. | Version | Function | UNO 16 MHz | ESP32 240 MHz | |:-------:|:---------|:----------:|:-------------:| -| 0.2.0 | add | 4040 us | | +| 0.2.0 | add | 4040 us | 160 us | Note: **add()** is about 6.6 us per byte. @@ -148,7 +154,7 @@ reference **add(array, length)**. | Version | Function | UNO 16 MHz | ESP32 240 MHz | |:-------:|:---------|:----------:|:-------------:| -| 0.2.0 | addFast | 1968 us | | +| 0.2.0 | addFast | 1968 us | 79 us | The gain of the faster 16 bit modulo meets the frequency of doing the modulo more often. @@ -169,7 +175,8 @@ Think of packets in a network, records in a database, or a checksum for an confi ### Performance -Not tested ESP32 (and many other platforms) yet. +Only tested on UNO and ESP32 yet. +If you have data of other platforms, please let me know. Numbers measured with **Adler_performance.ino**. @@ -179,18 +186,20 @@ Lorem Ipsum text = 868 bytes. |:-------:|:---------|:----------:|:-------------:| | 0.1.0 | Adler32 | 1116 us | | | 0.1.2 | Adler32 | 1116 us | | -| 0.2.0 | Adler32 | 1116 us | | -| 0.2.0 | Adler16 | 1736 us | | +| 0.2.0 | Adler32 | 1116 us | 60 us | +| 0.2.0 | Adler16 | 1736 us | 75 us | +#### UNO + Adler32 average 1116 / 868 = 1.29 us per byte. Adler16 average 1736 / 868 = 2.00 us per byte. (~1.5x slower !) Adler16 does more often the modulo math as it reaches halfway uint16_t faster than Adler32 reaches halfway uint32_t. -As the Adler16 is less performant as the Adler32, it is often the best to use -the 32 bit version. +As the Adler16 is less performant as the Adler32 (on all tested platforms), +it is often the best to use the 32 bit version. ## Operation @@ -200,17 +209,20 @@ See examples. ## Future -- return values for **add(array)** and **addFast(array)** - - updated checksum? - - not for **add(value)** as that would create quite some overhead. - Adler64 ? - - would need a large prime (which) + - would need a large prime (which) => 4294967291 + - max uint32_t = 4.294.967.296 + - max uint32_t prime = 4.294.967.291 + - need printHelpers library for printing. + - only on request. #### Wont - do the string wrappers need strlen() ? parameter. - yes, as string can be processed partially. +- no return value for **add(value)** + - would create too much overhead for repeated calls. diff --git a/libraries/Adler/examples/Adler32_performance/Adler32_performance_0.2.0_esp32.txt b/libraries/Adler/examples/Adler32_performance/Adler32_performance_0.2.0_esp32.txt new file mode 100644 index 00000000..ac4fb041 --- /dev/null +++ b/libraries/Adler/examples/Adler32_performance/Adler32_performance_0.2.0_esp32.txt @@ -0,0 +1,25 @@ +Adler32_performance +ADLER32_LIB_VERSION: 0.2.0 +randomtime: 6949 + total: 8639 + 1e4 x add: 1690 + checksum: 2580568639 + + total: 224706 + 1e6 x add: 217757 + checksum: 237492440 + +LENGTH LOREM: 868 + + lorem 1: 198 checksum: 3972480156 + lorem 2: 145 checksum: 3972480156 + lorem 3: 66 checksum: 3972480156 + +LENGTH HELLO: 11 + + hello 1: 3 checksum: 436929629 + hello 2: 3 checksum: 436929629 + hello 3: 3 checksum: 436929629 + + + diff --git a/libraries/Adler/library.json b/libraries/Adler/library.json index 40273c61..cc724123 100644 --- a/libraries/Adler/library.json +++ b/libraries/Adler/library.json @@ -15,7 +15,7 @@ "type": "git", "url": "https://github.com/RobTillaart/Adler.git" }, - "version": "0.2.0", + "version": "0.2.1", "license": "MIT", "frameworks": "arduino", "platforms": "*", diff --git a/libraries/Adler/library.properties b/libraries/Adler/library.properties index 878ad00e..699d8478 100644 --- a/libraries/Adler/library.properties +++ b/libraries/Adler/library.properties @@ -1,5 +1,5 @@ name=Adler -version=0.2.0 +version=0.2.1 author=Rob Tillaart maintainer=Rob Tillaart sentence=Arduino Library for calculating Adler-32 and Adler-16 checksum. diff --git a/libraries/Adler/test/unit_test_Adler16.cpp b/libraries/Adler/test/unit_test_Adler16.cpp index 316f33f9..7ab8c865 100644 --- a/libraries/Adler/test/unit_test_Adler16.cpp +++ b/libraries/Adler/test/unit_test_Adler16.cpp @@ -74,14 +74,17 @@ unittest(test_ADLER16_lorem) ad16.add(lorem[i]); } assertEqual(57303, ad16.getAdler()); + assertEqual(868, ad16.count()); ad16.begin(); - ad16.add(lorem, strlen(lorem)); + assertEqual(57303, ad16.add(lorem, strlen(lorem))); assertEqual(57303, ad16.getAdler()); + assertEqual(868, ad16.count()); ad16.begin(); - ad16.addFast(lorem, strlen(lorem)); + assertEqual(57303, ad16.addFast(lorem, strlen(lorem))); assertEqual(57303, ad16.getAdler()); + assertEqual(868, ad16.count()); } diff --git a/libraries/Adler/test/unit_test_Adler32.cpp b/libraries/Adler/test/unit_test_Adler32.cpp index 0868c096..581e1b36 100644 --- a/libraries/Adler/test/unit_test_Adler32.cpp +++ b/libraries/Adler/test/unit_test_Adler32.cpp @@ -74,15 +74,17 @@ unittest(test_ADLER32_lorem) ad32.add(lorem[i]); } assertEqual(3972480156, ad32.getAdler()); + assertEqual(868, ad32.count()); ad32.begin(); - ad32.add(lorem, strlen(lorem)); + assertEqual(3972480156, ad32.add(lorem, strlen(lorem))); assertEqual(3972480156, ad32.getAdler()); + assertEqual(868, ad32.count()); ad32.begin(); - ad32.addFast(lorem, strlen(lorem)); + assertEqual(3972480156, ad32.addFast(lorem, strlen(lorem))); assertEqual(3972480156, ad32.getAdler()); - + assertEqual(868, ad32.count()); }