mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 13:53:55 -07:00
Merge branch 'master' of https://github.com/iceman1001/proxmark3
Conflicts: client/cmdhfmf.c client/cmdmain.c
This commit is contained in:
commit
480e2f2394
12 changed files with 249 additions and 121 deletions
|
@ -141,7 +141,9 @@ CMDSRCS = nonce2key/crapto1.c\
|
||||||
reveng/poly.c\
|
reveng/poly.c\
|
||||||
reveng/getopt.c\
|
reveng/getopt.c\
|
||||||
tea.c\
|
tea.c\
|
||||||
prng.c
|
prng.c\
|
||||||
|
radixsort.c\
|
||||||
|
bucketsort.c
|
||||||
|
|
||||||
ZLIBSRCS = deflate.c adler32.c trees.c zutil.c inflate.c inffast.c inftrees.c
|
ZLIBSRCS = deflate.c adler32.c trees.c zutil.c inflate.c inffast.c inftrees.c
|
||||||
ZLIB_FLAGS = -DZ_SOLO -DZ_PREFIX -DNO_GZIP -DZLIB_PM3_TUNED
|
ZLIB_FLAGS = -DZ_SOLO -DZ_PREFIX -DNO_GZIP -DZLIB_PM3_TUNED
|
||||||
|
|
|
@ -63,8 +63,9 @@ start:
|
||||||
}
|
}
|
||||||
|
|
||||||
UsbCommand resp;
|
UsbCommand resp;
|
||||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
||||||
isOK = resp.arg[0];
|
isOK = resp.arg[0];
|
||||||
|
printf("\n\n");
|
||||||
switch (isOK) {
|
switch (isOK) {
|
||||||
case -1 : PrintAndLog("Button pressed. Aborted.\n"); break;
|
case -1 : PrintAndLog("Button pressed. Aborted.\n"); break;
|
||||||
case -2 : PrintAndLog("Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests).\n"); break;
|
case -2 : PrintAndLog("Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests).\n"); break;
|
||||||
|
@ -73,7 +74,7 @@ start:
|
||||||
PrintAndLog("generating polynomial with 16 effective bits only, but shows unexpected behaviour.\n"); break;
|
PrintAndLog("generating polynomial with 16 effective bits only, but shows unexpected behaviour.\n"); break;
|
||||||
default: ;
|
default: ;
|
||||||
}
|
}
|
||||||
uid = (uint32_t)bytes_to_num(resp.d.asBytes, 4);
|
uid = (uint32_t)bytes_to_num(resp.d.asBytes + 0, 4);
|
||||||
nt = (uint32_t)bytes_to_num(resp.d.asBytes + 4, 4);
|
nt = (uint32_t)bytes_to_num(resp.d.asBytes + 4, 4);
|
||||||
par_list = bytes_to_num(resp.d.asBytes + 8, 8);
|
par_list = bytes_to_num(resp.d.asBytes + 8, 8);
|
||||||
ks_list = bytes_to_num(resp.d.asBytes + 16, 8);
|
ks_list = bytes_to_num(resp.d.asBytes + 16, 8);
|
||||||
|
@ -711,6 +712,7 @@ int CmdHF14AMfNested(const char *Cmd)
|
||||||
|
|
||||||
// nested sectors
|
// nested sectors
|
||||||
iterations = 0;
|
iterations = 0;
|
||||||
|
PrintAndLog("enter nested...");
|
||||||
bool calibrate = true;
|
bool calibrate = true;
|
||||||
|
|
||||||
for (i = 0; i < NESTED_SECTOR_RETRY; i++) {
|
for (i = 0; i < NESTED_SECTOR_RETRY; i++) {
|
||||||
|
@ -731,7 +733,7 @@ int CmdHF14AMfNested(const char *Cmd)
|
||||||
case -5 :
|
case -5 :
|
||||||
calibrate = false;
|
calibrate = false;
|
||||||
iterations++;
|
iterations++;
|
||||||
e_sector[sectorNo].foundKey[trgKeyType] = TRUE;
|
e_sector[sectorNo].foundKey[trgKeyType] = 1;
|
||||||
e_sector[sectorNo].Key[trgKeyType] = bytes_to_num(keyBlock, 6);
|
e_sector[sectorNo].Key[trgKeyType] = bytes_to_num(keyBlock, 6);
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -1132,6 +1134,7 @@ int CmdHF14AMfChk(const char *Cmd)
|
||||||
// skip already found keys.
|
// skip already found keys.
|
||||||
if (e_sector[i].foundKey[trgKeyType]) continue;
|
if (e_sector[i].foundKey[trgKeyType]) continue;
|
||||||
|
|
||||||
|
|
||||||
for (uint32_t c = 0; c < keycnt; c += max_keys) {
|
for (uint32_t c = 0; c < keycnt; c += max_keys) {
|
||||||
|
|
||||||
uint32_t size = keycnt-c > max_keys ? max_keys : keycnt-c;
|
uint32_t size = keycnt-c > max_keys ? max_keys : keycnt-c;
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
// #define T55X7_FDXB_CONFIG_BLOCK 903F8080 // emulate fdx-b - xtended mode, BiPhase ('57), data rate 32, 4 data blocks
|
// #define T55X7_FDXB_CONFIG_BLOCK 903F8080 // emulate fdx-b - xtended mode, BiPhase ('57), data rate 32, 4 data blocks
|
||||||
#define T55X7_FDXB_CONFIG_BLOCK 0x903F0082 // emulate fdx-b - xtended mode, BiPhase ('50), invert data, data rate 32, 4 data blocks
|
#define T55X7_FDXB_CONFIG_BLOCK 0x903F0082 // emulate fdx-b - xtended mode, BiPhase ('50), invert data, data rate 32, 4 data blocks
|
||||||
#define T55X7_HID_26_CONFIG_BLOCK 0x00107060 // hid 26 bit - compat mode, FSK2a, data rate 50, 3 data blocks
|
#define T55X7_HID_26_CONFIG_BLOCK 0x00107060 // hid 26 bit - compat mode, FSK2a, data rate 50, 3 data blocks
|
||||||
|
#define T55X7_PYRAMID_CONFIG_BLOCK 0x00107080 // Pyramid 26 bit - compat mode, FSK2a, data rate 50, 4 data blocks
|
||||||
#define T55X7_INDALA_64_CONFIG_BLOCK 0x00081040 // emulate indala 64 bit - compat mode, PSK1, psk carrier FC * 2, data rate 32, maxblock 2
|
#define T55X7_INDALA_64_CONFIG_BLOCK 0x00081040 // emulate indala 64 bit - compat mode, PSK1, psk carrier FC * 2, data rate 32, maxblock 2
|
||||||
#define T55X7_INDALA_224_CONFIG_BLOCK 0x000810E0 // emulate indala 224 bit - compat mode, PSK1, psk carrier FC * 2, data rate 32, maxblock 7
|
#define T55X7_INDALA_224_CONFIG_BLOCK 0x000810E0 // emulate indala 224 bit - compat mode, PSK1, psk carrier FC * 2, data rate 32, maxblock 7
|
||||||
#define T55X7_GUARDPROXII_CONFIG_BLOCK 0x00150060 // bitrate 64pcb, Direct modulation, Biphase, 3 data blocks
|
#define T55X7_GUARDPROXII_CONFIG_BLOCK 0x00150060 // bitrate 64pcb, Direct modulation, Biphase, 3 data blocks
|
||||||
|
|
|
@ -81,6 +81,7 @@ int CmdVikingClone(const char *Cmd) {
|
||||||
|
|
||||||
rawID = getVikingBits(id);
|
rawID = getVikingBits(id);
|
||||||
|
|
||||||
|
PrintAndLog("Cloning - ID: %08X, Raw: %08X%08X",id,(uint32_t)(rawID >> 32),(uint32_t) (rawID & 0xFFFFFFFF));
|
||||||
UsbCommand c = {CMD_VIKING_CLONE_TAG,{rawID >> 32, rawID & 0xFFFFFFFF, Q5}};
|
UsbCommand c = {CMD_VIKING_CLONE_TAG,{rawID >> 32, rawID & 0xFFFFFFFF, Q5}};
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommand(&c);
|
SendCommand(&c);
|
||||||
|
@ -107,9 +108,10 @@ int CmdVikingSim(const char *Cmd) {
|
||||||
arg1 = clk << 8 | encoding;
|
arg1 = clk << 8 | encoding;
|
||||||
arg2 = invert << 8 | separator;
|
arg2 = invert << 8 | separator;
|
||||||
|
|
||||||
|
PrintAndLog("Simulating - ID: %08X, Raw: %08X%08X",id,(uint32_t)(rawID >> 32),(uint32_t) (rawID & 0xFFFFFFFF));
|
||||||
|
|
||||||
UsbCommand c = {CMD_ASK_SIM_TAG, {arg1, arg2, size}};
|
UsbCommand c = {CMD_ASK_SIM_TAG, {arg1, arg2, size}};
|
||||||
PrintAndLog("preparing to sim ask data: %d bits", size);
|
num_to_bytebits(rawID, size, c.d.asBytes);
|
||||||
num_to_bytebits(rawID, 64, c.d.asBytes);
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommand(&c);
|
SendCommand(&c);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -186,6 +186,7 @@ void UsbCommandReceived(UsbCommand *UC)
|
||||||
size_t len = MIN(UC->arg[0],USB_CMD_DATA_SIZE);
|
size_t len = MIN(UC->arg[0],USB_CMD_DATA_SIZE);
|
||||||
memcpy(s, UC->d.asBytes, len);
|
memcpy(s, UC->d.asBytes, len);
|
||||||
PrintAndLog("#db# %s", s);
|
PrintAndLog("#db# %s", s);
|
||||||
|
return;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case CMD_DEBUG_PRINT_INTEGERS:
|
case CMD_DEBUG_PRINT_INTEGERS:
|
||||||
|
@ -201,5 +202,6 @@ void UsbCommandReceived(UsbCommand *UC)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,90 +31,10 @@ static void __attribute__((constructor)) fill_lut()
|
||||||
#define filter(x) (filterlut[(x) & 0xfffff])
|
#define filter(x) (filterlut[(x) & 0xfffff])
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct bucket {
|
|
||||||
uint32_t *head;
|
|
||||||
uint32_t *bp;
|
|
||||||
} bucket_t;
|
|
||||||
|
|
||||||
typedef bucket_t bucket_array_t[2][0x100];
|
|
||||||
|
|
||||||
typedef struct bucket_info {
|
|
||||||
struct {
|
|
||||||
uint32_t *head, *tail;
|
|
||||||
} bucket_info[2][0x100];
|
|
||||||
uint32_t numbuckets;
|
|
||||||
} bucket_info_t;
|
|
||||||
|
|
||||||
|
|
||||||
static void bucket_sort_intersect(uint32_t* const estart, uint32_t* const estop,
|
|
||||||
uint32_t* const ostart, uint32_t* const ostop,
|
|
||||||
bucket_info_t *bucket_info, bucket_array_t bucket)
|
|
||||||
{
|
|
||||||
uint32_t *p1, *p2;
|
|
||||||
uint32_t *start[2];
|
|
||||||
uint32_t *stop[2];
|
|
||||||
|
|
||||||
start[0] = estart;
|
|
||||||
stop[0] = estop;
|
|
||||||
start[1] = ostart;
|
|
||||||
stop[1] = ostop;
|
|
||||||
|
|
||||||
// init buckets to be empty
|
|
||||||
for (uint32_t i = 0; i < 2; i++) {
|
|
||||||
for (uint32_t j = 0x00; j <= 0xff; j++) {
|
|
||||||
bucket[i][j].bp = bucket[i][j].head;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// sort the lists into the buckets based on the MSB (contribution bits)
|
|
||||||
for (uint32_t i = 0; i < 2; i++) {
|
|
||||||
for (p1 = start[i]; p1 <= stop[i]; p1++) {
|
|
||||||
uint32_t bucket_index = (*p1 & 0xff000000) >> 24;
|
|
||||||
*(bucket[i][bucket_index].bp++) = *p1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// write back intersecting buckets as sorted list.
|
|
||||||
// fill in bucket_info with head and tail of the bucket contents in the list and number of non-empty buckets.
|
|
||||||
uint32_t nonempty_bucket;
|
|
||||||
for (uint32_t i = 0; i < 2; i++) {
|
|
||||||
p1 = start[i];
|
|
||||||
nonempty_bucket = 0;
|
|
||||||
for (uint32_t j = 0x00; j <= 0xff; j++) {
|
|
||||||
if (bucket[0][j].bp != bucket[0][j].head && bucket[1][j].bp != bucket[1][j].head) { // non-empty intersecting buckets only
|
|
||||||
bucket_info->bucket_info[i][nonempty_bucket].head = p1;
|
|
||||||
for (p2 = bucket[i][j].head; p2 < bucket[i][j].bp; *p1++ = *p2++);
|
|
||||||
bucket_info->bucket_info[i][nonempty_bucket].tail = p1 - 1;
|
|
||||||
nonempty_bucket++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bucket_info->numbuckets = nonempty_bucket;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** binsearch
|
|
||||||
* Binary search for the first occurence of *stop's MSB in sorted [start,stop]
|
|
||||||
*/
|
|
||||||
static inline uint32_t* binsearch(uint32_t *start, uint32_t *stop)
|
|
||||||
{
|
|
||||||
uint32_t mid, val = *stop & 0xff000000;
|
|
||||||
while(start != stop)
|
|
||||||
if(start[mid = (stop - start) >> 1] > val)
|
|
||||||
stop = &start[mid];
|
|
||||||
else
|
|
||||||
start += mid + 1;
|
|
||||||
|
|
||||||
return start;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** update_contribution
|
/** update_contribution
|
||||||
* helper, calculates the partial linear feedback contributions and puts in MSB
|
* helper, calculates the partial linear feedback contributions and puts in MSB
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void update_contribution(uint32_t *item, const uint32_t mask1, const uint32_t mask2)
|
||||||
update_contribution(uint32_t *item, const uint32_t mask1, const uint32_t mask2)
|
|
||||||
{
|
{
|
||||||
uint32_t p = *item >> 25;
|
uint32_t p = *item >> 25;
|
||||||
|
|
||||||
|
@ -126,8 +46,7 @@ update_contribution(uint32_t *item, const uint32_t mask1, const uint32_t mask2)
|
||||||
/** extend_table
|
/** extend_table
|
||||||
* using a bit of the keystream extend the table of possible lfsr states
|
* using a bit of the keystream extend the table of possible lfsr states
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void extend_table(uint32_t *tbl, uint32_t **end, int bit, int m1, int m2, uint32_t in)
|
||||||
extend_table(uint32_t *tbl, uint32_t **end, int bit, int m1, int m2, uint32_t in)
|
|
||||||
{
|
{
|
||||||
in <<= 24;
|
in <<= 24;
|
||||||
for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1)
|
for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1)
|
||||||
|
@ -150,15 +69,17 @@ extend_table(uint32_t *tbl, uint32_t **end, int bit, int m1, int m2, uint32_t in
|
||||||
*/
|
*/
|
||||||
static inline void extend_table_simple(uint32_t *tbl, uint32_t **end, int bit)
|
static inline void extend_table_simple(uint32_t *tbl, uint32_t **end, int bit)
|
||||||
{
|
{
|
||||||
for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1)
|
for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1) {
|
||||||
if(filter(*tbl) ^ filter(*tbl | 1)) { // replace
|
if(filter(*tbl) ^ filter(*tbl | 1)) { // replace
|
||||||
*tbl |= filter(*tbl) ^ bit;
|
*tbl |= filter(*tbl) ^ bit;
|
||||||
} else if(filter(*tbl) == bit) { // insert
|
} else if(filter(*tbl) == bit) { // insert
|
||||||
*++*end = *++tbl;
|
*++*end = *++tbl;
|
||||||
*tbl = tbl[-1] | 1;
|
*tbl = tbl[-1] | 1;
|
||||||
} else // drop
|
} else { // drop
|
||||||
*tbl-- = *(*end)--;
|
*tbl-- = *(*end)--;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
/** recover
|
/** recover
|
||||||
* recursively narrow down the search space, 4 bits of keystream at a time
|
* recursively narrow down the search space, 4 bits of keystream at a time
|
||||||
*/
|
*/
|
||||||
|
@ -186,13 +107,11 @@ recover(uint32_t *o_head, uint32_t *o_tail, uint32_t oks,
|
||||||
oks >>= 1;
|
oks >>= 1;
|
||||||
eks >>= 1;
|
eks >>= 1;
|
||||||
in >>= 2;
|
in >>= 2;
|
||||||
extend_table(o_head, &o_tail, oks & 1, LF_POLY_EVEN << 1 | 1,
|
extend_table(o_head, &o_tail, oks & 1, LF_POLY_EVEN << 1 | 1, LF_POLY_ODD << 1, 0);
|
||||||
LF_POLY_ODD << 1, 0);
|
|
||||||
if(o_head > o_tail)
|
if(o_head > o_tail)
|
||||||
return sl;
|
return sl;
|
||||||
|
|
||||||
extend_table(e_head, &e_tail, eks & 1, LF_POLY_ODD,
|
extend_table(e_head, &e_tail, eks & 1, LF_POLY_ODD, LF_POLY_EVEN << 1 | 1, in & 3);
|
||||||
LF_POLY_EVEN << 1 | 1, in & 3);
|
|
||||||
if(e_head > e_tail)
|
if(e_head > e_tail)
|
||||||
return sl;
|
return sl;
|
||||||
}
|
}
|
||||||
|
@ -238,14 +157,8 @@ struct Crypto1State* lfsr_recovery32(uint32_t ks2, uint32_t in)
|
||||||
|
|
||||||
// allocate memory for out of place bucket_sort
|
// allocate memory for out of place bucket_sort
|
||||||
bucket_array_t bucket;
|
bucket_array_t bucket;
|
||||||
for (uint32_t i = 0; i < 2; i++)
|
|
||||||
for (uint32_t j = 0; j <= 0xff; j++) {
|
|
||||||
bucket[i][j].head = malloc(sizeof(uint32_t)<<14);
|
|
||||||
if (!bucket[i][j].head) {
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if ( !bucket_malloc(bucket) ) goto out;
|
||||||
|
|
||||||
// initialize statelists: add all possible states which would result into the rightmost 2 bits of the keystream
|
// initialize statelists: add all possible states which would result into the rightmost 2 bits of the keystream
|
||||||
for(i = 1 << 20; i >= 0; --i) {
|
for(i = 1 << 20; i >= 0; --i) {
|
||||||
|
@ -265,17 +178,12 @@ struct Crypto1State* lfsr_recovery32(uint32_t ks2, uint32_t in)
|
||||||
// 22 bits to go to recover 32 bits in total. From now on, we need to take the "in"
|
// 22 bits to go to recover 32 bits in total. From now on, we need to take the "in"
|
||||||
// parameter into account.
|
// parameter into account.
|
||||||
in = (in >> 16 & 0xff) | (in << 16) | (in & 0xff00); // Byte swapping
|
in = (in >> 16 & 0xff) | (in << 16) | (in & 0xff00); // Byte swapping
|
||||||
recover(odd_head, odd_tail, oks,
|
recover(odd_head, odd_tail, oks, even_head, even_tail, eks, 11, statelist, in << 1, bucket);
|
||||||
even_head, even_tail, eks, 11, statelist, in << 1, bucket);
|
|
||||||
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
free(odd_head);
|
free(odd_head);
|
||||||
free(even_head);
|
free(even_head);
|
||||||
for (uint32_t i = 0; i < 2; i++)
|
bucket_free(bucket);
|
||||||
for (uint32_t j = 0; j <= 0xff; j++)
|
|
||||||
free(bucket[i][j].head);
|
|
||||||
|
|
||||||
return statelist;
|
return statelist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#ifndef CRAPTO1_H__
|
#ifndef CRAPTO1_H__
|
||||||
#define CRAPTO1_H__
|
#define CRAPTO1_H__
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include "bucketsort.h"
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -80,10 +80,7 @@ void ProxGuiQT::MainLoop()
|
||||||
plotapp->exec();
|
plotapp->exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
ProxGuiQT::ProxGuiQT(int argc, char **argv) : plotapp(NULL), plotwidget(NULL),
|
ProxGuiQT::ProxGuiQT(int argc, char **argv) : plotapp(NULL), plotwidget(NULL), argc(argc), argv(argv) {}
|
||||||
argc(argc), argv(argv)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ProxGuiQT::~ProxGuiQT(void)
|
ProxGuiQT::~ProxGuiQT(void)
|
||||||
{
|
{
|
||||||
|
@ -310,7 +307,6 @@ void ProxWidget::mouseMoveEvent(QMouseEvent *event)
|
||||||
CursorBPos = x;
|
CursorBPos = x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
this->update();
|
this->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
65
common/bucketsort.c
Normal file
65
common/bucketsort.c
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
#include "bucketsort.h"
|
||||||
|
|
||||||
|
bool bucket_malloc(bucket_array_t bucket) {
|
||||||
|
for (uint32_t i = 0; i < 2; i++) {
|
||||||
|
for (uint32_t j = 0; j <= 0xff; j++) {
|
||||||
|
bucket[i][j].head = malloc(sizeof(uint32_t)<<14);
|
||||||
|
if (!bucket[i][j].head) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bucket_free(bucket_array_t bucket) {
|
||||||
|
for (uint8_t i = 0; i < 2; i++)
|
||||||
|
for (uint8_t j = 0; j <= 0xff; j++)
|
||||||
|
free(bucket[i][j].head);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bucket_sort_intersect(uint32_t* const estart, uint32_t* const estop,
|
||||||
|
uint32_t* const ostart, uint32_t* const ostop,
|
||||||
|
bucket_info_t *bucket_info, bucket_array_t bucket)
|
||||||
|
{
|
||||||
|
uint32_t *p1, *p2;
|
||||||
|
uint32_t *start[2];
|
||||||
|
uint32_t *stop[2];
|
||||||
|
|
||||||
|
start[0] = estart;
|
||||||
|
stop[0] = estop;
|
||||||
|
start[1] = ostart;
|
||||||
|
stop[1] = ostop;
|
||||||
|
|
||||||
|
// init buckets to be empty
|
||||||
|
for (uint32_t i = 0; i < 2; i++) {
|
||||||
|
for (uint32_t j = 0x00; j <= 0xff; j++) {
|
||||||
|
bucket[i][j].bp = bucket[i][j].head;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort the lists into the buckets based on the MSB (contribution bits)
|
||||||
|
for (uint32_t i = 0; i < 2; i++) {
|
||||||
|
for (p1 = start[i]; p1 <= stop[i]; p1++) {
|
||||||
|
uint32_t bucket_index = (*p1 & 0xff000000) >> 24;
|
||||||
|
*(bucket[i][bucket_index].bp++) = *p1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// write back intersecting buckets as sorted list.
|
||||||
|
// fill in bucket_info with head and tail of the bucket contents in the list and number of non-empty buckets.
|
||||||
|
uint32_t nonempty_bucket;
|
||||||
|
for (uint32_t i = 0; i < 2; i++) {
|
||||||
|
p1 = start[i];
|
||||||
|
nonempty_bucket = 0;
|
||||||
|
for (uint32_t j = 0x00; j <= 0xff; j++) {
|
||||||
|
if (bucket[0][j].bp != bucket[0][j].head && bucket[1][j].bp != bucket[1][j].head) { // non-empty intersecting buckets only
|
||||||
|
bucket_info->bucket_info[i][nonempty_bucket].head = p1;
|
||||||
|
for (p2 = bucket[i][j].head; p2 < bucket[i][j].bp; *p1++ = *p2++);
|
||||||
|
bucket_info->bucket_info[i][nonempty_bucket].tail = p1 - 1;
|
||||||
|
nonempty_bucket++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bucket_info->numbuckets = nonempty_bucket;
|
||||||
|
}
|
||||||
|
}
|
26
common/bucketsort.h
Normal file
26
common/bucketsort.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#ifndef BUCKETSORT_H__
|
||||||
|
#define BUCKETSORT_H__
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
typedef struct bucket {
|
||||||
|
uint32_t *head;
|
||||||
|
uint32_t *bp;
|
||||||
|
} bucket_t;
|
||||||
|
|
||||||
|
typedef bucket_t bucket_array_t[2][0x100];
|
||||||
|
|
||||||
|
typedef struct bucket_info {
|
||||||
|
struct {
|
||||||
|
uint32_t *head, *tail;
|
||||||
|
} bucket_info[2][0x100];
|
||||||
|
uint32_t numbuckets;
|
||||||
|
} bucket_info_t;
|
||||||
|
|
||||||
|
|
||||||
|
bool bucket_malloc(bucket_array_t bucket);
|
||||||
|
void bucket_free(bucket_array_t bucket);
|
||||||
|
void bucket_sort_intersect(uint32_t* const estart, uint32_t* const estop,
|
||||||
|
uint32_t* const ostart, uint32_t* const ostop,
|
||||||
|
bucket_info_t *bucket_info, bucket_array_t bucket);
|
||||||
|
#endif
|
99
common/radixsort.c
Normal file
99
common/radixsort.c
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
#include "radixsort.h"
|
||||||
|
|
||||||
|
uint64_t * radixSort(uint64_t * array, uint32_t size) {
|
||||||
|
rscounts_t counts;
|
||||||
|
memset(&counts, 0, 256 * 8 * sizeof(uint32_t));
|
||||||
|
uint64_t * cpy = (uint64_t *)malloc(size * sizeof(uint64_t));
|
||||||
|
uint32_t o8=0, o7=0, o6=0, o5=0, o4=0, o3=0, o2=0, o1=0;
|
||||||
|
uint32_t t8, t7, t6, t5, t4, t3, t2, t1;
|
||||||
|
uint32_t x;
|
||||||
|
// calculate counts
|
||||||
|
for(x = 0; x < size; ++x) {
|
||||||
|
t8 = array[x] & 0xff;
|
||||||
|
t7 = (array[x] >> 8) & 0xff;
|
||||||
|
t6 = (array[x] >> 16) & 0xff;
|
||||||
|
t5 = (array[x] >> 24) & 0xff;
|
||||||
|
t4 = (array[x] >> 32) & 0xff;
|
||||||
|
t3 = (array[x] >> 40) & 0xff;
|
||||||
|
t2 = (array[x] >> 48) & 0xff;
|
||||||
|
t1 = (array[x] >> 56) & 0xff;
|
||||||
|
counts.c8[t8]++;
|
||||||
|
counts.c7[t7]++;
|
||||||
|
counts.c6[t6]++;
|
||||||
|
counts.c5[t5]++;
|
||||||
|
counts.c4[t4]++;
|
||||||
|
counts.c3[t3]++;
|
||||||
|
counts.c2[t2]++;
|
||||||
|
counts.c1[t1]++;
|
||||||
|
}
|
||||||
|
// convert counts to offsets
|
||||||
|
for(x = 0; x < 256; ++x) {
|
||||||
|
t8 = o8 + counts.c8[x];
|
||||||
|
t7 = o7 + counts.c7[x];
|
||||||
|
t6 = o6 + counts.c6[x];
|
||||||
|
t5 = o5 + counts.c5[x];
|
||||||
|
t4 = o4 + counts.c4[x];
|
||||||
|
t3 = o3 + counts.c3[x];
|
||||||
|
t2 = o2 + counts.c2[x];
|
||||||
|
t1 = o1 + counts.c1[x];
|
||||||
|
counts.c8[x] = o8;
|
||||||
|
counts.c7[x] = o7;
|
||||||
|
counts.c6[x] = o6;
|
||||||
|
counts.c5[x] = o5;
|
||||||
|
counts.c4[x] = o4;
|
||||||
|
counts.c3[x] = o3;
|
||||||
|
counts.c2[x] = o2;
|
||||||
|
counts.c1[x] = o1;
|
||||||
|
o8 = t8;
|
||||||
|
o7 = t7;
|
||||||
|
o6 = t6;
|
||||||
|
o5 = t5;
|
||||||
|
o4 = t4;
|
||||||
|
o3 = t3;
|
||||||
|
o2 = t2;
|
||||||
|
o1 = t1;
|
||||||
|
}
|
||||||
|
// radix
|
||||||
|
for(x = 0; x < size; ++x) {
|
||||||
|
t8 = array[x] & 0xff;
|
||||||
|
cpy[counts.c8[t8]] = array[x];
|
||||||
|
counts.c8[t8]++;
|
||||||
|
}
|
||||||
|
for(x = 0; x < size; ++x) {
|
||||||
|
t7 = (cpy[x] >> 8) & 0xff;
|
||||||
|
array[counts.c7[t7]] = cpy[x];
|
||||||
|
counts.c7[t7]++;
|
||||||
|
}
|
||||||
|
for(x = 0; x < size; ++x) {
|
||||||
|
t6 = (array[x] >> 16) & 0xff;
|
||||||
|
cpy[counts.c6[t6]] = array[x];
|
||||||
|
counts.c6[t6]++;
|
||||||
|
}
|
||||||
|
for(x = 0; x < size; ++x) {
|
||||||
|
t5 = (cpy[x] >> 24) & 0xff;
|
||||||
|
array[counts.c5[t5]] = cpy[x];
|
||||||
|
counts.c5[t5]++;
|
||||||
|
}
|
||||||
|
for(x = 0; x < size; ++x) {
|
||||||
|
t4 = (array[x] >> 32) & 0xff;
|
||||||
|
cpy[counts.c4[t4]] = array[x];
|
||||||
|
counts.c4[t4]++;
|
||||||
|
}
|
||||||
|
for(x = 0; x < size; ++x) {
|
||||||
|
t3 = (cpy[x] >> 40) & 0xff;
|
||||||
|
array[counts.c3[t3]] = cpy[x];
|
||||||
|
counts.c3[t3]++;
|
||||||
|
}
|
||||||
|
for(x = 0; x < size; ++x) {
|
||||||
|
t2 = (array[x] >> 48) & 0xff;
|
||||||
|
cpy[counts.c2[t2]] = array[x];
|
||||||
|
counts.c2[t2]++;
|
||||||
|
}
|
||||||
|
for(x = 0; x < size; ++x) {
|
||||||
|
t1 = (cpy[x] >> 56) & 0xff;
|
||||||
|
array[counts.c1[t1]] = cpy[x];
|
||||||
|
counts.c1[t1]++;
|
||||||
|
}
|
||||||
|
free(cpy);
|
||||||
|
return array;
|
||||||
|
}
|
23
common/radixsort.h
Normal file
23
common/radixsort.h
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
#ifndef RADIXSORT_H__
|
||||||
|
#define RADIXSORT_H__
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
struct {
|
||||||
|
uint32_t c8[256];
|
||||||
|
uint32_t c7[256];
|
||||||
|
uint32_t c6[256];
|
||||||
|
uint32_t c5[256];
|
||||||
|
uint32_t c4[256];
|
||||||
|
uint32_t c3[256];
|
||||||
|
uint32_t c2[256];
|
||||||
|
uint32_t c1[256];
|
||||||
|
};
|
||||||
|
uint32_t counts[256 * 8];
|
||||||
|
} rscounts_t;
|
||||||
|
|
||||||
|
uint64_t * radixSort(uint64_t * array, uint32_t size);
|
||||||
|
#endif // RADIXSORT_H__
|
Loading…
Add table
Add a link
Reference in a new issue