Created
February 15, 2013 01:18
-
-
Save loriopatrick/4957921 to your computer and use it in GitHub Desktop.
An attempt to factor numbers using binary multiplication and bitwise operators.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <math.h> | |
#include <string.h> | |
// note, in binary 0x80 = [10000000], 0x7F = [011111111] | |
#define CHARS(BITS) (int)(((BITS) - (((BITS) - 1) % 8)) / 8) + 1 | |
#define BIT(DATA, POS) ((DATA[(int)((POS) / 8)] & (0x80 >> ((POS) % 8))) != 0) | |
#define SET0(DATA, POS) DATA[(int)((POS) / 8)] &= (0x7F >> ((POS) % 8) | 0x7F << (8 - ((POS) % 8))) | |
#define SET1(DATA, POS) DATA[(int)((POS) / 8)] |= 0x80 >> ((POS) % 8) | |
/* | |
* Numbers are seen as [00000000000...0000001] = 1 | |
*/ | |
void base2 (char data[], int buffer_bits) { | |
int i, start = 0; | |
for (i = 0; i < buffer_bits; ++i) { | |
int b = BIT(data, i); | |
if (!start && !b) continue; | |
start = 1; | |
printf("%i", b); | |
} | |
} | |
double base10 (char data[], int buffer_bits) { | |
int i; | |
double res = 0; | |
for (i = buffer_bits; i >= 0; --i) { | |
if (BIT(data, i)) { | |
res += pow(2.0, buffer_bits - i - 1); | |
} | |
} | |
return res; | |
} | |
int equal (char *a, char *b, int bits) { | |
int i, l = floor(bits / 8); | |
for (i = 0; i < l; ++i) { | |
if (a[i] != b[1]) { | |
return 0; | |
} | |
} | |
int mod = bits % 8; | |
if (mod == 0) return 1; | |
return ((a[l] >> mod) & (b[l] >> mod)) == 0xFF >> mod; | |
} | |
int add (char base[], int base_buffer_bits, int base_bits, char add[], int add_buffer_bits, int add_bits, int shift) { | |
// base2(base, base_buffer_bits); printf(" + "); base2(add, add_buffer_bits); printf("<<%i = ", shift); | |
int carry = 0; | |
int base_pos = base_buffer_bits - 1, | |
base_min = base_pos - base_bits, | |
add_pos = add_buffer_bits - 1, | |
add_min = add_pos - add_bits; | |
for (base_pos -= shift; base_pos > base_min && add_pos > add_min; --base_pos, --add_pos) { | |
int base_bit = BIT(base, base_pos), | |
add_bit = BIT(add, add_pos); | |
if (base_bit && add_bit) { | |
if (carry) { | |
SET1(base, base_pos); | |
continue; | |
} | |
SET0(base, base_pos); | |
carry = 1; | |
continue; | |
} | |
if (base_bit || add_bit) { | |
if (carry) { | |
SET0(base, base_pos); | |
continue; | |
} | |
SET1(base, base_pos); | |
continue; | |
} | |
if (carry) { | |
SET1(base, base_pos); | |
carry = 0; | |
continue; | |
} | |
SET0(base, base_pos); | |
} | |
// base2(base, base_buffer_bits); printf("\n"); | |
// if (add_bits == base_bits) return carry; | |
for (; add_pos > add_min; --add_pos) { | |
if (BIT(add, add_pos)) { | |
return 1; | |
} | |
} | |
return carry; | |
} | |
char *prefix (char *data, int bytes, int bits, int bit) { | |
char *res; | |
if (bytes * 8 <= bits) { // new data block shifts, shift over, prefix | |
res = (char *)malloc(bytes + 1); | |
memcpy(res+1, data, bytes); | |
res[0] = bit; | |
return res; | |
} | |
res = (char *)malloc(bytes); | |
memcpy(res, data, bytes); | |
if (bit) { | |
SET1(res, bytes * 8 - bits - 1); | |
} else { | |
SET0(res, bytes * 8 - bits - 1); | |
} | |
return res; | |
} | |
void factors (char data[], int bits) { | |
int size /* in bits */, chars /* # of chars to hold size # of bits */, noptions = 0, dead_options = 0; | |
int len_bytes = CHARS(bits); | |
float data_base10 = base10(data, len_bytes * 8); | |
char *multi = (char *) malloc(len_bytes + 1), // store the multiplication of options to verify they could be factors | |
**options = (char **)malloc(10000 * sizeof(char *)); // buffer for the possible factors | |
for (size = 1, chars = 1; size <= bits; ++size) { | |
printf("SIZE: %i\n", size); | |
// build options based off of successful priors | |
if (size == 1) { // set initial options, bits 1 and 0 as options | |
options[0] = (char *) malloc(1); | |
*options[0] = 1; | |
options[1] = (char *) malloc(1); | |
*options[1] = 0; | |
noptions = 2; | |
} else { // build 2 new options for every successful options with appending bit 1 for one and bit 0 for the other | |
int i, n = 0; | |
int new_chars = CHARS(size); // # of chars to hold size # of bits | |
int new_noptions = (noptions - dead_options) * 2; | |
char **new_options = (char **) malloc(new_noptions * sizeof(char *)); | |
printf("\nBUILD PRIFIX :: %i option(s) \n", new_noptions / 2); | |
for (i = 0; i < noptions; ++i) { | |
if (options[i] != NULL) { | |
char *prefix1 = prefix(options[i], chars, size - 1, 1); | |
char *prefix0 = prefix(options[i], chars, size - 1, 0); | |
// debug log DUH! | |
printf("option[%i] = ", i); | |
base2(options[i], new_chars * 8); | |
printf("\nPREFIX 1 = "); | |
base2(prefix1, new_chars * 8); | |
printf("\nPREFIX 0 = "); | |
base2(prefix0, new_chars * 8); | |
printf("\n"); | |
free(options[i]); | |
// assign new options | |
new_options[n++] = prefix1; | |
new_options[n++] = prefix0; | |
} | |
} | |
// copy over new data & clean up | |
memcpy(options, new_options, new_noptions * sizeof(char *)); | |
free(new_options); | |
noptions = new_noptions; | |
chars = new_chars; | |
dead_options = 0; | |
} | |
// printf("\n"); | |
// remove option that cannot be factors of data | |
int i, j; | |
int success[noptions]; | |
memset(success, 0, sizeof(success)); | |
for (i = 0; i < noptions; ++i) { | |
if (base10(options[i], chars * 8) > data_base10) { | |
free(options[i]); | |
options[i] = NULL; | |
++dead_options; | |
continue; | |
} | |
// printf("IS (options[%i] = ", i); base2(options[i], chars * 8); printf(") A FACTOR?\n"); | |
int is_factor = 0, buffer_bits = chars * 8; | |
for (j = 0; j < noptions; ++j) { | |
if (options[j] == NULL) continue; // factors is removed, so skip | |
if (success[i]) { | |
is_factor = 1; | |
break; | |
} | |
memset(multi, 0x0, len_bytes + 1); // clear multi so we can use it | |
// printf("- Factor with options[%i] = ", j); base2(options[j], buffer_bits, size); printf(" ?\n"); | |
// multiply the two binary numbers till know they do not form data or could, and take appropriate action | |
int k, good = 1; | |
for (k = 0; k < size; ++k) { // options[i] * options[j] | |
if (BIT(options[j], buffer_bits - 1 - k)) { // Add the shift to multi | |
if (add(multi, bits, bits, options[i], buffer_bits, size, k)) { | |
good = 0; | |
break; | |
} | |
} | |
if (BIT(data, bits - 1 - k) != BIT(multi, bits - 1 - k)) { // different values | |
good = 0; | |
// printf("- NOT FACTOR WITH options[%i]\n", j); | |
break; | |
} | |
} | |
if (base10(multi, bits) > data_base10) continue; | |
if (good) { | |
success[i] = 1; | |
success[j] = 1; | |
is_factor = 1; | |
// printf("YES: IS A FACTOR WITH options[%i], PRODUCT=", j); base2(multi, bits); printf("\n\n"); | |
break; | |
} | |
} | |
if (!is_factor) { | |
// printf("NO: IS NOT A FACTOR\n\n"); | |
free(options[i]); | |
options[i] = NULL; | |
++dead_options; | |
} | |
} | |
printf("SIZE: %i : %i \n", size, bits); | |
} | |
printf("GOT %i factors\n", noptions - dead_options); | |
int i; | |
for (i = 0; i < noptions; ++i) { | |
if (options[i] == NULL) continue; | |
base2(options[i], chars * 8); printf(" = %f\n", base10(options[i], chars * 8)); | |
} | |
} | |
int main (int args, char **argv) { | |
// char data[] = {1<<7|12}; | |
// base2(data, 8); printf("\n"); | |
// char *d2 = prefix(data, 1, 8, 1); | |
// base2(d2, 16); printf("\n"); | |
char data[] = {136, 19}; | |
int l = sizeof(data) * 8; | |
printf("number: %f\n", base10(data, l)); | |
base2(data, l); printf("\n"); | |
// return 0; | |
factors(data, l); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment