/* This is just a test run to factor 570771781=23801*23981*/


#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <signal.h>
#include "gmp.h"

void sieve_boot(mpz_t base,unsigned char *spbuffer,int ptop);
void sieve_block(mpz_t block_base,unsigned char *prime_buffer,int block_top);

int main(int argc,char *argv[]){
    int i,j; 
    int block_top=1000; 
    mpz_t block_base,prime_p,prime_q, n, test_value,aprime;
    unsigned char n_buffer[100];
    unsigned char prime_buffer[block_top];
    mpz_init_set_ui(block_base,(unsigned long)23000);
    mpz_init(n);
    mpz_init(test_value);
    mpz_init(aprime);
    printf("\nPlease input the number to factor\n a good example is  570771781\n");
    fflush(stdout);
    scanf("%s",n_buffer);
    mpz_set_str (n,n_buffer, 10);
   sieve_block(block_base,prime_buffer,block_top);
    for (j=0;j<block_top;j++) {
        if (prime_buffer[j]==1) {
            mpz_add_ui(aprime,block_base,(unsigned long)j);
            mpz_fdiv_r(test_value,n,aprime);
            if (mpz_cmp_ui(test_value,(unsigned long)0)==0) {
                mpz_out_str(stdout,10,n);printf(" equals  ");
                mpz_out_str(stdout,10,aprime);printf(" times ");
                mpz_fdiv_q(test_value,n,aprime);
                mpz_out_str(stdout,10,test_value);
                printf("\n");
                return 0;
            }
        }
    }

  return 1;
}


void sieve_block(mpz_t block_base,unsigned char *prime_buffer,int block_top){
    int i,j; 
    /* i and j are just used in various for loops */
    int small_prime_top=1000; 
    /*When this is embedded in RSAcracker the small_prime list and the block being sieved may be different sizes.*/

    mpz_t aprime,isprime,test_value,small_prime_base;   
    /* aprime will be a known prime in the small_prime list isprime is the element in the block_list being tested*/

    unsigned char small_prime_buffer[small_prime_top];
    mpz_init (isprime);
    mpz_init (test_value);
    mpz_init (aprime);
    mpz_init_set_ui(small_prime_base,(unsigned long)2);

    for (i=0;i<block_top;i++)small_prime_buffer[i]=1;
    for (i=0;i<block_top;i++)prime_buffer[i]=1;
    sieve_boot(small_prime_base,small_prime_buffer,small_prime_top);
    for (i=0;i<small_prime_top;i++) {
        if (small_prime_buffer[i]==1) {
            mpz_add_ui(aprime,small_prime_base,(unsigned long)i);
            for (j=0;j<block_top;j++) {
   //can do better block_base+j>=small_prime^2
                if (prime_buffer[j]==1) {
                    mpz_add_ui(test_value,block_base,(unsigned long)j);
                    mpz_fdiv_r(test_value,test_value,aprime);
                    if (mpz_cmp_ui(test_value,(unsigned long)0)==0)
                        prime_buffer[j]=0;
                } //if
            } //for
        }//if
    }//for

  /*  for (i=0;i<block_top;i++)
        if ( prime_buffer[i]==1) {
            mpz_add_ui(test_value,block_base,(unsigned long)i);
            mpz_out_str(stdout,10,test_value);
            printf("\n");
        }*/
    return ;
}

void sieve_boot(mpz_t spbase,unsigned char *spbuffer, int ptop){
    int i,j;
    mpz_t isprime,test_value;
    mpz_init (isprime);
    mpz_init (test_value);

    for (i=0;i<ptop;i++)spbuffer[i]=1;
    // printf("here 3");return;
    for (i=0;i<ptop;i++) {
        if (spbuffer[i]==1) {
            mpz_add_ui(isprime,spbase,(unsigned long)i);
            for (j=i+1;j<ptop;j++) {
                if (spbuffer[j]==1) {
                    mpz_add_ui(test_value,spbase,(unsigned long)j);
                    mpz_fdiv_r(test_value,test_value,isprime);
                    if (mpz_cmp_ui(test_value,(unsigned long)0)==0)
                        spbuffer[j]=0;
                } //if
            } //for

        }//if
    }//for
    return ;
}