0.2.0 Adler

This commit is contained in:
rob tillaart 2022-06-16 09:46:28 +02:00
parent 625779fd3d
commit 4df9ffbd6f
26 changed files with 1103 additions and 262 deletions

View File

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

View File

@ -1,158 +1,17 @@
// //
// FILE: Adler.cpp // FILE: Adler.cpp
// AUTHOR: Rob Tillaart // AUTHOR: Rob Tillaart
// VERSION: 0.1.2 // VERSION: 0.2.0
// DATE: 2022-01-27 // DATE: 2022-01-27
// PURPOSE: Arduino Library for calculating Adler-32 checksum // PURPOSE: Arduino Library for calculating Adler checksum
// URL: https://github.com/RobTillaart/Adler // URL: https://github.com/RobTillaart/Adler
// https://en.wikipedia.org/wiki/Adler-32 // https://en.wikipedia.org/wiki/Adler-32
// // (no Adler16 reference, implementation is experimental)
// HISTORY
// 0.1.0 2022-01-27 initial version
// 0.1.1 2022-04-15 split of .cpp file
// 0.1.2 2022-06-13 split interface and implementation
// rename ADLER32_MOD_PRIME
// rename ADLER32_LIB_VERSION
// add addFast(array, length)
// add char interfaces
#include "Adler.h" #include "Adler.h"
Adler32::Adler32()
{
begin(1, 0);
}
void Adler32::begin(uint32_t s1, uint32_t s2)
{
_s1 = s1;
_s2 = s2;
_count = 0;
}
// reference implementation
void Adler32::add(uint8_t value)
{
_count++;
_s1 += value;
if (_s1 >= ADLER32_MOD_PRIME) _s1 -= ADLER32_MOD_PRIME;
_s2 += _s1;
if (_s2 >= ADLER32_MOD_PRIME) _s2 -= ADLER32_MOD_PRIME;
}
// optimized version (~10% gain)
// void Adler32::add(uint8_t value)
// {
// _count++;
// _s1 += value;
// _s2 += _s1;
// if (_s2 >= ADLER32_MOD_PRIME)
// {
// _s2 -= ADLER32_MOD_PRIME;
// if (_s1 >= ADLER32_MOD_PRIME) _s1 -= ADLER32_MOD_PRIME;
// }
// }
// straightforward going through the array.
void Adler32::add(uint8_t * array, uint16_t length)
{
while (length--)
{
add(*array++);
}
return;
}
// optimized version (under test)
// S1 grows linear
// S2 grows quadratic
// as S2 grows faster than S1, S1 needs only to be checked
// if S2 hits the ADLER32_MOD_PRIME and probably far less.
//
// void Adler32::addFast(uint8_t * array, uint16_t length)
// {
// _count += length;
// while (length--)
// {
// _s1 += *array++;
// _s2 += _s1;
// if (_s2 >= ADLER32_MOD_PRIME)
// {
// _s2 -= ADLER32_MOD_PRIME;
// if (_s1 >= ADLER32_MOD_PRIME)
// {
// _s1 -= ADLER32_MOD_PRIME;
// }
// }
// }
// }
// further optimized version (under test)
// S1 grows linear
// S2 grows quadratic
// only do modulo when we reach halfway uint32_t
// or when really needed.
void Adler32::addFast(uint8_t * array, uint16_t length)
{
_count += length;
uint32_t s1 = _s1;
uint32_t s2 = _s2;
for (uint16_t i = 0; i < length;)
{
// if S2 is halfway it is time to do modulo
while ((i < length) && (s2 < 2147483648ULL))
{
s1 += array[i++];
s2 += s1;
}
if (s2 >= ADLER32_MOD_PRIME)
{
s2 %= ADLER32_MOD_PRIME;
if (s1 >= ADLER32_MOD_PRIME) s1 %= ADLER32_MOD_PRIME;
}
}
_s1 = s1;
_s2 = s2;
}
//////////////////////////////////////////////////////////////
//
// wrapper for strings.
//
void Adler32::add(char value)
{
add((uint8_t) value);
}
void Adler32::add(char * array, uint16_t length)
{
add((uint8_t *) array, length);
}
void Adler32::addFast(char * array, uint16_t length)
{
addFast((uint8_t *) array, length);
}
uint32_t Adler32::getAdler()
{
return (_s2 << 16) | _s1;
};
////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////
// //
// STATIC FUNCTION // STATIC FUNCTION
@ -176,5 +35,24 @@ uint32_t adler32(uint8_t * array, uint16_t length)
} }
uint16_t adler16(uint8_t * array, uint16_t length)
{
uint16_t s1 = 1;
uint16_t s2 = 0;
for (uint16_t i = 0; i < length;)
{
// if S2 is halfway it is time to do modulo
while ((i < length) && (s2 < 32768))
{
s1 += array[i++];
s2 += s1;
}
s1 %= ADLER16_MOD_PRIME;
s2 %= ADLER16_MOD_PRIME;
}
return (s2 << 8) | s1;
}
// -- END OF FILE -- // -- END OF FILE --

View File

