LCOV - code coverage report
Current view: top level - src/backend/utils/sort - qsort_tuple.c (source / functions) Hit Total Coverage
Test: PostgreSQL Lines: 148 148 100.0 %
Date: 2017-09-29 15:12:54 Functions: 5 5 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * autogenerated by src/backend/utils/sort/gen_qsort_tuple.pl, do not edit!
       3             :  *
       4             :  * This file is included by tuplesort.c, rather than compiled separately.
       5             :  */
       6             : 
       7             : /*  $NetBSD: qsort.c,v 1.13 2003/08/07 16:43:42 agc Exp $   */
       8             : 
       9             : /*-
      10             :  * Copyright (c) 1992, 1993
      11             :  *  The Regents of the University of California.  All rights reserved.
      12             :  *
      13             :  * Redistribution and use in source and binary forms, with or without
      14             :  * modification, are permitted provided that the following conditions
      15             :  * are met:
      16             :  * 1. Redistributions of source code must retain the above copyright
      17             :  *    notice, this list of conditions and the following disclaimer.
      18             :  * 2. Redistributions in binary form must reproduce the above copyright
      19             :  *    notice, this list of conditions and the following disclaimer in the
      20             :  *    documentation and/or other materials provided with the distribution.
      21             :  * 3. Neither the name of the University nor the names of its contributors
      22             :  *    may be used to endorse or promote products derived from this software
      23             :  *    without specific prior written permission.
      24             :  *
      25             :  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
      26             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      27             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      28             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
      29             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      30             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      31             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      32             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      33             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      34             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      35             :  * SUCH DAMAGE.
      36             :  */
      37             : 
      38             : /*
      39             :  * Qsort routine based on J. L. Bentley and M. D. McIlroy,
      40             :  * "Engineering a sort function",
      41             :  * Software--Practice and Experience 23 (1993) 1249-1265.
      42             :  *
      43             :  * We have modified their original by adding a check for already-sorted input,
      44             :  * which seems to be a win per discussions on pgsql-hackers around 2006-03-21.
      45             :  *
      46             :  * Also, we recurse on the smaller partition and iterate on the larger one,
      47             :  * which ensures we cannot recurse more than log(N) levels (since the
      48             :  * partition recursed to is surely no more than half of the input).  Bentley
      49             :  * and McIlroy explicitly rejected doing this on the grounds that it's "not
      50             :  * worth the effort", but we have seen crashes in the field due to stack
      51             :  * overrun, so that judgment seems wrong.
      52             :  */
      53             : 
      54             : static void
      55      202403 : swapfunc(SortTuple *a, SortTuple *b, size_t n)
      56             : {
      57             :     do
      58             :     {
      59      202403 :         SortTuple   t = *a;
      60      202403 :         *a++ = *b;
      61      202403 :         *b++ = t;
      62      202403 :     } while (--n > 0);
      63       99012 : }
      64             : 
      65             : #define swap(a, b)                      \
      66             :     do {                                \
      67             :         SortTuple t = *(a);             \
      68             :         *(a) = *(b);                    \
      69             :         *(b) = t;                       \
      70             :     } while (0);
      71             : 
      72             : #define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n)
      73             : 
      74             : static SortTuple *
      75      103158 : med3_tuple(SortTuple *a, SortTuple *b, SortTuple *c, SortTupleComparator cmp_tuple, Tuplesortstate *state)
      76             : {
      77      206316 :     return cmp_tuple(a, b, state) < 0 ?
      78       82528 :         (cmp_tuple(b, c, state) < 0 ? b :
      79       32234 :             (cmp_tuple(a, c, state) < 0 ? c : a))
      80      191022 :         : (cmp_tuple(b, c, state) > 0 ? b :
      81       37570 :             (cmp_tuple(a, c, state) < 0 ? a : c));
      82             : }
      83             : 
      84             : static void
      85      133423 : qsort_tuple(SortTuple *a, size_t n, SortTupleComparator cmp_tuple, Tuplesortstate *state)
      86             : {
      87             :     SortTuple  *pa,
      88             :                *pb,
      89             :                *pc,
      90             :                *pd,
      91             :                *pl,
      92             :                *pm,
      93             :                *pn;
      94             :     size_t      d1,
      95             :                 d2;
      96             :     int         r,
      97             :                 presorted;
      98             : 
      99             : loop:
     100      133423 :     CHECK_FOR_INTERRUPTS();
     101      133423 :     if (n < 7)
     102             :     {
     103      239249 :         for (pm = a + 1; pm < a + n; pm++)
     104      388698 :             for (pl = pm; pl > a && cmp_tuple(pl - 1, pl, state) > 0; pl--)
     105      208430 :                 swap(pl, pl - 1);
     106       58981 :         return;
     107             :     }
     108       74436 :     presorted = 1;
     109      420088 :     for (pm = a + 1; pm < a + n; pm++)
     110             :     {
     111      419575 :         CHECK_FOR_INTERRUPTS();
     112      419575 :         if (cmp_tuple(pm - 1, pm, state) > 0)
     113             :         {
     114       73923 :             presorted = 0;
     115       73923 :             break;
     116             :         }
     117             :     }
     118       74436 :     if (presorted)
     119         513 :         return;
     120       73923 :     pm = a + (n / 2);
     121       73923 :     if (n > 7)
     122             :     {
     123       66372 :         pl = a;
     124       66372 :         pn = a + (n - 1);
     125       66372 :         if (n > 40)
     126             :         {
     127       12262 :             size_t      d = (n / 8);
     128             : 
     129       12262 :             pl = med3_tuple(pl, pl + d, pl + 2 * d, cmp_tuple, state);
     130       12262 :             pm = med3_tuple(pm - d, pm, pm + d, cmp_tuple, state);
     131       12262 :             pn = med3_tuple(pn - 2 * d, pn - d, pn, cmp_tuple, state);
     132             :         }
     133       66372 :         pm = med3_tuple(pl, pm, pn, cmp_tuple, state);
     134             :     }
     135       73923 :     swap(a, pm);
     136       73923 :     pa = pb = a + 1;
     137       73923 :     pc = pd = a + (n - 1);
     138             :     for (;;)
     139             :     {
     140     3184542 :         while (pb <= pc && (r = cmp_tuple(pb, a, state)) <= 0)
     141             :         {
     142     1297020 :             if (r == 0)
     143             :             {
     144       17231 :                 swap(pa, pb);
     145       17231 :                 pa++;
     146             :             }
     147     1297020 :             pb++;
     148     1297020 :             CHECK_FOR_INTERRUPTS();
     149             :         }
     150     3104956 :         while (pb <= pc && (r = cmp_tuple(pc, a, state)) >= 0)
     151             :         {
     152     1217434 :             if (r == 0)
     153             :             {
     154       14159 :                 swap(pc, pd);
     155       14159 :                 pd--;
     156             :             }
     157     1217434 :             pc--;
     158     1217434 :             CHECK_FOR_INTERRUPTS();
     159             :         }
     160      943761 :         if (pb > pc)
     161       73923 :             break;
     162      869838 :         swap(pb, pc);
     163      869838 :         pb++;
     164      869838 :         pc--;
     165      869838 :     }
     166       73923 :     pn = a + n;
     167       73923 :     d1 = Min(pa - a, pb - pa);
     168       73923 :     vecswap(a, pb - d1, d1);
     169       73923 :     d1 = Min(pd - pc, pn - pd - 1);
     170       73923 :     vecswap(pb, pn - d1, d1);
     171       73923 :     d1 = pb - pa;
     172       73923 :     d2 = pd - pc;
     173       73923 :     if (d1 <= d2)
     174             :     {
     175             :         /* Recurse on left partition, then iterate on right partition */
     176       36623 :         if (d1 > 1)
     177       31378 :             qsort_tuple(a, d1, cmp_tuple, state);
     178       36623 :         if (d2 > 1)
     179             :         {
     180             :             /* Iterate rather than recurse to save stack space */
     181             :             /* qsort_tuple(pn - d2, d2, cmp_tuple, state); */
     182       36620 :             a = pn - d2;
     183       36620 :             n = d2;
     184       36620 :             goto loop;
     185             :         }
     186             :     }
     187             :     else
     188             :     {
     189             :         /* Recurse on right partition, then iterate on left partition */
     190       37300 :         if (d2 > 1)
     191       27495 :             qsort_tuple(pn - d2, d2, cmp_tuple, state);
     192       37300 :         if (d1 > 1)
     193             :         {
     194             :             /* Iterate rather than recurse to save stack space */
     195             :             /* qsort_tuple(a, d1, cmp_tuple, state); */
     196       37296 :             n = d1;
     197       37296 :             goto loop;
     198             :         }
     199             :     }
     200             : }
     201             : 
     202             : #define cmp_ssup(a, b, ssup) \
     203             :     ApplySortComparator((a)->datum1, (a)->isnull1, \
     204             :                         (b)->datum1, (b)->isnull1, ssup)
     205             : 
     206             : static SortTuple *
     207       33784 : med3_ssup(SortTuple *a, SortTuple *b, SortTuple *c, SortSupport ssup)
     208             : {
     209       67568 :     return cmp_ssup(a, b, ssup) < 0 ?
     210       27472 :         (cmp_ssup(b, c, ssup) < 0 ? b :
     211       11317 :             (cmp_ssup(a, c, ssup) < 0 ? c : a))
     212       62343 :         : (cmp_ssup(b, c, ssup) > 0 ? b :
     213       12404 :             (cmp_ssup(a, c, ssup) < 0 ? a : c));
     214             : }
     215             : 
     216             : static void
     217       42391 : qsort_ssup(SortTuple *a, size_t n, SortSupport ssup)
     218             : {
     219             :     SortTuple  *pa,
     220             :                *pb,
     221             :                *pc,
     222             :                *pd,
     223             :                *pl,
     224             :                *pm,
     225             :                *pn;
     226             :     size_t      d1,
     227             :                 d2;
     228             :     int         r,
     229             :                 presorted;
     230             : 
     231             : loop:
     232       42391 :     CHECK_FOR_INTERRUPTS();
     233       42391 :     if (n < 7)
     234             :     {
     235       78589 :         for (pm = a + 1; pm < a + n; pm++)
     236      121949 :             for (pl = pm; pl > a && cmp_ssup(pl - 1, pl, ssup) > 0; pl--)
     237       62787 :                 swap(pl, pl - 1);
     238       19427 :         return;
     239             :     }
     240       22964 :     presorted = 1;
     241      194039 :     for (pm = a + 1; pm < a + n; pm++)
     242             :     {
     243      193374 :         CHECK_FOR_INTERRUPTS();
     244      193374 :         if (cmp_ssup(pm - 1, pm, ssup) > 0)
     245             :         {
     246       22299 :             presorted = 0;
     247       22299 :             break;
     248             :         }
     249             :     }
     250       22964 :     if (presorted)
     251         665 :         return;
     252       22299 :     pm = a + (n / 2);
     253       22299 :     if (n > 7)
     254             :     {
     255       20758 :         pl = a;
     256       20758 :         pn = a + (n - 1);
     257       20758 :         if (n > 40)
     258             :         {
     259        4342 :             size_t      d = (n / 8);
     260             : 
     261        4342 :             pl = med3_ssup(pl, pl + d, pl + 2 * d, ssup);
     262        4342 :             pm = med3_ssup(pm - d, pm, pm + d, ssup);
     263        4342 :             pn = med3_ssup(pn - 2 * d, pn - d, pn, ssup);
     264             :         }
     265       20758 :         pm = med3_ssup(pl, pm, pn, ssup);
     266             :     }
     267       22299 :     swap(a, pm);
     268       22299 :     pa = pb = a + 1;
     269       22299 :     pc = pd = a + (n - 1);
     270             :     for (;;)
     271             :     {
     272     1095581 :         while (pb <= pc && (r = cmp_ssup(pb, a, ssup)) <= 0)
     273             :         {
     274      495103 :             if (r == 0)
     275             :             {
     276       50664 :                 swap(pa, pb);
     277       50664 :                 pa++;
     278             :             }
     279      495103 :             pb++;
     280      495103 :             CHECK_FOR_INTERRUPTS();
     281             :         }
     282      992543 :         while (pb <= pc && (r = cmp_ssup(pc, a, ssup)) >= 0)
     283             :         {
     284      392065 :             if (r == 0)
     285             :             {
     286       30063 :                 swap(pc, pd);
     287       30063 :                 pd--;
     288             :             }
     289      392065 :             pc--;
     290      392065 :             CHECK_FOR_INTERRUPTS();
     291             :         }
     292      300239 :         if (pb > pc)
     293       22299 :             break;
     294      277940 :         swap(pb, pc);
     295      277940 :         pb++;
     296      277940 :         pc--;
     297      277940 :     }
     298       22299 :     pn = a + n;
     299       22299 :     d1 = Min(pa - a, pb - pa);
     300       22299 :     vecswap(a, pb - d1, d1);
     301       22299 :     d1 = Min(pd - pc, pn - pd - 1);
     302       22299 :     vecswap(pb, pn - d1, d1);
     303       22299 :     d1 = pb - pa;
     304       22299 :     d2 = pd - pc;
     305       22299 :     if (d1 <= d2)
     306             :     {
     307             :         /* Recurse on left partition, then iterate on right partition */
     308       11722 :         if (d1 > 1)
     309       10051 :             qsort_ssup(a, d1, ssup);
     310       11722 :         if (d2 > 1)
     311             :         {
     312             :             /* Iterate rather than recurse to save stack space */
     313             :             /* qsort_ssup(pn - d2, d2, ssup); */
     314       11715 :             a = pn - d2;
     315       11715 :             n = d2;
     316       11715 :             goto loop;
     317             :         }
     318             :     }
     319             :     else
     320             :     {
     321             :         /* Recurse on right partition, then iterate on left partition */
     322       10577 :         if (d2 > 1)
     323        8888 :             qsort_ssup(pn - d2, d2, ssup);
     324       10577 :         if (d1 > 1)
     325             :         {
     326             :             /* Iterate rather than recurse to save stack space */
     327             :             /* qsort_ssup(a, d1, ssup); */
     328       10575 :             n = d1;
     329       10575 :             goto loop;
     330             :         }
     331             :     }
     332             : }

Generated by: LCOV version 1.11