%PDF- %PDF-
| Direktori : /data/down/eBOOKS/Handbook of Applied Cryptography/ |
| Current File : //data/down/eBOOKS/Handbook of Applied Cryptography/pminone.c |
/*
Author: Pate Williams (c) 1997
Multiple precision p - 1 factoring method.
See Algorithm 8.8.2 "A Course in
Computational Algebraic Number Theory"
by Henri Cohen page 439. The command line
is as follows:
pminone base exponent addend
where base, exponent, and addend are long
integers, factors base ^ exponent + addend.
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "lip.h"
#define B 1000000l
#define NUMBER_PRIMES 78498l
typedef struct Node * NodePtr;
struct Node {
long expon;
verylong value;
NodePtr next;
};
int Insert(verylong v, NodePtr *list)
{
NodePtr currentPtr, newPtr, previousPtr;
newPtr = malloc(sizeof(struct Node));
if (newPtr == 0) return 0;
newPtr->expon = 1l;
newPtr->value = 0;
zcopy(v, &newPtr->value);
previousPtr = 0;
for (currentPtr = *list; currentPtr != 0 &&
zcompare(v, currentPtr->value) > 0; currentPtr = currentPtr->next)
previousPtr = currentPtr;
if (currentPtr != 0 && zcompare(v, currentPtr->value) == 0) {
currentPtr->expon++;
zfree(&newPtr->value);
free(newPtr);
}
else if (previousPtr == 0) {
newPtr->next = *list;
*list = newPtr;
}
else {
previousPtr->next = newPtr;
newPtr->next = currentPtr;
}
return 1;
}
void Delete(NodePtr *list)
{
NodePtr currentPtr = *list, tempPtr;
while (currentPtr != 0) {
zfree(¤tPtr->value);
tempPtr = currentPtr;
currentPtr = currentPtr->next;
free(tempPtr);
}
*list = 0;
}
void zpow(long base, long exponent, verylong *zs)
{
static verylong za = 0, zt = 0;
zone(zs);
zzero(&zt);
zsadd(zt, base, &zt);
while (exponent > 0) {
zcopy(*zs, &za);
if ((exponent & 1) == 1) zmul(za, zt, zs);
exponent >>= 1;
zcopy(zt, &za);
zmul(za, za, &zt);
}
}
int MillerRabin(int C, verylong zn)
{
int i, j, k = 0;
static verylong za = 0, zb = 0, zar = 0, zn1 = 0, zr = 0;
zsadd(zn, - 1l, &zn1);
zcopy(zn1, &zr);
if (zscompare(zn, 4l) < 1) return 1;
if (zsmod(zn, 2l) == 0) return 0;
while (zsmod(zr, 2l) == 0) {
k++;
zcopy(zr, &za);
zsdiv(za, 2l, &zr);
if (zsmod(zr, 2l) == 1l) break;
}
for (j = 0; j < C; j++) {
zrandomb(zn1, &za);
if (zscompare(za, 2l) < 0) {
zzero(&zb);
zsadd(zb, 2, &za);
}
zexpmod(za, zr, zn, &zar);
if (zscompare(zar, 1l) != 0 && zcompare(zar, zn1) != 0) {
i = 0;
do {
zcopy(zar, &za);
zmul(za, za, &zar);
zcopy(zar, &za);
zmod(za, zn, &zar);
if (zcompare(zar, zn1) == 0) break;
i++;
} while (i < k);
if (i == k) return 0;
}
}
return 1;
}
int FirstStage(long k, verylong *zN, long x0, long *p,
verylong *zx, NodePtr *list)
{
long c = 0, i = - 1, j = i, l, q, q1;
static verylong zg = 0, zq1 = 0, zt = 0, zx1 = 0, zy = 0;
zzero(&zg);
zsadd(zg, x0, zx);
zcopy(*zx, &zy);
L2:
i++;
if (i >= k) {
zsadd(*zx, - 1l, &zx1);
zgcd(zx1, *zN, &zg);
if (zscompare(zg, 1l) == 0) return 0;
else {
i = j;
zcopy(zy, zx);
goto L5;
}
}
else {
q = p[i];
q1 = q;
l = B / q;
}
L3:
while (q1 <= l) q1 *= q;
zzero(&zt);
zsadd(zt, q1, &zq1);
zcopy(*zx, &zt);
zexpmod(zt, zq1, *zN, zx);
if (++c < 20) goto L2;
L4:
zsadd(*zx, - 1l, &zx1);
zgcd(zx1, *zN, &zg);
if (zscompare(zg, 1l) == 0) {
c = 0;
j = i;
zcopy(*zx, &zy);
goto L2;
}
else {
i = j;
zcopy(zy, zx);
}
L5:
i++;
q = p[i];
q1 = q;
L6:
zzero(&zt);
zsadd(zt, q , &zq1);
zcopy(*zx, &zt);
zexpmod(zt, zq1, *zN, zx);
zsadd(*zx, - 1l, &zx1);
zgcd(zx1, *zN, &zg);
if (zscompare(zg, 1l) == 0) {
q1 *= q;
if (q1 <= B) goto L6; else goto L5;
}
else {
if (zcompare(zg, *zN) < 0) {
Insert(zg, list);
zcopy(*zN, &zq1);
zdiv(zq1, zg, zN, &zx1);
return 1;
}
if (zcompare(zg, *zN) == 0) return 0;
}
return 1;
}
int main(int argc, char *argv[])
{
double time;
long addend, base, exponent, i, j, *p;
NodePtr list = 0, node;
clock_t time0 = clock();
verylong zn = 0, zx = 0;
if (argc != 4) {
printf("usage: pminone base exponent addend\n");
printf("where number to be factored is\n");
printf("base ^ exponent + addend\n");
exit(1);
}
base = atol(argv[1]), exponent = atol(argv[2]);
addend = atol(argv[3]);
zpow(base, exponent, &zn);
zsadd(zn, addend, &zn);
zwrite(zn);
printf(" is ");
if (MillerRabin(4, zn))
printf("prime\n");
else {
printf("composite\nfactors:\n");
p = (long *) malloc(NUMBER_PRIMES * sizeof(long));
for (i = 0; i < NUMBER_PRIMES; i++) p[i] = zpnext();
i = 0;
j = p[0];
do {
while (!FirstStage(NUMBER_PRIMES, &zn, j, p, &zx, &list) && i < NUMBER_PRIMES)
i++, j = p[i];
j = p[++i];
} while (!MillerRabin(4, zn) && i < NUMBER_PRIMES);
Insert(zn, &list);
for (node = list; node != 0; node = node->next) {
printf("\t");
zwrite(node->value);
if (node->expon != 1)
printf(" ^ %ld\n", node->expon);
else
printf("\n");
}
Delete(&list);
free(p);
}
zfree(&zn);
zfree(&zx);
time = (clock() - time0) / (double) CLK_TCK;
printf("total time required: %lf seconds\n", time);
return 0;
}