/* Output from p2c, the Pascal-to-C translator */
/* From input file "density.pas" */


/* Pascal program to determine the density of a quasi-     */
/* periodic sphere packing.                                */

/* AUTHOR :  Oliver Knill, 1995 Written at Caltech         */
/* See my paper                                            */
/* Expositiones Mathematicae, 14 (1996), p. 227-246, 1996  */
/* for the mathematics                                     */

/* DESCRIPTION                                             */
/* This program was used as a helper program to play       */
/* around, check other programs. It is not suited          */
/* to find new dense packings.                             */

/* USAGE                                                   */
/* After you compile the program  with a Pascal compiler   */
/* i.e. in UNIX by typing                                  */
/* cc -lm density.c                                        */
/* you can run it                                          */
/* i.e. in UNIX by typing                                  */
/* ./a.out                                                 */

/* The use of the program is explained by an example       */
/* which shows how the dialogue can go.                    */
/* The dimension is either 2,3,4, or 5                     */

/*   Give the dimension:                                   */
/*   3                                                     */
/*   Give the radius:                                      */
/*   12                                                    */
/*   Give alpha1:                                          */
/*   0.0472440944882                                       */
/*   Give alpha2:                                          */
/*   0.496062992126                                        */
/*   Give alpha3:                                          */
/*   0.616535433071                                        */
/*   Number of lattice points:                             */
/*   7122                                                  */
/*  ----------------------------------------------------   */
/*  dimension=      3    r*r=     144   radius= 12.0       */
/*  ----------------------------------------------------   */
/*  alpha= 0.0472441,0.4960630,0.616535   0.712424         */
/*  ----------------------------------------------------   */

/* This density  0.712424 can be found in table 1 in the   */
/* article Oliver Knill, Maximizing the packing density... */
/* Expositiones Mathematicae, 14 (1996), p. 227-246, 1996  */


#define pi              3.141592653589793

#define np              300000L


typedef double realarray[np];
typedef long vector2[2];
typedef long vector3[3];
typedef long vector4[4];
typedef long vector5[5];
typedef double realvector3[3];
typedef double realvector4[4];
typedef double realvector5[5];


 vector2 p2[np];
 vector3 p[np];
 vector4 p4[np];
 vector5 p5[np];
 long N;   /*Number of balls */
 double V;   /*Scaling factor for packing and covering */
 double r;   /* radius of balls */
 double a1, a2, a3, a4, a5;   /* alpha  */
 long rn;   /* sqrt(rn)=r      */
 realarray u;   /* the set R(r) alpha  */
 double d;   /* density             */
 long dimension;   /* dimension           */


 double modulo(s)
double s;
{
  return (s + 30000 - (long)(s + 30000));
}


void writearray(n, a)
long n;
double *a;
{
  long i;

  for (i = 0; i < n; i++)
    printf("%7.3f ", a[i]);
  putchar('\n');
}


 double squareroot(s)
double s;
{
  return exp(log(s) / 2);
}


 void rationalreadln(a)