@ -2,9 +2,9 @@
// //
// FILE: Adler.h // FILE: Adler.h
// AUTHOR: Rob Tillaart // AUTHOR: Rob Tillaart
// VERSION: 0.1.2 // VERSION: 0.2.0
// DATE: 2022-01-27 // DATE: 2022-01-27
// PURPOSE: Arduino Library for calculating Adler-32 checksum // PURPOSE: Arduino Library for calculating Adler checksum
// URL: https://github.com/RobTillaart/Adler // URL: https://github.com/RobTillaart/Adler
// https://en.wikipedia.org/wiki/Adler-32 // https://en.wikipedia.org/wiki/Adler-32
@ -12,11 +12,11 @@
#include "Arduino.h" #include "Arduino.h"
#define ADLER32_LIB_VERSION (F("0.1.2")) #define ADLER_LIB_VERSION (F("0.2.0"))
const uint16_t ADLER32_MOD_PRIME = 65521; const uint32_t ADLER32_MOD_PRIME = 65521;
const uint16_t ADLER16_MOD_PRIME = 251;
///////////////////////////////////////////////// /////////////////////////////////////////////////
@ -24,39 +24,7 @@ const uint16_t ADLER32_MOD_PRIME = 65521;
// STATIC FUNCTIONS // STATIC FUNCTIONS
// //
uint32_t adler32(uint8_t *data, uint16_t length); uint32_t adler32(uint8_t *data, uint16_t length);
uint16_t adler16(uint8_t *data, uint16_t length);
/////////////////////////////////////////////////
//
// CLASS VERSION
//
class Adler32
{
public:
Adler32();
void begin(uint32_t s1 = 1, uint32_t s2 = 0);
void add(uint8_t value);
void add(uint8_t * array, uint16_t length);
// trade PROGMEM for speed
void 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);
uint32_t getAdler();
uint32_t count() { return _count; };
private:
uint32_t _s1;
uint32_t _s2;
uint32_t _count;
};
// -- END OF FILE -- // -- END OF FILE --

127
libraries/Adler/Adler16.cpp Normal file
View File

@ -0,0 +1,127 @@
//
// FILE: Adler16.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.2.0
// DATE: 2022-06-14
// PURPOSE: Arduino Library for calculating Adler-16 checksum
// URL: https://github.com/RobTillaart/Adler
// https://en.wikipedia.org/wiki/Adler-32
// (no Adler16 reference, implementation is experimental)
//
// HISTORY: see CHANGELOG.md
#include "Adler16.h"
Adler16::Adler16()
{
begin(1, 0);
}
void Adler16::begin(uint16_t s1, uint16_t s2)
{
_s1 = s1;
_s2 = s2;
_count = 0;
}
// reference implementation
// void Adler16::add(uint8_t value)
// {
// _count++;
// _s1 += value;
// if (_s1 >= ADLER16_MOD_PRIME) _s1 -= ADLER16_MOD_PRIME;
// _s2 += _s1;
// if (_s2 >= ADLER16_MOD_PRIME) _s2 -= ADLER16_MOD_PRIME;
// }
// optimized version (~10% faster)
void Adler16::add(uint8_t value)
{
_count++;
_s1 += value;
_s2 += _s1;
if (_s2 >= ADLER16_MOD_PRIME)
{
_s2 -= ADLER16_MOD_PRIME;
if (_s1 >= ADLER16_MOD_PRIME) _s1 -= ADLER16_MOD_PRIME;
}
}
// straightforward going through the array.
// small footprint
void Adler16::add(uint8_t * array, uint16_t length)
{
while (length--)
{
add(*array++);
}
return;
}
// Optimized version
// S1 grows linear
// 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)
{
_count += length;
uint16_t s1 = _s1;
uint16_t s2 = _s2;
for (uint16_t i = 0; i < length;)
{
// if S2 is halfway it is time to do modulo
while ((i < length) && (s2 < 32768))
{
s1 += array[i++];
s2 += s1;
}
if (s2 >= ADLER16_MOD_PRIME)
{
s2 %= ADLER16_MOD_PRIME;
if (s1 >= ADLER16_MOD_PRIME) s1 %= ADLER16_MOD_PRIME;
}
}
_s1 = s1;
_s2 = s2;
}
uint16_t Adler16::getAdler()
{
return (_s2 << 8) | _s1;
};
//////////////////////////////////////////////////////////////
//
// wrappers for strings.
//
void Adler16::add(char value)
{
add((uint8_t) value);
}
void Adler16::add(char * array, uint16_t length)
{
add((uint8_t *) array, length);
}
void Adler16::addFast(char * array, uint16_t length)
{
addFast((uint8_t *) array, length);
}
// -- END OF FILE --

52
libraries/Adler/Adler16.h Normal file
View File

@ -0,0 +1,52 @@
#pragma once
//
// FILE: Adler16.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.2.0
// DATE: 2022-06-15
// PURPOSE: Arduino Library for calculating Adler-16 checksum
// URL: https://github.com/RobTillaart/Adler
// https://en.wikipedia.org/wiki/Adler-32
// (no Adler16 reference, implementation is experimental)
#include "Arduino.h"
#define ADLER16_LIB_VERSION (F("0.2.0"))
// largest prime below 2^8
const uint16_t ADLER16_MOD_PRIME = 251;
class Adler16
{
public:
Adler16();
void begin(uint16_t s1 = 1, uint16_t s2 = 0);
void add(uint8_t value);
void add(uint8_t * array, uint16_t length);
// trade PROGMEM for speed
void 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);
uint16_t getAdler();
uint16_t count() { return _count; };
private:
uint16_t _s1;
uint16_t _s2;
uint32_t _count;
};
// -- END OF FILE --

