From 1f94a93fb8f2e4a67c7ff1477d8e8c7ea60085e8 Mon Sep 17 00:00:00 2001 From: Joakim Gebart Date: Sun, 24 May 2015 07:31:43 +0200 Subject: [PATCH] sys/hashes: Add Fletcher's checksums --- sys/hashes/hashes.c | 39 +++++++++++++++++++++++++++++++++++++++ sys/include/hashes.h | 31 +++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/sys/hashes/hashes.c b/sys/hashes/hashes.c index 5086130f62..8b85642d1f 100644 --- a/sys/hashes/hashes.c +++ b/sys/hashes/hashes.c @@ -12,6 +12,7 @@ * @file * @author Jason Linehan * @author Christian Mehlis + * @author Joakim Gebart */ #include "hashes.h" @@ -109,3 +110,41 @@ uint32_t one_at_a_time_hash(const uint8_t *buf, size_t len) hash += hash << 15; return hash; } + +uint16_t fletcher16(const uint8_t *data, size_t bytes) +{ + uint16_t sum1 = 0xff, sum2 = 0xff; + + while (bytes) { + size_t tlen = bytes > 20 ? 20 : bytes; + bytes -= tlen; + do { + sum2 += sum1 += *data++; + } while (--tlen); + sum1 = (sum1 & 0xff) + (sum1 >> 8); + sum2 = (sum2 & 0xff) + (sum2 >> 8); + } + /* Second reduction step to reduce sums to 8 bits */ + sum1 = (sum1 & 0xff) + (sum1 >> 8); + sum2 = (sum2 & 0xff) + (sum2 >> 8); + return (sum2 << 8) | sum1; +} + +uint32_t fletcher32(const uint16_t *data, size_t words) +{ + uint32_t sum1 = 0xffff, sum2 = 0xffff; + + while (words) { + unsigned tlen = words > 359 ? 359 : words; + words -= tlen; + do { + sum2 += sum1 += *data++; + } while (--tlen); + sum1 = (sum1 & 0xffff) + (sum1 >> 16); + sum2 = (sum2 & 0xffff) + (sum2 >> 16); + } + /* Second reduction step to reduce sums to 16 bits */ + sum1 = (sum1 & 0xffff) + (sum1 >> 16); + sum2 = (sum2 & 0xffff) + (sum2 >> 16); + return (sum2 << 16) | sum1; +} diff --git a/sys/include/hashes.h b/sys/include/hashes.h index d81e2dfe39..c03848b12c 100644 --- a/sys/include/hashes.h +++ b/sys/include/hashes.h @@ -17,6 +17,7 @@ * * @author Jason Linehan * @author Christian Mehlis + * @author Joakim Gebart */ #ifndef HASHES_H_ @@ -159,6 +160,36 @@ uint32_t rotating_hash(const uint8_t *buf, size_t len); */ uint32_t one_at_a_time_hash(const uint8_t *buf, size_t len); +/** + * @brief Fletcher's 16 bit checksum + * + * found on + * http://en.wikipedia.org/w/index.php?title=Fletcher%27s_checksum&oldid=661273016#Optimizations + * + * @note the returned sum is never 0 + * + * @param buf input buffer to hash + * @param bytes length of buffer, in bytes + * @return 16 bit sized hash in the interval [1..65535] + */ +uint16_t fletcher16(const uint8_t *buf, size_t bytes); + +/** + * @brief Fletcher's 32 bit checksum + * + * found on + * http://en.wikipedia.org/w/index.php?title=Fletcher%27s_checksum&oldid=661273016#Optimizations + * + * @note the returned sum is never 0 + * @note pay attention to alignment issues since this operates on an input + * buffer containing 16 bit words, not bytes. + * + * @param buf input buffer to hash + * @param words length of buffer, in 16 bit words + * @return 32 bit sized hash in the interval [1..2^32] + */ +uint32_t fletcher32(const uint16_t *buf, size_t words); + #ifdef __cplusplus } #endif