talgo.c 9.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/*
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
 *
 * 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.
 *
 * 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/>.
 */
15

S
talgo  
Shengliang Guan 已提交
16
#define _DEFAULT_SOURCE
17 18
#include "talgo.h"

S
talgo  
Shengliang Guan 已提交
19 20 21 22 23 24
#define doswap(__left, __right, __size, __buf) \
  do {                                         \
    memcpy((__buf), (__left), (__size));       \
    memcpy((__left), (__right), (__size));     \
    memcpy((__right), (__buf), (__size));      \
  } while (0);
25

S
talgo  
Shengliang Guan 已提交
26 27
static void median(void *src, int64_t size, int64_t s, int64_t e, const void *param, __ext_compar_fn_t comparFn,
                   void *buf) {
S
Shengliang Guan 已提交
28
  int32_t mid = ((int32_t)(e - s) >> 1u) + (int32_t)s;
S
talgo  
Shengliang Guan 已提交
29

30 31 32
  if (comparFn(elePtrAt(src, size, mid), elePtrAt(src, size, s), param) == 1) {
    doswap(elePtrAt(src, size, mid), elePtrAt(src, size, s), size, buf);
  }
S
talgo  
Shengliang Guan 已提交
33

34 35 36 37 38 39
  if (comparFn(elePtrAt(src, size, mid), elePtrAt(src, size, e), param) == 1) {
    doswap(elePtrAt(src, size, mid), elePtrAt(src, size, s), size, buf);
    doswap(elePtrAt(src, size, mid), elePtrAt(src, size, e), size, buf);
  } else if (comparFn(elePtrAt(src, size, s), elePtrAt(src, size, e), param) == 1) {
    doswap(elePtrAt(src, size, s), elePtrAt(src, size, e), size, buf);
  }
S
talgo  
Shengliang Guan 已提交
40 41 42

  assert(comparFn(elePtrAt(src, size, mid), elePtrAt(src, size, s), param) <= 0 &&
         comparFn(elePtrAt(src, size, s), elePtrAt(src, size, e), param) <= 0);
43 44

#ifdef _DEBUG_VIEW
45 46 47
//  tTagsPrints(src[s], pOrderDesc->pColumnModel, &pOrderDesc->orderIdx);
//  tTagsPrints(src[mid], pOrderDesc->pColumnModel, &pOrderDesc->orderIdx);
//  tTagsPrints(src[e], pOrderDesc->pColumnModel, &pOrderDesc->orderIdx);
48 49 50
#endif
}

S
talgo  
Shengliang Guan 已提交
51 52
static void tInsertSort(void *src, int64_t size, int32_t s, int32_t e, const void *param, __ext_compar_fn_t comparFn,
                        void *buf) {
53 54 55 56 57 58 59 60 61 62 63
  for (int32_t i = s + 1; i <= e; ++i) {
    for (int32_t j = i; j > s; --j) {
      if (comparFn(elePtrAt(src, size, j), elePtrAt(src, size, j - 1), param) == -1) {
        doswap(elePtrAt(src, size, j), elePtrAt(src, size, j - 1), size, buf);
      } else {
        break;
      }
    }
  }
}