127
libraries/Adler/Adler32.cpp Normal file
View File

@ -0,0 +1,127 @@
//
// FILE: Adler32.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.2.0
// DATE: 2022-01-27
// PURPOSE: Arduino Library for calculating Adler-32 checksum
// URL: https://github.com/RobTillaart/Adler
// https://en.wikipedia.org/wiki/Adler-32
//
// HISTORY: see CHANGELOG.md
#include "Adler32.h"
Adler32::Adler32()
{
begin(1, 0);
}
void Adler32::begin(uint32_t s1, uint32_t s2)
{
_s1 = s1;
_s2 = s2;
_count = 0;
}
// reference implementation
// void Adler32::add(uint8_t value)
// {
// _count++;
// _s1 += value;
// if (_s1 >= ADLER32_MOD_PRIME) _s1 -= ADLER32_MOD_PRIME;
// _s2 += _s1;
// if (_s2 >= ADLER32_MOD_PRIME) _s2 -= ADLER32_MOD_PRIME;
// }
// optimized version (~10% faster)
void Adler32::add(uint8_t value)
{
_count++;
_s1 += value;
_s2 += _s1;
if (_s2 >= ADLER32_MOD_PRIME)
{
_s2 -= ADLER32_MOD_PRIME;
if (_s1 >= ADLER32_MOD_PRIME) _s1 -= ADLER32_MOD_PRIME;
}
}
// straightforward going through the array.
// small footprint.
void Adler32::add(uint8_t * array, uint16_t length)
{
while (length--)
{
add(*array++);
}
return;
}
// Optimized version
// S1 grows linear
// 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)
{
_count += length;
uint32_t s1 = _s1;
uint32_t s2 = _s2;
for (uint16_t i = 0; i < length;)
{
// if S2 is halfway it is time to do modulo
while ((i < length) && (s2 < 2147483648ULL))
{
s1 += array[i++];
s2 += s1;
}
if (s2 >= ADLER32_MOD_PRIME)
{
s2 %= ADLER32_MOD_PRIME;
if (s1 >= ADLER32_MOD_PRIME) s1 %= ADLER32_MOD_PRIME;
}
}
_s1 = s1;
_s2 = s2;
}
uint32_t Adler32::getAdler()
{
return (_s2 << 16) | _s1;
};
//////////////////////////////////////////////////////////////
//
// wrappers for strings.
//
void Adler32::add(char value)
{
add((uint8_t) value);
}
void Adler32::add(char * array, uint16_t length)
{
add((uint8_t *) array, length);
}
void Adler32::addFast(char * array, uint16_t length)
{
addFast((uint8_t *) array, length);
}
// -- END OF FILE --

52
libraries/Adler/Adler32.h Normal file
View File

@ -0,0 +1,52 @@
#pragma once
//
// FILE: Adler.h
// AUTHOR: Rob Tillaart
// VERSION: 0.2.0
// DATE: 2022-01-27
// PURPOSE: Arduino Library for calculating Adler-32 checksum
// URL: https://github.com/RobTillaart/Adler
// https://en.wikipedia.org/wiki/Adler-32
#include "Arduino.h"
#define ADLER32_LIB_VERSION (F("0.2.0"))
// largest prime below 2^16
const uint32_t ADLER32_MOD_PRIME = 65521;
class Adler32
{
public:
Adler32();
void begin(uint32_t s1 = 1, uint32_t s2 = 0);
void add(uint8_t value);
void add(uint8_t * array, uint16_t length);
// trade PROGMEM for speed
void 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);
uint32_t getAdler();
uint32_t count() { return _count; };
private:
uint32_t _s1;
uint32_t _s2;
uint32_t _count;
};
// -- END OF FILE --

View File

@ -0,0 +1,34 @@
# Change Log
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.0] - 2022-06-15
- breaking change
- reordering files.
- Adler.h for static functions
- Adler32.h for Adler32 class
- Adler16.h for Adler16 class (experimental).
- Added optimizations.
## [0.1.2] - 2022-06-13
- split interface and implementation
- rename ADLER32_MOD_PRIME
- rename ADLER32_LIB_VERSION
- add addFast(array, length)
- add char interfaces
## [0.1.1] - 2022-04-15
- split of .cpp file
### [0.1.0] - 2022-01-27
- initial version

View File

