home *** CD-ROM | disk | FTP | other *** search
/ Rat's Nest 1 / ratsnest1.iso / prgmming / c / fd3.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-19  |  39.8 KB  |  999 lines

  1. From:    MX%"BJ06@C53000.PETROBRAS.ANRJ.BR" 29-SEP-1994 16:43:48.79
  2.  
  3. To:    MX%"noel@erich.triumf.ca"
  4.  
  5. CC:    
  6.  
  7. Subj:    FD3 for DOS (FD3DOS.CPP) - Source code
  8.  
  9.  
  10.  
  11. Return-Path: <BJ06@C53000.PETROBRAS.ANRJ.BR>
  12.  
  13. Received: from fpsp.fapesp.br by Erich.Triumf.CA (MX V4.0-1 VAX) with SMTP;
  14.  
  15.           Thu, 29 Sep 1994 16:42:40 PST
  16.  
  17. Received: from DECNET-MAIL by fpsp.fapesp.br with PMDF#10108; Thu, 29 Sep 1994
  18.  
  19.           09:26 BSC (-0300 C)
  20.  
  21. Date: Thu, 29 Sep 1994 09:26 BSC (-0300 C)
  22.  
  23. From: "FAUSTO Arinos de Almeida Barbuto (Totxo)"
  24.  
  25.       <BJ06@C53000.PETROBRAS.ANRJ.BR>
  26.  
  27. Subject: FD3 for DOS (FD3DOS.CPP) - Source code
  28.  
  29. To: noel@erich.triumf.ca
  30.  
  31. Message-ID: <04B80DB3A0009621@fpsp.fapesp.br>
  32.  
  33. X-Envelope-to: noel@erich.triumf.ca
  34.  
  35. X-VMS-To: @NOEL
  36.  
  37. References: ANSP network   HEPnet SPAN Bitnet Internet gateway
  38.  
  39. Comments: @FPSP.FAPESP.BR - @FPSP.HEPNET - @BRFAPESP.BITNET - .BR gateway
  40.  
  41.  
  42.  
  43. /* BEGIN NOTICE
  44.  
  45.  
  46.  
  47. Copyright (c) 1992 by John Sarraille and Peter DiFalco
  48.  
  49. (john@ishi.csustan.edu)
  50.  
  51.  
  52.  
  53. Permission to use, copy, modify, and distribute this software
  54.  
  55. and its documentation for any purpose and without fee is hereby
  56.  
  57. granted, provided that the above copyright notice appear in all
  58.  
  59. copies and that both that copyright notice and this permission
  60.  
  61. notice appear in supporting documentation.
  62.  
  63.  
  64.  
  65. The algorithm used in this program was inspired by the paper
  66.  
  67. entitled "A Fast Algorithm To Determine Fractal Dimensions By
  68.  
  69. Box Counting", which was written by Liebovitch and Toth, and
  70.  
  71. which appeared in the journal "Physics Letters A", volume 141,
  72.  
  73. pp 386-390, (1989).
  74.  
  75.  
  76.  
  77. This program is not warranteed: use at your own risk.
  78.  
  79.  
  80.  
  81. -------------------------------------------------------
  82.  
  83. DOS Version created by Fausto Arinos de Almeida Barbuto
  84.  
  85. (BJ06@C53000.PETROBRAS.ANRJ.BR), September 23, 1994
  86.  
  87. (Rio de Janeiro, Federal Republic of BRAZIL)
  88.  
  89. -------------------------------------------------------
  90.  
  91.  
  92.  
  93. END NOTICE */
  94.  
  95.  
  96.  
  97. #include <stdio.h>
  98.  
  99. #include <stdlib.h>
  100.  
  101. #include "fd.h"
  102.  
  103. #include <math.h>
  104.  
  105.  
  106.  
  107. int  empty_Av(long int);
  108.  
  109. void push_Av(long int *, long int);
  110.  
  111. void pop_Av(long int *, long int*);
  112.  
  113. void create_Av(long int *);
  114.  
  115. void print_Av(long int);
  116.  
  117.  
  118.  
  119. int get_e_dim(char *);
  120.  
  121. void max_min(char*, double *, double *);
  122.  
  123. void rad_pass(int, int);
  124.  
  125. void radixsort(void);
  126.  
  127. void sweep(ulong[], double[], double[], double[]);
  128.  
  129. float fracdim();
  130.  
  131.  
  132.  
  133. int empty_Q(QHeader);
  134.  
  135. void en_Q(QHeader *, long int);
  136.  
  137. void de_Q(QHeader *, long int *);
  138.  
  139. void create_Q(QHeader *);
  140.  
  141. void transf_Q(QHeader *, QHeader *);
  142.  
  143. void print_Q(QHeader *);
  144.  
  145. void GetDims(double[], double[], double[], ulong, double*, double*, double*);
  146.  
  147. void findMark(ulong *, ulong[]);
  148.  
  149. void fitLSqrLine (long, long, double[], double[], double *, double *);
  150.  
  151.  
  152.  
  153. int empty_Av(long int avail)
  154.  
  155. //       long int avail;
  156.  
  157. {
  158.  
  159.   return (avail == -1);
  160.  
  161. }
  162.  
  163.  
  164.  
  165. /*
  166.  
  167.     Puts the info pointed to by "pointer" into the avail list.  Use
  168.  
  169.     this after dequeuing an element if you want to recycle it.  Note the
  170.  
  171.     need to access the global array "next_after", which holds all the
  172.  
  173.     pointers.
  174.  
  175. */
  176.  
  177. void push_Av(long int *p_avail, long int pointer)
  178.  
  179. //    long int *p_avail, pointer ;
  180.  
  181. {
  182.  
  183.   extern long int  *next_after;   /*  array for pointers to data. */
  184.  
  185.   next_after[pointer] = *p_avail;
  186.  
  187.   *p_avail = pointer;
  188.  
  189. }
  190.  
  191.  
  192.  
  193. /*
  194.  
  195.    Pops the info pointed to by "p_pointer" from the avail list.  Use
  196.  
  197.    this if you need an element to place on a queue.
  198.  
  199. */
  200.  
  201. void pop_Av(long int *p_avail, long int *p_pointer)
  202.  
  203. //    long int *p_avail, *p_pointer;
  204.  
  205. {
  206.  
  207.   extern long int  *next_after;   /*  array for pointers to data. */
  208.  
  209.   *p_pointer = *p_avail;
  210.  
  211.   *p_avail = next_after[*p_avail];
  212.  
  213. }
  214.  
  215.  
  216.  
  217. /*
  218.  
  219.     Creates an avail list with room for all the data, plus two more
  220.  
  221.     elements to be used as markers.
  222.  
  223. */
  224.  
  225. void create_Av(long int *p_avail)
  226.  
  227. //    long int *p_avail;
  228.  
  229. {
  230.  
  231.   extern long int  *next_after;   /*  array for pointers to data. */
  232.  
  233.   extern ulong dataLines;        /* number of data points in input file */
  234.  
  235.   unsigned long int i;
  236.  
  237.   for (i=0;i<dataLines+1;i++)
  238.  
  239.     next_after[i] = i+1;
  240.  
  241.   next_after[dataLines+1] = -1;
  242.  
  243.   *p_avail = 0;
  244.  
  245. }
  246.  
  247.  
  248.  
  249. /*
  250.  
  251.    This may prove to be useful when debugging.
  252.  
  253. */
  254.  
  255. void print_Av(long int avail)
  256.  
  257. //    long int avail;
  258.  
  259. {
  260.  
  261.   extern long int  *next_after;   /*  array for pointers to data. */
  262.  
  263.   extern int  *marker;    /*  To mark queues during radix sort */
  264.  
  265.   extern int   embed_dim;         /* How many coordinates points have. */
  266.  
  267.   extern ulong **data;    /* array of data points */
  268.  
  269.   long int temp;
  270.  
  271.   int coord;
  272.  
  273.   printf("Starting to print the avail list:\n\n");
  274.  
  275.   printf("Index\tNextField\tMarker?\t\tCoords\n\n");
  276.  
  277.   temp = avail;
  278.  
  279.   while (temp != -1)
  280.  
  281.     {
  282.  
  283.         printf("%ld\t%ld\t\t%d\t", temp, next_after[temp], marker[temp]);
  284.  
  285.     for (coord=0;coord<embed_dim;coord++)
  286.  
  287.       printf("\t%lu", data[coord][temp]);
  288.  
  289.         printf("\n");
  290.  
  291.         temp = next_after[temp];
  292.  
  293.      }
  294.  
  295.  printf("End of printing of avail list.\n");
  296.  
  297. }
  298.  
  299.  
  300.  
  301.  
  302.  
  303. int empty_Q(QHeader Q)
  304.  
  305. //    QHeader Q;     /* The queue to be tested. */
  306.  
  307. {
  308.  
  309.    return(Q.Qrear == -1);
  310.  
  311. }
  312.  
  313.  
  314.  
  315. /*
  316.  
  317.     This function enqueues the info at "pointer" into "*p_QHeader".  It does
  318.  
  319.     NOT remove the info from the avail list, NOR does it check to see if the
  320.  
  321.     queue is full.  Use with caution.  BEFORE calling this function, you
  322.  
  323.     should free the info from the avail list and be sure somehow that
  324.  
  325.     "*p_QHeader" is not full.  Note also that the function needs to access
  326.  
  327.     the array called "next_after" globally.
  328.  
  329. */
  330.  
  331.  
  332.  
  333. void en_Q(QHeader *p_QHeader, long int pointer)
  334.  
  335. //    QHeader *p_QHeader;        /* Queue to enqueue. */
  336.  
  337. //    long int pointer;    /* array index of info to go into the queue. */
  338.  
  339. {
  340.  
  341.   extern long int  *next_after;   /*  array for pointers to data. */
  342.  
  343.   next_after[pointer] = -1;
  344.  
  345.   if (empty_Q(*p_QHeader))
  346.  
  347.      p_QHeader->Qfront = pointer;
  348.  
  349.   else
  350.  
  351.      next_after[p_QHeader->Qrear] = pointer;
  352.  
  353.   p_QHeader->Qrear = pointer;
  354.  
  355. }
  356.  
  357.  
  358.  
  359. /*
  360.  
  361.     This Dequeuing function does NOT check to see if the queue is
  362.  
  363.     empty first, nor does it return the dequeued info to the avail
  364.  
  365.     list.  The caller MUST take care of these things!  Note also
  366.  
  367.     that the function needs to access the array called "next_after"
  368.  
  369.     globally.
  370.  
  371. */
  372.  
  373. void de_Q(QHeader *p_QHeader,long int *p_pointer)
  374.  
  375. //     QHeader *p_QHeader;        /* Queue to be dequeued. */
  376.  
  377. //    long int *p_pointer;    /* Pointer to the data to be returned */
  378.  
  379.                 /* to the calling function. */    
  380.  
  381. {
  382.  
  383.   extern long int  *next_after;   /*  array for pointers to data. */
  384.  
  385.   *p_pointer = p_QHeader->Qfront;
  386.  
  387.   if ((p_QHeader->Qfront) == (p_QHeader->Qrear))
  388.  
  389.      p_QHeader->Qrear = -1 ;
  390.  
  391.   p_QHeader->Qfront = next_after[p_QHeader->Qfront];
  392.  
  393. }
  394.  
  395.  
  396.  
  397. void create_Q (QHeader *p_QHeader)
  398.  
  399. //    QHeader *p_QHeader;    /* Queue to be created. */
  400.  
  401. {
  402.  
  403.   p_QHeader->Qfront = -1;
  404.  
  405.   p_QHeader->Qrear = -1;
  406.  
  407. }
  408.  
  409.  
  410.  
  411. /*
  412.  
  413.     This is a function to rapidly move an "element" from the source
  414.  
  415.     to the target queue.  It bypasses the actions of placing the info
  416.  
  417.     into the avail list, and taking it back out again.  It also
  418.  
  419.     avoids testing to see if the source queue is being emptied, and
  420.  
  421.     testing to see if the target queue is empty before the enqueue
  422.  
  423.     is done.
  424.  
  425.  
  426.  
  427.     Such a function is useful because there will be a great many of
  428.  
  429.     these operations done in the radix sort of a large set.  For
  430.  
  431.     further time-savings, one should think about putting this code
  432.  
  433.     in-line, so that the overhead of function-calling can be saved.
  434.  
  435.  
  436.  
  437.     USE with EXTREME CAUTION.  The effect of the function will be
  438.  
  439.     INCORRECT if the source has one element left, or the target is
  440.  
  441.     empty!
  442.  
  443.  
  444.  
  445.     Note the reliance on the global array "next_after".
  446.  
  447. */
  448.  
  449. void transf_Q(QHeader *p_Q1, QHeader *p_Q2)
  450.  
  451. //        QHeader *p_Q1, *p_Q2;  /* source and target queues */
  452.  
  453. {
  454.  
  455.   extern long int  *next_after;   /*  array for pointers to data. */
  456.  
  457.   long int temp;
  458.  
  459.   temp = p_Q1->Qfront;                     /* save front of Q1 */
  460.  
  461.   p_Q1->Qfront = next_after[p_Q1->Qfront];  /* fast dequeue */
  462.  
  463.   next_after[temp] = -1;               /* fast enqueue */
  464.  
  465.   next_after[p_Q2->Qrear] = temp;        /* fast enqueue */
  466.  
  467.   p_Q2->Qrear = temp;                    /* fast enqueue */
  468.  
  469. }
  470.  
  471.  
  472.  
  473. /*
  474.  
  475.     This may come in handy when de-bugging.  Note the reliance on
  476.  
  477.     the global arrays "next_after" and "data".
  478.  
  479. */
  480.  
  481. void print_Q(QHeader *p_Q)
  482.  
  483. //     QHeader *p_Q;
  484.  
  485. {
  486.  
  487.   extern long int  *next_after;   /*  array for pointers to data. */
  488.  
  489.   extern int  *marker;    /*  To mark queues during radix sort */
  490.  
  491.   extern int   embed_dim;         /* How many coordinates points have. */
  492.  
  493.   extern ulong **data;    /* array of data points */  
  494.  
  495.   long int temp;
  496.  
  497.   int coord;
  498.  
  499.   printf("Starting to print the queue:\n\n");
  500.  
  501.   printf("Index\tNextField\tMarker?\t\tCoords\n\n");
  502.  
  503.   temp = p_Q->Qfront;
  504.  
  505.   while (temp != -1)
  506.  
  507.     {
  508.  
  509.         printf("%ld\t%ld\t\t%d\t", temp, next_after[temp], marker[temp]);
  510.  
  511.     for (coord=0;coord<embed_dim;coord++)
  512.  
  513.       printf("\t%lu", data[coord][temp]);
  514.  
  515.         printf("\n");
  516.  
  517.     temp = next_after[temp];
  518.  
  519.      }
  520.  
  521.  printf("End of printing of queue.\n");
  522.  
  523. }
  524.  
  525.  
  526.  
  527. /* BEGIN NOTICE
  528.  
  529.  
  530.  
  531. Copyright (c) 1992 by John Sarraille and Peter DiFalco
  532.  
  533. (john@ishi.csustan.edu)
  534.  
  535.  
  536.  
  537. Permission to use, copy, modify, and distribute this software
  538.  
  539. and its documentation for any purpose and without fee is hereby
  540.  
  541. granted, provided that the above copyright notice appear in all
  542.  
  543. copies and that both that copyright notice and this permission
  544.  
  545. notice appear in supporting documentation.
  546.  
  547.  
  548.  
  549. The algorithm used in this program was inspired by the paper
  550.  
  551. entitled "A Fast Algorithm To Determine Fractal Dimensions By
  552.  
  553. Box Counting", which was written by Liebovitch and Toth, and
  554.  
  555. which appeared in the journal "Physics Letters A", volume 141,
  556.  
  557. pp 386-390, (1989).
  558.  
  559.  
  560.  
  561. This program is not warranteed: use at your own risk.
  562.  
  563.  
  564.  
  565. END NOTICE */
  566.  
  567.  
  568.  
  569. /* ################################################################## */
  570.  
  571. /* ################################################################## */
  572.  
  573. int get_e_dim(char *userinputfile)
  574.  
  575. //    char *userinputfile;
  576.  
  577. {
  578.  
  579.    extern FILE  *infile;
  580.  
  581.    int c, count ;   double temp ;
  582.  
  583.    if (debugging || checking) printf("Now inside get_e_dim.\n");
  584.  
  585.    if (debugging || checking) printf("About to open input file.\n");
  586.  
  587.    if((infile = fopen(userinputfile,"r")) == NULL)  /* open input file */
  588.  
  589.      {
  590.  
  591.        printf("Cannot open input file, %s\n",userinputfile);
  592.  
  593.        exit(-1);
  594.  
  595.      }
  596.  
  597.       /* get past "dataLines", and the first number on the first line of
  598.  
  599.          actual data. */
  600.  
  601.    fscanf (infile, "%f%f", &temp, &temp);
  602.  
  603.    count = 1 ;        /* One number on this line, so far. */
  604.  
  605.    do      /*  Read and count the rest of the numbers on this line. */
  606.  
  607.     {
  608.  
  609.       do     c=getc(infile) ;          /* Skip over same-line white space */
  610.  
  611.       while  ( (c=='\t') || (c==' ')  ) ;
  612.  
  613.       if   ( (c != '\n') && (c != '\r') && (c !='\f') )
  614.  
  615.        {                       /* if we don't seem to be on a new line */
  616.  
  617.         count = count + 1 ;    /* then increment # of numbers on this line */
  618.  
  619.         do   c=getc(infile) ;  /* and read past that next number */
  620.  
  621.         while  ( (c != '\n') && (c != '\r') && (c !='\f')
  622.  
  623.                  && (c !='\t') && (c != ' ') );
  624.  
  625.        }
  626.  
  627.     }  while ( (c != '\n') && (c != '\r') && (c !='\f') ) ;
  628.  
  629.    fclose (infile);
  630.  
  631.    return (count);
  632.  
  633. }
  634.  
  635. /* ################################################################## */
  636.  
  637. /* ################################################################## */
  638.  
  639. void max_min(char *userinputfile, double *pmax, double *pmin)
  640.  
  641. //        char *userinputfile;
  642.  
  643. //        double *pmax, *pmin ;
  644.  
  645. {
  646.  
  647.         extern int   embed_dim;      /* How many coordinates points have. */
  648.  
  649.         FILE    *infile;        /* input file */
  650.  
  651.         double  temp;
  652.  
  653.         ulong   i, numToRead;           /* control variable */
  654.  
  655.         ulong   dataLines;      /* number of data points in input file */
  656.  
  657.         /* open input file */
  658.  
  659.         if((infile = fopen(userinputfile,"r")) == NULL)
  660.  
  661.         {
  662.  
  663.                 printf("Cannot open input file, %s\n",userinputfile);
  664.  
  665.                 exit(-1);
  666.  
  667.         }
  668.  
  669.         /* get dataLines */
  670.  
  671.         if ((fscanf(infile,"%lu",&dataLines)) == 0)
  672.  
  673.           {
  674.  
  675.              printf ("Format of input file, %s, ", userinputfile);
  676.  
  677.              printf ("is incorrect -- please check.\n");
  678.  
  679.              exit(-1);
  680.  
  681.           }
  682.  
  683.         if (debugging || checking)
  684.  
  685.       { printf ("Now control is in max_min.\n");
  686.  
  687.             printf ("Number of data lines is %lu ...\n", dataLines);
  688.  
  689.             printf ("Starting to read data.\n");
  690.  
  691.       }
  692.  
  693.           /* find maximum and minimum data values in the input file.
  694.  
  695.          These are needed so that the data can be scaled to be a set
  696.  
  697.          of non-negative integers between 0 and maxdiam, where
  698.  
  699.          maxdiam will be the largest integer value expressible as an
  700.  
  701.          element of the data type "unsigned long int". */
  702.  
  703.  
  704.  
  705.         fscanf(infile,"%lf",&temp);
  706.  
  707.         if (debugging || checking) printf ("First datum is %lf.\n", temp);
  708.  
  709.         *pmin=*pmax=temp;
  710.  
  711.         if (debugging)
  712.  
  713.       printf ("Pmin is now: %lf, Pmax is now: %lf\n", *pmin, *pmax);
  714.  
  715.         numToRead = ((ulong) (embed_dim)) * dataLines;
  716.  
  717.         if (debugging)
  718.  
  719.       printf ("Total number of coordinates to read is: %lu\n", numToRead);
  720.  
  721.         for(i=1;i<numToRead;i++)
  722.  
  723.         {
  724.  
  725.                 fscanf(infile,"%lf",&temp);
  726.  
  727.                 if (debugging) printf ("Next datum read is: %lf\n", temp);
  728.  
  729.                 if(temp > *pmax)
  730.  
  731.                         *pmax = temp;
  732.  
  733.                 else
  734.  
  735.                         if(temp < *pmin)
  736.  
  737.                                 *pmin = temp;
  738.  
  739.  if (debugging) printf ("Pmin is now: %lf, Pmax is now: %lf\n", *pmin, *pmax);
  740.  
  741.         }
  742.  
  743.         /* check to see if the maximum equals the minimum -- this is a
  744.  
  745.            degenerate case -- or it might mean that the input file is
  746.  
  747. }          faulty. */
  748.  
  749.         if(*pmax == *pmin)
  750.  
  751.         {
  752.  
  753.           printf ("The input file, %s, is confusing!\n\n", userinputfile);
  754.  
  755.           printf ("Either all the points in %s have the same ", userinputfile);
  756.  
  757.           printf ("coordinates,\n");
  758.  
  759.           printf ("(THE FRACTAL DIMENSION IS ZERO IN THIS CASE.)\n\n");
  760.  
  761.           printf ("or %s is simply of the wrong form for an\n",userinputfile);
  762.  
  763.           printf ("input file to this program -- please check.\n");
  764.  
  765.           exit(-1);
  766.  
  767.         }
  768.  
  769.         /*  close the input file */
  770.  
  771.         fclose(infile);
  772.  
  773. }
  774.  
  775. /* ################################################################## */
  776.  
  777. /* ################################################################## */
  778.  
  779. /*
  780.  
  781.    This procedure performs one pass of the radix sort.  It assumes that the
  782.  
  783.    queues each have a marker in front at the time of the call, and this is
  784.  
  785.    the condition the procedure LEAVES the queues in when it terminates.
  786.  
  787. */
  788.  
  789. void rad_pass(int coord, int bitpos)
  790.  
  791. //        int coord,   /*  The coordinate we are doing this pass on */
  792.  
  793. //            bitpos;  /*  The bit position we are doing this pass on */
  794.  
  795. {  extern int  *marker;           /*  To mark queues during radix sort */
  796.  
  797.    extern QHeader Q[2];       /* array of two queues for the radix sort */
  798.  
  799.    extern ulong **data;   /* initial array of data points */
  800.  
  801.    int queue_num;
  802.  
  803.    long int index ;
  804.  
  805.     /*  Move the markers to the rear of the queues */
  806.  
  807.  if (debugging)
  808.  
  809.     printf ("Starting pass on bit %d of coord %d.\n",bitpos,coord);
  810.  
  811.  if (debugging) printf ("Moving markers to the rear of queues.\n");
  812.  
  813.  for (queue_num=0;queue_num<2;queue_num++) {
  814.  
  815.      de_Q(&(Q[queue_num]),&index);
  816.  
  817.      en_Q(&(Q[queue_num]),index);
  818.  
  819.  }
  820.  
  821.  if (debugging) print_Q(&Q[0]);
  822.  
  823.  if (debugging) print_Q(&Q[1]);
  824.  
  825.  
  826.  
  827.     /*  Move all non-marker elements to the appropriate queue. */
  828.  
  829.  if (debugging) printf ("Starting main part of pass.\n");
  830.  
  831.  for (queue_num=0;queue_num<2;queue_num++)
  832.  
  833.    {    /* Peek first to see if Qfront is a marker -- this violates
  834.  
  835.            information hiding, and would be "cleaner" if done with a
  836.  
  837.            procedure in the queue package.  */
  838.  
  839.      while ( marker[Q[queue_num].Qfront] == 0 )
  840.  
  841.        {     /*  Peeking again! */
  842.  
  843.          if (IS_A_ONE(data[coord][Q[queue_num].Qfront],bitpos))
  844.  
  845.                /* Directly transfer from the source to target queue */
  846.  
  847.           transf_Q( &(Q[queue_num]),&(Q[1]) );
  848.  
  849.          else transf_Q( &(Q[queue_num]),&(Q[0]) ) ;
  850.  
  851.         if (debugging) printf("A queue transfer is done.  \n");
  852.  
  853.         if (debugging) print_Q(&Q[0]);
  854.  
  855.         if (debugging) print_Q(&Q[1]);
  856.  
  857.        }  }  }
  858.  
  859.  
  860.  
  861. /* ################################################################## */
  862.  
  863. /* ################################################################## */
  864.  
  865. /*
  866.  
  867. THIS SORT IS TO BE USED DIRECTLY AFTER FDDRIVER DOES THE INITIAL LOADING OF
  868.  
  869. THE DATA INTO THE QUEUES.  IT LEAVES THE DATA ESSENTIALLY SORTED, WITH ALL
  870.  
  871. THE DATA WHOSE X-COORD STARTS WITH 0 IN Q[0], IN ORDER, AND ALL THE DATA
  872.  
  873. WHOSE X-COORD STARTS WITH 1 IN Q[1], IN ORDER.  THUS THE SWEEP THAT COMES
  874.  
  875. NEXT MUST TRAVERSE Q[0], AND THEN Q    [1].
  876.  
  877. */
  878.  
  879. void radixsort()
  880.  
  881. {
  882.  
  883.   extern QHeader Q[2];       /* ARRAY OF TWO QUEUES FOR THE RADIX SORT */
  884.  
  885.   extern int   embed_dim;      /* HOW MANY COORDINATES POINTS HAVE. */
  886.  
  887.   extern long int  avail;             /*  AVAIL LIST POINTER */
  888.  
  889.   int  bitpos, coord, queue_num;
  890.  
  891.   long int index;
  892.  
  893.  
  894.  
  895.     /* FINISH UP ON THE ZERO-BIT -- LOADING DATA TOOK CARE OF FIRST PASS. */
  896.  
  897.   for (coord=embed_dim-2;coord>=0;coord--) rad_pass(coord,0);
  898.  
  899.  
  900.  
  901.       /* NOW SORT ON THE REST OF THE BITS. */
  902.  
  903.   for (bitpos=1;bitpos<numbits;bitpos++)
  904.  
  905.       for (coord=embed_dim-1;coord>=0;coord--) rad_pass(coord,bitpos);
  906.  
  907.  
  908.  
  909.       /*  LASTLY, GET THE MARKERS OUT OF THE QUEUES. */
  910.  
  911.   for (queue_num=0;queue_num<2;queue_num++)
  912.  
  913.     {
  914.  
  915.       de_Q(&(Q[queue_num]),&index);
  916.  
  917.       push_Av(&avail,index);
  918.  
  919.     }}
  920.  
  921. /* ################################################################## */
  922.  
  923. /* ################################################################## */
  924.  
  925. /*
  926.  
  927. THIS PROCEDURE TRAVERSES THE SORTED DATA POINT LIST, AND EXTRACTS THE
  928.  
  929. INFORMATION NEEDED TO COMPUTE THE CAPACITY, INFORMATION, AND CORRELATION
  930.  
  931. DIMENSIONS OF THE DATA.  DATA IS CORRECTED ON THE FLY DURING THE TRAVERSAL,
  932.  
  933. AND THEN "MASSAGED".  AFTER "SWEEP" RUNS, WE NEED ONLY FIT A SLOPE TO THE
  934.  
  935. DATA TO OBTAIN THE FRACTAL DIMENSIONS.
  936.  
  937. */
  938.  
  939. void sweep(ulong boxCountS[], double negLogBoxCountS[], double logSumSqrFreqS[],
  940.  
  941.        double informationS[])
  942.  
  943.  
  944.  
  945. //   ulong   boxCountS[numbits+1];  /* COUNT BOXES OF EACH SIZE */
  946.  
  947.  
  948.  
  949. //   double
  950.  
  951.            /* FOR EACH BOX SIZE #s, negLogBoxCountS[s] WILL EVENTUALLY BE
  952.  
  953.           SET TO THE NEGATIVE OF THE LOG (BASE TWO) OF THE NUMBER OF
  954.  
  955.           BOXES OF SIZE #s THAT ARE OCCUPIED BY ONE OR MORE DATA
  956.  
  957.           POINTS.
  958.  
  959.         */
  960.  
  961.  
  962.  
  963. //       negLogBoxCountS[numbits+1],
  964.  
  965.  
  966.  
  967.            /* FOR EACH BOX SIZE #s, logSumSqrFreqS[s] WILL EVENTUALLY BE
  968.  
  969.           SET TO THE LOG (BASE TWO) OF THE PROBABILITY THAT TWO
  970.  
  971.           RANDOMLY CHOSEN DATA POINTS ARE IN THE SAME BOX OF SIZE
  972.  
  973.           #s.
  974.  
  975.            */
  976.  
  977.  
  978.  
  979. //       logSumSqrFreqS[numbits+1],
  980.  
  981.  
  982.  
  983.           /* FOR EACH BOX SIZE #s, informationS[s] WILL EVENTUALLY BE
  984.  
  985.          SET TO THE INFORMATION (BASE TWO) IN THE DISTRIBUTION OF
  986.  
  987.          DATA POINTS IN THE BOXES OF SIZE #s.
  988.  
  989.           */
  990.  
  991. //       informationS[numbits+1] ;
  992.  
  993.  
  994.  
  995. { extern int  embed_dim;         /* HOW MANY COORDINATES POINTS HAVE. */
  996.  
  997.   extern ulong **data,           /* INITIAL ARRAY OF DATA POINTS */
  998.  
  999.            dataLines ;
  1000.  
  1001.   extern QHeader Q[2];           /* ARRAY OF TWO QUEUES FOR THE RADIX SORT */
  1002.  
  1003.   extern ulong  *diff_test;      /* XOR'S OF PAIRS OF COORDINATES */
  1004.  
  1005.   extern long int  *next_after;  /*  ARRAY FOR POINTERS TO DATA. */
  1006.  
  1007.  
  1008.  
  1009.   int       bitpos, countpos, coord, queue_num, found;
  1010.  
  1011.   ulong     pointCount[numbits+1] ;
  1012.  
  1013.   long int  current, previous;
  1014.  
  1015.   double    sumSqrFreq[numbits+1], freq, log2=log(2.0) ;
  1016.  
  1017.  
  1018.  
  1019.     /* GET A POINTER TO THE FIRST DATA VALUE */
  1020.  
  1021.   if    (Q[0].Qfront != -1) previous = Q[0].Qfront;
  1022.  
  1023.   else  previous = Q[1].Qfront;
  1024.  
  1025.  
  1026.  
  1027.      /* INIT boxCountS, pointCountS, sumSqrFreq, AND informationS.*/
  1028.  
  1029.   for(countpos=0;countpos<=numbits;countpos++) {
  1030.  
  1031.        boxCountS[countpos]=1;
  1032.  
  1033.        sumSqrFreq[countpos]=0.0;
  1034.  
  1035.        pointCount[countpos]=1;
  1036.  
  1037.        informationS[countpos]=0.0;
  1038.  
  1039.   }
  1040.  
  1041.  
  1042.  
  1043.   for (queue_num=0;queue_num<2;queue_num++)
  1044.  
  1045.   { current = Q[queue_num].Qfront;
  1046.  
  1047.     while (current != -1)
  1048.  
  1049.     { found = 0 ;
  1050.  
  1051.         /* START BY LOOKING AT THE BIGGEST BOX SIZE */
  1052.  
  1053.       bitpos=numbits-1;
  1054.  
  1055.       for (coord=embed_dim-1;coord>=0;coord--)
  1056.  
  1057.         diff_test[coord] = data[coord][previous]^ data[coord][current];
  1058.  
  1059.       do {coord = embed_dim - 1;
  1060.  
  1061.           do {/* IF THE CURRENT POINT AND PREVIOUS POINTS ARE IN DIFFERENT
  1062.  
  1063.              BOXES OF THIS SIZE, */
  1064.  
  1065.            if ( IS_A_ONE(diff_test[coord],bitpos) )
  1066.  
  1067.                {/* THEN THE CURRENT POINT IS IN NEW BOXES OF ALL SMALLER
  1068.  
  1069.            SIZES TOO, AND STILL IN THE SAME BOXES OF LARGER SIZES,
  1070.  
  1071.            SO ... */
  1072.  
  1073.             for (countpos=bitpos;countpos>=0;countpos--)
  1074.  
  1075.           {/* CALCULATE FREQUENCY OF POINTS IN THE BOX, ASSUMING FOR
  1076.  
  1077.               NOW THAT THE NUMBER OF DATA LINES IN THE INPUT FILE IS
  1078.  
  1079.               THE NUMBER OF DISTINCT POINTS IN THE DATA SET.  WE
  1080.  
  1081.               ADJUST THIS AT THE END OF THIS FUNCTION. */
  1082.  
  1083.                    if (debugging)
  1084.  
  1085.             printf("pointCount[%d] is %d...\n", countpos, pointCount[countpos]);
  1086.  
  1087.            freq = pointCount[countpos]/(double)dataLines ;
  1088.  
  1089.              /* WE WILL ENCOUNTER NO MORE OF THE POINTS IN THE BOX
  1090.  
  1091.             WE JUST LEFT (THE SPECIAL ORDERING OF THE SORT WE
  1092.  
  1093.             USED ABOVE GUARANTEES THIS!), SO WE COMPUTE WHAT
  1094.  
  1095.             THIS BOX CONTRIBUTES TO THE RUNNING SUMS. */
  1096.  
  1097.                    sumSqrFreq[countpos] += (freq * freq) ;
  1098.  
  1099.                    informationS[countpos] += ( freq*log(freq)/log2 ) ;
  1100.  
  1101.               /* WE HAVE GOTTEN INTO A NEW BOX AT THIS LEVEL, SO WE
  1102.  
  1103.             REFLECT THE NEW BOX IN THE COUNT */
  1104.  
  1105.                    boxCountS[countpos]++ ;
  1106.  
  1107.                      /* SINCE WE HAVE A NEW BOX AT THIS LEVEL, THERE IS ONLY
  1108.  
  1109.                 ONE KNOWN POINT IN IT SO FAR -- THE CURRENT POINT */
  1110.  
  1111.            pointCount[countpos]=1;
  1112.  
  1113.                   }
  1114.  
  1115.                 for (countpos=bitpos+1;countpos<=numbits;countpos++)
  1116.  
  1117.             /* THE CURRENT POINT IS IN THE BOXES AT THESE LEVELS, SO
  1118.  
  1119.                JUST INCREMENT THE POINT COUNTER.  */
  1120.  
  1121.                   pointCount[countpos]++ ;
  1122.  
  1123.                 found = 1;
  1124.  
  1125.                }
  1126.  
  1127.                else coord-- ;
  1128.  
  1129.              }
  1130.  
  1131.           while ( (found == 0) && (coord > -1) );
  1132.  
  1133.           bitpos-- ;
  1134.  
  1135.          }
  1136.  
  1137.       while ( (found == 0) && (bitpos > -1) );
  1138.  
  1139.       previous = current; current = next_after[current];
  1140.  
  1141.     } }
  1142.  
  1143.     
  1144.  
  1145.     /* NOW ADD IN THE CONTRIBUTION DUE TO THE COUNTS REMAINING AFTER THE
  1146.  
  1147.        LAST POINT HAS BEEN FOUND, RENORMALIZE WITH BOXCOUNT[0], AND MASSAGE
  1148.  
  1149.        THE RAW DATA FROM THE TRAVERSAL SO THAT IS IS READY FOR THE LEAST
  1150.  
  1151.        SQUARES FITTING. */
  1152.  
  1153.        
  1154.  
  1155.   for (countpos=numbits;countpos>=0;countpos--)
  1156.  
  1157.   {
  1158.  
  1159.     negLogBoxCountS[countpos] = -log((double)boxCountS[countpos])/log(2.0);
  1160.  
  1161.  
  1162.  
  1163.     if (debugging)
  1164.  
  1165.       printf("pointCount[%d] is %d...\n", countpos, pointCount[countpos]);
  1166.  
  1167.     freq = pointCount[countpos]/(double)dataLines ;
  1168.  
  1169.  
  1170.  
  1171.     sumSqrFreq[countpos] += (freq * freq) ;
  1172.  
  1173.     sumSqrFreq[countpos] *= (dataLines/(double) boxCountS[0]) ;
  1174.  
  1175.     sumSqrFreq[countpos] *= (dataLines/(double) boxCountS[0]) ;
  1176.  
  1177.  
  1178.  
  1179.        /* sumSqrFreq[countpos] NOW CONTAINS THE SUM OF THE SQUARES OF THE
  1180.  
  1181.       FREQUENCIES OF POINTS IN ALL OCCUPIED BOXES OF THE SIZE
  1182.  
  1183.       CORRESPONDING TO countpos. */
  1184.  
  1185.       
  1186.  
  1187.     logSumSqrFreqS[countpos] = log(sumSqrFreq[countpos])/log(2.0) ;
  1188.  
  1189.     informationS[countpos] += ( freq*log(freq)/log(2.0) ) ;
  1190.  
  1191.     informationS[countpos] *= (dataLines/(double)boxCountS[0]) ;
  1192.  
  1193.     informationS[countpos] +=
  1194.  
  1195.        ( log((double)dataLines)-log((double)boxCountS[0]) ) / log(2.0) ;
  1196.  
  1197.  
  1198.  
  1199.        /* information[countpos] NOW CONTAINS THE INFORMATION SUM FOR ALL THE
  1200.  
  1201.           OCCUPIED BOXES OF THIS SIZE. */
  1202.  
  1203.  
  1204.  
  1205.    }
  1206.  
  1207. }
  1208.  
  1209. /* ################################################################## */
  1210.  
  1211. /* ################################################################## */
  1212.  
  1213.   /*  FIT LEAST SQUARE LINE TO DATA IN X,Y.  NO PROTECTION AGAINST OVERFLOW
  1214.  
  1215.       HERE.  IT IS ASSUMED THAT LAST > FIRST AND THAT THE X'S ARE NOT ALL THE
  1216.  
  1217.       SAME -- ELSE DIVISION BY ZERO WILL OCCUR.  */
  1218.  
  1219. void fitLSqrLine (long first, long last, double X[], double Y[],
  1220.  
  1221.           double *slopePtr, double *interceptPtr)
  1222.  
  1223. //     long   first, last ;
  1224.  
  1225. //     double X[], Y[], *slopePtr, *interceptPtr ;
  1226.  
  1227. {
  1228.  
  1229.   int    index , pointCount ;
  1230.  
  1231.   double Xsum=0, Ysum=0, XYsum=0, XXsum=0, Xmean=0, Ymean=0,
  1232.  
  1233.          Xtemp, Ytemp;
  1234.  
  1235.   for (index=first; index<=last; index++)
  1236.  
  1237.     { Xtemp = X[index]; Ytemp = Y[index];
  1238.  
  1239.       Xsum += Xtemp; Ysum += Ytemp;
  1240.  
  1241.       XYsum += (Xtemp * Ytemp); XXsum += (Xtemp * Xtemp);  }
  1242.  
  1243.   pointCount = last - first + 1 ;
  1244.  
  1245.   Xmean = Xsum/pointCount;  Ymean = Ysum/pointCount;
  1246.  
  1247.   *slopePtr = (XYsum - Xsum * Ymean)/(XXsum - Xsum * Xmean) ;
  1248.  
  1249.   *interceptPtr = Ymean - *slopePtr * Xmean ;
  1250.  
  1251. }
  1252.  
  1253. /* ################################################################## */
  1254.  
  1255. /* ################################################################## */
  1256.  
  1257. /*
  1258.  
  1259. MARK GREATEST INDEX WHERE COUNT > boxCountF[0]/cutOff_factor.
  1260.  
  1261.  
  1262.  
  1263. COUNTS AT LESSER INDEXES WILL NOT BE USED IN THE ESTIMATE OF FRACTAL
  1264.  
  1265. DIMENSION -- DISTORTION DUE TO SATURATION IS THE CONCERN.
  1266.  
  1267.  
  1268.  
  1269. NOTE THAT boxCountF[0] IS THE NUMBER OF BOXES OF SIZE 1 (THE SMALLEST SIZE)
  1270.  
  1271. THAT CONTAIN A POINT OF THE SET.  FOR ALL PRACTICAL PURPOSES, boxCountF[0]
  1272.  
  1273. WILL EQUAL THE NUMBER OF DISTINCT POINTS IN THE INPUT FILE, BECAUSE THESE
  1274.  
  1275. BOXES ARE REALLY SMALL COMPARED TO THE SIZE OF THE BIGGEST BOX (ABOUT 4
  1276.  
  1277. BILLION IF AN UNSIGNED LONG INT IS 32 BITS TO THE PLATFORM COMPILER.  THE
  1278.  
  1279. POINTS ARE SCALED BY THE PROGRAM SO THAT THE SET IS TOO "LARGE" TO FIT IN
  1280.  
  1281. THE NEXT SMALLEST BOX SIZE, SO THAT "1" IS THE SMALLEST DIFFERENCE IN
  1282.  
  1283. VALUE THAT CAN BE RESOLVED.) ONE BOX, IN EFFECT, COVERS ONLY A SINGLE POINT
  1284.  
  1285. OF THE INPUT SET BECAUSE THE PROGRAM CAN'T RESOLVE POINTS WITH A SMALLER
  1286.  
  1287. DIFFERENCE.
  1288.  
  1289.  
  1290.  
  1291. WE THINK IT WOULD BE A BAD IDEA TO USE dataLines/cutOff_factor AS THE LIMIT
  1292.  
  1293. BECAUSE IN CASES WHERE THERE WERE MANY DUPLICATE POINTS, WE WOULD SERIOUSLY
  1294.  
  1295. OVER-ESTIMATE THE NUMBER OF DISTINCT POINTS, AND THUS USE SATURATED DATA TO
  1296.  
  1297. BASE THE ESTIMATE OF FRACTAL DIMENSION UPON.  WHEN TESTING THE PROGRAM WITH
  1298.  
  1299. RANDOM DATA SAMPLED WITH REPLACEMENT, THIS COULD THROW THE RESULTS WAY OFF.
  1300.  
  1301. (THIS HAPPENED TO US, AND IT TOOK US A WHILE TO FIGURE OUT WHY.  AFTERWARDS,
  1302.  
  1303. WE STOPPED USING dataLines/cutOff_factor, AND CHANGED TO
  1304.  
  1305. boxCountF[0]/cutOff_factor.)
  1306.  
  1307. */
  1308.  
  1309. void findMark(ulong *markPtr, ulong boxCountM[])
  1310.  
  1311. //   ulong *markPtr, boxCountM[numbits+1] ;
  1312.  
  1313. {
  1314.  
  1315.     int     i,  cutOff_factor=1;
  1316.  
  1317.     
  1318.  
  1319.    /* Calculate cutOff_factor = 2^(embed_dim) + 1 */
  1320.  
  1321.  for (i=1;i<=embed_dim;i++) cutOff_factor = cutOff_factor * 2;
  1322.  
  1323.  cutOff_factor++;
  1324.  
  1325.  
  1326.  
  1327.  *markPtr=0;
  1328.  
  1329.  for(i=0;i<numbits;i++)
  1330.  
  1331.    { if(boxCountM[i] > boxCountM[0]/cutOff_factor) *markPtr=i; }
  1332.  
  1333. }
  1334.  
  1335.  
  1336.  
  1337. /* ################################################################## */
  1338.  
  1339. /* ################################################################## */
  1340.  
  1341. void GetDims(double negLogBoxCountF[], double logSumSqrFreqF[],
  1342.  
  1343.           double informationF[], ulong markF,
  1344.  
  1345.           double *capDimPtr, double *infDimPtr, double *corrDimPtr)
  1346.  
  1347. //      ulong   markF ;
  1348.  
  1349. //      double  negLogBoxCountF[numbits+1], informationF[numbits+1],
  1350.  
  1351. //              logSumSqrFreqF[numbits+1],
  1352.  
  1353. //              *capDimPtr, *infDimPtr, *corrDimPtr;
  1354.  
  1355. {
  1356.  
  1357.     int     i;
  1358.  
  1359.     double  logEps[numbits+1], slope, intercept;
  1360.  
  1361.     
  1362.  
  1363.     /* GET LOG (BASE 2) OF THE DIAMETER OF THE I'TH SIZE OF BOX. */
  1364.  
  1365.   for(i=numbits; i>=0; i--)  logEps[i] = i;
  1366.  
  1367.  
  1368.  
  1369. /* fitLSqrLine (markF, numbits-4, logEps, negLogBoxCountF, &slope,&intercept);*/
  1370.  
  1371.   fitLSqrLine (markF, numbits-2, logEps, negLogBoxCountF, &slope, &intercept);
  1372.  
  1373.   *capDimPtr = slope ;
  1374.  
  1375. /*fitLSqrLine(markF, numbits-4, logEps, informationF, &slope, &intercept);*/
  1376.  
  1377.   fitLSqrLine(markF, numbits-2, logEps, informationF, &slope, &intercept);
  1378.  
  1379.   *infDimPtr = slope ;
  1380.  
  1381. /*fitLSqrLine(markF,numbits-4, logEps, logSumSqrFreqF, &slope, &intercept);*/
  1382.  
  1383.   fitLSqrLine(markF,numbits-2, logEps, logSumSqrFreqF, &slope, &intercept);
  1384.  
  1385.   *corrDimPtr = slope ;
  1386.  
  1387. }
  1388.  
  1389. /* ################################################################## */
  1390.  
  1391. /* ################################################################## */
  1392.  
  1393.  
  1394.  
  1395. void main(int argc, char *argv[])
  1396.  
  1397. //        int     argc;
  1398.  
  1399. //        char    *argv[];
  1400.  
  1401. {
  1402.  
  1403.   extern FILE  *infile;
  1404.  
  1405.   extern int   embed_dim,         /* How many coordinates points have. */
  1406.  
  1407.                *marker;           /*  To mark queues during radix sort */
  1408.  
  1409.   extern ulong **data,    /* initial array of data points */
  1410.  
  1411.                dataLines,        /* number of data points in input file */
  1412.  
  1413.               *diff_test;        /* XOR's of pairs of coordinates */
  1414.  
  1415.   extern long int  *next_after,    /*  array for pointers to data. */
  1416.  
  1417.                    avail;             /*  avail list pointer */
  1418.  
  1419.   extern QHeader Q[2];       /* array of two queues for the radix sort */
  1420.  
  1421.  
  1422.  
  1423.  
  1424.  
  1425.   int    i,j,m;
  1426.  
  1427.   ulong  maxdiam=0,              /* 2^numbits - 1: determines the scaling. */
  1428.  
  1429.          boxCount[numbits+1],  /* Array to keep track of the box
  1430.  
  1431.                                          counts of each size.  Each index
  1432.  
  1433.                                          is the base-2 log of the
  1434.  
  1435.                                          corresponding box size. */
  1436.  
  1437.          pointCount[numbits+1],  /*  Array to keep track of how many points
  1438.  
  1439.                                      of the data set are contained in each
  1440.  
  1441.                                      box */
  1442.  
  1443.      mark;                  /* Marks smallest usable box count */
  1444.  
  1445.   double    max, min,   /* Maximum and minimum values in input file-- we
  1446.  
  1447.                            need to know these in order to scale the
  1448.  
  1449.                            input points. */
  1450.  
  1451.             buf,        /* A buffer for inputs to stay in until they are
  1452.  
  1453.                            scaled and converted to integers.  */
  1454.  
  1455.         negLogBoxCount[numbits+1],
  1456.  
  1457.             logSumSqrFreq[numbits+1],
  1458.  
  1459.             information[numbits+1],
  1460.  
  1461.         capDim, infDim, corrDim;
  1462.  
  1463.   long int  pointer;    /* holds indexes used as pointers to records */
  1464.  
  1465.  
  1466.  
  1467. printf("\n\n") ;
  1468.  
  1469. printf("******************************************************************\n");
  1470.  
  1471. printf("  FRACTAL DIMENSION REPORT -- by fd software (DiFalco/Sarraille)\n");
  1472.  
  1473. printf("******************************************************************\n");
  1474.  
  1475. printf("\n") ;
  1476.  
  1477.  
  1478.  
  1479.      /*  IDENTIFY THE INPUT FILE */
  1480.  
  1481.   printf ("\nReporting on file named: %s.\n\n", argv[1]) ;
  1482.  
  1483.  
  1484.  
  1485.      /* FIND OUT HOW MANY COORDINATES POINTS HAVE -- 1?, 2?, 3?, MORE? */
  1486.  
  1487.   printf("Getting the embedding dimension ...\n");
  1488.  
  1489.   embed_dim = get_e_dim(argv[1]);
  1490.  
  1491.   printf("Embedding Dimension taken to be: %d\n\n",embed_dim);
  1492.  
  1493.  
  1494.  
  1495. /*
  1496.  
  1497.    find max and min in input file.  This function should open the input file
  1498.  
  1499.    for reading, scan it to get the maximum and minimum data values it
  1500.  
  1501.    contains, and then seek to the beginning of the input file so that the
  1502.  
  1503.    code below can proceed to read the data sequentially from the beginning.
  1504.  
  1505.    We are having trouble getting that to work, so we have temporarily taken
  1506.  
  1507.    the expedient of closing the file in the function max_min, and opening it
  1508.  
  1509.    again below.
  1510.  
  1511. */
  1512.  
  1513.   printf("Finding max and min values in data ...");
  1514.  
  1515.   fflush(stdout);
  1516.  
  1517.   max_min (argv[1], &max, &min) ;
  1518.  
  1519.   printf ("\n\nMinimum value in input file is: %lf ...\n", min) ;
  1520.  
  1521.   printf ("Maximum value in input file is: %lf ...\n\n", max) ;
  1522.  
  1523.      /*
  1524.  
  1525.         set maxdiam=2^numbits-1 -- this is the largest value that an
  1526.  
  1527.         unsigned integer can have with the host compiler.
  1528.  
  1529.         (I checked the value obtained in this manner, and it
  1530.  
  1531.          is correct -- j.s.)
  1532.  
  1533.      */
  1534.  
  1535.   if (debugging || checking) printf("numbits is: %d\n",numbits);
  1536.  
  1537.   printf("%d different cell sizes will be used ...\n",numbits);  
  1538.  
  1539.   for (m=0;m<numbits;m++)       maxdiam = maxdiam + (1<<m);
  1540.  
  1541.   printf("Data will be shifted and re-scaled so that minimum coordinate\n");
  1542.  
  1543.   printf("value is ZERO and maximum coordinate value is: %lu ...\n\n",maxdiam);
  1544.  
  1545.  
  1546.  
  1547.      /* open input file */
  1548.  
  1549.   if((infile = fopen(argv[1],"r")) == NULL)
  1550.  
  1551.     {
  1552.  
  1553.       printf("Cannot open input file, %s\n",argv[1]);
  1554.  
  1555.       exit(-1);
  1556.  
  1557.     }
  1558.  
  1559.  
  1560.  
  1561.      /* get number of data points from input file */
  1562.  
  1563.   fscanf(infile,"%lu",&dataLines);
  1564.  
  1565.   if (debugging || checking) printf("dataLines is: %ld\n",dataLines);
  1566.  
  1567.  
  1568.  
  1569. /*
  1570.  
  1571.     In the next few statements, we allocate "parallel arrays" which are
  1572.  
  1573.     being used to implement records containing fields for as many
  1574.  
  1575.     coordinates as the embedding dimension requires, for a "next_after"
  1576.  
  1577.     pointer field to be used to link the records into lists, and for a
  1578.  
  1579.     "marker" field to indicate whether the element is being used to mark the
  1580.  
  1581.     end of a pass in the radix sort.
  1582.  
  1583. */
  1584.  
  1585. /*  allocate memory to point to a coordinate array for each coordinate --
  1586.  
  1587.     embedding dimension determines how many coordinates.
  1588.  
  1589. */
  1590.  
  1591.  
  1592.  
  1593.   printf("Allocating storage ...");
  1594.  
  1595.   fflush(stdout);
  1596.  
  1597.    
  1598.  
  1599.   if ( (data = (ulong **) malloc (embed_dim*sizeof(ulong *))) == NULL)
  1600.  
  1601.     {
  1602.  
  1603.       printf("Memory allocation failure: \"data\".\n");
  1604.  
  1605.       exit(-1);
  1606.  
  1607.     }
  1608.  
  1609.  
  1610.  
  1611. /*  Here we allocate the storage for the coordinates of data points, plus
  1612.  
  1613.     extra room for 2 queue markers needed in the radix sort.
  1614.  
  1615. */
  1616.  
  1617.   for (i=0;i<embed_dim;i++)
  1618.  
  1619.      if ((data[i] = (ulong *) malloc ((dataLines+2)*sizul)) == NULL)
  1620.  
  1621.         {
  1622.  
  1623.           printf("Memory allocation failure: \"data[%d]\").\n",i);
  1624.  
  1625.           exit(-1);
  1626.  
  1627.         }
  1628.  
  1629.  
  1630.  
  1631. /*  Here we allocate the storage for the pointers.  These are implemented as
  1632.  
  1633.     long integers.  The values of these pointers will be used as indexes into
  1634.  
  1635.     the arrays being declared here.  Note that here we also allocate room for
  1636.  
  1637.     two markers.
  1638.  
  1639. */
  1640.  
  1641.   if((next_after=(long *)malloc((dataLines+2)*sizeof(long))) == NULL)
  1642.  
  1643.      {
  1644.  
  1645.        printf("Memory allocation failure: \"next_after\" array).\n");
  1646.  
  1647.        exit(-1);
  1648.  
  1649.      }
  1650.  
  1651.  
  1652.  
  1653. /* Here we allocate storage for a tag field that tells whether a record is a
  1654.  
  1655.    marker.
  1656.  
  1657. */
  1658.  
  1659.  
  1660.  
  1661.    if ( (marker = (int *) malloc( (dataLines+2)*sizeof(int) ) ) == NULL)
  1662.  
  1663.        {
  1664.  
  1665.          printf("Memory allocation failure: \"marker\" array).\n");
  1666.  
  1667.          exit(-1);
  1668.  
  1669.        }
  1670.  
  1671.  
  1672.  
  1673. /* Here we allocate storage for a word that describes the bit changes
  1674.  
  1675.    between two different unsigned long int's.  We have one of these words
  1676.  
  1677.    for each of the embedding dimensions.  These will come in handy when the
  1678.  
  1679.    sweep is done that gets the box counts.
  1680.  
  1681. */
  1682.  
  1683.  
  1684.  
  1685.    if ( (diff_test = (ulong *) malloc ((embed_dim)*sizeof(ulong)) ) == NULL)
  1686.  
  1687.        {
  1688.  
  1689.          printf("Memory allocation failure: \"diff_test\" array).\n");
  1690.  
  1691.          exit(-1);
  1692.  
  1693.        }
  1694.  
  1695.  
  1696.  
  1697.    printf(" Done ...\n");
  1698.  
  1699.  
  1700.  
  1701. /* Initialize the queues to an empty state.  We load the data directly into
  1702.  
  1703.    these queues, and use them afterwards to do the radix sort and the sweep.
  1704.  
  1705. */
  1706.  
  1707.    printf("Initializing queues ... ");
  1708.  
  1709.    fflush(stdout);
  1710.  
  1711.  
  1712.  
  1713.    create_Q(&Q[0]); create_Q(&Q[1]);
  1714.  
  1715.    if (debugging || checking) printf ("Just created queues.\n");
  1716.  
  1717.    if (debugging) print_Q(&Q[0]);
  1718.  
  1719.    if (debugging) print_Q(&Q[1]);
  1720.  
  1721.  
  1722.  
  1723. /* Initialize the avail list to hold all the records implemented by the
  1724.  
  1725.    parallel arrays.
  1726.  
  1727. */
  1728.  
  1729.    create_Av(&avail)   ;
  1730.  
  1731.    if (debugging || checking) printf ("Just created avail.\n");
  1732.  
  1733.    if (debugging) print_Av(avail);
  1734.  
  1735.  
  1736.  
  1737. /* Place a marker in each queue. Markers will be in front of each queue
  1738.  
  1739.    after all the data has been loaded.
  1740.  
  1741. */
  1742.  
  1743.    for (i=0;i<2;i++)
  1744.  
  1745.       {
  1746.  
  1747.         pop_Av(&avail, &pointer);
  1748.  
  1749.         marker[pointer] = 1;
  1750.  
  1751.         en_Q(&(Q[i]),pointer);
  1752.  
  1753.       }
  1754.  
  1755.  
  1756.  
  1757.    printf("Done ...\n");
  1758.  
  1759.       
  1760.  
  1761. /* Place all the data points in the appropriate queue. */
  1762.  
  1763.  
  1764.  
  1765.    printf ("Loading data ... ");
  1766.  
  1767.    fflush(stdout);
  1768.  
  1769.  
  1770.  
  1771.    for(i=0;i<dataLines;i++)
  1772.  
  1773.       {
  1774.  
  1775.         pop_Av(&avail, &pointer);   /* get next record */
  1776.  
  1777.         marker[pointer] = 0;        /* it is not a marker */
  1778.  
  1779.         for (j=0; j<embed_dim;j++)
  1780.  
  1781.           { fscanf(infile,"%lf",&buf);  /* put scaled data in array */
  1782.  
  1783.             if (debugging) printf ("Just read %lf\n",buf);
  1784.  
  1785.             data[j][pointer]=(ulong)((buf-min)*(maxdiam/(max-min)));
  1786.  
  1787.           }
  1788.  
  1789.            /* Get started on the radix sort by putting the data in the
  1790.  
  1791.               queue corresponding to the least significant bit of the
  1792.  
  1793.               last coordinate. */
  1794.  
  1795.         if (IS_A_ONE(data[embed_dim-1][pointer],0))
  1796.  
  1797.         en_Q(&(Q[1]),pointer);       /* last coord ends in "1" */
  1798.  
  1799.         else en_Q(&(Q[0]),pointer);   /* last coord ends in "0" */
  1800.  
  1801.       }
  1802.  
  1803.  
  1804.  
  1805.   /* close the input file */
  1806.  
  1807.   fclose(infile);
  1808.  
  1809.   printf ("Done ...\n");
  1810.  
  1811.   if (debugging) print_Av(avail);
  1812.  
  1813.   if (debugging) print_Q(&Q[0]);
  1814.  
  1815.   if (debugging) print_Q(&Q[1]);
  1816.  
  1817.  
  1818.  
  1819.      /* radix sort queues */
  1820.  
  1821.  
  1822.  
  1823.   printf("Sorting the data ... ");
  1824.  
  1825.   fflush(stdout);
  1826.  
  1827.  
  1828.  
  1829.   radixsort();
  1830.  
  1831.  
  1832.  
  1833.   printf("Done ... \n");
  1834.  
  1835.  
  1836.  
  1837.     /* sweep data */
  1838.  
  1839.  
  1840.  
  1841.   printf("Doing sweep to get counts ... ");
  1842.  
  1843.   fflush(stdout);
  1844.  
  1845.  
  1846.  
  1847.   sweep(boxCount, negLogBoxCount, logSumSqrFreq, information);
  1848.  
  1849.  
  1850.  
  1851.   printf("Done ...\n\n");
  1852.  
  1853.  
  1854.  
  1855.   findMark(&mark, boxCount) ;
  1856.  
  1857.  
  1858.  
  1859.   /* GET RID OF THIS LINE WHEN DONE WITH TEST!!! */
  1860.  
  1861.   /* mark = 24; */
  1862.  
  1863.  
  1864.  
  1865.      /* WRITE COUNTS AND DERIVED DATA TO STANDARD OUTPUT. */
  1866.  
  1867.   printf("\n");
  1868.  
  1869.   printf("[log(epsl)]"); printf("  [CellCount]");
  1870.  
  1871.   printf("  [log(CellCount)]");  printf("  [informtn]");
  1872.  
  1873.   printf("  [-log(SumSqrFreqs)]\n");
  1874.  
  1875.  
  1876.  
  1877.   printf(" = [log(e)]"); printf("   = [N(e)] ");
  1878.  
  1879.   printf("     = [logN(e)]  ");  printf("    = [I(e)] ");
  1880.  
  1881.   printf("    = [-logSSF(e)]\n\n");
  1882.  
  1883.  
  1884.  
  1885.   for(i=0;i<=numbits;i++)
  1886.  
  1887.   {
  1888.  
  1889.    if ( (mark < numbits-2) && (i == mark) )
  1890.  
  1891.       { printf ("**************************************");
  1892.  
  1893.         printf ("**************************************\n");    }
  1894.  
  1895.     printf("%9d", i );
  1896.  
  1897.     printf("%13lu", boxCount[i]);
  1898.  
  1899.     printf("%18.5f", -negLogBoxCount[i]);
  1900.  
  1901.     printf("%12.5f", -information[i]);
  1902.  
  1903.     printf("%21.5f\n", -logSumSqrFreq[i]);
  1904.  
  1905.     if ( (mark < numbits-2) && (i == numbits-2) )
  1906.  
  1907.       { printf ("**************************************");
  1908.  
  1909.         printf ("**************************************\n");    }
  1910.  
  1911.   }
  1912.  
  1913.  
  1914.  
  1915.   printf ("\n\n\nTwo-Point Estimates of FD's:\n\n");
  1916.  
  1917.   printf("[log(e)]");      printf("  [logN(e)-logN(2e)]");
  1918.  
  1919.   printf("  [I(e)-I(2e)]");  printf("  [logSSF(2e)-logSSF(e)]\n\n");
  1920.  
  1921.     
  1922.  
  1923.   for(i=0; i<=numbits-1; i++)  
  1924.  
  1925.     {
  1926.  
  1927.       if ( (mark < numbits-2) && (i == mark) )
  1928.  
  1929.     { printf ("**************************************");
  1930.  
  1931.           printf ("**************************************\n");    }
  1932.  
  1933.       printf ("%8d",i);
  1934.  
  1935.       printf ("%20.5f",negLogBoxCount[i+1]-negLogBoxCount[i]);
  1936.  
  1937.       printf ("%14.5f",information[i+1]-information[i]);
  1938.  
  1939.       printf ("%24.5f\n",logSumSqrFreq[i+1]-logSumSqrFreq[i]);
  1940.  
  1941.       if ( (mark < numbits-2) && (i==numbits-3) )
  1942.  
  1943.         { printf ("**************************************");
  1944.  
  1945.           printf ("**************************************\n");    }
  1946.  
  1947.     }
  1948.  
  1949.     
  1950.  
  1951.   if (mark >= numbits-2)
  1952.  
  1953.   {
  1954.  
  1955.     printf("\nInsufficient Data.  More points are needed.\n") ;
  1956.  
  1957.     printf("Cannot assign a Fractal Dimension to this set.\n");
  1958.  
  1959.     printf("Examine the data above to make your own conjecture.\n");
  1960.  
  1961.     exit(-1) ;
  1962.  
  1963.   }
  1964.  
  1965.  
  1966.  
  1967.   printf ("\n\n\n%d is the smallest cell size used in ", mark);
  1968.  
  1969.   printf ("the overall dimension estimates\n");
  1970.  
  1971.   printf ("below.  The largest cell size is ");
  1972.  
  1973.   printf ("%d.  Data above corresponding to\n", numbits-2);
  1974.  
  1975.   printf ("this range is between rows of asterisks.\n\n");
  1976.  
  1977.  
  1978.  
  1979.   GetDims(negLogBoxCount, logSumSqrFreq, information, mark,
  1980.  
  1981.       &capDim, &infDim, &corrDim) ;
  1982.  
  1983.  
  1984.  
  1985.   printf("\n\nLeast-Square Estimates based on Indicated Cell Range:\n\n");
  1986.  
  1987.   printf("Fractal Dimension  (Capacity)   =  %.5f\n", capDim );
  1988.  
  1989.   printf("Fractal Dimension (Information) =  %.5f\n", infDim );
  1990.  
  1991.   printf("Fractal Dimension (Correlation) =  %.5f\n", corrDim);
  1992.  
  1993.   printf("\n\n****************************************\n");    
  1994.  
  1995. }
  1996.  
  1997.