LCOV - code coverage report
Current view: top level - src - hash.c (source / functions) Hit Total Coverage
Test: cov_nosys.info Lines: 59 59 100.0 %
Date: 2024-06-16 08:54:54 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /*
       2             :  *  hash.c
       3             :  *  Patater GUI Kit
       4             :  *
       5             :  *  Created by Jaeden Amero on 2019-05-04.
       6             :  *  Copyright 2019. SPDX-License-Identifier: AGPL-3.0-or-later
       7             :  */
       8             : 
       9             : #include "guikit/hash.h"
      10             : 
      11             : /* FNV-1a algorithm description from
      12             :  * http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-param */
      13         212 : static u32 hash_fnv1a_32(const char *buf, size_t len)
      14             : {
      15             :     /* FNV-1a parameters for a 32-bit hash */
      16         212 :     const u32 PRIME_32 = 16777619UL;
      17         212 :     const u32 OFFSET_32 = 2166136261UL;
      18             : 
      19         212 :     u32 h = OFFSET_32;
      20             :     size_t i;
      21             : 
      22             :     /* Note: could be faster if we do machine-word-sized chunks. */
      23        7331 :     for (i = 0; i < len; i++)
      24             :     {
      25        7119 :         h ^= ((u8)buf[i]) & 0xFFUL;
      26        7119 :         h *= PRIME_32;
      27             :     }
      28             : 
      29         212 :     return h;
      30             : }
      31             : 
      32             : /* Set out to the 64-bit truncated result of the unsigned multiplication of a *
      33             :  * b, where a and b are 64-bit little endian and out is 64-bit. */
      34             : /* Use long multiplication with 16-bit word size, so we can store the full
      35             :  * multiplication result in a word on a 32-bit machine, per Algorithm M from
      36             :  * Knuth Vol 2. Unlike Algorithm M, cut out all calculations for the upper
      37             :  * 64-bits of the result, as we know we won't use those; this makes the
      38             :  * calculation triangly. */
      39             : /* Note that this function does not work in place. out can't be one of the
      40             :  * input parameters, a or b. */
      41        7099 : static void umul64(u16 out[], const u16 a[], const u16 b[])
      42             : {
      43             :     u32 k;
      44             :     u32 t;
      45             : 
      46        7099 :     t = a[0] * b[0];
      47        7099 :     out[0] = t;
      48        7099 :     k = t >> 16;
      49             : 
      50        7099 :     t = a[1] * b[0] + k;
      51        7099 :     out[1] = t;
      52        7099 :     k = t >> 16;
      53             : 
      54        7099 :     t = a[2] * b[0] + k;
      55        7099 :     out[2] = t;
      56        7099 :     k = t >> 16;
      57             : 
      58        7099 :     t = a[3] * b[0] + k;
      59        7099 :     out[3] = t;
      60             : 
      61        7099 :     t = a[0] * b[1] + out[1];
      62        7099 :     out[1] = t;
      63        7099 :     k = t >> 16;
      64             : 
      65        7099 :     t = a[1] * b[1] + out[2] + k;
      66        7099 :     out[2] = t;
      67        7099 :     k = t >> 16;
      68             : 
      69        7099 :     t = a[2] * b[1] + out[3] + k;
      70        7099 :     out[3] = t;
      71             : 
      72        7099 :     t = a[0] * b[2] + out[2];
      73        7099 :     out[2] = t;
      74        7099 :     k = t >> 16;
      75             : 
      76        7099 :     t = a[1] * b[2] + out[3] + k;
      77        7099 :     out[3] = t;
      78             : 
      79        7099 :     t = a[0] * b[3] + out[3];
      80        7099 :     out[3] = t;
      81        7099 : }
      82             : 
      83             : /* FNV-1a algorithm description from
      84             :  * http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-param */
      85         211 : static void hash_fnv1a_64(u32 hash[], const char *buf, size_t len)
      86             : {
      87             :     /* FNV-1a parameters for a 64-bit hash:
      88             :      * 64 bit FNV_prime = 1 << 40 + 1 << 8 + 0xB3
      89             :      *                  = 1099511628211 = 0x100000001B3
      90             :      * 64 bit offset_basis = 14695981039346656037 = 0xCBF29CE484222325
      91             :      */
      92         211 :     const u16 PRIME_64[4] = {0x01B3, 0x0000, 0x0100, 0x0000};
      93             :     const u16 OFFSET_64[4] = {0x2325, 0x8422, 0x9CE4, 0xCBF2};
      94             : 
      95         211 :     u16 h[4];
      96         211 :     u16 h_next[4];
      97             :     size_t i;
      98             : 
      99         211 :     h[0] = OFFSET_64[0];
     100         211 :     h[1] = OFFSET_64[1];
     101         211 :     h[2] = OFFSET_64[2];
     102         211 :     h[3] = OFFSET_64[3];
     103             : 
     104             :     /* Note: could be faster if we do machine-word-sized chunks. */
     105        7310 :     for (i = 0; i < len; i++)
     106             :     {
     107        7099 :         h[0] ^= ((u8)buf[i]) & 0xFFUL;
     108             : 
     109             :         /* Multiply h by PRIME_64 */
     110        7099 :         umul64(h_next, h, PRIME_64);
     111        7099 :         h[0] = h_next[0];
     112        7099 :         h[1] = h_next[1];
     113        7099 :         h[2] = h_next[2];
     114        7099 :         h[3] = h_next[3];
     115             :         /* Note we are throwing away the upper 64-bits of the multiplication */
     116             :     }
     117             : 
     118         211 :     hash[0] = ((u32)h[1] << 16) | h[0];
     119         211 :     hash[1] = ((u32)h[3] << 16) | h[2];
     120         211 : }
     121             : 
     122         212 : unsigned long hash(const char *buf, size_t len)
     123             : {
     124         212 :     return hash_fnv1a_32(buf, len);
     125             : }
     126             : 
     127         211 : void hash64(u32 out[], const char *buf, size_t len)
     128             : {
     129         211 :     hash_fnv1a_64(out, buf, len);
     130         211 : }

Generated by: LCOV version 1.14