"Fossies" - the Fresh Open Source Software Archive

Member "n2n-3.1.1/src/pearson.c" (31 Mar 2022, 5255 Bytes) of package /linux/misc/n2n-3.1.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "pearson.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 3.0_vs_3.1.1.

    1 /**
    2  * (C) 2007-22 - ntop.org and contributors
    3  *
    4  * This program is free software; you can redistribute it and/or modify
    5  * it under the terms of the GNU General Public License as published by
    6  * the Free Software Foundation; either version 3 of the License, or
    7  * (at your option) any later version.
    8  *
    9  * This program is distributed in the hope that it will be useful,
   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12  * GNU General Public License for more details.
   13  *
   14  * You should have received a copy of the GNU General Public License
   15  * along with this program; if not see see <http://www.gnu.org/licenses/>
   16  *
   17  */
   18 
   19 
   20 // taken from https://github.com/Logan007/pearsonB
   21 // this is free and unencumbered software released into the public domain
   22 
   23 
   24 #include "pearson.h"
   25 
   26 
   27 // Christopher Wellons' triple32 from https://github.com/skeeto/hash-prospector
   28 // published under The Unlicense
   29 #define permute32(in) \
   30     in ^= in >> 17;   \
   31     in *= 0xed5ad4bb; \
   32     in ^= in >> 11;   \
   33     in *= 0xac4c1b51; \
   34     in ^= in >> 15;   \
   35     in *= 0x31848bab; \
   36     in ^= in >> 14
   37 
   38 // David Stafford's Mix13 from http://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html
   39 // the author clarified via eMail that this of his work is released to the public domain
   40 #define permute64(in)         \
   41     in ^= (in >> 30);         \
   42     in *= 0xbf58476d1ce4e5b9; \
   43     in ^= (in >> 27);         \
   44     in *= 0x94d049bb133111eb; \
   45     in ^= (in >> 31)
   46 
   47 #define dec1(in) \
   48     in--
   49 
   50 #define dec2(in) \
   51     dec1(in);    \
   52     dec1(in)
   53 
   54 #define dec3(in) \
   55     dec2(in);    \
   56     dec1(in)
   57 
   58 #define dec4(in) \
   59     dec3(in);    \
   60     dec1(in)
   61 
   62 #define hash_round(hash, in, part) \
   63     hash##part ^= in;              \
   64     dec##part(hash##part);         \
   65     permute64(hash##part)
   66 
   67 
   68 void pearson_hash_256 (uint8_t *out, const uint8_t *in, size_t len) {
   69 
   70     uint64_t *current;
   71     current = (uint64_t*)in;
   72     uint64_t org_len = len;
   73     uint64_t hash1 = 0;
   74     uint64_t hash2 = 0;
   75     uint64_t hash3 = 0;
   76     uint64_t hash4 = 0;
   77 
   78     while (len > 7) {
   79         // digest words little endian first
   80         hash_round(hash, le64toh(*current), 1);
   81         hash_round(hash, le64toh(*current), 2);
   82         hash_round(hash, le64toh(*current), 3);
   83         hash_round(hash, le64toh(*current), 4);
   84 
   85         current++;
   86         len-=8;
   87     }
   88 
   89     // handle the rest
   90     hash1 = ~hash1;
   91     hash2 = ~hash2;
   92     hash3 = ~hash3;
   93     hash4 = ~hash4;
   94 
   95     while(len) {
   96         // byte-wise, no endianess
   97         hash_round(hash, *(uint8_t*)current, 1);
   98         hash_round(hash, *(uint8_t*)current, 2);
   99         hash_round(hash, *(uint8_t*)current, 3);
  100         hash_round(hash, *(uint8_t*)current, 4);
  101 
  102         current = (uint64_t*)((uint8_t*)current + 1);
  103         len--;
  104     }
  105 
  106     // digest length
  107     hash1 = ~hash1;
  108     hash2 = ~hash2;
  109     hash3 = ~hash3;
  110     hash4 = ~hash4;
  111 
  112     hash_round(hash, org_len, 1);
  113     hash_round(hash, org_len, 2);
  114     hash_round(hash, org_len, 3);
  115     hash_round(hash, org_len, 4);
  116 
  117     // hash string is stored big endian, the natural way to read
  118     uint64_t *o;
  119     o = (uint64_t*)out;
  120     *o = htobe64(hash4);
  121     o++;
  122     *o = htobe64(hash3);
  123     o++;
  124     *o = htobe64(hash2);
  125     o++;
  126     *o = htobe64(hash1);
  127 }
  128 
  129 
  130 void pearson_hash_128 (uint8_t *out, const uint8_t *in, size_t len) {
  131 
  132     uint64_t *current;
  133     current = (uint64_t*)in;
  134     uint64_t org_len = len;
  135     uint64_t hash1 = 0;
  136     uint64_t hash2 = 0;
  137 
  138     while (len > 7) {
  139         // digest words little endian first
  140         hash_round(hash, le64toh(*current), 1);
  141         hash_round(hash, le64toh(*current), 2);
  142 
  143         current++;
  144         len-=8;
  145     }
  146 
  147     // handle the rest
  148     hash1 = ~hash1;
  149     hash2 = ~hash2;
  150 
  151     while(len) {
  152         // byte-wise, no endianess
  153         hash_round(hash, *(uint8_t*)current, 1);
  154         hash_round(hash, *(uint8_t*)current, 2);
  155 
  156         current = (uint64_t*)((uint8_t*)current + 1);
  157         len--;
  158     }
  159 
  160     // digest length
  161     hash1 = ~hash1;
  162     hash2 = ~hash2;
  163 
  164     hash_round(hash, org_len, 1);
  165     hash_round(hash, org_len, 2);
  166 
  167     // hash string is stored big endian, the natural way to read
  168     uint64_t *o;
  169     o = (uint64_t*)out;
  170     *o = htobe64(hash2);
  171     o++;
  172     *o = htobe64(hash1);
  173 }
  174 
  175 
  176 uint64_t pearson_hash_64 (const uint8_t *in, size_t len) {
  177 
  178     uint64_t *current;
  179     current = (uint64_t*)in;
  180     uint64_t org_len = len;
  181     uint64_t hash1 = 0;
  182 
  183     while(len > 7) {
  184         // digest words little endian first
  185         hash_round(hash, le64toh(*current), 1);
  186 
  187         current++;
  188         len-=8;
  189     }
  190 
  191     // handle the rest
  192     hash1 = ~hash1;
  193     while(len) {
  194         // byte-wise, no endianess
  195         hash_round(hash, *(uint8_t*)current, 1);
  196 
  197         current = (uint64_t*)((uint8_t*)current + 1);
  198         len--;
  199     }
  200 
  201     // digest length
  202     hash1 = ~hash1;
  203     hash_round(hash, org_len, 1);
  204 
  205     // caller is responsible for storing it big endian to memory (if ever)
  206     return hash1;
  207 }
  208 
  209 
  210 uint32_t pearson_hash_32 (const uint8_t *in, size_t len) {
  211 
  212     return pearson_hash_64(in, len);
  213 }
  214 
  215 
  216 uint16_t pearson_hash_16 (const uint8_t *in, size_t len) {
  217 
  218     return pearson_hash_64(in, len);
  219 }
  220 
  221 
  222 void pearson_hash_init(void) {
  223 
  224 }