File indexing completed on 2025-01-18 09:51:48
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #ifndef BOOST_SORT_SPREADSORT_DETAIL_FLOAT_SORT_HPP
0018 #define BOOST_SORT_SPREADSORT_DETAIL_FLOAT_SORT_HPP
0019 #include <algorithm>
0020 #include <vector>
0021 #include <limits>
0022 #include <functional>
0023 #include <boost/static_assert.hpp>
0024 #include <boost/utility/enable_if.hpp>
0025 #include <boost/sort/spreadsort/detail/constants.hpp>
0026 #include <boost/sort/spreadsort/detail/integer_sort.hpp>
0027 #include <boost/sort/spreadsort/detail/spreadsort_common.hpp>
0028 #include <boost/cstdint.hpp>
0029
0030 namespace boost {
0031 namespace sort {
0032 namespace spreadsort {
0033 namespace detail {
0034
0035 template<class Cast_type, class RandomAccessIter>
0036 inline Cast_type
0037 cast_float_iter(const RandomAccessIter & floatiter)
0038 {
0039 typedef typename std::iterator_traits<RandomAccessIter>::value_type
0040 Data_type;
0041
0042 BOOST_STATIC_ASSERT(sizeof(Cast_type) == sizeof(Data_type));
0043 BOOST_STATIC_ASSERT(std::numeric_limits<Data_type>::is_iec559);
0044 BOOST_STATIC_ASSERT(std::numeric_limits<Cast_type>::is_integer);
0045 Cast_type result;
0046 std::memcpy(&result, &(*floatiter), sizeof(Data_type));
0047 return result;
0048 }
0049
0050
0051
0052 template <class RandomAccessIter, class Div_type, class Right_shift>
0053 inline bool
0054 is_sorted_or_find_extremes(RandomAccessIter current, RandomAccessIter last,
0055 Div_type & max, Div_type & min, Right_shift rshift)
0056 {
0057 min = max = rshift(*current, 0);
0058 RandomAccessIter prev = current;
0059 bool sorted = true;
0060 while (++current < last) {
0061 Div_type value = rshift(*current, 0);
0062 sorted &= *current >= *prev;
0063 prev = current;
0064 if (max < value)
0065 max = value;
0066 else if (value < min)
0067 min = value;
0068 }
0069 return sorted;
0070 }
0071
0072
0073
0074 template <class RandomAccessIter, class Div_type, class Right_shift,
0075 class Compare>
0076 inline bool
0077 is_sorted_or_find_extremes(RandomAccessIter current, RandomAccessIter last,
0078 Div_type & max, Div_type & min,
0079 Right_shift rshift, Compare comp)
0080 {
0081 min = max = rshift(*current, 0);
0082 RandomAccessIter prev = current;
0083 bool sorted = true;
0084 while (++current < last) {
0085 Div_type value = rshift(*current, 0);
0086 sorted &= !comp(*current, *prev);
0087 prev = current;
0088 if (max < value)
0089 max = value;
0090 else if (value < min)
0091 min = value;
0092 }
0093 return sorted;
0094 }
0095
0096
0097 template <class RandomAccessIter, class Div_type>
0098 inline void inner_float_swap_loop(RandomAccessIter * bins,
0099 const RandomAccessIter & nextbinstart, unsigned ii
0100 , const unsigned log_divisor, const Div_type div_min)
0101 {
0102 RandomAccessIter * local_bin = bins + ii;
0103 for (RandomAccessIter current = *local_bin; current < nextbinstart;
0104 ++current) {
0105 for (RandomAccessIter * target_bin =
0106 (bins + ((cast_float_iter<Div_type, RandomAccessIter>(current) >>
0107 log_divisor) - div_min)); target_bin != local_bin;
0108 target_bin = bins + ((cast_float_iter<Div_type, RandomAccessIter>
0109 (current) >> log_divisor) - div_min)) {
0110 typename std::iterator_traits<RandomAccessIter>::value_type tmp;
0111 RandomAccessIter b = (*target_bin)++;
0112 RandomAccessIter * b_bin = bins + ((cast_float_iter<Div_type,
0113 RandomAccessIter>(b) >> log_divisor) - div_min);
0114
0115
0116 if (b_bin != local_bin) {
0117 RandomAccessIter c = (*b_bin)++;
0118 tmp = *c;
0119 *c = *b;
0120 }
0121 else
0122 tmp = *b;
0123 *b = *current;
0124 *current = tmp;
0125 }
0126 }
0127 *local_bin = nextbinstart;
0128 }
0129
0130 template <class RandomAccessIter, class Div_type>
0131 inline void float_swap_loop(RandomAccessIter * bins,
0132 RandomAccessIter & nextbinstart, unsigned ii,
0133 const size_t *bin_sizes,
0134 const unsigned log_divisor, const Div_type div_min)
0135 {
0136 nextbinstart += bin_sizes[ii];
0137 inner_float_swap_loop<RandomAccessIter, Div_type>
0138 (bins, nextbinstart, ii, log_divisor, div_min);
0139 }
0140
0141
0142
0143 template <class RandomAccessIter, class Cast_type>
0144 inline bool
0145 is_sorted_or_find_extremes(RandomAccessIter current, RandomAccessIter last,
0146 Cast_type & max, Cast_type & min)
0147 {
0148 min = max = cast_float_iter<Cast_type, RandomAccessIter>(current);
0149 RandomAccessIter prev = current;
0150 bool sorted = true;
0151 while (++current < last) {
0152 Cast_type value = cast_float_iter<Cast_type, RandomAccessIter>(current);
0153 sorted &= *current >= *prev;
0154 prev = current;
0155 if (max < value)
0156 max = value;
0157 else if (value < min)
0158 min = value;
0159 }
0160 return sorted;
0161 }
0162
0163
0164 template <class RandomAccessIter, class Div_type, class Size_type>
0165 inline void
0166 positive_float_sort_rec(RandomAccessIter first, RandomAccessIter last,
0167 std::vector<RandomAccessIter> &bin_cache, unsigned cache_offset
0168 , size_t *bin_sizes)
0169 {
0170 Div_type max, min;
0171 if (is_sorted_or_find_extremes<RandomAccessIter, Div_type>(first, last,
0172 max, min))
0173 return;
0174 unsigned log_divisor = get_log_divisor<float_log_mean_bin_size>(
0175 last - first, rough_log_2_size(Size_type(max - min)));
0176 Div_type div_min = min >> log_divisor;
0177 Div_type div_max = max >> log_divisor;
0178 unsigned bin_count = unsigned(div_max - div_min) + 1;
0179 unsigned cache_end;
0180 RandomAccessIter * bins = size_bins(bin_sizes, bin_cache, cache_offset,
0181 cache_end, bin_count);
0182
0183
0184 for (RandomAccessIter current = first; current != last;)
0185 bin_sizes[unsigned((cast_float_iter<Div_type, RandomAccessIter>(
0186 current++) >> log_divisor) - div_min)]++;
0187 bins[0] = first;
0188 for (unsigned u = 0; u < bin_count - 1; u++)
0189 bins[u + 1] = bins[u] + bin_sizes[u];
0190
0191
0192
0193 RandomAccessIter nextbinstart = first;
0194 for (unsigned u = 0; u < bin_count - 1; ++u)
0195 float_swap_loop<RandomAccessIter, Div_type>
0196 (bins, nextbinstart, u, bin_sizes, log_divisor, div_min);
0197 bins[bin_count - 1] = last;
0198
0199
0200 if (!log_divisor)
0201 return;
0202
0203
0204 size_t max_count = get_min_count<float_log_mean_bin_size,
0205 float_log_min_split_count,
0206 float_log_finishing_count>(log_divisor);
0207 RandomAccessIter lastPos = first;
0208 for (unsigned u = cache_offset; u < cache_end; lastPos = bin_cache[u],
0209 ++u) {
0210 size_t count = bin_cache[u] - lastPos;
0211 if (count < 2)
0212 continue;
0213 if (count < max_count)
0214 boost::sort::pdqsort(lastPos, bin_cache[u]);
0215 else
0216 positive_float_sort_rec<RandomAccessIter, Div_type, Size_type>
0217 (lastPos, bin_cache[u], bin_cache, cache_end, bin_sizes);
0218 }
0219 }
0220
0221
0222
0223 template <class RandomAccessIter, class Div_type, class Size_type>
0224 inline void
0225 negative_float_sort_rec(RandomAccessIter first, RandomAccessIter last,
0226 std::vector<RandomAccessIter> &bin_cache,
0227 unsigned cache_offset, size_t *bin_sizes)
0228 {
0229 Div_type max, min;
0230 if (is_sorted_or_find_extremes<RandomAccessIter, Div_type>(first, last,
0231 max, min))
0232 return;
0233
0234 unsigned log_divisor = get_log_divisor<float_log_mean_bin_size>(
0235 last - first, rough_log_2_size(Size_type(max - min)));
0236 Div_type div_min = min >> log_divisor;
0237 Div_type div_max = max >> log_divisor;
0238 unsigned bin_count = unsigned(div_max - div_min) + 1;
0239 unsigned cache_end;
0240 RandomAccessIter * bins = size_bins(bin_sizes, bin_cache, cache_offset,
0241 cache_end, bin_count);
0242
0243
0244 for (RandomAccessIter current = first; current != last;)
0245 bin_sizes[unsigned((cast_float_iter<Div_type, RandomAccessIter>(
0246 current++) >> log_divisor) - div_min)]++;
0247 bins[bin_count - 1] = first;
0248 for (int ii = bin_count - 2; ii >= 0; --ii)
0249 bins[ii] = bins[ii + 1] + bin_sizes[ii + 1];
0250
0251
0252 RandomAccessIter nextbinstart = first;
0253
0254 for (int ii = bin_count - 1; ii > 0; --ii)
0255 float_swap_loop<RandomAccessIter, Div_type>
0256 (bins, nextbinstart, ii, bin_sizes, log_divisor, div_min);
0257
0258 bin_cache[cache_offset] = last;
0259
0260
0261 if (!log_divisor)
0262 return;
0263
0264
0265 size_t max_count = get_min_count<float_log_mean_bin_size,
0266 float_log_min_split_count,
0267 float_log_finishing_count>(log_divisor);
0268 RandomAccessIter lastPos = first;
0269 for (int ii = cache_end - 1; ii >= static_cast<int>(cache_offset);
0270 lastPos = bin_cache[ii], --ii) {
0271 size_t count = bin_cache[ii] - lastPos;
0272 if (count < 2)
0273 continue;
0274 if (count < max_count)
0275 boost::sort::pdqsort(lastPos, bin_cache[ii]);
0276 else
0277 negative_float_sort_rec<RandomAccessIter, Div_type, Size_type>
0278 (lastPos, bin_cache[ii], bin_cache, cache_end, bin_sizes);
0279 }
0280 }
0281
0282
0283
0284 template <class RandomAccessIter, class Div_type, class Right_shift,
0285 class Size_type>
0286 inline void
0287 negative_float_sort_rec(RandomAccessIter first, RandomAccessIter last,
0288 std::vector<RandomAccessIter> &bin_cache, unsigned cache_offset
0289 , size_t *bin_sizes, Right_shift rshift)
0290 {
0291 Div_type max, min;
0292 if (is_sorted_or_find_extremes(first, last, max, min, rshift))
0293 return;
0294 unsigned log_divisor = get_log_divisor<float_log_mean_bin_size>(
0295 last - first, rough_log_2_size(Size_type(max - min)));
0296 Div_type div_min = min >> log_divisor;
0297 Div_type div_max = max >> log_divisor;
0298 unsigned bin_count = unsigned(div_max - div_min) + 1;
0299 unsigned cache_end;
0300 RandomAccessIter * bins = size_bins(bin_sizes, bin_cache, cache_offset,
0301 cache_end, bin_count);
0302
0303
0304 for (RandomAccessIter current = first; current != last;)
0305 bin_sizes[unsigned(rshift(*(current++), log_divisor) - div_min)]++;
0306 bins[bin_count - 1] = first;
0307 for (int ii = bin_count - 2; ii >= 0; --ii)
0308 bins[ii] = bins[ii + 1] + bin_sizes[ii + 1];
0309
0310
0311 RandomAccessIter nextbinstart = first;
0312
0313 for (int ii = bin_count - 1; ii > 0; --ii)
0314 swap_loop<RandomAccessIter, Div_type, Right_shift>
0315 (bins, nextbinstart, ii, rshift, bin_sizes, log_divisor, div_min);
0316
0317 bin_cache[cache_offset] = last;
0318
0319
0320 if (!log_divisor)
0321 return;
0322
0323
0324 size_t max_count = get_min_count<float_log_mean_bin_size,
0325 float_log_min_split_count,
0326 float_log_finishing_count>(log_divisor);
0327 RandomAccessIter lastPos = first;
0328 for (int ii = cache_end - 1; ii >= static_cast<int>(cache_offset);
0329 lastPos = bin_cache[ii], --ii) {
0330 size_t count = bin_cache[ii] - lastPos;
0331 if (count < 2)
0332 continue;
0333 if (count < max_count)
0334 boost::sort::pdqsort(lastPos, bin_cache[ii]);
0335 else
0336 negative_float_sort_rec<RandomAccessIter, Div_type, Right_shift,
0337 Size_type>
0338 (lastPos, bin_cache[ii], bin_cache, cache_end, bin_sizes, rshift);
0339 }
0340 }
0341
0342 template <class RandomAccessIter, class Div_type, class Right_shift,
0343 class Compare, class Size_type>
0344 inline void
0345 negative_float_sort_rec(RandomAccessIter first, RandomAccessIter last,
0346 std::vector<RandomAccessIter> &bin_cache, unsigned cache_offset,
0347 size_t *bin_sizes, Right_shift rshift, Compare comp)
0348 {
0349 Div_type max, min;
0350 if (is_sorted_or_find_extremes(first, last, max, min, rshift, comp))
0351 return;
0352 unsigned log_divisor = get_log_divisor<float_log_mean_bin_size>(
0353 last - first, rough_log_2_size(Size_type(max - min)));
0354 Div_type div_min = min >> log_divisor;
0355 Div_type div_max = max >> log_divisor;
0356 unsigned bin_count = unsigned(div_max - div_min) + 1;
0357 unsigned cache_end;
0358 RandomAccessIter * bins = size_bins(bin_sizes, bin_cache, cache_offset,
0359 cache_end, bin_count);
0360
0361
0362 for (RandomAccessIter current = first; current != last;)
0363 bin_sizes[unsigned(rshift(*(current++), log_divisor) - div_min)]++;
0364 bins[bin_count - 1] = first;
0365 for (int ii = bin_count - 2; ii >= 0; --ii)
0366 bins[ii] = bins[ii + 1] + bin_sizes[ii + 1];
0367
0368
0369 RandomAccessIter nextbinstart = first;
0370
0371 for (int ii = bin_count - 1; ii > 0; --ii)
0372 swap_loop<RandomAccessIter, Div_type, Right_shift>
0373 (bins, nextbinstart, ii, rshift, bin_sizes, log_divisor, div_min);
0374
0375 bin_cache[cache_offset] = last;
0376
0377
0378 if (!log_divisor)
0379 return;
0380
0381
0382 size_t max_count = get_min_count<float_log_mean_bin_size,
0383 float_log_min_split_count,
0384 float_log_finishing_count>(log_divisor);
0385 RandomAccessIter lastPos = first;
0386 for (int ii = cache_end - 1; ii >= static_cast<int>(cache_offset);
0387 lastPos = bin_cache[ii], --ii) {
0388 size_t count = bin_cache[ii] - lastPos;
0389 if (count < 2)
0390 continue;
0391 if (count < max_count)
0392 boost::sort::pdqsort(lastPos, bin_cache[ii], comp);
0393 else
0394 negative_float_sort_rec<RandomAccessIter, Div_type, Right_shift,
0395 Compare, Size_type>(lastPos, bin_cache[ii],
0396 bin_cache, cache_end,
0397 bin_sizes, rshift, comp);
0398 }
0399 }
0400
0401
0402 template <class RandomAccessIter, class Div_type, class Size_type>
0403 inline void
0404 float_sort_rec(RandomAccessIter first, RandomAccessIter last,
0405 std::vector<RandomAccessIter> &bin_cache, unsigned cache_offset
0406 , size_t *bin_sizes)
0407 {
0408 Div_type max, min;
0409 if (is_sorted_or_find_extremes<RandomAccessIter, Div_type>(first, last,
0410 max, min))
0411 return;
0412 unsigned log_divisor = get_log_divisor<float_log_mean_bin_size>(
0413 last - first, rough_log_2_size(Size_type(max/2 - min/2)) + 1);
0414 Div_type div_min = min >> log_divisor;
0415 Div_type div_max = max >> log_divisor;
0416 unsigned bin_count = unsigned(div_max - div_min) + 1;
0417 unsigned cache_end;
0418 RandomAccessIter * bins = size_bins(bin_sizes, bin_cache, cache_offset,
0419 cache_end, bin_count);
0420
0421
0422 for (RandomAccessIter current = first; current != last;)
0423 bin_sizes[unsigned((cast_float_iter<Div_type, RandomAccessIter>(
0424 current++) >> log_divisor) - div_min)]++;
0425
0426
0427 unsigned first_positive = (div_min < 0) ? unsigned(-div_min) : 0;
0428
0429 if (cache_offset + first_positive > cache_end)
0430 first_positive = cache_end - cache_offset;
0431
0432
0433
0434
0435 if (first_positive > 0) {
0436 bins[first_positive - 1] = first;
0437 for (int ii = first_positive - 2; ii >= 0; --ii) {
0438 bins[ii] = first + bin_sizes[ii + 1];
0439 bin_sizes[ii] += bin_sizes[ii + 1];
0440 }
0441
0442 if (first_positive < bin_count) {
0443 bins[first_positive] = first + bin_sizes[0];
0444 bin_sizes[first_positive] += bin_sizes[0];
0445 }
0446 }
0447 else
0448 bins[0] = first;
0449 for (unsigned u = first_positive; u < bin_count - 1; u++) {
0450 bins[u + 1] = first + bin_sizes[u];
0451 bin_sizes[u + 1] += bin_sizes[u];
0452 }
0453
0454
0455 RandomAccessIter nextbinstart = first;
0456 for (unsigned u = 0; u < bin_count; ++u) {
0457 nextbinstart = first + bin_sizes[u];
0458 inner_float_swap_loop<RandomAccessIter, Div_type>
0459 (bins, nextbinstart, u, log_divisor, div_min);
0460 }
0461
0462 if (!log_divisor)
0463 return;
0464
0465
0466 size_t max_count = get_min_count<float_log_mean_bin_size,
0467 float_log_min_split_count,
0468 float_log_finishing_count>(log_divisor);
0469 RandomAccessIter lastPos = first;
0470 for (int ii = cache_offset + first_positive - 1;
0471 ii >= static_cast<int>(cache_offset);
0472 lastPos = bin_cache[ii--]) {
0473 size_t count = bin_cache[ii] - lastPos;
0474 if (count < 2)
0475 continue;
0476 if (count < max_count)
0477 boost::sort::pdqsort(lastPos, bin_cache[ii]);
0478
0479 else
0480 negative_float_sort_rec<RandomAccessIter, Div_type, Size_type>
0481 (lastPos, bin_cache[ii], bin_cache, cache_end, bin_sizes);
0482 }
0483
0484 for (unsigned u = cache_offset + first_positive; u < cache_end;
0485 lastPos = bin_cache[u], ++u) {
0486 size_t count = bin_cache[u] - lastPos;
0487 if (count < 2)
0488 continue;
0489 if (count < max_count)
0490 boost::sort::pdqsort(lastPos, bin_cache[u]);
0491
0492 else
0493 positive_float_sort_rec<RandomAccessIter, Div_type, Size_type>
0494 (lastPos, bin_cache[u], bin_cache, cache_end, bin_sizes);
0495 }
0496 }
0497
0498
0499 template <class RandomAccessIter, class Div_type, class Right_shift
0500 , class Size_type>
0501 inline void
0502 float_sort_rec(RandomAccessIter first, RandomAccessIter last,
0503 std::vector<RandomAccessIter> &bin_cache, unsigned cache_offset
0504 , size_t *bin_sizes, Right_shift rshift)
0505 {
0506 Div_type max, min;
0507 if (is_sorted_or_find_extremes(first, last, max, min, rshift))
0508 return;
0509 unsigned log_divisor = get_log_divisor<float_log_mean_bin_size>(
0510 last - first, rough_log_2_size(Size_type(max/2 - min/2)) + 1);
0511 Div_type div_min = min >> log_divisor;
0512 Div_type div_max = max >> log_divisor;
0513 unsigned bin_count = unsigned(div_max - div_min) + 1;
0514 unsigned cache_end;
0515 RandomAccessIter * bins = size_bins(bin_sizes, bin_cache, cache_offset,
0516 cache_end, bin_count);
0517
0518
0519 for (RandomAccessIter current = first; current != last;)
0520 bin_sizes[unsigned(rshift(*(current++), log_divisor) - div_min)]++;
0521
0522 unsigned first_positive = (div_min < 0) ? unsigned(-div_min) : 0;
0523
0524 if (cache_offset + first_positive > cache_end)
0525 first_positive = cache_end - cache_offset;
0526
0527
0528
0529
0530 if (first_positive > 0) {
0531 bins[first_positive - 1] = first;
0532 for (int ii = first_positive - 2; ii >= 0; --ii) {
0533 bins[ii] = first + bin_sizes[ii + 1];
0534 bin_sizes[ii] += bin_sizes[ii + 1];
0535 }
0536
0537 if (static_cast<unsigned>(first_positive) < bin_count) {
0538 bins[first_positive] = first + bin_sizes[0];
0539 bin_sizes[first_positive] += bin_sizes[0];
0540 }
0541 }
0542 else
0543 bins[0] = first;
0544 for (unsigned u = first_positive; u < bin_count - 1; u++) {
0545 bins[u + 1] = first + bin_sizes[u];
0546 bin_sizes[u + 1] += bin_sizes[u];
0547 }
0548
0549
0550 RandomAccessIter next_bin_start = first;
0551 for (unsigned u = 0; u < bin_count; ++u) {
0552 next_bin_start = first + bin_sizes[u];
0553 inner_swap_loop<RandomAccessIter, Div_type, Right_shift>
0554 (bins, next_bin_start, u, rshift, log_divisor, div_min);
0555 }
0556
0557
0558 if (!log_divisor)
0559 return;
0560
0561
0562 size_t max_count = get_min_count<float_log_mean_bin_size,
0563 float_log_min_split_count,
0564 float_log_finishing_count>(log_divisor);
0565 RandomAccessIter lastPos = first;
0566 for (int ii = cache_offset + first_positive - 1;
0567 ii >= static_cast<int>(cache_offset);
0568 lastPos = bin_cache[ii--]) {
0569 size_t count = bin_cache[ii] - lastPos;
0570 if (count < 2)
0571 continue;
0572 if (count < max_count)
0573 boost::sort::pdqsort(lastPos, bin_cache[ii]);
0574
0575 else
0576 negative_float_sort_rec<RandomAccessIter, Div_type,
0577 Right_shift, Size_type>(lastPos, bin_cache[ii], bin_cache,
0578 cache_end, bin_sizes, rshift);
0579 }
0580
0581 for (unsigned u = cache_offset + first_positive; u < cache_end;
0582 lastPos = bin_cache[u], ++u) {
0583 size_t count = bin_cache[u] - lastPos;
0584 if (count < 2)
0585 continue;
0586 if (count < max_count)
0587 boost::sort::pdqsort(lastPos, bin_cache[u]);
0588
0589 else
0590 spreadsort_rec<RandomAccessIter, Div_type, Right_shift, Size_type,
0591 float_log_mean_bin_size, float_log_min_split_count,
0592 float_log_finishing_count>
0593 (lastPos, bin_cache[u], bin_cache, cache_end, bin_sizes, rshift);
0594 }
0595 }
0596
0597 template <class RandomAccessIter, class Div_type, class Right_shift,
0598 class Compare, class Size_type>
0599 inline void
0600 float_sort_rec(RandomAccessIter first, RandomAccessIter last,
0601 std::vector<RandomAccessIter> &bin_cache, unsigned cache_offset,
0602 size_t *bin_sizes, Right_shift rshift, Compare comp)
0603 {
0604 Div_type max, min;
0605 if (is_sorted_or_find_extremes(first, last, max, min, rshift, comp))
0606 return;
0607 unsigned log_divisor = get_log_divisor<float_log_mean_bin_size>(
0608 last - first, rough_log_2_size(Size_type(max/2 - min/2)) + 1);
0609 Div_type div_min = min >> log_divisor;
0610 Div_type div_max = max >> log_divisor;
0611 unsigned bin_count = unsigned(div_max - div_min) + 1;
0612 unsigned cache_end;
0613 RandomAccessIter * bins = size_bins(bin_sizes, bin_cache, cache_offset,
0614 cache_end, bin_count);
0615
0616
0617 for (RandomAccessIter current = first; current != last;)
0618 bin_sizes[unsigned(rshift(*(current++), log_divisor) - div_min)]++;
0619
0620 unsigned first_positive =
0621 (div_min < 0) ? static_cast<unsigned>(-div_min) : 0;
0622
0623 if (cache_offset + first_positive > cache_end)
0624 first_positive = cache_end - cache_offset;
0625
0626
0627
0628
0629 if (first_positive > 0) {
0630 bins[first_positive - 1] = first;
0631 for (int ii = first_positive - 2; ii >= 0; --ii) {
0632 bins[ii] = first + bin_sizes[ii + 1];
0633 bin_sizes[ii] += bin_sizes[ii + 1];
0634 }
0635
0636 if (static_cast<unsigned>(first_positive) < bin_count) {
0637 bins[first_positive] = first + bin_sizes[0];
0638 bin_sizes[first_positive] += bin_sizes[0];
0639 }
0640 }
0641 else
0642 bins[0] = first;
0643 for (unsigned u = first_positive; u < bin_count - 1; u++) {
0644 bins[u + 1] = first + bin_sizes[u];
0645 bin_sizes[u + 1] += bin_sizes[u];
0646 }
0647
0648
0649 RandomAccessIter next_bin_start = first;
0650 for (unsigned u = 0; u < bin_count; ++u) {
0651 next_bin_start = first + bin_sizes[u];
0652 inner_swap_loop<RandomAccessIter, Div_type, Right_shift>
0653 (bins, next_bin_start, u, rshift, log_divisor, div_min);
0654 }
0655
0656
0657 if (!log_divisor)
0658 return;
0659
0660
0661 size_t max_count = get_min_count<float_log_mean_bin_size,
0662 float_log_min_split_count,
0663 float_log_finishing_count>(log_divisor);
0664 RandomAccessIter lastPos = first;
0665 for (int ii = cache_offset + first_positive - 1;
0666 ii >= static_cast<int>(cache_offset);
0667 lastPos = bin_cache[ii--]) {
0668 size_t count = bin_cache[ii] - lastPos;
0669 if (count < 2)
0670 continue;
0671 if (count < max_count)
0672 boost::sort::pdqsort(lastPos, bin_cache[ii], comp);
0673
0674 else
0675 negative_float_sort_rec<RandomAccessIter, Div_type, Right_shift,
0676 Compare, Size_type>(lastPos, bin_cache[ii],
0677 bin_cache, cache_end,
0678 bin_sizes, rshift, comp);
0679 }
0680
0681 for (unsigned u = cache_offset + first_positive; u < cache_end;
0682 lastPos = bin_cache[u], ++u) {
0683 size_t count = bin_cache[u] - lastPos;
0684 if (count < 2)
0685 continue;
0686 if (count < max_count)
0687 boost::sort::pdqsort(lastPos, bin_cache[u], comp);
0688
0689 else
0690 spreadsort_rec<RandomAccessIter, Div_type, Right_shift, Compare,
0691 Size_type, float_log_mean_bin_size,
0692 float_log_min_split_count, float_log_finishing_count>
0693 (lastPos, bin_cache[u], bin_cache, cache_end, bin_sizes, rshift, comp);
0694 }
0695 }
0696
0697
0698 template <class RandomAccessIter>
0699 inline typename boost::enable_if_c< sizeof(boost::uint32_t) ==
0700 sizeof(typename std::iterator_traits<RandomAccessIter>::value_type)
0701 && std::numeric_limits<typename
0702 std::iterator_traits<RandomAccessIter>::value_type>::is_iec559,
0703 void >::type
0704 float_sort(RandomAccessIter first, RandomAccessIter last)
0705 {
0706 size_t bin_sizes[1 << max_finishing_splits];
0707 std::vector<RandomAccessIter> bin_cache;
0708 float_sort_rec<RandomAccessIter, boost::int32_t, boost::uint32_t>
0709 (first, last, bin_cache, 0, bin_sizes);
0710 }
0711
0712
0713 template <class RandomAccessIter>
0714 inline typename boost::enable_if_c< sizeof(boost::uint64_t) ==
0715 sizeof(typename std::iterator_traits<RandomAccessIter>::value_type)
0716 && std::numeric_limits<typename
0717 std::iterator_traits<RandomAccessIter>::value_type>::is_iec559,
0718 void >::type
0719 float_sort(RandomAccessIter first, RandomAccessIter last)
0720 {
0721 size_t bin_sizes[1 << max_finishing_splits];
0722 std::vector<RandomAccessIter> bin_cache;
0723 float_sort_rec<RandomAccessIter, boost::int64_t, boost::uint64_t>
0724 (first, last, bin_cache, 0, bin_sizes);
0725 }
0726
0727 template <class RandomAccessIter>
0728 inline typename boost::disable_if_c< (sizeof(boost::uint64_t) ==
0729 sizeof(typename std::iterator_traits<RandomAccessIter>::value_type)
0730 || sizeof(boost::uint32_t) ==
0731 sizeof(typename std::iterator_traits<RandomAccessIter>::value_type))
0732 && std::numeric_limits<typename
0733 std::iterator_traits<RandomAccessIter>::value_type>::is_iec559,
0734 void >::type
0735 float_sort(RandomAccessIter first, RandomAccessIter last)
0736 {
0737 BOOST_STATIC_ASSERT(!(sizeof(boost::uint64_t) ==
0738 sizeof(typename std::iterator_traits<RandomAccessIter>::value_type)
0739 || sizeof(boost::uint32_t) ==
0740 sizeof(typename std::iterator_traits<RandomAccessIter>::value_type))
0741 || !std::numeric_limits<typename
0742 std::iterator_traits<RandomAccessIter>::value_type>::is_iec559);
0743 boost::sort::pdqsort(first, last);
0744 }
0745
0746
0747
0748 template <class RandomAccessIter, class Div_type, class Right_shift>
0749 inline typename boost::enable_if_c< sizeof(size_t) >= sizeof(Div_type),
0750 void >::type
0751 float_sort(RandomAccessIter first, RandomAccessIter last, Div_type,
0752 Right_shift rshift)
0753 {
0754 size_t bin_sizes[1 << max_finishing_splits];
0755 std::vector<RandomAccessIter> bin_cache;
0756 float_sort_rec<RandomAccessIter, Div_type, Right_shift, size_t>
0757 (first, last, bin_cache, 0, bin_sizes, rshift);
0758 }
0759
0760
0761 template <class RandomAccessIter, class Div_type, class Right_shift>
0762 inline typename boost::enable_if_c< sizeof(size_t) < sizeof(Div_type)
0763 && sizeof(boost::uintmax_t) >= sizeof(Div_type), void >::type
0764 float_sort(RandomAccessIter first, RandomAccessIter last, Div_type,
0765 Right_shift rshift)
0766 {
0767 size_t bin_sizes[1 << max_finishing_splits];
0768 std::vector<RandomAccessIter> bin_cache;
0769 float_sort_rec<RandomAccessIter, Div_type, Right_shift, boost::uintmax_t>
0770 (first, last, bin_cache, 0, bin_sizes, rshift);
0771 }
0772
0773
0774 template <class RandomAccessIter, class Div_type, class Right_shift>
0775 inline typename boost::disable_if_c< sizeof(boost::uintmax_t) >=
0776 sizeof(Div_type), void >::type
0777 float_sort(RandomAccessIter first, RandomAccessIter last, Div_type,
0778 Right_shift rshift)
0779 {
0780 boost::sort::pdqsort(first, last);
0781 }
0782
0783
0784 template <class RandomAccessIter, class Div_type, class Right_shift,
0785 class Compare>
0786 inline typename boost::enable_if_c< sizeof(size_t) >= sizeof(Div_type),
0787 void >::type
0788 float_sort(RandomAccessIter first, RandomAccessIter last, Div_type,
0789 Right_shift rshift, Compare comp)
0790 {
0791 size_t bin_sizes[1 << max_finishing_splits];
0792 std::vector<RandomAccessIter> bin_cache;
0793 float_sort_rec<RandomAccessIter, Div_type, Right_shift, Compare,
0794 size_t>
0795 (first, last, bin_cache, 0, bin_sizes, rshift, comp);
0796 }
0797
0798
0799 template <class RandomAccessIter, class Div_type, class Right_shift,
0800 class Compare>
0801 inline typename boost::enable_if_c< sizeof(size_t) < sizeof(Div_type)
0802 && sizeof(boost::uintmax_t) >= sizeof(Div_type), void >::type
0803 float_sort(RandomAccessIter first, RandomAccessIter last, Div_type,
0804 Right_shift rshift, Compare comp)
0805 {
0806 size_t bin_sizes[1 << max_finishing_splits];
0807 std::vector<RandomAccessIter> bin_cache;
0808 float_sort_rec<RandomAccessIter, Div_type, Right_shift, Compare,
0809 boost::uintmax_t>
0810 (first, last, bin_cache, 0, bin_sizes, rshift, comp);
0811 }
0812
0813
0814 template <class RandomAccessIter, class Div_type, class Right_shift,
0815 class Compare>
0816 inline typename boost::disable_if_c< sizeof(boost::uintmax_t) >=
0817 sizeof(Div_type), void >::type
0818 float_sort(RandomAccessIter first, RandomAccessIter last, Div_type,
0819 Right_shift rshift, Compare comp)
0820 {
0821 boost::sort::pdqsort(first, last, comp);
0822 }
0823 }
0824 }
0825 }
0826 }
0827
0828 #endif