S
talgo  
Shengliang Guan 已提交
64 65
static void tqsortImpl(void *src, int32_t start, int32_t end, int64_t size, const void *param,
                       __ext_compar_fn_t comparFn, void *buf) {
66 67 68 69 70 71
  // short array sort, incur another sort procedure instead of quick sort process
  const int32_t THRESHOLD_SIZE = 6;
  if (end - start + 1 <= THRESHOLD_SIZE) {
    tInsertSort(src, size, start, end, param, comparFn, buf);
    return;
  }
S
talgo  
Shengliang Guan 已提交
72

73
  median(src, size, start, end, param, comparFn, buf);
S
talgo  
Shengliang Guan 已提交
74

75 76
  int32_t s = start, e = end;
  int32_t endRightS = end, startLeftS = start;
S
talgo  
Shengliang Guan 已提交
77

78 79 80 81 82 83
  while (s < e) {
    while (e > s) {
      int32_t ret = comparFn(elePtrAt(src, size, e), elePtrAt(src, size, s), param);
      if (ret < 0) {
        break;
      }
S
talgo  
Shengliang Guan 已提交
84 85

      // move the data that equals to pivotal value to the right end of the list
86 87 88 89
      if (ret == 0 && e != endRightS) {
        doswap(elePtrAt(src, size, e), elePtrAt(src, size, endRightS), size, buf);
        endRightS--;
      }
S
talgo  
Shengliang Guan 已提交
90

91 92
      e--;
    }
S
talgo  
Shengliang Guan 已提交
93

94 95 96
    if (e != s) {
      doswap(elePtrAt(src, size, e), elePtrAt(src, size, s), size, buf);
    }
S
talgo  
Shengliang Guan 已提交
97

98 99 100 101 102
    while (s < e) {
      int32_t ret = comparFn(elePtrAt(src, size, s), elePtrAt(src, size, e), param);
      if (ret > 0) {
        break;
      }
S
talgo  
Shengliang Guan 已提交
103

104 105 106 107 108 109
      if (ret == 0 && s != startLeftS) {
        doswap(elePtrAt(src, size, s), elePtrAt(src, size, startLeftS), size, buf);
        startLeftS++;
      }
      s++;
    }
S
talgo  
Shengliang Guan 已提交
110

111 112 113 114
    if (e != s) {
      doswap(elePtrAt(src, size, s), elePtrAt(src, size, e), size, buf);
    }
  }
S
talgo  
Shengliang Guan 已提交
115

116 117 118 119
  int32_t rightPartStart = e + 1;
  if (endRightS != end && e < end) {
    int32_t left = rightPartStart;
    int32_t right = end;
S
talgo  
Shengliang Guan 已提交
120

121 122
    while (right > endRightS && left <= endRightS) {
      doswap(elePtrAt(src, size, left), elePtrAt(src, size, right), size, buf);
S
talgo  
Shengliang Guan 已提交
123

124 125 126
      left++;
      right--;
    }
S
talgo  
Shengliang Guan 已提交
127

128 129
    rightPartStart += (end - endRightS);
  }
S
talgo  
Shengliang Guan 已提交
130

131 132 133 134
  int32_t leftPartEnd = e - 1;
  if (startLeftS != end && s > start) {
    int32_t left = start;
    int32_t right = leftPartEnd;
S
talgo  
Shengliang Guan 已提交
135

136 137
    while (left < startLeftS && right >= startLeftS) {
      doswap(elePtrAt(src, size, left), elePtrAt(src, size, right), size, buf);
S
talgo  
Shengliang Guan 已提交
138

139 140 141
      left++;
      right--;
    }
S
talgo  
Shengliang Guan 已提交
142

143 144
    leftPartEnd -= (startLeftS - start);
  }
S
talgo  
Shengliang Guan 已提交
145

146
  if (leftPartEnd > start) {
H
hjxilinx 已提交
147
    tqsortImpl(src, start, leftPartEnd, size, param, comparFn, buf);
148
  }
S
talgo  
Shengliang Guan 已提交
149

150
  if (rightPartStart < end) {
H
hjxilinx 已提交
151
    tqsortImpl(src, rightPartStart, end, size, param, comparFn, buf);
152 153 154
  }
}

S
talgo  
Shengliang Guan 已提交
155 156
void taosqsort(void *src, int64_t numOfElem, int64_t size, const void *param, __ext_compar_fn_t comparFn) {
  char *buf = calloc(1, size);  // prepare the swap buffer
S
Shengliang Guan 已提交
157
  tqsortImpl(src, 0, (int32_t)numOfElem - 1, (int32_t)size, param, comparFn, buf);
S
TD-1848  
Shengliang Guan 已提交
158
  tfree(buf);
159 160
}

S
Shengliang Guan 已提交
161
void *taosbsearch(const void *key, const void *base, int64_t nmemb, int64_t size, __compar_fn_t compar, int32_t flags) {
162
  // TODO: need to check the correctness of this function
S
Shengliang Guan 已提交
163 164 165 166
  int32_t l = 0;
  int32_t r = (int32_t)nmemb;
  int32_t idx = 0;
  int32_t comparison;
S
talgo  
Shengliang Guan 已提交
167

168 169 170
  if (flags == TD_EQ) {
    return bsearch(key, base, nmemb, size, compar);
  } else if (flags == TD_GE) {
H
hzcheng 已提交
171
    if (nmemb <= 0) return NULL;
172 173
    if ((*compar)(key, elePtrAt(base, size, 0)) <= 0) return elePtrAt(base, size, 0);
    if ((*compar)(key, elePtrAt(base, size, nmemb - 1)) > 0) return NULL;
S
talgo  
Shengliang Guan 已提交
174

175 176 177 178 179 180 181 182 183 184 185
    while (l < r) {
      idx = (l + r) / 2;
      comparison = (*compar)(key, elePtrAt(base, size, idx));
      if (comparison < 0) {
        r = idx;
      } else if (comparison > 0) {
        l = idx + 1;
      } else {
        return elePtrAt(base, size, idx);
      }
    }
S
talgo  
Shengliang Guan 已提交
186

187 188 189 190 191 192 193 194 195 196
    if ((*compar)(key, elePtrAt(base, size, idx)) < 0) {
      return elePtrAt(base, size, idx);
    } else {
      if (idx + 1 > nmemb - 1) {
        return NULL;
      } else {
        return elePtrAt(base, size, idx + 1);
      }
    }
  } else if (flags == TD_LE) {
H
hzcheng 已提交
197
    if (nmemb <= 0) return NULL;
198 199
    if ((*compar)(key, elePtrAt(base, size, nmemb - 1)) >= 0) return elePtrAt(base, size, nmemb - 1);
    if ((*compar)(key, elePtrAt(base, size, 0)) < 0) return NULL;
S
talgo  
Shengliang Guan 已提交
200

201 202 203 204 205 206 207 208 209 210 211
    while (l < r) {
      idx = (l + r) / 2;
      comparison = (*compar)(key, elePtrAt(base, size, idx));
      if (comparison < 0) {
        r = idx;
      } else if (comparison > 0) {
        l = idx + 1;
      } else {
        return elePtrAt(base, size, idx);
      }
    }
S
talgo  
Shengliang Guan 已提交
212

213 214 215 216 217 218 219 220 221
    if ((*compar)(key, elePtrAt(base, size, idx)) > 0) {
      return elePtrAt(base, size, idx);
    } else {
      if (idx == 0) {
        return NULL;
      } else {
        return elePtrAt(base, size, idx - 1);
      }
    }
S
talgo  
Shengliang Guan 已提交
222

223 224 225 226
  } else {
    assert(0);
    return NULL;
  }
S
talgo  
Shengliang Guan 已提交
227

228 229
  return NULL;
}
230

