/****************************************************************************
 * This formula file or any formula file derived from it cannot be used for
 * commercial purposes or to create hard copy output without the explicit
 * consent of the original author.
 ****************************************************************************/

fractal {

   // Establish the mapping between complex coordinates
   // and display coordinates

   mapping {
      (-6.00000000000000000000,
       -6.00000000000000000000,
       6.00000000000000000000,
       6.00000000000000000000) => (960,960)
   }

   formula {

      z = [0, 0];

      $xavg = 0;    
      $yavg = 0;    
      $mavg = 0;    

      $xmax = 0;    
      $ymax = 0;    
      $mmax = 0;    

      $xtot = 0;    
      $ytot = 0;    
      $mtot = 0;    

      // Variations: change $maxCount and/or $maxSSQ

      $maxCount = 20;
      $maxSSQ   = 40;

      while($count < $maxCount && ssq(z) < $maxSSQ)
      {
         z = current ^ z;

         // Variations: use a different function to calculate value
         // Examples:
         //    z = log(z);
         //    z = sec(z);
         //    z = csc(z);
         //    z = sec(z) ^ log(z);

         value = sec(log(z));

         $x = real(value);
         $y = imag(value);
         $m = mag(value);

         // Here we want to calculate a "running average"
         // of $x, $y and $m.  Here's how this works:
         //
         //    - suppose you have the numbers: 1, 2, 3, 4
         // 
         //    - the average is: (1 + 2 + 3 + 4) / 4 => 2.5
         //
         //    - but you can also calculate it one number at
         //      a time.
         //
         //    - suppose you've got the average of the first 3
         //      numbers: (1 + 2 + 3) / 3 => 2
         //
         //    - to add in the 4th number observe that the previous
         //      average (2) should be 3/4 of the total whereas the
         //      next number (4) should be 1/4 of the total:
         //
         //         3 * (3/4) + 4 * (1/4) => 10/4 => 2.5
         //
         //    - in general, to add the nth number to a running
         //      average:
         //
         //         average = (currentAverage * (n-1)/n) +
         //                   nextNumber / n
         //         or:
         //
         //         average = (currentAverage * (n - 1) + nextNumber) / n
         //
         //     - so for the numbers: 1, 2, 3, 4
         //
         //          the running average would be calculated thusly:
         //
         //          start: avg = 0
         //
         //          n is 1 => avg = (avg * (n - 1) + 1) / n => avg = 1
         //          n is 2 => avg = (avg * (n - 1) + 2) / n => avg = 1.5
         //          n is 3 => avg = (avg * (n - 1) + 3) / n => avg = 2
         //          n is 4 => avg = (avg * (n - 1) + 4) / n => avg = 2.5
         //
         //    - lastly, in our while loop $count begins at zero (not 1)
         //      so our calculation has to be:
         //
         //         avg = (avg * count + nextValue) / (count + 1)

         $xavg = ($x + $xavg * $count) / ($count + 1);
         $yavg = ($y + $yavg * $count) / ($count + 1);
         $mavg = ($m + $mavg * $count) / ($count + 1);

         // Ok, we've got our running averages for $x, $y and $m
         // now calculate the standard deviation which is the
         // sqrt of the square of the distance between the value
         // and its average

         $xdev = sqrt(($x - $xavg) * ($x - $xavg));
         $ydev = sqrt(($y - $yavg) * ($y - $yavg));
         $mdev = sqrt(($m - $mavg) * ($m - $mavg));

         // Keep track of the largest standard deviation we've encountered

         $xmax = max($xmax, $xdev);
         $ymax = max($ymax, $ydev);
         $mmax = max($mmax, $mdev);

         // Keep track of the sum of the standard deviations

         $xtot += $xdev;
         $ytot += $ydev;
         $mtot += $mdev;
      }

      $r = 0; $g = 0; $b = 0;

      if($count > 0)
      {
         // Here we divide the average standard deviation by the
         // largest standard deviation

         $r = ($xtot/$count) / $xmax;
         $g = ($ytot/$count) / $ymax;
         $b = ($mtot/$count) / $mmax;

         $r = get_sin_color($r, 255, 1);
         $g = get_sin_color($g, 255, 1);
         $b = get_sin_color($b, 255, 1);
      }

      set_color($r, $g, $b);
   }
}











