1
0
mirror of https://git.disroot.org/80486DX2-66/polonium.git synced 2024-11-09 15:02:20 +05:30

create a faster implementation

This commit is contained in:
Intel A80486DX2-66 2024-07-20 03:19:23 +03:00
parent f81100fbf1
commit 53e3fdee50
Signed by: 80486DX2-66
GPG Key ID: 83631EF27054609B
4 changed files with 28 additions and 54 deletions

View File

@ -89,5 +89,7 @@ typedef off_t file_offset_t;
#define LOOP_ACTION_CONFIG(f, x) \
f(x); \
continue
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif /* _COMMON_H */

View File

@ -20,9 +20,6 @@
/* structures */
struct _corrupter_result {
bool error;
size_t hit_counter,
file_size,
damaged_bytes;
};
struct _corrupter_param {

View File

@ -3,12 +3,15 @@
/* cached operations */
const size_t UINT16_MAX_PLUS_1 = UINT16_MAX + 1;
/* global variables */
uint16_t desired_chance;
/* function definitions */
static bool get_chance(uint16_t desired_chance);
static bool get_chance(void);
static bool is_line_ending(byte c);
/* function implementations */
static bool get_chance(uint16_t desired_chance) {
static bool get_chance(void) {
/* TODO: remove this multi-line comment before merging into main branch
// algorithm v1
// calculate the cumulative distribution function (CDF)
@ -31,15 +34,10 @@ static bool get_chance(uint16_t desired_chance) {
// algorithm v2
if (desired_chance == UINT16_MAX)
return true;
else if (desired_chance == 0)
return false;
uint16_t cdf[UINT16_MAX_PLUS_1];
memset(cdf, 0, sizeof(cdf));
for (uint16_t i = 0; i < UINT16_MAX; i++) {
cdf[i] = (i <= desired_chance) ? i + 1 : cdf[i - 1];
}
uint16_t random_number = mt_next() & UINT16_MAX;
return random_number < cdf[desired_chance];
return (bool) (mt_next() & 1);
}
static bool is_line_ending(byte c) {
@ -53,7 +51,7 @@ Corrupter_Result* corrupt_file(Corrupter_Param* param) {
// copy and cast parameters
FILE* file = param->file;
uint8_t probability = param->probability;
desired_chance = param->probability;
file_offset_t threshold = (file_offset_t) param->threshold;
uint8_t config = param->config;
@ -70,6 +68,9 @@ Corrupter_Result* corrupt_file(Corrupter_Param* param) {
FSEEK_MACRO(file, FILE_OFFSET_C(0), SEEK_END);
end = FTELL_MACRO(file);
// calculate parameters
file_offset_t increment_value = MAX((UINT16_MAX - desired_chance) >> 12, 1);
// determine file boundaries
const char* failed_function = NULL;
file_boundaries_t* boundaries = NULL;
@ -93,22 +94,14 @@ Corrupter_Result* corrupt_file(Corrupter_Param* param) {
break;
}
// output data to result
result->file_size = end;
result->damaged_bytes = 0;
// initialize the PRNG
mt_seed(param->seed);
for (size_t pass = 0; pass < param->passes; pass++) {
// display information
printf("Pass: %zu/%zu", pass + 1, param->passes);
fflush(stdout);
rewind(file);
// iterate over the file contents
for (file_offset_t i = start; i < end; i++) {
for (file_offset_t i = start; i < end; i += increment_value) {
FSEEK_MACRO(file, i, SEEK_SET);
byte byte_value;
if (fread(&byte_value, sizeof(byte), 1, file) != 1) {
@ -122,27 +115,13 @@ Corrupter_Result* corrupt_file(Corrupter_Param* param) {
else if (READ_CONFIG(C_LINE_ENDINGS) && is_line_ending(byte_value))
continue;
// generate bit mask
unsigned char damage_left = (unsigned char) param->threshold;
static bool bit_mask[CHAR_BIT];
for (unsigned char bit = 0; bit < CHAR_BIT; bit++) {
if (get_chance(probability) && (damage_left > 0)) {
bit_mask[bit] = true;
damage_left--;
} else {
bit_mask[bit] = false;
}
}
bool damaged_byte = false;
for (unsigned char bit = 0; bit < threshold; bit++) {
if (bit_mask[bit] == false)
for (unsigned char shift = 0; shift < threshold; shift++) {
if (get_chance())
continue;
byte_value = FLIP_BIT(byte_value, bit);
result->hit_counter++;
unsigned char bit = 1 << shift;
damaged_byte = true;
byte_value = FLIP_BIT(byte_value, bit);
// write the modified byte back to the file
FSEEK_MACRO(file, i, SEEK_SET);
@ -155,11 +134,16 @@ Corrupter_Result* corrupt_file(Corrupter_Param* param) {
return result;
}
if (damaged_byte)
result->damaged_bytes++;
// display progress
if (((i - start) & 65535 /* reporting frequency */) == 0) {
putc('.', stdout);
fflush(stdout);
}
}
puts(" [OK]");
// display progress
putc('\n', stdout);
fflush(stdout);
}
result->error = false;

View File

@ -325,6 +325,7 @@ int main(int argc, char** argv) {
}
}
puts("Working, please wait");
fflush(stdout);
Corrupter_Param param = {
@ -354,16 +355,6 @@ int main(int argc, char** argv) {
putchar('\n');
if (result->damaged_bytes) {
size_t dmg = result->damaged_bytes, fsize = result->file_size,
passes = param.passes;
printf("Byte hit counter: %" PRIuMAX " / %" PRIuMAX " = %.3Lf%%\n",
(uintmax_t) dmg, (uintmax_t) (fsize * passes),
((long double) dmg * 100.l) / (long double) (fsize * passes));
} else {
puts("No bytes were damaged");
}
free(result);
// finish working with the file