@ -8,12 +8,16 @@
# Adler # Adler
Arduino Library for Adler-32 checksum Arduino Library for Adler-32 and experimental Adler-16 checksum.
## Description ## Description
This library provides a Adler checksum of a data array. 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.
Relates to https://github.com/RobTillaart/CRC Relates to https://github.com/RobTillaart/CRC
@ -21,13 +25,21 @@ Relates to https://github.com/RobTillaart/Fletcher
Tested on Arduino UNO only. Tested on Arduino UNO only.
0.2.0 is a breaking change, file names have been changed to be more
in line with the CRC library.
- Adler.h for the static functions
- Adler32.h for the Adler32 class
- Adler16.h for the Adler16 class.
## Interface ## Interface
## Adler class ### Adler class
Use **\#include "Adler.h"** Use **\#include "Adler32.h"** or **\#include "Adler16.h"**
The interface for the Adler16 is very similar.
- **Adler32()** Constructor, initializes internals. - **Adler32()** Constructor, initializes internals.
- **void begin(uint8_t s1 = 1, uint8_t s2 = 0)** resets the internals. - **void begin(uint8_t s1 = 1, uint8_t s2 = 0)** resets the internals.
@ -43,58 +55,142 @@ The class is typically used for streaming very large blocks of data,
optional with intermediate checksum tests. optional with intermediate checksum tests.
#### Performance ## Performance Adler32
Not tested ESP32 (and many other platforms) yet. Not tested ESP32 (and many other platforms) yet.
First numbers of **.add(value)** measured with test sketch shows the following timing.
| Version | Checksum | UNO 16 MHz | ESP32 240 MHz | Numbers measured with **Adler32_performance.ino**.
|:-------:|:---------|:------------:|:---------------:|
| 0.1.0 | Adler32 | 5.6 us | |
| 0.1.2 | Adler32 | 6.6 us | |
Todo elaborate / investigate.
#### Performance 2 ### add(value)
(since 0.1.2) The **add(value)** adds one byte and does a subtraction
instead of a modulo.
The **addFast(array, length)** is faster than the reference **add(array, length)** but uses 108 bytes more, so a slightly larger footprint. | Version | Function | UNO 16 MHz | ESP32 240 MHz |
So depending on your needs, you choose performance or footprint. |:-------:|:---------|:----------:|:-------------:|
| 0.1.0 | add | 5.6 us | |
| 0.1.2 | add | 6.6 us | |
| 0.2.0 | add | 5.9 us | |
### add(lorem) 868 chars
The **add(array, length)** is a straightforward loop
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 | |
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.
So the function has a larger footprint.
Depending on your needs, choose performance or footprint.
See **Adler32_performance_addFast.ino** See **Adler32_performance_addFast.ino**
| Version | Function | UNO 16 MHz | ESP32 240 MHz |
|:-------:|:---------|:----------:|:-------------:|
| 0.1.0 | addFast | | |
| 0.1.2 | addFast | 1348 us | |
| 0.2.0 | addFast | 1348 us | |
Note: **addFast()** is less than 2 us per byte.
## Performance Adler16
Not tested ESP32 (and many other platforms) yet.
Numbers measured with **Adler16_performance.ino**.
### add(value)
The **add(value)** adds one byte and does a subtraction
instead of a modulo.
| Version | Function | UNO 16 MHz | ESP32 240 MHz |
|:-------:|:---------|:----------:|:-------------:|
| 0.2.0 | add | 4.0 us | |
The per byte performance of the Adler16 (on UNO) is faster
than the Adler32 **add(value)**. The reason is that a 16 bit
subtraction on an UNO is faster than a 32 bit subtraction.
### add(lorem) 868 chars
The **add(array, length)** is a straightforward loop
over the array and has a small footprint.
| Version | Function | UNO 16 MHz | ESP32 240 MHz |
|:-------:|:---------|:----------:|:-------------:|
| 0.2.0 | add | 4040 us | |
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)**.
| Version | Function | UNO 16 MHz | ESP32 240 MHz |
|:-------:|:---------|:----------:|:-------------:|
| 0.2.0 | addFast | 1968 us | |
The gain of the faster 16 bit modulo meets the frequency of
doing the modulo more often.
## Interface static functions ## Interface static functions
The function is straightforward. The functions are straightforward.
Use **\#include "Adler.h"** Use **\#include "Adler.h"**
- **uint32_t adler32(uint8_t \*data, uint16_t length)** length in units of 1 byte = 8 bits. - **uint32_t adler32(uint8_t \*data, uint16_t length)** length in units of 1 byte = 8 bits.
- **uint16_t adler16(uint8_t \*data, uint16_t length)** length in units of 1 byte = 8 bits.
The function is typically used for an in memory buffer to calculate The functions are typically used for an in memory buffer to calculate the checksum once.
the Adler checksum once. Think of packets in a network, records in a database, or a checksum for an configuration in EEPROM.
#### Performance ### Performance
Not tested ESP32 (and many other platforms) yet.
Not tested extensively, first numbers of **.add(array, length)** Numbers measured with **Adler_performance.ino**.
measured with **Adler_performance.ino** sketch shows the following timing.
Lorem Ipsum text = 868 bytes. Lorem Ipsum text = 868 bytes.
| Checksum | UNO 16 MHz | ESP32 240 MHz | | Version | Function | UNO 16 MHz | ESP32 240 MHz |
|:------------|:-----------:|:-------------:| |:-------:|:---------|:----------:|:-------------:|
| Adler32 | 1116 us | | | 0.1.0 | Adler32 | 1116 us | |
| 0.1.2 | Adler32 | 1116 us | |
Average 1116 / 868 = 1.29 us per byte. | 0.2.0 | Adler32 | 1116 us | |
| 0.2.0 | Adler16 | 1736 us | |
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.
## Operation ## Operation
@ -104,9 +200,17 @@ See examples.
## Future ## Future
- test other platforms - return values for **add(array)** and **addFast(array)**
- add Adler-16, similar algorithm - updated checksum?
- ADLER16_MOD_PRIME 32749 = largest prime below 2^15 (32768) - not for **add(value)** as that would create quite some overhead.
- (0.2.0) - Adler64 ?
- would need a large prime (which)
#### Wont
- do the string wrappers need strlen() ? parameter.
- yes, as string can be processed partially.