double *a;
{
  long u, v;

  scanf("%ld%*[^\n]", &u);
  getchar();
  putchar('/');
  scanf("%ld%*[^\n]", &v);
  getchar();
  *a = (double)u / v;
}


 void datainput()
{
  printf("\nGive the dimension: \n");
  scanf("%ld%*[^\n]", &dimension);
  getchar();
  printf("Give the radius:  \n");
  scanf("%lg%*[^\n]", &r);
  getchar();
  if (r == 0) {
    printf("Give the radius squared: \n");
    scanf("%ld%*[^\n]", &rn);
    getchar();
    r = squareroot((double)rn);
  } else
    rn = (long)floor(r * r + 0.5);
  printf("Give alpha1:  \n");
  scanf("%lg%*[^\n]", &a1);
  getchar();
  if (a1 == 0)
    rationalreadln(&a1);
  printf("Give alpha2:  \n");
  scanf("%lg%*[^\n]", &a2);
  getchar();
  if (a2 == 0)
    rationalreadln(&a2);
  if (dimension > 2) {
    printf("Give alpha3:  \n");
    scanf("%lg%*[^\n]", &a3);
    getchar();
    if (a3 == 0)
      rationalreadln(&a3);
  }
  if (dimension > 3) {
    printf("Give alpha4:  \n");
    scanf("%lg%*[^\n]", &a4);
    getchar();
    if (a4 == 0)
      rationalreadln(&a4);
  }
  if (dimension <= 4)
    return;


  printf("Give alpha5:  \n");
  scanf("%lg%*[^\n]", &a5);
  getchar();
  if (a5 == 0)
    rationalreadln(&a5);
}


 void initialisation2d()
{
  long ll;
  vector2 vec;
  long rr;

  rr = (long)r + 1;
  ll = 1;
  vec[0] = -rr;
  vec[1] = -rr;
  while (vec[0] <= r) {
    while (vec[1] <= r) {
      if (vec[0] * vec[0] + vec[1] * vec[1] < rn &&
	  vec[0] * vec[0] + vec[1] * vec[1] > 0) {
	memcpy(p2[ll - 1], vec, sizeof(vector2));
	ll++;
      }
      vec[1]++;
    }
    vec[0]++;
    vec[1] = -rr;
  }
  N = ll - 1;
  V = r * r * pi / 4;
}


 void initialisation3d()
{
  long ll;
  vector3 vec;
  long rr;

  rr = (long)r + 1;
  ll = 1;
  vec[0] = -rr;
  vec[1] = -rr;
  vec[2] = -rr;
  while (vec[0] <= r) {
    while (vec[1] <= r) {
      while (vec[2] <= r) {
	if (vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2] < rn &&
	    vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2] > 0) {
	  memcpy(p[ll - 1], vec, sizeof(vector3));
	  ll++;
	}
	vec[2]++;
      }
      vec[1]++;
      vec[2] = -rr;
    }
    vec[0]++;
    vec[2] = -rr;
    vec[1] = -rr;
  }
  N = ll - 1;
  V = r * r * r * pi / 6;
}


 void initialisation4d()
{
  long l;
  vector4 vec;
  long rr;

  rr = (long)r;
  l = 1;
  vec[0] = -rr;
  vec[1] = -rr;
  vec[2] = -rr;
  vec[3] = -rr;
  while (vec[0] <= r) {
    while (vec[1] <= r) {
      while (vec[2] <= r) {
	while (vec[3] <= r) {
	  if (vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2] +
	      vec[3] * vec[3] < rn && vec[0] * vec[0] + vec[1] * vec[1] +
				      vec[2] * vec[2] + vec[3] * vec[3] > 0) {
	    memcpy(p4[l - 1], vec, sizeof(vector4));
	    l++;
	  }
	  vec[3]++;
	}
	vec[2]++;
	vec[3] = -rr;
      }
      vec[1]++;
      vec[3] = -rr;
      vec[2] = -rr;
    }
    vec[0]++;
    vec[3] = -rr;
    vec[2] = -rr;
    vec[1] = -rr;
  }
  N = l - 1;
  V = r * r * r * r * pi * pi / 32;
}


 void initialisation5d()
{
  long l;
  vector5 vec;
  long rr;

  rr = (long)r;
  l = 1;
  vec[0] = -rr;
  vec[1] = -rr;
  vec[2] = -rr;
  vec[3] = -rr;
  vec[4] = -rr;
  while (vec[0] <= r) {
    while (vec[1] <= r) {
      while (vec[2] <= r) {
	while (vec[3] <= r) {
	  while (vec[4] <= r) {
	    if (vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2] +
		vec[3] * vec[3] + vec[4] * vec[4] < rn &&
		vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2] +
		vec[3] * vec[3] + vec[4] * vec[4] > 0) {
	      memcpy(p5[l - 1], vec, sizeof(vector5));
	      l++;
	    }
	    vec[4]++;
	  }
	  vec[3]++;
	  vec[4] = -rr;
	}
	vec[2]++;
	vec[3] = -rr;
	vec[4] = -rr;
      }
      vec[1]++;
      vec[2] = -rr;
      vec[3] = -rr;
      vec[4] = -rr;
    }
    vec[0]++;
    vec[1] = -rr;
    vec[2] = -rr;
    vec[3] = -rr;
    vec[4] = -rr;
  }
  N = l - 1;
  V = r * r * r * r * r * pi * pi / 60;
}


 double min(n, ra)
long n;
double *ra;
{
  long g;
  double m;

  m = ra[0];
  for (g = 1; g < n; g++) {
    if (ra[g] < m)
      m = ra[g];
  }
  return m;
}


 void showresult()
{
  printf("--------------------------------------------------------------\n");
  printf("dimension= %12ld    r*r=  %12ld   radius= %5.3f\n",
	 dimension, rn, r);
  printf("---------------------------------------------------------------\n");
  if (dimension == 2)
    printf("alpha={%12.10f,%12.10f}  %12.10f\n", a1, a2, d);
  if (dimension == 3)
    printf("alpha={%12.10f,%12.10f,%12.10f}  %12.10f\n", a1, a2, a3, d);
  if (dimension == 4)
    printf("alpha={%12.10f,%12.10f,%12.10f,%12.10f}  %12.10f\n",
	   a1, a2, a3, a4, d);
  if (dimension == 5)
    printf("alpha={%12.10f,%12.10f,%12.10f,%12.10f,%12.10f}  %12.10f\n",
	   a1, a2, a3, a4, a5, d);
  printf("--------------------------------------------------------------\n");

}


 void run()
{
  long l, FORLIM;

  if (dimension == 2) {
    FORLIM = N;
    for (l = 0; l < FORLIM; l++)
      u[l] = modulo(a1 * p2[l][0] + a2 * p2[l][1]);
  }
  if (dimension == 3) {
    FORLIM = N;
    for (l = 0; l < FORLIM; l++)
      u[l] = modulo(a1 * p[l][0] + a2 * p[l][1] + a3 * p[l][2]);
  }
  if (dimension == 4) {
    FORLIM = N;
    for (l = 0; l < FORLIM; l++)
      u[l] = modulo(a1 * p4[l][0] + a2 * p4[l][1] + a3 * p4[l][2] + a4 * p4[l]
								    [3]);
  }
  if (dimension == 5) {
    FORLIM = N;
    for (l = 0; l < FORLIM; l++)
      u[l] = modulo(a1 * p5[l][0] + a2 * p5[l][1] + a3 * p5[l][2] + a4 * p5[l]
		      [3] + a5 * p5[l][4]);
  }
  d = min(N, u) * V;
}


 void initialisation()
{
  if (dimension == 2)
    initialisation2d();
  if (dimension == 3)
    initialisation3d();
  if (dimension == 4)
    initialisation4d();
  if (dimension == 5)
    initialisation5d();
  printf(" Number of lattice points:  \n");
  printf("%12ld\n", N);
}


main(argc, argv)
int argc;
char *argv[];
{  /* main program */
  datainput();
  initialisation();
  run();
  showresult();
}




/* End. */
