/*CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
C                                                                             C
C  COMPUTE MERTENS FUNCTION (local maxima using Deleglise and Rivat)	      C
C  10/16/15 (DKC) (more limited range of N values compared to test1af.c)      C
C                                                                             C
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC*/
#include <stdio.h>
#include <math.h>
#include "table2.h"
extern char *malloc();
int newmob(unsigned int a, unsigned int b, int *out, unsigned int *table);
int nuriv(unsigned int x1, unsigned int x2, unsigned int u, char *mobb, int *M);
void div64_32(unsigned int *dividend, unsigned int *quotient,
	      unsigned int divisor);
void mul64_32(unsigned int a0, unsigned int a2, unsigned int m0,
	      unsigned int *product);
void sub64(unsigned int *a, unsigned int *b);
//
unsigned int incnt=62;
unsigned int in[62*2]={
 14, 60, 
 21, 64, 
 28, 72, 
 42, 80, 
 56, 84, 
 70, 90, 
 77, 96, 
 126, 100, 
 140, 108, 
 154, 120, 
 231, 128, 
 308, 144, 
 462, 160, 
 616, 168, 
 770, 180, 
 924, 192, 
 1386, 200, 
 1540, 216, 
 1848, 224, 
 2002, 240, 
 3003, 256, 
 4004, 288, 
 6006, 320, 
 8008, 336, 
 10010, 360, 
 12012, 384, 
 18018, 400, 
 20020, 432, 
 24024, 448, 
 30030, 480, 
 40040, 504, 
 48048, 512, 
 60060, 576, 
 90090, 600, 
 102102, 640, 
 120120, 672, 
 170170, 720, 
 204204, 768, 
 306306, 800, 
 340340, 864, 
 408408, 896, 
 510510, 960, 
 680680, 1008, 
 816816, 1024, 
 1021020, 1152, 
 1531530, 1200, 
 1939938, 1280, 
 2042040, 1344, 
 3063060, 1440, 
 3879876, 1536, 
 5819814, 1600, 
 6126120, 1680, 
 6466460, 1728, 
 7759752, 1792, 
 9699690, 1920, 
 12932920, 2016, 
 15519504, 2048, 
 19399380, 2304, 
 29099070, 2400, 
 38798760, 2688, 
 58198140, 2880, 
 77597520, 3072};
//
void main() {
int t,*temp,savet;
int *M;
char *m;
unsigned int MAXN,N[2],P[3],T[2],J[2],g,h,i,j,count,u,index,ta,tb;
double sum,f1,f2;
FILE *Outfp;
Outfp = fopen("out1ag.dat","w");
MAXN=in[2*incnt-2];
f1=log(log((double)MAXN)+log(360.0));
f1=f1*f1;
f1=exp(1.0/3.0*log(f1));
f2=exp(1.0/3.0*(log((double)MAXN)+log(360.0)));
u=(unsigned int)(f1*f2);
printf("x/u=%d \n",(MAXN/u)*360);
if (((MAXN/u)*360)>390000000) {
   printf("not enough memory \n");
   goto zskip;
   }
//
temp=(int*) malloc(4004);
if (temp==NULL) {
   printf("not enough memory \n");
   return;
   }
M=(int*) malloc(1560000004);
if (M==NULL) {
   printf("not enough memory \n");
   return;
   }
m=(char*) malloc(390000001);
if (m==NULL) {
   printf("not enough memory \n");
   return;
   }
printf("computing Mobius function \n");
index=0;
ta=1;
tb=1001;
for (i=0; i<390000; i++) {
   t=newmob(ta,tb,temp,table);
   if (t!=1) {
      printf("error \n");
      goto zskip;
      }
   ta=tb;
   tb=tb+1000;
   for (j=0; j<1000; j++)
      M[j+index]=temp[j];
   index=index+1000;
   }
//
// compute Mertens function
//
printf("computing Mertens function \n");
m[0]=(char)M[0];
for (i=1; i<=390000000; i++) {
   m[i]=(char)M[i];
   M[i]=M[i-1]+M[i];
   }
mul64_32(0,MAXN,360,P);
printf("computing sum: MAXN=%#010x %#010x \n",P[1],P[2]);
//
for (g=0; g<incnt; g++) {
   mul64_32(0,in[2*g],360,P);
   N[0]=P[1];
   N[1]=P[2];
   sum=0.0;
   count=0;
   h=(unsigned int)(sqrt((double)in[2*g])*sqrt(360.0));
   for (i=1; i<=h; i++) {
      div64_32(N,J,i);
      mul64_32(J[0],J[1],i,P);
      T[0]=P[1];
      T[1]=P[2];
      sub64(N,T);
      if ((T[0]==0)&&(T[1]==0)) {
	 j=J[1];
	 if ((j>390000000)||(J[0]!=0)) {
	    t=nuriv(J[0],J[1],u,m,M);
	    printf("x=%#010x %#010x, t=%d \n",J[0],J[1],t);
	    }
	 else
	    t=M[j-1];
	 if (i==1)
	    savet=t;
	 sum=sum+(double)t*(double)t;
	 count=count+1;
	 if ((j!=i)||(J[0]!=0)) {
	    t=M[i-1];
	    sum=sum+(double)t*(double)t;
	    count=count+1;
	    }
	 }
      }
   if (count!=in[2*g+1]) {
      printf("error: count=%d %d \n",count,in[2*g+1]);
      goto zskip;
      }
   if (savet<0)
      savet=-savet;
   printf(" %#010x %#010x %d %d %d \n",N[0],N[1],(unsigned int)sum,count,savet);
   fprintf(Outfp," %#010x, %#010x, %d, %d, %d, \n",N[0],N[1],(unsigned int)sum,count,savet);
   }
zskip:
fclose(Outfp);
return;
}