thashutil.c 4.5 KB
Newer Older
S
TD-4088  
Shengliang Guan 已提交
1 2
/*
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
H
hzcheng 已提交
3
 *
S
TD-4088  
Shengliang Guan 已提交
4 5 6
 * This program is free software: you can use, redistribute, and/or modify
 * it under the terms of the GNU Affero General Public License, version 3
 * or later ("AGPL"), as published by the Free Software Foundation.
H
hzcheng 已提交
7
 *
S
TD-4088  
Shengliang Guan 已提交
8 9 10 11 12 13
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
H
hzcheng 已提交
14
 */
S
TD-4088  
Shengliang Guan 已提交
15 16

#include "os.h"
H
Haojun Liao 已提交
17
#include "thash.h"
H
Hongze Cheng 已提交
18
#include "compare.h"
19
#include "taos.h"
H
Hongze Cheng 已提交
20
#include "types.h"
H
hzcheng 已提交
21

H
Haojun Liao 已提交
22
#define ROTL32(x, r) ((x) << (r) | (x) >> (32u - (r)))
H
hzcheng 已提交
23

24 25 26
#define DLT (FLT_COMPAR_TOL_FACTOR * FLT_EPSILON)
#define BASE 1000

H
hzcheng 已提交
27 28 29 30 31 32
#define FMIX32(h)      \
  do {                 \
    (h) ^= (h) >> 16;  \
    (h) *= 0x85ebca6b; \
    (h) ^= (h) >> 13;  \
    (h) *= 0xc2b2ae35; \
33
    (h) ^= (h) >> 16; } while (0)
H
Haojun Liao 已提交
34 35
  
uint32_t MurmurHash3_32(const char *key, uint32_t len) {
H
hzcheng 已提交
36
  const uint8_t *data = (const uint8_t *)key;
H
Haojun Liao 已提交
37
  const int nblocks = len >> 2u;
H
hzcheng 已提交
38

H
Haojun Liao 已提交
39
  uint32_t h1 = 0x12345678;
H
hzcheng 已提交
40 41 42 43 44 45 46 47 48 49

  const uint32_t c1 = 0xcc9e2d51;
  const uint32_t c2 = 0x1b873593;

  const uint32_t *blocks = (const uint32_t *)(data + nblocks * 4);

  for (int i = -nblocks; i; i++) {
    uint32_t k1 = blocks[i];

    k1 *= c1;
H
Haojun Liao 已提交
50
    k1 = ROTL32(k1, 15u);
H
hzcheng 已提交
51 52 53
    k1 *= c2;

    h1 ^= k1;
H
Haojun Liao 已提交
54
    h1 = ROTL32(h1, 13u);
H
hzcheng 已提交
55 56 57 58 59 60 61
    h1 = h1 * 5 + 0xe6546b64;
  }

  const uint8_t *tail = (data + nblocks * 4);

  uint32_t k1 = 0;

H
Haojun Liao 已提交
62
  switch (len & 3u) {
H
hzcheng 已提交
63 64 65 66 67 68 69
    case 3:
      k1 ^= tail[2] << 16;
    case 2:
      k1 ^= tail[1] << 8;
    case 1:
      k1 ^= tail[0];
      k1 *= c1;
H
Haojun Liao 已提交
70
      k1 = ROTL32(k1, 15u);
H
hzcheng 已提交
71 72 73 74 75 76 77 78
      k1 *= c2;
      h1 ^= k1;
  };

  h1 ^= len;

  FMIX32(h1);

H
Haojun Liao 已提交
79
  return h1;
H
hzcheng 已提交
80
}
81 82