S
talgo  
Shengliang Guan 已提交
231 232 233 234 235
void taosheapadjust(void *base, int32_t size, int32_t start, int32_t end, const void *parcompar,
                    __ext_compar_fn_t compar, const void *parswap, __ext_swap_fn_t swap, bool maxroot) {
  int32_t parent;
  int32_t child;
  char   *buf;
236 237 238 239 240 241 242 243 244 245 246 247 248 249

  if (base && size > 0 && compar) {
    parent = start;
    child = 2 * parent + 1;

    if (swap == NULL) {
      buf = calloc(1, size);
      if (buf == NULL) {
        return;
      }
    }

    if (maxroot) {
      while (child <= end) {
S
talgo  
Shengliang Guan 已提交
250 251
        if (child + 1 <= end &&
            (*compar)(elePtrAt(base, size, child), elePtrAt(base, size, child + 1), parcompar) < 0) {
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269
          child++;
        }

        if ((*compar)(elePtrAt(base, size, parent), elePtrAt(base, size, child), parcompar) > 0) {
          break;
        }

        if (swap == NULL) {
          doswap(elePtrAt(base, size, parent), elePtrAt(base, size, child), size, buf);
        } else {
          (*swap)(elePtrAt(base, size, parent), elePtrAt(base, size, child), parswap);
        }

        parent = child;
        child = 2 * parent + 1;
      }
    } else {
      while (child <= end) {
S
talgo  
Shengliang Guan 已提交
270 271
        if (child + 1 <= end &&
            (*compar)(elePtrAt(base, size, child), elePtrAt(base, size, child + 1), parcompar) > 0) {
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295
          child++;
        }

        if ((*compar)(elePtrAt(base, size, parent), elePtrAt(base, size, child), parcompar) < 0) {
          break;
        }

        if (swap == NULL) {
          doswap(elePtrAt(base, size, parent), elePtrAt(base, size, child), size, buf);
        } else {
          (*swap)(elePtrAt(base, size, parent), elePtrAt(base, size, child), parswap);
        }

        parent = child;
        child = 2 * parent + 1;
      }
    }

    if (swap == NULL) {
      tfree(buf);
    }
  }
}

S
talgo  
Shengliang Guan 已提交
296 297 298
void taosheapsort(void *base, int32_t size, int32_t len, const void *parcompar, __ext_compar_fn_t compar,
                  const void *parswap, __ext_swap_fn_t swap, bool maxroot) {
  int32_t i;
299 300 301 302 303 304 305

  if (base && size > 0) {
    for (i = len / 2 - 1; i >= 0; i--) {
      taosheapadjust(base, size, i, len - 1, parcompar, compar, parswap, swap, maxroot);
    }
  }

S
talgo  
Shengliang Guan 已提交
306 307
  /*
    char *buf = calloc(1, size);
308

S
talgo  
Shengliang Guan 已提交
309 310 311 312
    for (i = len - 1; i > 0; i--) {
      doswap(elePtrAt(base, size, 0), elePtrAt(base, size, i));
      taosheapadjust(base, size, 0, i - 1, parcompar, compar, parswap, swap, maxroot);
    }
313

S
talgo  
Shengliang Guan 已提交
314 315
    tfree(buf);
  */
316
}