/* multiply two complex numbers. c = (a.real * b.real - a.imag * b.imag) + i(a.imag * b.real + a.real * b.imag) */ void bf_multiply_cmplx( COMPLEX *a, COMPLEX *b, COMPLEX *c) { COMPLEX mya, myb; FLOAT temp1, temp2; bf_copy_cmplx( a, &mya); bf_copy_cmplx( b, &myb); bf_multiply( &mya.real, &myb.real, &temp1); bf_multiply( &mya.imag, &myb.imag, &temp2); bf_subtract( &temp1, &temp2, &c->real); bf_multiply( &mya.real, &myb.imag, &temp1); bf_multiply( &mya.imag, &myb.real, &temp2); bf_add( &temp1, &temp2, &c->imag); }
static int is_there_an_anagram(struct wordlist *words, struct wordlist *stack, struct bitfield *bits, int maxwords, int length, int *maxtotal) { struct bitfield *remaining_bits = NULL; struct wordlist *w = words; if (maxwords <= 0) return 0; if (*maxtotal <= 0) return 0; while (w != NULL) { if (length >= w->word->length) { if (bf_contains(bits, w->word->bits)) { int newlength = length - w->word->length; //printf(" -- considering %s\n", w->word->utf8_form); stack = push_wordstack(stack, w->word); if (newlength > 0) { remaining_bits = bf_subtract(bits, w->word->bits); int r = is_there_an_anagram(w, stack, remaining_bits, maxwords - 1, newlength, maxtotal); free_bitfield(remaining_bits); if (r) { stack = pop_wordstack(stack); return 1; } } else { stack = pop_wordstack(stack); return 1; } stack = pop_wordstack(stack); } } w = w->next; } return 0; }
static void find_anagrams(struct wordlist *words, struct wordlist *stack, struct bitfield *bits, int maxwords, int length, int *maxtotal) { struct bitfield *remaining_bits = NULL; struct wordlist *w = words; if (maxwords <= 0) return; if (*maxtotal <= 0) return; /* printf("word depth = %d, length = %d\n", INT_MAX-maxwords, length); */ while (w != NULL) { if (length >= w->word->length) { if (bf_contains(bits, w->word->bits)) { int newlength = length - w->word->length; /* printf(" considering %s\n", w->word->utf8_form); */ stack = push_wordstack(stack, w->word); if (newlength > 0) { remaining_bits = bf_subtract(bits, w->word->bits); find_anagrams(w, stack, remaining_bits, maxwords - 1, newlength, maxtotal); free_bitfield(remaining_bits); } else { if (*maxtotal > 0) { print_wordstack(stack); fputs("\n", stdout); (*maxtotal)--; } } stack = pop_wordstack(stack); } } w = w->next; } }
int main(int argc, char **argv) { char *dictionary = NULL; char *contains = NULL; struct word phrase, contain; struct bitfield *temp_bf; UChar *internal, *alphabet; struct wordlist *words = NULL, *stack = NULL, *w; int maxlen, minlen = 0; int maxwords = INT_MAX, maxtotal = INT_MAX; int opt, longindex; bool just_test = false, include_contains = false, just_words = false, just_anagram_words = false; const struct option long_opts[] = { {"contain", required_argument, 0, 'c'}, {"dict", required_argument, 0, 'd'}, {"length", required_argument, 0, 'l'}, {"minimum", required_argument, 0, 'm'}, {"number", required_argument, 0, 'n'}, {"words", no_argument, 0, 'w'}, {"help", no_argument, 0, 'h'}, {"used", required_argument, 0, 'u'}, {"test", required_argument, 0, 't'}, {"version", no_argument, 0, 'v'}, {0, 0, 0, 0} }; memset(&phrase, 0, sizeof(phrase)); memset(&contain, 0, sizeof(contain)); /* parse arguments */ while ((opt = getopt_long (argc, argv, "c:d:hl:m:n:t:u:vwW", long_opts, &longindex)) != -1) { switch (opt) { case 'c': contains = safe_strdup(optarg); just_test = false; include_contains = true; break; case 'd': dictionary = safe_strdup(optarg); break; case 'h': case '?': print_help(argv[0]); exit(0); case 'l': maxwords = atoi(optarg); break; case 'm': minlen = atoi(optarg); break; case 'n': maxtotal = atoi(optarg); break; case 't': contains = safe_strdup(optarg); just_test = true; break; case 'u': contains = safe_strdup(optarg); include_contains = false; break; case 'v': printf("%s\n", VERSION); exit(0); case 'w': just_words = true; break; case 'W': just_anagram_words = true; break; default: fprintf(stderr, "Unexpected option %c\n", optopt); exit(99); } } if (argc - optind != 1) { fprintf(stderr, "%s: incorrect number of arguments\n", argv[0]); print_help(argv[0]); exit(1); } phrase.utf8_form = safe_strdup(argv[optind]); internal = utf8tointernal(phrase.utf8_form); maxlen = phrase.length = u_strlen(internal); alphabet = make_alphabet(internal); if (u_strlen(alphabet) > BITFIELD_MAX_LENGTH) { fprintf(stderr, "The phrase contains too many unique letters.\n"); exit(1); } phrase.bits = make_bitfield(internal, alphabet); free(internal); if (contains) { contain.utf8_form = contains; internal = utf8tointernal(contains); contain.length = u_strlen(internal); contain.bits = make_bitfield(internal, alphabet); if ((contain.bits == NULL) || !bf_contains(phrase.bits, contain.bits)) { printf("Phrase '%s' does not contain '%s'\n", phrase.utf8_form, contain.utf8_form); exit(1); } if (include_contains) stack = push_wordstack(stack, &contain); temp_bf = bf_subtract(phrase.bits, contain.bits); free_bitfield(phrase.bits); phrase.bits = temp_bf; maxlen -= contain.length; if (just_test) { if (maxlen == 0) { printf("%s can be made from %s\n", contain.utf8_form, phrase.utf8_form); exit(0); } else { printf("%s can not be made from %s\n", contain.utf8_form, phrase.utf8_form); exit(1); } } } if (dictionary == NULL) dictionary = safe_strdup(DEFAULT_DICT); load_words(&words, alphabet, phrase.bits, maxlen, minlen, dictionary); free(alphabet); if (just_words) { for (w = words; w != NULL; w = w->next) { /* printf(" %3d %s\n", w->word->length, w->word->utf8_form); */ puts(w->word->utf8_form); } } else if (just_anagram_words) { find_anagram_words(words, stack, phrase.bits, maxwords, maxlen, &maxtotal); } else { find_anagrams(words, stack, phrase.bits, maxwords, maxlen, &maxtotal); } return 0; }
main() { FLOAT o1, dcubed, n, *offset; INDEX i, j, k, limit; MULTIPOLY sigma3; MULTIPOLY q24, tau1, tau2; MULTIPOLY joftop, jofbot, joftau; FLOAT *coef, *tsubj, *tnew, *prevc; FLOAT bctop, bcbottom; int shift, maxstore; MULTIPOLY cheb[100]; struct { ELEMENT x, y; COMPLEX start, jt; } datablock; FILE *svplot; COMPLEX tau, jtau, arc[512], q, qn; FLOAT theta, dtheta; COMPLEX temp; limit = 50; maxstore = limit+5; bf_init_ram_space(); bf_init_float(); /* create table of sigma_3(n) (sum of cube of all factors of n). */ sigma3.degree = limit; if( !bf_get_space( &sigma3)) { printf("no space for that much data\n"); exit(0); } bf_one( &o1); bf_null( &n); for( i=1; i<limit; i++) { bf_add( &o1, &n, &n); bf_multiply( &n, &n, &dcubed); bf_multiply( &n, &dcubed, &dcubed); for( j=i; j<limit; j+=i) { offset = Address( sigma3) + j; bf_add( &dcubed, offset, offset); } } /* save to disk here if necessary */ /* for( i=0; i<limit; i++) { tsubj = Address( sigma3) + i; printf("i=%d\n", i); printfloat("sigma3(i) = ", tsubj); } /* compute Ramanujan's tau function to some ridiculous degree. First step is compute coefficients of (1-x)^24 using binomial expansion. */ q24.degree = 24; if( !bf_get_space( &q24)) { printf("no room for binomial coefficients?\n"); exit(0); } coef = Address(q24); bf_int_to_float( 1, coef); bf_int_to_float( 24, &bctop); bf_int_to_float( 1, &bcbottom); for( i=1; i<=24; i++) { prevc = coef; coef = Address(q24) + i; bf_multiply( prevc, &bctop, coef); bf_divide( coef, &bcbottom, coef); bf_negate( coef); bf_round( coef, coef); /* printf("i= %d\n", i); printfloat(" coef =", coef); /* decrement top and increment bottom for next term in binomial expansion */ bf_subtract( &bctop, &o1, &bctop); bf_add( &o1, &bcbottom, &bcbottom); } /* now compute Ramanujan's tau. Keep two versions, a source and a destination. work back and forth multiplying source by binomial coefficients and sum to power shifted location. Seeking coefficients for each power of q: q*product( 1- q^n)^24 n = 1 to infinity. */ tau1.degree = maxstore; tau2.degree = maxstore; if( !bf_get_space( &tau1)) { printf("can't allocate first tau block.\n"); exit(0); } if( !bf_get_space( &tau2)) { printf("can't allocate second tau block.\n"); exit(0); } coef = Address( q24); tnew = Address( tau1); bf_multi_copy( 25, coef, tnew); k = 2; while( k<maxstore ) /* loop over products */ { /* multiply by 1, first coefficient of each product term */ prevc = Address( tau1); tnew = Address( tau2); bf_multi_copy( maxstore, prevc, tnew); /* for each coefficient in 24 term product of next term, multiply by every term in previous product and sum to shifted location. */ for( i=1; i <= 24; i++) { coef = Address( q24) + i; shift = k*i; if( shift > maxstore) continue; for( j=0; j<= k*24; j++) { if( j + shift > maxstore) continue; tsubj = Address( tau1) + j; tnew = Address( tau2) + j + shift; bf_multiply( tsubj, coef, &bctop); bf_add( &bctop, tnew, tnew); bf_round( tnew, tnew); } } k++; /* now flip things over and go back to tau 1 */ if( k>maxstore) break; prevc = Address( tau2); tnew = Address( tau1); bf_multi_copy( maxstore, prevc, tnew); for( i=1; i<=24; i++) { coef = Address(q24) + i; shift = k*i; if( shift > maxstore) continue; for( j=0; j<= k*24; j++) { if( j + shift > maxstore) continue; tsubj = Address( tau2) + j; tnew = Address( tau1) + j + shift; bf_multiply( tsubj, coef, &bctop); bf_add( &bctop, tnew, tnew); bf_round( tnew, tnew); } } k++; } /* compute top polynomial of joftau (1 + 240*sum(sigma3(n)*q^n))^3 */ bf_multi_dup( sigma3, &joftop); coef = Address( joftop); bf_int_to_float( 1, coef); bf_int_to_float( 240, &bctop); for( i=1; i<limit; i++) { coef = Address( joftop) + i; bf_multiply( &bctop, coef, coef); } bf_power_mul( joftop, joftop, &joftau); bf_power_mul( joftop, joftau, &joftop); /* finally compute joftau coefficients */ bf_power_div( joftop, tau1, &joftau); /* for( i=0; i<limit; i++) { tsubj = Address( joftau) + i; printf("i=%d\n", i); printfloat("joftau(i) = ", tsubj); } */ /* region F is defined as | Re(tau) | < 1/2 and || tau || > 1. For each point tau in F, find j(tau). save binary data to disk. Format is (x, y) and (start, end) where x and y are integer indexes, and start, end are complex points. Initial start is an arc along tau = 1. */ svplot = fopen("joftau.complex", "wb"); if( !svplot) { printf( "can't create output file\n"); exit(0); } /* create an arc along bottom of F */ bf_copy( &P2, &theta); theta.expnt += 2; // create 2PI/3 bf_int_to_float( 3, &n); bf_divide( &theta, &n, &theta); bf_copy( &theta, &dtheta); dtheta.expnt--; // create PI/3/511 bf_int_to_float( gridsize-1, &n); bf_divide( &dtheta, &n, &dtheta); for( i=0; i<gridsize; i++) { bf_cosine( &theta, &arc[i].real); bf_sine( &theta, &arc[i].imag); bf_subtract( &theta, &dtheta, &theta); } /* Move arc up F, and find j(tau) for each point */ bf_int_to_float( 10, &bctop); bf_int_to_float( gridsize, &n); bf_divide( &bctop, &n, &bctop); // upper limit of F for( i=0; i<gridsize; i++) { printf("i= %d\n", i); bf_int_to_float(i, &n); bf_multiply( &bctop, &n, &tau.imag); bf_null( &tau.real); datablock.y = i; for( j=0; j<gridsize; j++) { datablock.x = j; bf_add_cmplx( &tau, &arc[j], &datablock.start); // print_cmplx("data block start", &datablock.start); /* compute j(tau) for this point. Note power of q = index - 1 */ bf_firstj( &datablock.start, &q, &jtau); // print_cmplx("q = exp(2 i PI tau)", &q); // print_cmplx("first terms", &jtau); bf_copy_cmplx( &q, &qn); for( k=2; k<limit; k++) { offset = Address( joftau) + k; bf_multiply( offset, &qn.real, &temp.real); bf_multiply( offset, &qn.imag, &temp.imag); bf_add_cmplx( &temp, &jtau, &jtau); bf_multiply_cmplx( &q, &qn, &qn); } /* save data point to disk */ // print_cmplx("j(tau) = ", &jtau); bf_copy_cmplx( &jtau, &datablock.jt); if( fwrite( &datablock, sizeof( datablock), 1, svplot) <= 0) printf("can't write to disk\n"); } } fclose( svplot); printf("all done!\n\n"); }