uint32_t taosIntHash_32(const char *key, uint32_t UNUSED_PARAM(len)) { return *(uint32_t *)key; }
H
hjxilinx 已提交
83 84
uint32_t taosIntHash_16(const char *key, uint32_t UNUSED_PARAM(len)) { return *(uint16_t *)key; }
uint32_t taosIntHash_8(const char *key, uint32_t UNUSED_PARAM(len)) { return *(uint8_t *)key; }
85 86 87 88 89
uint32_t taosFloatHash(const char *key, uint32_t UNUSED_PARAM(len)) {
  float f = GET_FLOAT_VAL(key); 
  if (isnan(f)) {
    return 0x7fc00000;
  }
90 91
   
  if (FLT_EQUAL(f, 0.0)) {
92
    return 0;
93
  } 
Y
yihaoDeng 已提交
94 95 96 97 98
  if (fabs(f) < FLT_MAX/BASE - DLT) {
   int t = (int)(round(BASE * (f + DLT)));
   return (uint32_t)t;
  } else {
   return 0x7fc00000;
99
  }
100 101 102 103 104 105
}
uint32_t taosDoubleHash(const char *key, uint32_t UNUSED_PARAM(len)) {
  double f = GET_DOUBLE_VAL(key);  
  if (isnan(f)) {
    return 0x7fc00000;
  }
106 107

  if (FLT_EQUAL(f, 0.0)) {
108
    return 0;
109
  } 
Y
yihaoDeng 已提交
110 111 112 113 114 115
  if (fabs(f) < DBL_MAX/BASE - DLT) {
   int t = (int)(round(BASE * (f + DLT)));
   return (uint32_t)t;
  } else {
   return 0x7fc00000;
  } 
116
}
117 118 119 120 121 122
uint32_t taosIntHash_64(const char *key, uint32_t UNUSED_PARAM(len)) {
  uint64_t val = *(uint64_t *)key;

  uint64_t hash = val >> 16U;
  hash += (val & 0xFFFFU);
  
S
TD-1037  
Shengliang Guan 已提交
123
  return (uint32_t)hash;
124 125 126 127 128
}

_hash_fn_t taosGetDefaultHashFunction(int32_t type) {
  _hash_fn_t fn = NULL;
  switch(type) {
H
hjxilinx 已提交
129
    case TSDB_DATA_TYPE_TIMESTAMP:
W
wpan 已提交
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
    case TSDB_DATA_TYPE_UBIGINT:
    case TSDB_DATA_TYPE_BIGINT:   
      fn = taosIntHash_64;
      break;
    case TSDB_DATA_TYPE_BINARY:   
      fn = MurmurHash3_32;
      break;
    case TSDB_DATA_TYPE_NCHAR:    
      fn = MurmurHash3_32;
      break;
    case TSDB_DATA_TYPE_UINT:
    case TSDB_DATA_TYPE_INT:      
      fn = taosIntHash_32; 
      break;
    case TSDB_DATA_TYPE_SMALLINT: 
    case TSDB_DATA_TYPE_USMALLINT:  
      fn = taosIntHash_16; 
      break;
    case TSDB_DATA_TYPE_BOOL:
    case TSDB_DATA_TYPE_UTINYINT:
    case TSDB_DATA_TYPE_TINYINT:  
      fn = taosIntHash_8; 
      break;
    case TSDB_DATA_TYPE_FLOAT:    
      fn = taosFloatHash; 
      break;                             
    case TSDB_DATA_TYPE_DOUBLE:   
      fn = taosDoubleHash; 
      break;                             
    default: 
      fn = taosIntHash_32;
      break;
162 163 164
  }
  
  return fn;
165 166
}

D
dapan1121 已提交
167 168 169 170 171 172 173
int32_t taosFloatEqual(const void *a, const void *b, size_t UNUSED_PARAM(sz)) {
  return getComparFunc(TSDB_DATA_TYPE_FLOAT, -1)(a, b);
}

int32_t taosDoubleEqual(const void *a, const void *b, size_t UNUSED_PARAM(sz)) {
  return getComparFunc(TSDB_DATA_TYPE_DOUBLE, -1)(a, b);
}
174 175 176

_equal_fn_t taosGetDefaultEqualFunction(int32_t type) {
  _equal_fn_t fn = NULL;
D
dapan1121 已提交
177 178 179 180 181
  switch (type) {
    case TSDB_DATA_TYPE_FLOAT:  fn = taosFloatEqual;  break;
    case TSDB_DATA_TYPE_DOUBLE: fn = taosDoubleEqual; break;
    default: fn = memcmp; break;
  }
182 183
  return fn;
}