View File

@ -0,0 +1,178 @@
//
// FILE: Adler16_performance.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo
#include "Arduino.h"
#include "Adler16.h"
Adler16 ad;
volatile uint8_t z;
uint32_t start, stop, randomtime;
char lorem[] = "Lorem ipsum dolor sit amet, \
consectetuer adipiscing elit. Aenean commodo ligula eget dolor. \
Aenean massa. Cum sociis natoque penatibus et magnis dis parturient \
montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, \
pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. \
Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. \
In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. \
Nullam dictum felis eu pede mollis pretium. Integer tincidunt. \
Cras dapibus. Vivamus elementum semper nisi. \
Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, \
consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, \
viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus \
varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies \
nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui.";
char hello[] = "hello world";
void setup()
{
Serial.begin(115200);
while (!Serial);
Serial.println();
Serial.println("Adler16_performance");
Serial.print("ADLER16_LIB_VERSION: ");
Serial.println(ADLER16_LIB_VERSION);
start = micros();
for (uint16_t x = 0; x < 10000; x++)
{
z = random(255);
}
stop = micros();
randomtime = stop - start;
Serial.print("randomtime: ");
Serial.println(randomtime);
delay(100);
ad.begin();
start = micros();
for (uint16_t x = 0; x < 10000; x++)
{
z = random(255);
ad.add(z);
}
stop = micros();
Serial.print(" total: ");
Serial.println(stop - start);
Serial.print(" 1e4 x add: ");
Serial.println(stop - start - randomtime);
delay(100);
Serial.print(" checksum: ");
Serial.println(ad.getAdler());
Serial.println();
delay(100);
ad.begin();
start = micros();
for (uint32_t x = 0; x < 1000000; x++)
{
z = x & 0xFF;
ad.add(z);
}
stop = micros();
Serial.print(" total: ");
Serial.println(stop - start);
Serial.print(" 1e6 x add: ");
Serial.println(stop - start - randomtime);
delay(100);
Serial.print(" checksum: ");
Serial.println(ad.getAdler());
Serial.println();
delay(100);
/////////////////////////////////////////////////////////////////
ad.begin();
Serial.print("LENGTH LOREM: ");
Serial.println(strlen(lorem));
Serial.println();
delay(100);
start = micros();
for (int i = 0; lorem[i] != 0; i++)
{
ad.add(lorem[i]);
}
stop = micros();
Serial.print(" lorem 1: ");
Serial.print(stop - start);
Serial.print("\tchecksum: ");
Serial.println(ad.getAdler());
delay(100);
ad.begin();
start = micros();
ad.add(lorem, strlen(lorem));
stop = micros();
Serial.print(" lorem 2: ");
Serial.print(stop - start);
Serial.print("\tchecksum: ");
Serial.println(ad.getAdler());
delay(100);
ad.begin();
start = micros();
ad.addFast(lorem, strlen(lorem));
stop = micros();
Serial.print(" lorem 3: ");
Serial.print(stop - start);
Serial.print("\tchecksum: ");
Serial.println(ad.getAdler());
Serial.println();
delay(100);
/////////////////////////////////////////////////////////////////
ad.begin();
Serial.print("LENGTH HELLO: ");
Serial.println(strlen(hello));
Serial.println();
delay(100);
start = micros();
for (int i = 0; hello[i] != 0; i++)
{
ad.add(hello[i]);
}
stop = micros();
Serial.print(" hello 1: ");
Serial.print(stop - start);
Serial.print("\tchecksum: ");
Serial.println(ad.getAdler());
delay(100);
ad.begin();
start = micros();
ad.add(hello, strlen(hello));
stop = micros();
Serial.print(" hello 2: ");
Serial.print(stop - start);
Serial.print("\tchecksum: ");
Serial.println(ad.getAdler());
delay(100);
ad.begin();
start = micros();
ad.addFast(hello, strlen(hello));
stop = micros();
Serial.print(" hello 3: ");
Serial.print(stop - start);
Serial.print("\tchecksum: ");
Serial.println(ad.getAdler());
Serial.println();
}
void loop()
{
}
// -- END OF FILE --

View File

@ -0,0 +1,24 @@
Adler16_performance
ADLER16_LIB_VERSION: 0.1.0
randomtime: 901476
total: 942656
1e4 x add: 41180
checksum: 46478
total: 5157524
1e6 x add: 4256048
checksum: 63140
LENGTH LOREM: 868
lorem 1: 3792 checksum: 57303
lorem 2: 4224 checksum: 57303
lorem 3: 1972 checksum: 57303
LENGTH HELLO: 11
hello 1: 52 checksum: 36209
hello 2: 60 checksum: 36209
hello 3: 48 checksum: 36209

View File

@ -0,0 +1,23 @@
Adler16_performance
ADLER16_LIB_VERSION: 0.2.0
randomtime: 901476
total: 941076
1e4 x add: 39600
checksum: 6798
total: 5000108
1e6 x add: 4098632
checksum: 5028
LENGTH LOREM: 868
lorem 1: 3600 checksum: 57303
lorem 2: 4040 checksum: 57303
lorem 3: 1968 checksum: 57303
LENGTH HELLO: 11
hello 1: 48 checksum: 36209
hello 2: 56 checksum: 36209
hello 3: 48 checksum: 36209

