/*
 * MandelVroom 2.0
 *
 * (c) Copyright 1987,1989  Kevin L. Clague, San Jose, CA
 *
 * All rights reserved.
 *
 * Permission is hereby granted to distribute this program's source
 * executable, and documentation for non-comercial purposes, so long as the
 * copyright notices are not removed from the sources, executable or
 * documentation.  This program may not be distributed for a profit without
 * the express written consent of the author Kevin L. Clague.
 *
 * This program is not in the public domain.
 *
 * Fred Fish is expressly granted permission to distribute this program's
 * source and executable as part of the "Fred Fish freely redistributable
 * Amiga software library."
 *
 * Permission is expressly granted for this program and it's source to be
 * distributed as part of the Amicus Amiga software disks, and the
 * First Amiga User Group's Hot Mix disks.
 *
 * contents: this file contains the Mandelbrot and Julia picture generators
 * in IEEE floating point format.
 */

#include "mandp.h"
#include "parms.h"

extern SHORT MaxOrbit;

extern char *IEEELib;

/*
 * IEEE Floating Point Mandelbrot Generator
 */
int
MandelbrotIEEE( Pict )
  register struct Picture *Pict;
{
  register int i, j, k;
  register SHORT *CountPtr;
  register int  MathMode;

  struct PotentialParms Parms;
  struct RastPort *Rp;

  struct MathIeeeDoubBasBase *LocalMathBase;

  LocalMathBase = (struct MathIeeeDoubBasBase *) OpenLibrary( IEEELib, 0L );

  if (LocalMathBase == NULL)
    return;

  MathMode = Pict->MathMode;

  if (Pict->Flags & NO_RAM_GENERATE)
    CountPtr = Pict->Counts;
  else
    CountPtr = Pict->Counts + (Pict->CurLine*Pict->CountX);

  Parms.ScreenReal = Pict->Real;
  Parms.ScreenImag = Pict->Imag;

  /* start in the upper left hand corner */

  Parms.C_Imag = Pict->ImagLow;
  Parms.C_Imag += Pict->CurLine*Pict->ImagGap;

  Parms.MaxIteration = Pict->MaxIteration;

  /*
   * for each pixel, calculate mandelbrot
   */
  for (i = Pict->CurLine; i < Pict->CountY; i++) {

    Parms.C_Real = Pict->RealLow;

    if ( Pict->Flags & NO_RAM_GENERATE )
      CountPtr = Pict->Counts;

    for (j = 0; j < Pict->CountX; j++) {

      if (*CountPtr == 0) {
        if (MathMode == 4) {
          k = Height_68881( &Parms );
        } else {
          k = IEEE_Height( &Parms );
        }

        *CountPtr = k;
      }
      CountPtr++;

      Parms.C_Real += Pict->RealGap;

      ChildPause( Pict );
    }
    Parms.C_Imag += Pict->ImagGap;

    CheckEOL( Pict );
  }
  CloseLibrary( LocalMathBase );
} /* MandelbrotIEEE */

/*
 * IEEE Floating Point Juliaelbrot Generator
 */
JuliaIEEE( Pict )
  register struct Picture *Pict;
{
  register int i, j, k;
  register SHORT *CountPtr;

  struct PotentialParms Parms;

  struct MathIeeeDoubBasBase *LocalMathBase;

  LocalMathBase = (struct MathIeeeDoubBasBase *) OpenLibrary( IEEELib, 0L );

  if (Pict->Flags & NO_RAM_GENERATE)
    CountPtr = Pict->Counts;
  else
    CountPtr = Pict->Counts + (Pict->CurLine*Pict->CountX);

  Parms.C_Real = Pict->Real;
  Parms.C_Imag = Pict->Imag;
  Parms.C_Imag += Pict->CurLine*Pict->ImagGap;

  /* start in the upper left hand corner */
  Parms.ScreenImag = Pict->ImagLow;

  Parms.MaxIteration = Pict->MaxIteration;

  /*
   * for each pixel, calculate mandelbrot
   */
  for (i = Pict->CurLine; i < Pict->CountY; i++) {

    Parms.ScreenReal = Pict->RealLow;

    if ( Pict->Flags & NO_RAM_GENERATE )
      CountPtr = Pict->Counts;

    for (j = 0; j < Pict->CountX; j++) {

      if (*CountPtr == 0) {
        if (Pict->MathMode == 2) {
          k = IEEE_Height( &Parms );
        } else {
          k = Height_68881( &Parms );
        }

        *CountPtr = k;
      }
      CountPtr++;

      Parms.ScreenReal += Pict->RealGap;

      ChildPause( Pict );
    }
    Parms.ScreenImag += Pict->ImagGap;

    CheckEOL( Pict );
  }
  CloseLibrary( LocalMathBase );
} /* JuliaIEEE */

