Skip to content

Instantly share code, notes, and snippets.

@loriopatrick
Created February 15, 2013 01:18
Show Gist options
  • Save loriopatrick/4957921 to your computer and use it in GitHub Desktop.
Save loriopatrick/4957921 to your computer and use it in GitHub Desktop.
An attempt to factor numbers using binary multiplication and bitwise operators.
#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