LCOV - code coverage report
Current view: top level - gdk - gdk_rsort.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 77 85 90.6 %
Date: 2024-12-20 21:24:02 Functions: 1 1 100.0 %

          Line data    Source code
       1             : /*
       2             :  * SPDX-License-Identifier: MPL-2.0
       3             :  *
       4             :  * This Source Code Form is subject to the terms of the Mozilla Public
       5             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       6             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       7             :  *
       8             :  * Copyright 2024 MonetDB Foundation;
       9             :  * Copyright August 2008 - 2023 MonetDB B.V.;
      10             :  * Copyright 1997 - July 2008 CWI.
      11             :  */
      12             : 
      13             : #include "monetdb_config.h"
      14             : #include "gdk.h"
      15             : #include "gdk_private.h"
      16             : 
      17             : #define RADIX 8                 /* one char at a time */
      18             : #define NBUCKETS (1 << RADIX)
      19             : 
      20             : gdk_return
      21       20367 : GDKrsort(void *restrict h, void *restrict t, size_t n, size_t hs, size_t ts, bool reverse, bool isuuid)
      22             : {
      23       20367 :         size_t (*counts)[NBUCKETS] = GDKzalloc(hs * sizeof(counts[0]));
      24       20367 :         size_t pos[NBUCKETS];
      25       20367 :         uint8_t *h1 = h;
      26       20367 :         uint8_t *h2;
      27       20367 :         uint8_t *t1 = NULL;
      28       20367 :         uint8_t *t2 = NULL;
      29       20367 :         Heap tmph, tmpt;
      30             : 
      31       20367 :         if (counts == NULL)
      32             :                 return GDK_FAIL;
      33             : 
      34       20367 :         tmph = tmpt = (Heap) {
      35             :                 .farmid = 1,
      36             :         };
      37             : 
      38       40734 :         snprintf(tmph.filename, sizeof(tmph.filename), "%s%crsort%zuh",
      39       20367 :                  TEMPDIR_NAME, DIR_SEP, (size_t) MT_getpid());
      40       20367 :         if (HEAPalloc(&tmph, n, hs) != GDK_SUCCEED) {
      41           0 :                 GDKfree(counts);
      42           0 :                 return GDK_FAIL;
      43             :         }
      44       20367 :         h2 = (uint8_t *) tmph.base;
      45             : 
      46       20367 :         if (t) {
      47       40284 :                 snprintf(tmpt.filename, sizeof(tmpt.filename), "%s%crsort%zut",
      48       20142 :                          TEMPDIR_NAME, DIR_SEP, (size_t) MT_getpid());
      49       20142 :                 if (HEAPalloc(&tmpt, n, ts) != GDK_SUCCEED) {
      50           0 :                         GDKfree(counts);
      51           0 :                         HEAPfree(&tmph, true);
      52           0 :                         return GDK_FAIL;
      53             :                 }
      54       20142 :                 t1 = t;
      55       20142 :                 t2 = (uint8_t *) tmpt.base;
      56             :         } else {
      57             :                 ts = 0;
      58             :         }
      59             : 
      60             : #ifndef WORDS_BIGENDIAN
      61       20367 :         if (isuuid /* UUID, treat like big-endian */) {
      62             : #endif
      63           5 :                 for (size_t i = 0, o = 0; i < n; i++, o += hs) {
      64          68 :                         for (size_t j = 0, k = hs - 1; j < hs; j++, k--) {
      65          64 :                                 uint8_t v = h1[o + k];
      66          64 :                                 counts[j][v]++;
      67             :                         }
      68             :                 }
      69             : #ifndef WORDS_BIGENDIAN
      70             :         } else {
      71    44613481 :                 for (size_t i = 0, o = 0; i < n; i++, o += hs) {
      72   225645502 :                         for (size_t j = 0; j < hs; j++) {
      73   181052387 :                                 uint8_t v = h1[o + j];
      74   181052387 :                                 counts[j][v]++;
      75             :                         }
      76             :                 }
      77             :         }
      78             : #endif
      79             :         /* When sorting in ascending order, the negative numbers occupy
      80             :          * the second half of the buckets in the last iteration; when
      81             :          * sorting in descending order, the negative numbers occupy the
      82             :          * first half.  In either case, at the end we need to put the
      83             :          * second half first and the first half after. */
      84       20367 :         size_t negpos = 0;
      85      102277 :         for (size_t j = 0, k = hs - 1; j < hs; j++, k--) {
      86       81910 :                 size_t nb = counts[j][0] > 0;
      87       81910 :                 if (reverse) {
      88          74 :                         pos[NBUCKETS - 1] = 0;
      89       18944 :                         for (size_t i = NBUCKETS - 1; i > 0; i--) {
      90       18870 :                                 pos[i - 1] = pos[i] + counts[j][i];
      91       18870 :                                 nb += counts[j][i] > 0;
      92             :                         }
      93             :                 } else {
      94       81836 :                         pos[0] = 0;
      95    20948996 :                         for (size_t i = 1; i < NBUCKETS; i++) {
      96    20867160 :                                 pos[i] = pos[i - 1] + counts[j][i - 1];
      97    20867160 :                                 nb += counts[j][i] > 0;
      98             :                         }
      99             :                 }
     100             :                 /* we're only interested in the position in the last
     101             :                  * iteration */
     102       81910 :                 negpos = pos[NBUCKETS / 2 - reverse];
     103       81910 :                 if (nb == 1) {
     104             :                         /* no need to reshuffle data for this iteration:
     105             :                          * everything is in the same bucket */
     106       22168 :                         continue;
     107             :                 }
     108             :                 /* note, this loop changes the pos array */
     109             : #ifndef WORDS_BIGENDIAN
     110       59742 :                 if (isuuid /* UUID, treat like big-endian */)
     111             : #endif
     112          80 :                         for (size_t i = 0, ho = 0, to = 0; i < n; i++, ho += hs, to += ts) {
     113          64 :                                 uint8_t v = h1[ho + k];
     114          64 :                                 if (t)
     115          64 :                                         memcpy(t2 + ts * pos[v], t1 + to, ts);
     116          64 :                                 memcpy(h2 + hs * pos[v]++, h1 + ho, hs);
     117             :                         }
     118             : #ifndef WORDS_BIGENDIAN
     119             :                 else
     120    81796752 :                         for (size_t i = 0, ho = 0, to = 0; i < n; i++, ho += hs, to += ts) {
     121    81737026 :                                 uint8_t v = h1[ho + j];
     122    81737026 :                                 if (t)
     123    77874137 :                                         memcpy(t2 + ts * pos[v], t1 + to, ts);
     124    81737026 :                                 memcpy(h2 + hs * pos[v]++, h1 + ho, hs);
     125             :                         }
     126             : #endif
     127             :                 uint8_t *t = h1;
     128             :                 h1 = h2;
     129             :                 h2 = t;
     130             :                 t = t1;
     131             :                 t1 = t2;
     132             :                 t2 = t;
     133             :         }
     134       20367 :         GDKfree(counts);
     135             : 
     136       20367 :         if (h1 != (uint8_t *) h) {
     137             :                 /* we need to copy the data back to the correct heap */
     138       19120 :                 if (isuuid) {
     139             :                         /* no negative values in uuid, so no shuffling */
     140           0 :                         memcpy(h2, h1, n * hs);
     141           0 :                         if (t)
     142           0 :                                 memcpy(t2, t1, n * ts);
     143             :                 } else {
     144             :                         /* copy the negative integers to the start, copy positive after */
     145       19120 :                         if (negpos < n) {
     146          25 :                                 memcpy(h2, h1 + hs * negpos, (n - negpos) * hs);
     147          25 :                                 if (t)
     148          22 :                                         memcpy(t2, t1 + ts * negpos, (n - negpos) * ts);
     149             :                         }
     150       19120 :                         if (negpos > 0) {
     151       19109 :                                 memcpy(h2 + hs * (n - negpos), h1, negpos * hs);
     152       19109 :                                 if (t)
     153       18961 :                                         memcpy(t2 + ts * (n - negpos), t1, negpos * ts);
     154             :                         }
     155             :                 }
     156        1247 :         } else if (negpos > 0 && negpos < n && !isuuid) {
     157             :                 /* copy the negative integers to the start, copy positive after */
     158          25 :                 memcpy(h2, h1 + hs * negpos, (n - negpos) * hs);
     159          25 :                 memcpy(h2 + hs * (n - negpos), h1, negpos * hs);
     160          25 :                 memcpy(h, h2, n * hs);
     161          25 :                 if (t) {
     162          23 :                         memcpy(t2, t1 + ts * negpos, (n - negpos) * ts);
     163          23 :                         memcpy(t2 + ts * (n - negpos), t1, negpos * ts);
     164          23 :                         memcpy(t, t2, n * ts);
     165             :                 }
     166             :         } /* else, everything is already in the correct place */
     167       20367 :         HEAPfree(&tmph, true);
     168       20367 :         if (t)
     169       20142 :                 HEAPfree(&tmpt, true);
     170             :         return GDK_SUCCEED;
     171             : }

Generated by: LCOV version 1.14