IEEE_Height( Parms )
  register struct PotentialParms *Parms;
{
  register double cura,  curb;
           double cura2, curb2;

  int k;

#ifdef CHECK_TASK_STACK

  CheckStack();

#endif

  cura = cura2 = Parms->ScreenReal;
  curb = curb2 = Parms->ScreenImag;

  cura2 *= cura2;
  curb2 *= curb2;

  for (k = 0; k < Parms->MaxIteration; k++ ) {

    curb *= cura;
    curb += curb + Parms->C_Imag;

    cura = cura2 - curb2 + Parms->C_Real;

    cura2 = cura * cura;
    curb2 = curb * curb;

    if (cura2+curb2 >= 16.0)
      return( k );
  }
  return( k );
}

DrawOrbitIEEE( Pict )
  register struct Picture *Pict;
{
  register struct RastPort *Rp;
  register double cura,  curb;
           double cura2, curb2;
           double realc, imagc;
  register int k;
  double x_scale, y_scale;
  int x_center, y_center;
  int width, height;
  int x, y;

  struct Window *Window;

  Window = OrbitWind;

  Rp = Window->RPort;

  width  = (Window->Width-Pict->LeftMarg-Pict->RightMarg);
  height = (Window->Height-Pict->TopMarg-Pict->BotMarg);

  x_center = width/2 + Pict->LeftMarg;
  y_center = height/2 + Pict->TopMarg;

  y_scale = x_scale = (float) height / 2.0;
/*x_scale *= AspectRatio( Pict );*/

  realc = Pict->RealLow + (float) (MouseX-Pict->LeftMarg) * Pict->RealGap;
  imagc = Pict->ImagLow + (float) (MouseY-Pict->TopMarg)  * Pict->ImagGap;

  if ( Pict->pNode.ln_Type == MANDPICT ) {

    cura = cura2 = Pict->Real;
    curb = curb2 = Pict->Imag;

  } else {

    cura = cura2 = realc;
    curb = curb2 = imagc;
    realc = Pict->Real;
    imagc = Pict->Imag;
  }

  cura2 *= cura2;
  curb2 *= curb2;

  SetAPen( Rp, 0 );
  RectFill( Rp, Pict->LeftMarg, Pict->TopMarg, width+Pict->LeftMarg-1, height+Pict->TopMarg-1);

  SetAPen( Rp, HIGHLIGHTPEN);

  for (k = 0; k < MaxOrbit; k++ ) {

    curb *= cura;
    curb += curb + imagc;

    cura  = cura2 - curb2 + realc;

    cura2 = cura * cura;
    curb2 = curb * curb;

    if (cura2+curb2 >= 16.0)
      return( k );

    /* map real and imaginary parts into window coordinates */

    x = x_center + (int)(x_scale*cura);
    y = y_center + (int)(y_scale*curb);

    if ( x >= Pict->LeftMarg && x < Window->Width-Pict->RightMarg &&
         y >= Pict->TopMarg  && y < Window->Height-Pict->BotMarg ) {

      /* plot pixel location */

      WritePixel( Rp, x, y);
    }

  }
  return( k );
}



