pdqhash-go

git clone git://archive.git.mtrnord.blog/MTRNord/pdqhash-go.git
Log | Files | Refs | LICENSE

hash256.go (4319B)


      1 package types
      2 
      3 import (
      4 	"fmt"
      5 	"strconv"
      6 	"strings"
      7 )
      8 
      9 // 16 slots of 16 bytes each
     10 // See hashing/pdq/README-MIH.md in upstream repo for why not 8x32 or 32x8, etc.
     11 const HASH256_NUM_SLOTS = 16
     12 const HASH256_HEX_NUM_NYBBLES = 4 * HASH256_NUM_SLOTS
     13 
     14 type Hash256 struct {
     15 	W [HASH256_NUM_SLOTS]int
     16 }
     17 
     18 func (h *Hash256) Clone() Hash256 {
     19 	rv := Hash256{}
     20 	for i := 0; i < HASH256_NUM_SLOTS; i++ {
     21 		rv.W[i] = h.W[i]
     22 	}
     23 	return rv
     24 }
     25 
     26 func (h *Hash256) String() string {
     27 	var result []string
     28 
     29 	for i := HASH256_NUM_SLOTS - 1; i >= 0; i-- {
     30 		result = append(result, fmt.Sprintf("%04x", h.W[i]&0xFFFF))
     31 	}
     32 
     33 	return strings.Join(result, "")
     34 }
     35 
     36 func Hash256FromHexString(s string) (*Hash256, error) {
     37 	if len(s) != HASH256_HEX_NUM_NYBBLES {
     38 		return nil, fmt.Errorf("incorrect hash length: %s", s)
     39 	}
     40 
     41 	rv := &Hash256{}
     42 	i := HASH256_NUM_SLOTS
     43 	for x := 0; x < len(s); x += 4 {
     44 		i -= 1
     45 		val, err := strconv.ParseUint(s[x:x+4], 16, 16)
     46 		if err != nil {
     47 			return nil, fmt.Errorf("incorrect format: %s", s)
     48 		}
     49 		rv.W[i] = int(val)
     50 	}
     51 	return rv, nil
     52 }
     53 
     54 func (h *Hash256) HammingNorm16(h2 int) int {
     55 	return BitCount(h2 & 0xFFFF)
     56 }
     57 
     58 func BitCount(x int) int {
     59 	x -= (x >> 1) & 0x55555555
     60 	x = ((x >> 2) & 0x33333333) + (x & 0x33333333)
     61 	x = ((x >> 4) + x) & 0x0F0F0F0F
     62 	x += x >> 8
     63 	x += x >> 16
     64 	return x & 0x0000003F
     65 }
     66 
     67 func (h *Hash256) ClearAll() {
     68 	for i := 0; i < HASH256_NUM_SLOTS; i++ {
     69 		h.W[i] = 0
     70 	}
     71 }
     72 
     73 func (h *Hash256) SetAll() {
     74 	for i := 0; i < HASH256_NUM_SLOTS; i++ {
     75 		h.W[i] = 0xFFFF
     76 	}
     77 }
     78 
     79 func (h *Hash256) HammingNorm() int {
     80 	n := 0
     81 
     82 	for i := 0; i < HASH256_NUM_SLOTS; i++ {
     83 		n += h.HammingNorm16(h.W[i])
     84 	}
     85 	return n
     86 }
     87 
     88 func (h *Hash256) HammingDistance(that *Hash256) int {
     89 	n := 0
     90 	for i := 0; i < HASH256_NUM_SLOTS; i++ {
     91 		n += h.HammingNorm16(h.W[i] ^ that.W[i])
     92 	}
     93 	return n
     94 }
     95 
     96 func (h *Hash256) HammingDistanceLE(that *Hash256, d int) bool {
     97 	e := 0
     98 	for i := 0; i < HASH256_NUM_SLOTS; i++ {
     99 		e += h.HammingNorm16(h.W[i] ^ that.W[i])
    100 		if e > d {
    101 			return false
    102 		}
    103 	}
    104 	return true
    105 }
    106 
    107 func (h *Hash256) SetBit(k int) {
    108 	h.W[(k&255)>>4] |= 1 << (k & 15)
    109 }
    110 
    111 func (h *Hash256) FlipBit(k int) {
    112 	h.W[(k&255)>>4] ^= 1 << (k & 15)
    113 }
    114 
    115 func (h *Hash256) BitwiseXOR(that *Hash256) Hash256 {
    116 	rv := Hash256{}
    117 	for i := 0; i < HASH256_NUM_SLOTS; i++ {
    118 		rv.W[i] = (h.W[i] ^ that.W[i])
    119 	}
    120 	return rv
    121 }
    122 
    123 func (h *Hash256) BitwiseAND(that *Hash256) Hash256 {
    124 	rv := Hash256{}
    125 	for i := 0; i < HASH256_NUM_SLOTS; i++ {
    126 		rv.W[i] = (h.W[i] & that.W[i])
    127 	}
    128 	return rv
    129 }
    130 
    131 func (h *Hash256) BitwiseOR(that *Hash256) Hash256 {
    132 	rv := Hash256{}
    133 	for i := 0; i < HASH256_NUM_SLOTS; i++ {
    134 		rv.W[i] = (h.W[i] | that.W[i])
    135 	}
    136 	return rv
    137 }
    138 
    139 func (h *Hash256) BitwiseNOT() Hash256 {
    140 	rv := Hash256{}
    141 	for i := 0; i < HASH256_NUM_SLOTS; i++ {
    142 		rv.W[i] = (int((^h.W[i])) & 0xFFFF)
    143 	}
    144 	return rv
    145 }
    146 
    147 func (h *Hash256) DumpBits() string {
    148 	var str []string
    149 
    150 	for i := HASH256_NUM_SLOTS - 1; i >= 0; i-- {
    151 		word := h.W[i] & 0xFFFF
    152 		var bits []string
    153 		for j := 15; j >= 0; j-- {
    154 			if (word & (1 << uint(j))) != 0 {
    155 				bits = append(bits, "1")
    156 			} else {
    157 				bits = append(bits, "0")
    158 			}
    159 		}
    160 		str = append(str, strings.Join(bits, " "))
    161 	}
    162 	return strings.Join(str, "\n")
    163 }
    164 
    165 func (h *Hash256) DumpBitsAcross() string {
    166 	var str []string
    167 
    168 	for i := HASH256_NUM_SLOTS - 1; i >= 0; i-- {
    169 		word := h.W[i] & 0xFFFF
    170 		for j := 15; j >= 0; j-- {
    171 			if (word & (1 << uint(j))) != 0 {
    172 				str = append(str, "1")
    173 			} else {
    174 				str = append(str, "0")
    175 			}
    176 		}
    177 	}
    178 	return strings.Join(str, " ")
    179 }
    180 
    181 func (h *Hash256) DumpWords() string {
    182 	var words []string
    183 
    184 	// Iterate over the reversed list of words
    185 	for i := len(h.W) - 1; i >= 0; i-- {
    186 		words = append(words, strconv.Itoa(int(h.W[i])))
    187 	}
    188 
    189 	// Join the words with commas
    190 	return strings.Join(words, ",")
    191 }
    192 
    193 func (h *Hash256) Eq(other *Hash256) bool {
    194 	for i := 0; i < HASH256_NUM_SLOTS; i++ {
    195 		if h.W[i] != other.W[i] {
    196 			return false
    197 		}
    198 	}
    199 	return true
    200 }
    201 
    202 func (h *Hash256) Greater(other *Hash256) bool {
    203 	for i := 0; i < HASH256_NUM_SLOTS; i++ {
    204 		if h.W[i] > other.W[i] {
    205 			return true
    206 		} else if h.W[i] < other.W[i] {
    207 			return false
    208 		}
    209 	}
    210 	return false
    211 }
    212 
    213 func (h *Hash256) Less(other *Hash256) bool {
    214 	for i := 0; i < HASH256_NUM_SLOTS; i++ {
    215 		if h.W[i] < other.W[i] {
    216 			return true
    217 		} else if h.W[i] > other.W[i] {
    218 			return false
    219 		}
    220 	}
    221 	return false
    222 }