View File

@ -0,0 +1,52 @@
//
// FILE: Adler16_test.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo
#include "Arduino.h"
#include "Adler16.h"
// expected output
// Adler16_test
// ADLER16_LIB_VERSION: 0.2.0
// 6012
// 7293
// 6269
Adler16 ad;
uint8_t arr1[5] = { 100, 120, 130, 135, 140 };
uint8_t arr2[5] = { 101, 120, 130, 135, 140 }; // minimal diff.
uint8_t arr3[5] = { 100, 120, 130, 135, 141 }; // minimal diff.
void setup()
{
Serial.begin(115200);
while (!Serial);
Serial.println();
Serial.println("Adler16_test");
Serial.print("ADLER16_LIB_VERSION: ");
Serial.println(ADLER16_LIB_VERSION);
ad.begin();
ad.add(arr1, 5);
Serial.println(ad.getAdler());
ad.begin();
ad.add(arr2, 5);
Serial.println(ad.getAdler());
ad.begin();
ad.add(arr3, 5);
Serial.println(ad.getAdler());
}
void loop()
{
}
// -- END OF FILE --

View File

@ -0,0 +1,5 @@
Adler16_test
ADLER16_LIB_VERSION: 0.1.0
7292
8573
7549

View File

@ -4,8 +4,7 @@
// PURPOSE: demo // PURPOSE: demo
#include "Arduino.h" #include "Arduino.h"
#include "Adler.h" #include "Adler32.h"
Adler32 ad; Adler32 ad;

View File

@ -0,0 +1,24 @@
Adler32_performance
ADLER32_LIB_VERSION: 0.2.0
randomtime: 901476
total: 960236
1e4 x add: 58760
checksum: 1607808947
total: 6919548
1e6 x add: 6018072
checksum: 237492440
LENGTH LOREM: 868
lorem 1: 5308 checksum: 3972480156
lorem 2: 5748 checksum: 3972480156
lorem 3: 1348 checksum: 3972480156
LENGTH HELLO: 11
hello 1: 64 checksum: 436929629
hello 2: 80 checksum: 436929629
hello 3: 32 checksum: 436929629

View File

@ -4,7 +4,7 @@
// PURPOSE: demo // PURPOSE: demo
#include "Arduino.h" #include "Arduino.h"
#include "Adler.h" #include "Adler32.h"
@ -31,7 +31,6 @@ nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui.";
char hello[] = "hello world"; char hello[] = "hello world";
void setup() void setup()
{ {
Serial.begin(115200); Serial.begin(115200);

View File

@ -4,10 +4,11 @@
// PURPOSE: demo // PURPOSE: demo
#include "Arduino.h" #include "Arduino.h"
#include "Adler.h" #include "Adler32.h"
// expected output // expected output
// Adler32_test // Adler32_test
// ADLER32_LIB_VERSION: 0.2.0
// 116982386 // 116982386
// 117310067 // 117310067
// 117047923 // 117047923
@ -27,7 +28,9 @@ void setup()
Serial.println(); Serial.println();
Serial.println("Adler32_test"); Serial.println("Adler32_test");
Serial.print("ADLER32_LIB_VERSION: ");
Serial.println(ADLER32_LIB_VERSION);
ad.begin(); ad.begin();
ad.add(arr1, 5); ad.add(arr1, 5);
Serial.println(ad.getAdler()); Serial.println(ad.getAdler());

View File

@ -30,8 +30,8 @@ void setup()
while (!Serial); while (!Serial);
Serial.println(); Serial.println();
Serial.print("ADLER32_LIB_VERSION: "); Serial.print("ADLER_LIB_VERSION: ");
Serial.println(ADLER32_LIB_VERSION); Serial.println(ADLER_LIB_VERSION);
for (int i = 0; i < 60; i++) for (int i = 0; i < 60; i++)
{ {
@ -53,6 +53,18 @@ void setup()
Serial.print(x); Serial.print(x);
Serial.print("\t"); Serial.print("\t");
Serial.println(x, HEX); Serial.println(x, HEX);
delay(200);
start = micros();
volatile uint16_t y = adler16((uint8_t *) str, len);
stop = micros();
Serial.print(" TIME us: ");
Serial.println(stop - start);
Serial.print(" ADLER-16: ");
Serial.print(y);
Serial.print("\t");
Serial.println(y, HEX);
delay(100); delay(100);
} }

View File

@ -9,13 +9,20 @@
// expected output // expected output
// ADLER32_LIB_VERSION: 0.1.2 // ADLER_LIB_VERSION: 0.2.0
//
// E1F5
// 4660
// 4634
// 40A7
//
// 5C801F0 // 5C801F0
// 81E0256 // 81E0256
// E000325 // E000325
// 11E60398 // 11E60398
char str1[24] = "abcde"; char str1[24] = "abcde";
char str2[24] = "abcdef"; char str2[24] = "abcdef";
char str3[24] = "abcdefgh"; char str3[24] = "abcdefgh";
@ -28,13 +35,21 @@ void setup()
while (!Serial); while (!Serial);
Serial.println(); Serial.println();
Serial.print("ADLER32_LIB_VERSION: "); Serial.print("ADLER_LIB_VERSION: ");
Serial.println(ADLER32_LIB_VERSION); Serial.println(ADLER_LIB_VERSION);
Serial.println();
Serial.println(adler16((uint8_t *) str1, 5), HEX);
Serial.println(adler16((uint8_t *) str2, 6), HEX);
Serial.println(adler16((uint8_t *) str3, 8), HEX);
Serial.println(adler16((uint8_t *) str4, 9), HEX);
Serial.println();
Serial.println(adler32((uint8_t *) str1, 5), HEX); Serial.println(adler32((uint8_t *) str1, 5), HEX);
Serial.println(adler32((uint8_t *) str2, 6), HEX); Serial.println(adler32((uint8_t *) str2, 6), HEX);
Serial.println(adler32((uint8_t *) str3, 8), HEX); Serial.println(adler32((uint8_t *) str3, 8), HEX);
Serial.println(adler32((uint8_t *) str4, 9), HEX); Serial.println(adler32((uint8_t *) str4, 9), HEX);
Serial.println();
} }

