LCOV - app.info - js/src/ds/Sort.h

LCOV - code coverage report
| Current view: | directory - js/src/ds - Sort.h (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 63 | 60 | 95.2 %
| Date: | 2012-07-07 | Functions: | 13 | 8 | 61.5 %

           1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
           2                 :  * vim: set ts=4 sw=4 et tw=99 ft=cpp:
           3                 :  *
           4                 :  * ***** BEGIN LICENSE BLOCK *****
           5                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           6                 :  *
           7                 :  * The contents of this file are subject to the Mozilla Public License Version
           8                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           9                 :  * the License. You may obtain a copy of the License at
          10                 :  * http://www.mozilla.org/MPL/
          11                 :  *
          12                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          13                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          14                 :  * for the specific language governing rights and limitations under the
          15                 :  * License.
          16                 :  *
          17                 :  * The Original Code is SpiderMonkey JavaScript engine.
          18                 :  *
          19                 :  * The Initial Developer of the Original Code is
          20                 :  * Mozilla Corporation.
          21                 :  * Portions created by the Initial Developer are Copyright (C) 2011
          22                 :  * the Initial Developer. All Rights Reserved.
          23                 :  *
          24                 :  * Contributor(s):
          25                 :  *
          26                 :  * Alternatively, the contents of this file may be used under the terms of
          27                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
          28                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          30                 :  * of those above. If you wish to allow use of your version of this file only
          31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          32                 :  * use your version of this file under the terms of the MPL, indicate your
          33                 :  * decision by deleting the provisions above and replace them with the notice
          34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          35                 :  * the provisions above, a recipient may use your version of this file under
          36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          37                 :  *
          38                 :  * ***** END LICENSE BLOCK ***** */
          39                 :
          40                 : #ifndef Sort_h__
          41                 : #define Sort_h__
          42                 :
          43                 : #include "jstypes.h"
          44                 :
          45                 : namespace js {
          46                 :
          47                 : namespace detail {
          48                 :
          49                 : template<typename T>
          50                 : JS_ALWAYS_INLINE void
          51           13254 : CopyNonEmptyArray(T *dst, const T *src, size_t nelems)
          52                 : {
          53           13254 :     JS_ASSERT(nelems != 0);
          54           13254 :     const T *end = src + nelems;
          55           37585 :     do {
          56           37585 :         *dst++ = *src++;
          57                 :     } while (src != end);
          58           13254 : }
          59                 :
          60                 : /* Helper function for MergeSort. */
          61                 : template<typename T, typename Comparator>
          62                 : JS_ALWAYS_INLINE bool
          63           12383 : MergeArrayRuns(T *dst, const T *src, size_t run1, size_t run2, Comparator c)
          64                 : {
          65           12383 :     JS_ASSERT(run1 >= 1);
          66           12383 :     JS_ASSERT(run2 >= 1);
          67                 :
          68                 :     /* Copy runs already in sorted order. */
          69           12383 :     const T *b = src + run1;
          70                 :     bool lessOrEqual;
          71           12383 :     if (!c(b[-1],  b[0], &lessOrEqual))
          72               0 :         return false;
          73                 :
          74           12383 :     if (!lessOrEqual) {
          75                 :         /* Runs are not already sorted, merge them. */
          76          274299 :         for (const T *a = src;;) {
          77          274299 :             if (!c(*a, *b, &lessOrEqual))
          78               0 :                 return false;
          79          274299 :             if (lessOrEqual) {
          80          145312 :                 *dst++ = *a++;
          81          145312 :                 if (!--run1) {
          82            5146 :                     src = b;
          83            5146 :                     break;
          84                 :                 }
          85                 :             } else {
          86          128987 :                 *dst++ = *b++;
          87          128987 :                 if (!--run2) {
          88            6229 :                     src = a;
          89            6229 :                     break;
          90                 :                 }
          91                 :             }
          92                 :         }
          93                 :     }
          94           12383 :     CopyNonEmptyArray(dst, src, run1 + run2);
          95           12383 :     return true;
          96                 : }
          97                 :
          98                 : } /* namespace detail */
          99                 :
         100                 : /*
         101                 :  * Sort the array using the merge sort algorithm. The scratch should point to
         102                 :  * a temporary storage that can hold nelems elements.
         103                 :  *
         104                 :  * The comparator must provide the () operator with the following signature:
         105                 :  *
         106                 :  *     bool operator()(const T& a, const T& a, bool *lessOrEqualp);
         107                 :  *
         108                 :  * It should return true on success and set *lessOrEqualp to the result of
         109                 :  * a <= b operation. If it returns false, the sort terminates immediately with
         110                 :  * the false result. In this case the content of the array and scratch is
         111                 :  * arbitrary.
         112                 :  */
         113                 : template<typename T, typename Comparator>
         114                 : bool
         115           34711 : MergeSort(T *array, size_t nelems, T *scratch, Comparator c)
         116                 : {
         117           34711 :     const size_t INS_SORT_LIMIT = 3;
         118                 :
         119           34711 :     if (nelems <= 1)
         120            1157 :         return true;
         121                 :
         122                 :     /*
         123                 :      * Apply insertion sort to small chunks to reduce the number of merge
         124                 :      * passes needed.
         125                 :      */
         126           79473 :     for (size_t lo = 0; lo < nelems; lo += INS_SORT_LIMIT) {
         127           45937 :         size_t hi = lo + INS_SORT_LIMIT;
         128           45937 :         if (hi >= nelems)
         129           33545 :             hi = nelems;
         130          104057 :         for (size_t i = lo + 1; i != hi; i++) {
         131           65879 :             for (size_t j = i; ;) {
         132                 :                 bool lessOrEqual;
         133           65879 :                 if (!c(array[j - 1], array[j], &lessOrEqual))
         134              18 :                     return false;
         135           65861 :                 if (lessOrEqual)
         136           32527 :                     break;
         137           33334 :                 T tmp = array[j - 1];
         138           33334 :                 array[j - 1] = array[j];
         139           33334 :                 array[j] = tmp;
         140           33334 :                 if (--j == lo)
         141           25593 :                     break;
         142                 :             }
         143                 :         }
         144                 :     }
         145                 :
         146           33536 :     T *vec1 = array;
         147           33536 :     T *vec2 = scratch;
         148           34826 :     for (size_t run = INS_SORT_LIMIT; run < nelems; run *= 2) {
         149           13673 :         for (size_t lo = 0; lo < nelems; lo += 2 * run) {
         150           12682 :             size_t hi = lo + run;
         151           12682 :             if (hi >= nelems) {
         152             299 :                 detail::CopyNonEmptyArray(vec2 + lo, vec1 + lo, nelems - lo);
         153             299 :                 break;
         154                 :             }
         155           12383 :             size_t run2 = (run <= nelems - hi) ? run : nelems - hi;
         156           12383 :             if (!detail::MergeArrayRuns(vec2 + lo, vec1 + lo, run, run2, c))
         157               0 :                 return false;
         158                 :         }
         159            1290 :         T *swap = vec1;
         160            1290 :         vec1 = vec2;
         161            1290 :         vec2 = swap;
         162                 :     }
         163           33536 :     if (vec1 == scratch)
         164             572 :         detail::CopyNonEmptyArray(array, scratch, nelems);
         165           33536 :     return true;
         166                 : }
         167                 :
         168                 : } /* namespace js */
         169                 :
         170                 : #endif

Generated by: LCOV version 1.7