main.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <stdint.h>
  4. #include <string.h>
  5. #include <stdatomic.h>
  6. #include <pthread.h>
  7. // #include "ds.h"
  8. #define KILOBYTE (1024ul)
  9. #define MEGABYTE (KILOBYTE * 1024)
  10. #define GIGABYTE (MEGABYTE * 1024)
  11. #define TERABYTE (GIGABYTE * 1024)
  12. #define PETABYTE (TERABYTE * 1024)
  13. #define KILOBYTES(x) ((x) * 1024ul)
  14. #define MEGABYTES(x) ((x) * KILOBYTE * 1024)
  15. #define GIGABYTES(x) ((x) * MEGABYTE * 1024)
  16. #define TERABYTES(x) ((x) * GIGABYTE * 1024)
  17. #define PETABYTES(x) ((x) * TERABYTE * 1024)
  18. // uint8_t quotients[257][257];
  19. // uint8_t remainders[257][257];
  20. size_t g_mem_usage = 0;
  21. static void pretty_print_mem(size_t sz);
  22. typedef struct {
  23. uint32_t* data;
  24. uint32_t length;
  25. uint32_t divisor;
  26. uint32_t remainder;
  27. uint32_t add_cursor;
  28. pthread_mutex_t lock;
  29. char negative;
  30. char finished;
  31. } Fraction;
  32. typedef struct {
  33. struct {
  34. uint64_t length;
  35. Fraction* fr;
  36. }* fractions;
  37. size_t alloc_sz, length;
  38. pthread_mutex_t lock;
  39. } FStore;
  40. void add_fraction(Fraction* into, Fraction* addend);
  41. void free_fraction(Fraction* fr);
  42. void init_fstore(FStore* fs) {
  43. fs->alloc_sz = 1024*64;
  44. fs->length = 0;
  45. fs->fractions = calloc(1, sizeof(*fs->fractions) * fs->alloc_sz);
  46. pthread_mutex_init(&fs->lock, NULL);
  47. }
  48. void fstore_push(FStore* fs, Fraction* fr) {
  49. int32_t flen = fr->length;
  50. size_t lowest_i = 0;
  51. size_t lowest_len = 0;
  52. for(size_t i = 0; i < fs->length; i++) {
  53. // if(flen > fs->fractions[i].length) continue;
  54. int32_t l = fs->fractions[i].length;
  55. if(flen <= l && l % flen == 0) {
  56. if(lowest_len == 0 || l < lowest_len) {
  57. lowest_i = i;
  58. lowest_len = l;
  59. }
  60. continue;
  61. }
  62. else if(flen > l && flen % l == 0) {
  63. // printf("-%d goes into %d \n", l, flen);
  64. /*
  65. add_fraction(fr, fs->fractions[i].fr);
  66. free_fraction(fs->fractions[i].fr);
  67. fs->fractions[i].fr = fr;
  68. fs->fractions[i].length = flen;
  69. */
  70. if(lowest_len == 0 || l < lowest_len) {
  71. lowest_i = i;
  72. lowest_len = l;
  73. }
  74. continue;
  75. }
  76. }
  77. if(lowest_len) {
  78. // pthread_mutex_lock(&fs->lock);
  79. // pthread_mutex_lock(&fs->fractions[lowest_i].lock);
  80. // pthread_mutex_unlock(&fs->lock);
  81. printf("%d goes into %ld at [%ld]\n", flen, lowest_len, lowest_i);
  82. if(flen > lowest_len) {
  83. add_fraction(fr, fs->fractions[lowest_i].fr);
  84. free_fraction(fs->fractions[lowest_i].fr);
  85. pthread_mutex_lock(&fs->lock);
  86. fs->fractions[lowest_i].fr = fr;
  87. fs->fractions[lowest_i].length = flen;
  88. pthread_mutex_unlock(&fs->lock);
  89. }
  90. else {
  91. add_fraction(fs->fractions[lowest_i].fr, fr);
  92. free_fraction(fr);
  93. }
  94. // pthread_mutex_unlock(&fs->fractions[lowest_i].lock);
  95. // pthread_mutex_unlock(&fs->lock);
  96. return;
  97. }
  98. fr->data = realloc(fr->data, flen * sizeof(fr->data));
  99. // else append
  100. pthread_mutex_lock(&fs->lock);
  101. if(fs->length >= fs->alloc_sz) {
  102. fs->alloc_sz *= 2;
  103. fs->fractions = realloc(fs->fractions, sizeof(*fs->fractions) * fs->alloc_sz);
  104. }
  105. fs->fractions[fs->length].length = flen;
  106. fs->fractions[fs->length].fr = fr;
  107. // pthread_mutex_init(&fs->fractions[fs->length].lock, NULL);
  108. fs->length++;
  109. g_mem_usage += flen * 4;
  110. if(g_mem_usage > GIGABYTES(2)) {
  111. printf("limit exceeded\n");
  112. exit(0);
  113. }
  114. pthread_mutex_unlock(&fs->lock);
  115. printf("fstore length: %ld\n", fs->length);
  116. }
  117. void free_fraction(Fraction* fr) {
  118. pthread_mutex_lock(&fr->lock);
  119. if(fr) {
  120. free(fr->data);
  121. }
  122. free(fr);
  123. }
  124. void add_fraction(Fraction* into, Fraction* addend) {
  125. // printf("adding %d\n", addend->length);
  126. pthread_mutex_lock(&into->lock);
  127. int sub = into->negative ^ addend->negative;
  128. uint32_t a, i;
  129. uint32_t* out = into->data, *in = addend->data;
  130. uint32_t len = into->length;
  131. uint32_t alen = addend->length;
  132. uint32_t carry = 0; // or borrow
  133. if(sub) { // subtract
  134. for(a = 0, i = 0; i < len; a++, i++) {
  135. if(a >= alen) a = 0;
  136. // VERY WRONG
  137. uint64_t sum = (uint64_t)out[i] - (uint64_t)in[a] - carry;
  138. out[i] = (uint32_t)sum;
  139. carry = sum >> 32;
  140. }
  141. // wrap the borrow around to the front
  142. i = 0;
  143. a = 0;
  144. while(carry) {
  145. uint64_t sum = (uint64_t)out[i] - (uint64_t)in[a] - carry;
  146. out[i] = (uint32_t)sum;
  147. carry = sum >> 32;
  148. i++;
  149. a++;
  150. if(a >= alen) a = 0;
  151. if(i >= len) i = 0;
  152. }
  153. }
  154. else { // add
  155. for(a = 0, i = 0; i < len; a++, i++) {
  156. if(a >= alen) a = 0;
  157. uint64_t sum = (uint64_t)out[i] + (uint64_t)in[a] + carry;
  158. out[i] = (uint32_t)sum;
  159. carry = sum >> 32;
  160. }
  161. // wrap the carry around to the front
  162. i = 0;
  163. a = 0;
  164. while(carry) {
  165. uint64_t sum = (uint64_t)out[i] + (uint64_t)in[a] + carry;
  166. out[i] = (uint32_t)sum;
  167. carry = sum >> 32;
  168. i++;
  169. a++;
  170. if(a >= alen) a = 0;
  171. if(i >= len) i = 0;
  172. }
  173. }
  174. pthread_mutex_unlock(&into->lock);
  175. }
  176. Fraction* fill_fraction(Fraction* fr, uint32_t sz) {
  177. uint32_t i;
  178. Fraction* of = malloc(sizeof(of));
  179. of->length = sz;
  180. of->data = malloc(sz * sizeof(*of->data));
  181. of->divisor = 0;
  182. uint32_t* out = of->data, *in = fr->data;
  183. uint32_t alen = fr->length;
  184. uint32_t len = sz;
  185. for(i = 0; i < len; i++) {
  186. out[i] = in[i % alen];
  187. }
  188. return of;
  189. }
  190. Fraction* new_fraction32(uint32_t divisor, uint32_t max_len) {
  191. int finished = 0;
  192. int32_t r;
  193. int32_t b = divisor;
  194. int64_t i = 0;
  195. int32_t lz = 0;
  196. int32_t* o = malloc(max_len * sizeof(*o));
  197. Fraction* fr = malloc(sizeof(*fr));
  198. fr->data = o;
  199. fr->divisor = b;
  200. pthread_mutex_init(&fr->lock, NULL);
  201. fr->negative = (b - 3) % 4 == 0; // 3 is negative
  202. int64_t t = 1ul << 32;
  203. int32_t first_q = t / b;
  204. int32_t first_r = t % b;
  205. if(first_q == 0) lz++;
  206. o[0] = first_q;
  207. t = (int64_t)first_r << 32;
  208. for(i = 1; i < max_len; i++) {
  209. int32_t q;
  210. q = t / b;
  211. r = t % b;
  212. if(q == 0) lz++;
  213. o[i] = q;
  214. // printf(" %d,%d, %ld\n", q, r, t);
  215. if(first_q == q && first_r == r) {
  216. finished = 1;
  217. break;
  218. }
  219. t = (int64_t)r << 32;
  220. }
  221. if(lz > 0) {
  222. printf("leading zeros: %d (%d)\n", lz, b);
  223. }
  224. fr->finished = finished;
  225. if(!finished) {
  226. // store remainder for later processing
  227. fr->remainder = r;
  228. }
  229. fr->length = i;
  230. return fr;
  231. }
  232. typedef struct {
  233. pthread_t thread;
  234. _Atomic int should_die;
  235. FStore* fs;
  236. } ThreadInfo;
  237. _Atomic uint64_t next_divisor;
  238. int64_t MAX = 1024*16*16;
  239. void* work_thread_fn(ThreadInfo* ti) {
  240. while(1) {
  241. uint64_t b = atomic_fetch_add(&next_divisor, 2);
  242. Fraction* fr = new_fraction32(b, MAX);
  243. if(b % 1001 == 0) {
  244. pretty_print_mem(g_mem_usage);
  245. printf("\n");
  246. }
  247. if(fr->length == MAX) {
  248. printf("%ld: %d\n", b, fr->length);
  249. break;
  250. }
  251. else {
  252. // int32_t i = fr->length;
  253. fstore_push(ti->fs, fr);
  254. }
  255. }
  256. return NULL;
  257. }
  258. int main(int argc, char* argv[]) {
  259. int num_threads = 11;
  260. ThreadInfo threads[num_threads];
  261. // 3 starts negative
  262. atomic_init(&next_divisor, 3);
  263. FStore* fs = malloc(sizeof(*fs));
  264. init_fstore(fs);
  265. // Fraction* sixty = NULL;
  266. // VEC(Fraction*) fractions;
  267. // VEC_INIT(&fractions);
  268. /*
  269. for(int i = 1; i < 2; i++) {
  270. for(int j = 3; j <= 256; j+=2) {
  271. int q = (i << 8) / j;
  272. int r = (i << 8) % j;
  273. quotients[i][j] = q;
  274. remainders[i][j] = r;
  275. // printf(" %d / %d = [%d , %d] \n", i, j, q, r);
  276. }
  277. }
  278. */
  279. for(int i = 0; i < num_threads; i++) {
  280. ThreadInfo* t = &threads[i];
  281. t->fs = fs;
  282. atomic_init(&t->should_die, 0);
  283. pthread_create(&t->thread, NULL, (void*(*)(void*))work_thread_fn, t);
  284. }
  285. /*
  286. for(int64_t b = 3; b < 256*64*128; b += 2) {
  287. Fraction* fr = new_fraction32(b, MAX);
  288. if(b % 1001 == 0) {
  289. pretty_print_mem(g_mem_usage);
  290. printf("\n");
  291. }
  292. if(fr->length == MAX) {
  293. printf("%ld: %d\n", b, fr->length);
  294. break;
  295. }
  296. else {
  297. // int32_t i = fr->length;
  298. fstore_push(fs, fr);
  299. // int comp = (2*3*5*7);
  300. /*
  301. if(comp % i == 0 && sixty == NULL) {
  302. sixty = fill_fraction(fr, comp);
  303. free_fraction(fr);
  304. g_mem_usage += comp;
  305. }
  306. else if(sixty && comp % i == 0) {
  307. add_fraction(sixty, fr);
  308. free_fraction(fr);
  309. }
  310. else {
  311. fr->data = realloc(fr->data, i);
  312. VEC_PUSH(&fractions, fr);
  313. g_mem_usage += i;
  314. }
  315. * /
  316. }
  317. }
  318. */
  319. for(int i = 0; i < num_threads; ++i) {
  320. pthread_join(threads[i].thread, NULL);
  321. }
  322. printf("%ld bytes\n", g_mem_usage);
  323. // getchar();
  324. return 0;
  325. }
  326. static void pretty_print_mem(size_t sz) {
  327. if(sz >= PETABYTE) {
  328. printf("%d", (int)(sz / PETABYTE));
  329. // printf(".%d", (int)((sz % PETABYTE) / TERABYTE));
  330. printf("PB");
  331. }
  332. else if(sz >= TERABYTE) {
  333. printf("%d", (int)(sz / TERABYTE));
  334. // printf(".%d", (int)((sz % TERABYTE) / GIGABYTE));
  335. printf("TB");
  336. }
  337. else if(sz >= GIGABYTE) {
  338. printf("%d", (int)(sz / GIGABYTE));
  339. // printf(".%d", (int)((sz % GIGABYTE) / MEGABYTE));
  340. printf("GB");
  341. }
  342. else if(sz >= MEGABYTE) {
  343. printf("%d", (int)(sz / MEGABYTE));
  344. // printf(".%d", (int)((sz % MEGABYTE) / KILOBYTE));
  345. printf("MB");
  346. }
  347. else if(sz >= KILOBYTE) {
  348. printf("%d", (int)(sz / KILOBYTE));
  349. // printf(".%d", (int)(sz % KILOBYTE));
  350. printf("KB");
  351. }
  352. else {
  353. printf("%dB", (int)sz);
  354. }
  355. }