|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - download
Length: 5061 (0x13c5) Types: TextFile Notes: UNIX file Names: »knapsack.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code └─⟦f4b8d8c84⟧ UNIX Filesystem └─ ⟦this⟧ »cmd/knapsack/knapsack.c«
/* * Knapsack() creates a knapsack structure from the passphrase s. * The knapsack is placed in the structure pointed to by kp. * Sxrand sets a multi-precision random number generator to return values * in the range 0 to (2^exp - 1). Xrand calls that r.n.g. */ #include <stdio.h> #include "knapsack.h" static mint t1, t2; /* Temporaries for knapsack(). */ static mint g2R; /* Used to hold 2^R for wpair(). */ static mint g; /* Used by choose() and as a temporary. */ static mint m; /* modulus for the r.n.gen. */ static mint a; /* multiplier for r.n.gen. */ static mint c; /* increment for r.n.gen. */ static mint seed; /* seed for the r.n. gen. */ static mint t; /* temporary for the r.n.g. */ knapsack(kp, s) register struct knapsack *kp; char *s; { register int i; sxrand(R, s); mitom(2, &g); spow(&g, R, &g); mcopy(&g, &g2R); /* * Use choose() to pick the k.d's and k.m. */ for (i = 0; i < K; ++i) choose(&kp->d[i]); choose(&kp->m1); /* * To choose m2 we want g = 2^(8 + K + R). Right now g = 2^(K + R + 1). */ mitom(128, &t1); mult(&g, &t1, &g); choose(&kp->m2); /* * Choose w1, w1inv, w2 and w2inv. * Note that it is now ok to use g for a temporary. */ wpair(&kp->m1, &kp->w1, &kp->w1inv); wpair(&kp->m2, &kp->w2, &kp->w2inv); /* * Before we shuffle k.shufl, seed rand() from the knapsack info. */ mdiv(&kp->d[0], mmaxint, &t1, &g); srand(mtoi(&g)); shuffle(kp->shufl); return; } /* * Repeated calls to choose(m) pick m so that g - 2^R < m <= g. * g is multiplied by 2 each time. Calling choose() as is done above in * knapsack() ensures that k.d[] and k.m have the super-sequence property. */ static choose(m) register mint *m; { xrand(m); msub(&g, m, m); smult(&g, 2, &g); return; } static shuffle(buf) register int buf[K]; { register int i; register int j; register int k; for (i = 0; i < K; ++i) buf[i] = i; for (i = 0; i < K; ++i) { j = rand() % (K - i) + i; k = buf[i]; buf[i] = buf[j]; buf[j] = k; } return; } /* * Select w and winv for m. Note that it is now ok to use g as a temporary. */ static wpair(m, w, winv) register mint *m, *w, *winv; { do { xrand(w); msub(m, w, w); msub(w, &g2R, w); while (gcd(m, w, &g), mcmp(&g, mone) > 0) for (;;) { mdiv(w, &g, &t1, &t2); if (not zerop(&t2)) break; mcopy(&t1, w); } }while (mcmp(w, &g2R) < 0); /* Insures minimum size of w. */ xgcd(m, w, &t1, winv, &t2); mdiv(winv, m, &t1, winv); if (not ispos(winv)) madd(winv, m, winv); return; } /* * Multiprecision random number generator for knapsack encryption. * General ref. Knuth - Art of Computer Programming. * This is a linear congruential r.n.g. Such a generator has three parameters, * the modulus m, the additive generator c, and the multiplicative * generator a. It generates a sequence {r0, r1, r2, ...} of pseudo-random * variables as follows: r0 is set to some initial value by sxrand(). Then * r1 = (r0 * a + c) mod m, and this calculation is iterated to get * r2, r3, etc. * We have m a power of two. We choose a to be the odd power of 5 closest to * but less than m. Knuth suggests c should be close to * (3 - sqrt(3)) * m / 6 and odd. */ /* * Put a random variable into r and return. */ static xrand(r) register mint *r; { mult(&seed, &a, &seed); madd(&seed, &c, &seed); mdiv(&seed, &m, r, &seed); /* r used as temporary here */ mcopy(&seed, r); return; } /* * Initialize the random number generator. This means initializing the * mints m, a and c as well as seed. */ static sxrand(exp, s) register unsigned exp; register char *s; { short tshort; /* temporary for sdiv */ /* * Initialize m to be 2^exp. */ mitom(2, &m); /* m = 2 */ spow(&m, exp, &m); /* m = 2^exp */ /* * Initialize a to be the odd power of 5 closest to but less than m. * This power will be nearly exp * (log base 5 of 2), and * (log base 5 of 2) is about .4306765. We first make this power a * little larger than it need be. */ exp = (unsigned int) ((long)exp * 43068L / 100000L); if (exp % 2 == 0) --exp; /* make exp odd */ mitom(5, &a); /* a = 5 */ spow(&a, exp, &a); /* a = 5^exp */ while (mcmp(&m, &a) <= 0) /* a is not yet less than m */ sdiv(&a, 25, &a, &tshort); /* * Initialize c. Knuth suggests c be about (3 - sqrt(3)) * m / 6 * and odd. We go out of the way to avoid serious roundoff with the * sqrt(). Seed is used as a temporary here. */ smult(&m, 3, &c); /* c = 3*m */ mult(&c, &m, &t); /* t = 3*m^2 */ msqrt(&t, &t, &seed); /* t = sqrt(3)*m */ msub(&c, &t, &c); /* c = (3 - sqrt(3)) * m */ sdiv(&c, 6, &c, &tshort); /* almost done, now make it odd */ sdiv(&c, 2, &t, &tshort); if (tshort == 0) msub(&c, mone, &c); /* * Initialize seed. Start with seed = c, and massage it with the * characters of string s. Exp is used as a register temporary here. */ mcopy(&c, &seed); while ((exp = *s++) != '\0') { mitom(exp, &t); mult(&seed, &t, &seed); madd(&seed, &c, &seed); mdiv(&seed, &m, &t, &seed); } return; }