mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 11:37:35 +00:00
6e6fc38935
Commit bc6c183
introduced a bunch of discrepancies between what files
look like in the repo and what clang-format says they should look like.
However, there were already a few discrepancies prior to that. Most of
these discrepancies seemed to be unintentional, but a few of them were
load-bearing (e.g., a #include that violated header ordering needing
something to have been #defined by a 'later' #include.)
I opted to take what I hope is a relatively smooth-brained approach: I
reverted the .clang-format change, ran clang-format on the whole repo,
reapplied the .clang-format change, reran clang-format again, and then
reverted the commit that contained the first run. Thus the full effect
of this PR should only be to apply the changed formatting rules to the
repo, and from skimming the results, this seems to be the case.
My work can be checked by applying the short, manual commits, and then
rerunning the command listed in the autogenerated commits (those whose
messages I have prefixed auto:) and seeing if your results agree.
It might be that the other diffs should be fixed at some point but I'm
leaving that aside for now.
fd '\.c(c|pp)?$' --print0| xargs -0 clang-format -i
244 lines
7.8 KiB
C
244 lines
7.8 KiB
C
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
|
│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │
|
|
╚──────────────────────────────────────────────────────────────────────────────╝
|
|
│ Copyright (C) 2011 by Valentin Ochs │
|
|
│ │
|
|
│ Permission is hereby granted, free of charge, to any person obtaining a copy │
|
|
│ of this software and associated documentation files (the "Software"), to │
|
|
│ deal in the Software without restriction, including without limitation the │
|
|
│ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or │
|
|
│ sell copies of the Software, and to permit persons to whom the Software is │
|
|
│ furnished to do so, subject to the following conditions: │
|
|
│ │
|
|
│ The above copyright notice and this permission notice shall be included in │
|
|
│ all copies or substantial portions of the Software. │
|
|
│ │
|
|
│ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR │
|
|
│ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, │
|
|
│ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE │
|
|
│ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER │
|
|
│ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING │
|
|
│ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS │
|
|
│ IN THE SOFTWARE. │
|
|
└─────────────────────────────────────────────────────────────────────────────*/
|
|
#include "libc/intrin/bsf.h"
|
|
#include "libc/limits.h"
|
|
#include "libc/mem/alg.h"
|
|
#include "libc/str/str.h"
|
|
|
|
__notice(smoothsort_notice, "\
|
|
Smoothsort (MIT License)\n\
|
|
Copyright 2011 Valentin Ochs\n\
|
|
Discovered by Edsger Dijkstra");
|
|
|
|
typedef int (*cmpfun)(const void *, const void *, void *);
|
|
|
|
struct SmoothSort {
|
|
size_t lp[12 * sizeof(size_t)];
|
|
unsigned char *ar[14 * sizeof(size_t) + 1];
|
|
unsigned char tmp[256];
|
|
};
|
|
|
|
static inline int ntz(unsigned long x) {
|
|
return __builtin_ctzl(x);
|
|
}
|
|
|
|
static inline int pntz(size_t p[2]) {
|
|
int r = ntz(p[0] - 1);
|
|
if (r != 0 || (r = CHAR_BIT * sizeof(size_t) + ntz(p[1])) !=
|
|
CHAR_BIT * sizeof(size_t)) {
|
|
return r;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// SmoothSort_shl() and SmoothSort_shr() need n > 0
|
|
static inline void SmoothSort_shl(size_t p[2], int n) {
|
|
if (n >= CHAR_BIT * sizeof(size_t)) {
|
|
n -= CHAR_BIT * sizeof(size_t);
|
|
p[1] = p[0];
|
|
p[0] = 0;
|
|
}
|
|
p[1] <<= n;
|
|
p[1] |= p[0] >> (sizeof(size_t) * CHAR_BIT - n);
|
|
p[0] <<= n;
|
|
}
|
|
|
|
static inline void SmoothSort_shr(size_t p[2], int n) {
|
|
if (n >= CHAR_BIT * sizeof(size_t)) {
|
|
n -= CHAR_BIT * sizeof(size_t);
|
|
p[0] = p[1];
|
|
p[1] = 0;
|
|
}
|
|
p[0] >>= n;
|
|
p[0] |= p[1] << (sizeof(size_t) * CHAR_BIT - n);
|
|
p[1] >>= n;
|
|
}
|
|
|
|
static void SmoothSort_cycle(struct SmoothSort *s, size_t width, int n) {
|
|
size_t l;
|
|
int i;
|
|
if (n < 2) {
|
|
return;
|
|
}
|
|
s->ar[n] = s->tmp;
|
|
while (width) {
|
|
l = sizeof(s->tmp) < width ? sizeof(s->tmp) : width;
|
|
memcpy(s->ar[n], s->ar[0], l);
|
|
for (i = 0; i < n; i++) {
|
|
memcpy(s->ar[i], s->ar[i + 1], l);
|
|
s->ar[i] += l;
|
|
}
|
|
width -= l;
|
|
}
|
|
}
|
|
|
|
static void SmoothSort_sift(struct SmoothSort *s, unsigned char *head,
|
|
size_t width, cmpfun cmp, void *arg, int pshift) {
|
|
unsigned char *rt, *lf;
|
|
int i = 1;
|
|
s->ar[0] = head;
|
|
while (pshift > 1) {
|
|
rt = head - width;
|
|
lf = head - width - s->lp[pshift - 2];
|
|
if (cmp(s->ar[0], lf, arg) >= 0 && cmp(s->ar[0], rt, arg) >= 0) {
|
|
break;
|
|
}
|
|
if (cmp(lf, rt, arg) >= 0) {
|
|
s->ar[i++] = lf;
|
|
head = lf;
|
|
pshift -= 1;
|
|
} else {
|
|
s->ar[i++] = rt;
|
|
head = rt;
|
|
pshift -= 2;
|
|
}
|
|
}
|
|
SmoothSort_cycle(s, width, i);
|
|
}
|
|
|
|
static void SmoothSort_trinkle(struct SmoothSort *s, unsigned char *head,
|
|
size_t width, cmpfun cmp, void *arg,
|
|
size_t pp[2], int pshift, int trusty) {
|
|
unsigned char *stepson, *rt, *lf;
|
|
size_t p[2];
|
|
int i = 1;
|
|
int trail;
|
|
p[0] = pp[0];
|
|
p[1] = pp[1];
|
|
s->ar[0] = head;
|
|
while (p[0] != 1 || p[1] != 0) {
|
|
stepson = head - s->lp[pshift];
|
|
if (cmp(stepson, s->ar[0], arg) <= 0) {
|
|
break;
|
|
}
|
|
if (!trusty && pshift > 1) {
|
|
rt = head - width;
|
|
lf = head - width - s->lp[pshift - 2];
|
|
if (cmp(rt, stepson, arg) >= 0 || cmp(lf, stepson, arg) >= 0) {
|
|
break;
|
|
}
|
|
}
|
|
s->ar[i++] = stepson;
|
|
head = stepson;
|
|
trail = pntz(p);
|
|
SmoothSort_shr(p, trail);
|
|
pshift += trail;
|
|
trusty = 0;
|
|
}
|
|
if (!trusty) {
|
|
SmoothSort_cycle(s, width, i);
|
|
SmoothSort_sift(s, head, width, cmp, arg, pshift);
|
|
}
|
|
}
|
|
|
|
static void SmoothSort(struct SmoothSort *s, void *base, size_t nel,
|
|
size_t width, cmpfun cmp, void *arg) {
|
|
size_t i, size = width * nel;
|
|
unsigned char *head, *high;
|
|
size_t p[2] = {1, 0};
|
|
int pshift = 1;
|
|
int trail;
|
|
if (!size)
|
|
return;
|
|
head = base;
|
|
high = head + size - width;
|
|
// precompute Leonardo numbers, scaled by element width
|
|
for (s->lp[0] = s->lp[1] = width, i = 2;
|
|
(s->lp[i] = s->lp[i - 2] + s->lp[i - 1] + width) < size; i++) {
|
|
}
|
|
while (head < high) {
|
|
if ((p[0] & 3) == 3) {
|
|
SmoothSort_sift(s, head, width, cmp, arg, pshift);
|
|
SmoothSort_shr(p, 2);
|
|
pshift += 2;
|
|
} else {
|
|
if (s->lp[pshift - 1] >= high - head) {
|
|
SmoothSort_trinkle(s, head, width, cmp, arg, p, pshift, 0);
|
|
} else {
|
|
SmoothSort_sift(s, head, width, cmp, arg, pshift);
|
|
}
|
|
if (pshift == 1) {
|
|
SmoothSort_shl(p, 1);
|
|
pshift = 0;
|
|
} else {
|
|
SmoothSort_shl(p, pshift - 1);
|
|
pshift = 1;
|
|
}
|
|
}
|
|
p[0] |= 1;
|
|
head += width;
|
|
}
|
|
SmoothSort_trinkle(s, head, width, cmp, arg, p, pshift, 0);
|
|
while (pshift != 1 || p[0] != 1 || p[1] != 0) {
|
|
if (pshift <= 1) {
|
|
trail = pntz(p);
|
|
SmoothSort_shr(p, trail);
|
|
pshift += trail;
|
|
} else {
|
|
SmoothSort_shl(p, 2);
|
|
pshift -= 2;
|
|
p[0] ^= 7;
|
|
SmoothSort_shr(p, 1);
|
|
SmoothSort_trinkle(s, head - s->lp[pshift] - width, width, cmp, arg, p,
|
|
pshift + 1, 1);
|
|
SmoothSort_shl(p, 1);
|
|
p[0] |= 1;
|
|
SmoothSort_trinkle(s, head - width, width, cmp, arg, p, pshift, 1);
|
|
}
|
|
head -= width;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sorts array.
|
|
*
|
|
* @param base points to an array to sort in-place
|
|
* @param count is the item count
|
|
* @param width is the size of each item
|
|
* @param cmp is a callback returning <0, 0, or >0
|
|
* @param arg will optionally be passed as the third argument to cmp
|
|
* @see smoothsort()
|
|
* @see qsort()
|
|
*/
|
|
void smoothsort_r(void *base, size_t count, size_t width, cmpfun cmp,
|
|
void *arg) {
|
|
struct SmoothSort s;
|
|
SmoothSort(&s, base, count, width, cmp, arg);
|
|
}
|
|
|
|
/**
|
|
* Sorts array.
|
|
*
|
|
* @param base points to an array to sort in-place
|
|
* @param count is the item count
|
|
* @param width is the size of each item
|
|
* @param cmp is a callback returning <0, 0, or >0
|
|
* @see smoothsort_r()
|
|
* @see qsort()
|
|
*/
|
|
void smoothsort(void *base, size_t count, size_t width,
|
|
int cmp(const void *, const void *)) {
|
|
struct SmoothSort s;
|
|
SmoothSort(&s, base, count, width, (cmpfun)cmp, 0);
|
|
}
|