Tengo un pequeño problema y no puedo encontrar una solución satisfactoria para él. Hay una matriz de bytes y necesito estos bytes ordenados por 7 bits altos, mientras que conserva el orden de los bits bajos.Tipo de arreglo de byte rápido in situ
Así que originalmente era la siguiente:
// sort buf[N] to tmp[N]
uint offs[128+1]; uint c,i,s;
for(i=0; i<128; i++) offs[i]=0;
for(i=0; i<l; i++) offs[buf[i]>>1]++;
for(i=0,s=0; i<128; i++) c=offs[i], offs[i]=s, s+=c; offs[i]=s;
byte* tmp = new byte[N];
for(i=0; i<N; i++) c=buf[i], tmp[offs[c>>1]++]=c; // sort
Pero estos bloques son lo suficientemente grandes (8M en la actualidad), y quiero utilizar múltiples hilos, 8M y un extra por hilo es notable.
así que he intentado utilizar algunos simples Radix sort:
void radix(byte* buf, uint h, uint l, uint mask) {
uint p = (h+l)>>1, q = h;
uint i = offs[h], j = offs[l]-1; h = offs[p];
if((i<h) && (j>=h)) {
byte c = buf[i], d = buf[j];
while((i<h) && (j>=h)) {
while((c&mask)==0) c = buf[++i]; // find value with bit 1
while((d&mask)!=0) d = buf[--j]; // find value with bit 0
buf[i]=d; buf[j]=c; // swap 1-0 -> 0-1
c = buf[++i]; d = buf[--j];
}
if(mask>=4) {
radix(buf, q,p, mask>>1);
radix(buf, p,l, mask>>1);
}
}
}
pero cambia el orden de estos bits de baja y se vuelve inutilizable.
En realidad, algunos métodos más simples, como bubblesort, simplemente haz lo que yo quiero, pero son mucho más lentos, y la velocidad también es un problema.
Así actualmente en cierto modo me bloques más pequeños a través de una memoria intermedia temporal, a continuación, utilizar una tabla de índice para acceder a trozos parcialmente ordenados en orden:
struct tmpsort {
enum{ blocksize = (1<<16)-1 };
unsigned short ofs[(max_quants+blocksize-1)/blocksize][probN];
tmpsort(byte* buf, uint f_len) {
uint i,j,k;
uint freq[2*probN]; // prob freqs
byte tmp[blocksize+1];
for(k=0,j=0; k<f_len; k+=blocksize,j++) {
uint l = Min(k+blocksize,f_len)-k;
byte* p = &buf[k];
// compute offsets of sorted chunks
for(i=0; i<2*probN; i++) freq[i]=0;
for(i=0; i<l; i++) freq[p[i]]++;
for(i=0; i<probN; i++) freq[i+1]=freq[2*i+0]+freq[2*i+1]; // 1=0+1, 2=2+3, 3=4+5
freq[0] = 0;
for(i=0; i<probN; i++) freq[i+1]+=freq[i];
for(i=0; i<probN; i++) ofs[j][i]=freq[i+1];
// sort the block via tmp
for(i=0; i<l; i++) { byte c=p[i]; tmp[freq[c>>1]++]=c; }
for(i=0; i<l; i++) p[i]=tmp[i];
}
}
};
[...]
tmpsort ts(buf, f_len);
for(i=0; i<probN; i++) {
for(k=0,j=0; k<f_len; k+=ts.blocksize,j++) {
uint x = i>0 ? ts.ofs[j][i-1] : 0;
for(; x<ts.ofs[j][i]; x++) putc(buf[k+x],g);
}
}
Pero tmp [] y OFS [] matrices utilizan demasiado espacio pila , y su no es un tipo completo, así que sigo preguntándome si hay alguna solución clara para esto.
Una muestra de datos y mis implementaciones están disponibles aquí: http://nishi.dreamhosters.com/u/tmpsort_v0.rar
Gracias, realmente extrañaba este enfoque, podría valer la pena intentarlo. – Shelwien