View File

@ -2,10 +2,12 @@
# Data types (KEYWORD1) # Data types (KEYWORD1)
Adler32 KEYWORD1 Adler32 KEYWORD1
Adler16 KEYWORD1
# Methods and Functions (KEYWORD2) # Methods and Functions (KEYWORD2)
adler32 KEYWORD2 adler32 KEYWORD2
adler16 KEYWORD2
begin KEYWORD2 begin KEYWORD2
add KEYWORD2 add KEYWORD2
addFast KEYWORD2 addFast KEYWORD2
@ -15,5 +17,7 @@ count KEYWORD2
# Constants (LITERAL1) # Constants (LITERAL1)
ADLER32_LIB_VERSION LITERAL1 ADLER32_LIB_VERSION LITERAL1
ADLER16_LIB_VERSION LITERAL1
ADLER32_MOD_PRIME LITERAL1 ADLER32_MOD_PRIME LITERAL1
ADLER16_MOD_PRIME LITERAL1

View File

@ -1,6 +1,6 @@
{ {
"name": "Adler", "name": "Adler",
"keywords": "Adler, checksum", "keywords": "Adler32, Adler16, checksum",
"description": "Arduino Library for calculating Adler-32 checksum.", "description": "Arduino Library for calculating Adler-32 checksum.",
"authors": "authors":
[ [
@ -15,7 +15,7 @@
"type": "git", "type": "git",
"url": "https://github.com/RobTillaart/Adler.git" "url": "https://github.com/RobTillaart/Adler.git"
}, },
"version": "0.1.2", "version": "0.2.0",
"license": "MIT", "license": "MIT",
"frameworks": "arduino", "frameworks": "arduino",
"platforms": "*", "platforms": "*",

View File

@ -1,11 +1,11 @@
name=Adler name=Adler
version=0.1.2 version=0.2.0
author=Rob Tillaart <rob.tillaart@gmail.com> author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com> maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence="Arduino Library for calculating Adler-32 checksum. sentence=Arduino Library for calculating Adler-32 and Adler-16 checksum.
paragraph= paragraph=Adler-16 is experimental.
category=Signal Input/Output category=Signal Input/Output
url=https://github.com/RobTillaart/Adler url=https://github.com/RobTillaart/Adler
architectures=* architectures=*
includes=Adler.h includes=Adler.h,Adler16.h,Adler32.h
depends= depends=

View File

@ -27,6 +27,7 @@
#include "Arduino.h" #include "Arduino.h"
#include "Adler.h" #include "Adler.h"
char lorem[] = "Lorem ipsum dolor sit amet, \ char lorem[] = "Lorem ipsum dolor sit amet, \
consectetuer adipiscing elit. Aenean commodo ligula eget dolor. \ consectetuer adipiscing elit. Aenean commodo ligula eget dolor. \
Aenean massa. Cum sociis natoque penatibus et magnis dis parturient \ Aenean massa. Cum sociis natoque penatibus et magnis dis parturient \
@ -45,7 +46,7 @@ nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui.";
unittest_setup() unittest_setup()
{ {
fprintf(stderr, "ADLER32_LIB_VERSION: %s\n", (char *) ADLER32_LIB_VERSION); fprintf(stderr, "ADLER_LIB_VERSION: %s\n", (char *) ADLER_LIB_VERSION);
} }
unittest_teardown() unittest_teardown()
@ -55,11 +56,12 @@ unittest_teardown()
unittest(test_constants) unittest(test_constants)
{ {
assertEqual(ADLER16_MOD_PRIME, 251);
assertEqual(ADLER32_MOD_PRIME, 65521); assertEqual(ADLER32_MOD_PRIME, 65521);
} }
unittest(test_adler32) unittest(test_adler_static)
{ {
char str1[24] = "abcde"; char str1[24] = "abcde";
char str2[24] = "abcdef"; char str2[24] = "abcdef";
@ -68,32 +70,10 @@ unittest(test_adler32)
assertEqual(96993776, adler32((uint8_t *) str1, 5)); assertEqual(96993776, adler32((uint8_t *) str1, 5));
assertEqual(136184406, adler32((uint8_t *) str2, 6)); assertEqual(136184406, adler32((uint8_t *) str2, 6));
assertEqual(234881829, adler32((uint8_t *) str3, 8)); assertEqual(234881829, adler32((uint8_t *) str3, 8));
}
unittest(test_lorem)
{
Adler32 ad32;
ad32.begin();
fprintf(stderr, "strlen lorem\n");
assertEqual(868, strlen(lorem));
for (int i = 0; lorem[i] != 0; i++)
{
ad32.add(lorem[i]);
}
assertEqual(3972480156, ad32.getAdler());
ad32.begin();
ad32.add(lorem, strlen(lorem));
assertEqual(3972480156, ad32.getAdler());
ad32.begin();
ad32.addFast(lorem, strlen(lorem));
assertEqual(3972480156, ad32.getAdler());
assertEqual(57845, adler16((uint8_t *) str1, 5));
assertEqual(18016, adler16((uint8_t *) str2, 6));
assertEqual(17972, adler16((uint8_t *) str3, 8));
} }

View File

@ -0,0 +1,90 @@
//
// FILE: unit_test_001.cpp
// AUTHOR: Rob Tillaart
// DATE: 2022-01-25
// PURPOSE: unit tests for the Adler library
// https://github.com/RobTillaart/Adler
// https://github.com/Arduino-CI/arduino_ci/blob/master/REFERENCE.md
//
// supported assertions
// https://github.com/Arduino-CI/arduino_ci/blob/master/cpp/unittest/Assertion.h#L33-L42
// ----------------------------
// assertEqual(expected, actual)
// assertNotEqual(expected, actual)
// assertLess(expected, actual)
// assertMore(expected, actual)
// assertLessOrEqual(expected, actual)
// assertMoreOrEqual(expected, actual)
// assertTrue(actual)
// assertFalse(actual)
// assertNull(actual)
// assertNotNull(actual)
#include <ArduinoUnitTests.h>
#include "Arduino.h"
#include "Adler16.h"
char lorem[] = "Lorem ipsum dolor sit amet, \
consectetuer adipiscing elit. Aenean commodo ligula eget dolor. \
Aenean massa. Cum sociis natoque penatibus et magnis dis parturient \
montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, \
pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. \
Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. \
In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. \
Nullam dictum felis eu pede mollis pretium. Integer tincidunt. \
Cras dapibus. Vivamus elementum semper nisi. \
Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, \
consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, \
viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus \
varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies \
nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui.";
unittest_setup()
{
fprintf(stderr, "ADLER16_LIB_VERSION: %s\n", (char *) ADLER16_LIB_VERSION);
}
unittest_teardown()
{
}
unittest(test_constants)
{
assertEqual(ADLER16_MOD_PRIME, 251);
}
unittest(test_ADLER16_lorem)
{
Adler16 ad16;
ad16.begin();
fprintf(stderr, "strlen lorem\n");
assertEqual(868, strlen(lorem));
for (int i = 0; lorem[i] != 0; i++)
{
ad16.add(lorem[i]);
}
assertEqual(57303, ad16.getAdler());
ad16.begin();
ad16.add(lorem, strlen(lorem));
assertEqual(57303, ad16.getAdler());
ad16.begin();
ad16.addFast(lorem, strlen(lorem));
assertEqual(57303, ad16.getAdler());
}
unittest_main()
// --------

View File

@ -0,0 +1,91 @@
//
// FILE: unit_test_001.cpp
// AUTHOR: Rob Tillaart
// DATE: 2022-01-25
// PURPOSE: unit tests for the Adler library
// https://github.com/RobTillaart/Adler
// https://github.com/Arduino-CI/arduino_ci/blob/master/REFERENCE.md
//
// supported assertions
// https://github.com/Arduino-CI/arduino_ci/blob/master/cpp/unittest/Assertion.h#L33-L42
// ----------------------------
// assertEqual(expected, actual)
// assertNotEqual(expected, actual)
// assertLess(expected, actual)
// assertMore(expected, actual)
// assertLessOrEqual(expected, actual)
// assertMoreOrEqual(expected, actual)
// assertTrue(actual)
// assertFalse(actual)
// assertNull(actual)
// assertNotNull(actual)
#include <ArduinoUnitTests.h>
#include "Arduino.h"
#include "Adler32.h"
char lorem[] = "Lorem ipsum dolor sit amet, \
consectetuer adipiscing elit. Aenean commodo ligula eget dolor. \
Aenean massa. Cum sociis natoque penatibus et magnis dis parturient \
montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, \
pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. \
Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. \
In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. \
Nullam dictum felis eu pede mollis pretium. Integer tincidunt. \
Cras dapibus. Vivamus elementum semper nisi. \
Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, \
consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, \
viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus \
varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies \
nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui.";
unittest_setup()
{
fprintf(stderr, "ADLER32_LIB_VERSION: %s\n", (char *) ADLER32_LIB_VERSION);
}
unittest_teardown()
{
}
unittest(test_constants)
{
assertEqual(ADLER32_MOD_PRIME, 65521);
}
unittest(test_ADLER32_lorem)
{
Adler32 ad32;
ad32.begin();
fprintf(stderr, "strlen lorem\n");
assertEqual(868, strlen(lorem));
for (int i = 0; lorem[i] != 0; i++)
{
ad32.add(lorem[i]);
}
assertEqual(3972480156, ad32.getAdler());
ad32.begin();
ad32.add(lorem, strlen(lorem));
assertEqual(3972480156, ad32.getAdler());
ad32.begin();
ad32.addFast(lorem, strlen(lorem));
assertEqual(3972480156, ad32.getAdler());
}
unittest_main()
// --------