コード例 #1
0
void
check_consistency (void)
{
  mpf_t  x;
  unsigned long  i, a, b;

  mpf_init (x);

  for (i = 1; i < 2000; i++)
    {
      mpf_set_prec (x, i);
      a = mpf_get_prec (x);
      mpf_set_prec (x, a);
      b = mpf_get_prec (x);
      if (a != b)
        {
          printf ("mpf_get_prec / mpf_set_prec inconsistent\n");
          printf ("   set %lu gives %lu, but then set %lu gives %lu\n",
                  i, a,
                  a, b);
          abort ();
        }
    }

  mpf_clear (x);
}
コード例 #2
0
ファイル: exprfa.c プロジェクト: AlexeiSheplyakov/gmp.pkg
/* Don't want to change the precision of w, can only do an actual swap when
   w and x have the same precision.  */
static void
e_mpf_set_or_swap (mpf_ptr w, mpf_ptr x)
{
  if (mpf_get_prec (w) == mpf_get_prec (x))
    mpf_swap (w, x);
  else
    mpf_set (w, x);
}
コード例 #3
0
ファイル: input-output.c プロジェクト: akobel/MPSolve
/**
 * @brief Print a float to stdout (or whatever the output stream is
 * atm) respecting the given options, and only with the significant
 * digits.
 *
 * @param s A pointer to the current mps_context.
 * @param f The float approximation that should be printed.
 * @param rad The current inclusion radius for that approximation.
 * @param out_digit The number of output digits required.
 * @param sign The sign of the approximation.
 */
MPS_PRIVATE void
mps_outfloat (mps_context * s, mpf_t f, rdpe_t rad, long out_digit,
              mps_boolean sign)
{
  mpf_t t;
  rdpe_t r, ro;
  double d;
  long l, digit, true_digit;

  if (s->output_config->format == MPS_OUTPUT_FORMAT_FULL)
    {
      mpf_init2 (t, mpf_get_prec (f));
      mpf_set (t, f);
      mpf_out_str (s->outstr, 10, 0, t);
      mpf_clear (t);
      return;
    }

  mpf_init2 (t, s->output_config->prec);

  mpf_get_rdpe (ro, f);
  if (s->output_config->format == MPS_OUTPUT_FORMAT_GNUPLOT ||
      s->output_config->format == MPS_OUTPUT_FORMAT_GNUPLOT_FULL)
    rdpe_out_str_u (s->outstr, ro);
  else
    {
      rdpe_abs_eq (ro);
      if (rdpe_ne (ro, rdpe_zero))
        rdpe_div (r, rad, ro);
      else
        rdpe_set_d (r, 1.0e-10);
      digit = (long)(-rdpe_log10 (r) - 0.5);
      if (digit <= 0)
        {
          rdpe_get_dl (&d, &l, ro);
          fprintf (s->outstr, "0.e%ld", l);
        }
      else
        {
          true_digit = (long)(LOG10_2 * mpf_get_prec (f));
          true_digit = MIN (digit, true_digit);
          true_digit = MIN (true_digit, out_digit);
          if (sign)
            mpf_set (t, f);
          else
            mpf_abs (t, f);
          mpf_out_str (s->outstr, 10, true_digit, t);
        }
    }

  mpf_clear (t);
}
コード例 #4
0
ファイル: context.c プロジェクト: akobel/MPSolve
static void
mps_context_init (mps_context * s)
{
  mpf_t test;

  /* Set default streams */
  s->instr = stdin;
  s->outstr = stdout;
  s->logstr = stdout;

  /* Allocate space for the configurations */
  s->input_config = (mps_input_configuration*)mps_malloc (sizeof(mps_input_configuration));
  s->output_config = (mps_output_configuration*)mps_malloc (sizeof(mps_output_configuration));

  mps_set_default_values (s);

  /* Find minimum GMP supported precision */
  mpf_init2 (test, 1);
  s->minimum_gmp_precision = mpf_get_prec (test);
  mpf_clear (test);

  /* Set standard precision */
  s->output_config->prec = (int)(0.9 * DBL_DIG * LOG2_10);
  MPS_DEBUG (s, "Setting prec_out to %ld digits", s->output_config->prec);

  mps_mp_set_prec (s, DBL_DIG * LOG2_10 + 1);

  s->initialized = false;
  s->exit_required = false;
}
コード例 #5
0
void coords_set_precision(coords* c, mpfr_prec_t precision)
{
    mpf_t test;

    if (precision < DEFAULT_PRECISION)
        precision = DEFAULT_PRECISION;

    mpf_init2(test, precision);
    c->gmp_precision = mpf_get_prec(test);

    if ((unsigned long)c->gmp_precision > (unsigned long)precision)
        precision = c->gmp_precision;

    precision_change(c->xmin,   precision);
    precision_change(c->xmax,   precision);
    precision_change(c->ymin,   precision);
    precision_change(c->ymax,   precision);
    precision_change(c->cx,     precision);
    precision_change(c->cy,     precision);
    precision_change(c->width,  precision);
    precision_change(c->height, precision);
    precision_change(c->_size,  precision);

    c->precision = precision;
    c->size = (c->aspect > 1.0) ? &c->width : &c->height;

    mpf_clear(test);
}
コード例 #6
0
void extrapolate(index_t num_samples, mpf_t *samples, mpf_t ans) {
    // The Richardson extrapolation recursive formula is
    //
    // A_n+1(x) = (2^n A_n(2x) - A_n(x)) / (2^n - 1)

    mpf_t mult;  // mult = 2^n
    mpf_init_set_d(mult, 1);

    mpf_t denom;  // denom = 1 / (mult - 1)
    mp_bitcnt_t precision = mpf_get_prec(ans);
    mpf_init2(denom, precision);

    mpf_t *end = samples + num_samples;
    for (mpf_t *lim = samples; lim < end; lim++) {  // lim - samples = n
        mpf_mul_ui(mult, mult, 2);
        mpf_set(denom, mult);
        mpf_sub_ui(denom, denom, 1);
        mpf_ui_div(denom, 1, denom);
        // evaluate all extrapolations
        for (mpf_t *ptr = end; --ptr > lim; ) {
            // A_n+1(x) = (mult A_n(2x) - A_n(x)) * denom
            mpf_mul(*ptr, *ptr, mult);
            mpf_sub(*ptr, *ptr, *(ptr - 1));
            mpf_mul(*ptr, *ptr, denom);
        }
    }
    mpf_set(ans, *(end - 1));  // move to ans

    // Clean
    mpf_clear(mult);
    mpf_clear(denom);
}
コード例 #7
0
ファイル: gmp-chudnovsky.c プロジェクト: gongchengra/hacker
/* r = sqrt(x) */
void
my_sqrt_ui(mpf_t r, unsigned long x)
{
  unsigned long prec, bits, prec0;

  prec0 = mpf_get_prec(r);

  if (prec0<=DOUBLE_PREC) {
    mpf_set_d(r, sqrt(x));
    return;
  }

  bits = 0;
  for (prec=prec0; prec>DOUBLE_PREC;)
    {
      int bit = prec&1;
      prec = (prec+bit)/2;
      bits = bits*2+bit;
    }

  mpf_set_prec_raw(t1, DOUBLE_PREC);
  mpf_set_d(t1, 1/sqrt(x));

  while (prec<prec0)
    {
      prec *=2;
      if (prec<prec0)
	{
	  /* t1 = t1+t1*(1-x*t1*t1)/2; */
	  mpf_set_prec_raw(t2, prec);
	  mpf_mul(t2, t1, t1);         /* half x half -> full */
	  mpf_mul_ui(t2, t2, x);
	  mpf_ui_sub(t2, 1, t2);
	  mpf_set_prec_raw(t2, prec/2);
	  mpf_div_2exp(t2, t2, 1);
	  mpf_mul(t2, t2, t1);         /* half x half -> half */
	  mpf_set_prec_raw(t1, prec);
	  mpf_add(t1, t1, t2);
	}
      else
	{
	  break;
	}
      prec -= (bits&1);
      bits /=2;
    }
  /* t2=x*t1, t1 = t2+t1*(x-t2*t2)/2; */
  mpf_set_prec_raw(t2, prec0/2);
  mpf_mul_ui(t2, t1, x);
  mpf_mul(r, t2, t2);          /* half x half -> full */
  mpf_ui_sub(r, x, r);
  mpf_mul(t1, t1, r);          /* half x half -> half */
  mpf_div_2exp(t1, t1, 1);
  mpf_add(r, t1, t2);
}
コード例 #8
0
ファイル: my.c プロジェクト: macroxue/const-pi
// r = sqrt(x)
void my_sqrt(mpf_t r, mpf_t x)
{
    unsigned prec, bits, prec0;

    prec0 = mpf_get_prec(r);

    if (prec0 <= DOUBLE_PREC) {
        mpf_set_d(r, sqrt(mpf_get_d(x)));
        return;
    }

    bits = 0;
    for (prec = prec0; prec > DOUBLE_PREC;) {
        int bit = prec & 1;
        prec = (prec + bit) / 2;
        bits = bits * 2 + bit;
    }

    mpf_set_prec_raw(t1, DOUBLE_PREC);
    mpf_set_d(t1, 1 / sqrt(mpf_get_d(x)));

    while (prec < prec0) {
        prec *= 2;
        /*printf("prec=%d, prec0=%d\n", prec, prec0); */
        if (prec < prec0) {
            /* t1 = t1+t1*(1-x*t1*t1)/2; */
            mpf_set_prec_raw(t2, prec);
            mpf_mul(t2, t1, t1);
            mpf_set_prec_raw(x, prec/2);
            mpf_mul(t2, t2, x);
            mpf_ui_sub(t2, 1, t2);
            mpf_set_prec_raw(t2, prec/2);
            mpf_div_2exp(t2, t2, 1);
            mpf_mul(t2, t2, t1);
            mpf_set_prec_raw(t1, prec);
            mpf_add(t1, t1, t2);
        } else {
            prec = prec0;
            /* t2=x*t1, t1 = t2+t1*(x-t2*t2)/2; */
            mpf_set_prec_raw(t2, prec/2);
            mpf_set_prec_raw(x, prec/2);
            mpf_mul(t2, t1, x);
            mpf_mul(r, t2, t2);
            mpf_set_prec_raw(x, prec);
            mpf_sub(r, x, r);
            mpf_mul(t1, t1, r);
            mpf_div_2exp(t1, t1, 1);
            mpf_add(r, t1, t2);
            break;
        }
        prec -= (bits & 1);
        bits /= 2;
    }
}
コード例 #9
0
ファイル: GmpFloat.cpp プロジェクト: whitwham/libmaus2
libmaus2::math::GmpFloat libmaus2::math::operator/(
	libmaus2::math::GmpFloat const &
		#if defined(LIBMAUS2_HAVE_GMP)
		A
		#endif
		,
	libmaus2::math::GmpFloat const &
		#if defined(LIBMAUS2_HAVE_GMP)
		B
		#endif
)
{
	unsigned int const outprec =
	#if defined(LIBMAUS2_HAVE_GMP)
		std::max(mpf_get_prec(decode(A.v)),mpf_get_prec(decode(B.v)));
	#else
		0;
	#endif
	libmaus2::math::GmpFloat R(0,outprec);
	#if defined(LIBMAUS2_HAVE_GMP)
	mpf_div(decode(R.v),decode(A.v),decode(B.v));
	#endif
	return R;
}
コード例 #10
0
ファイル: t-trunc.c プロジェクト: AllardJ/Tomato
void
check_one (mpf_srcptr src, mpf_srcptr trunc, mpf_srcptr ceil, mpf_srcptr floor)
{
  mpf_t  got;

  mpf_init2 (got, mpf_get_prec (trunc));
  ASSERT_ALWAYS (PREC(got) == PREC(trunc));
  ASSERT_ALWAYS (PREC(got) == PREC(ceil));
  ASSERT_ALWAYS (PREC(got) == PREC(floor));

#define CHECK_SEP(name, fun, want)              \
  mpf_set_ui (got, 54321L); /* initial junk */  \
  fun (got, src);                               \
  MPF_CHECK_FORMAT (got);                       \
  if (mpf_cmp (got, want) != 0)                 \
    {                                           \
	printf ("%s wrong\n", name);            \
	check_print (src, got, want);           \
	abort ();                               \
    }

  CHECK_SEP ("mpf_trunc", mpf_trunc, trunc);
  CHECK_SEP ("mpf_ceil",  mpf_ceil,  ceil);
  CHECK_SEP ("mpf_floor", mpf_floor, floor);

#define CHECK_INPLACE(name, fun, want)  \
  mpf_set (got, src);                   \
  fun (got, got);                       \
  MPF_CHECK_FORMAT (got);               \
  if (mpf_cmp (got, want) != 0)         \
    {                                   \
	printf ("%s wrong\n", name);    \
	check_print (src, got, want);   \
	abort ();                       \
    }

  CHECK_INPLACE ("mpf_trunc", mpf_trunc, trunc);

  /* Can't do these unconditionally in case truncation by mpf_set strips
     some low non-zero limbs which would have rounded the result.  */
  if (ABSIZ(src) <= PREC(trunc)+1)
    {
      CHECK_INPLACE ("mpf_ceil",  mpf_ceil,  ceil);
      CHECK_INPLACE ("mpf_floor", mpf_floor, floor);
    }

  mpf_clear (got);
}
コード例 #11
0
// r = y/x   WARNING: r cannot be the same as y.
void
my_div(mpf_t r, mpf_t y, mpf_t x)
{
  unsigned long prec, bits, prec0;

  prec0 = mpf_get_prec(r);

  if (prec0<=DOUBLE_PREC) {
    mpf_set_d(r, mpf_get_d(y)/mpf_get_d(x));
    return;
  }

  bits = 0;
  for (prec=prec0; prec>DOUBLE_PREC;) {
    int bit = prec&1;
    prec = (prec+bit)/2;
    bits = bits*2+bit;
  }

  mpf_set_prec_raw(t1, DOUBLE_PREC);
  mpf_ui_div(t1, 1, x);

  while (prec<prec0) {
    prec *=2;
    if (prec<prec0) {
      /* t1 = t1+t1*(1-x*t1); */
      mpf_set_prec_raw(t2, prec);
      mpf_mul(t2, x, t1);          // full x half -> full
      mpf_ui_sub(t2, 1, t2);
      mpf_set_prec_raw(t2, prec/2);
      mpf_mul(t2, t2, t1);         // half x half -> half
      mpf_set_prec_raw(t1, prec);
      mpf_add(t1, t1, t2);
    } else {
      prec = prec0;
      /* t2=y*t1, t1 = t2+t1*(y-x*t2); */
      mpf_set_prec_raw(t2, prec/2);
      mpf_mul(t2, t1, y);          // half x half -> half
      mpf_mul(r, x, t2);           // full x half -> full
      mpf_sub(r, y, r);
      mpf_mul(t1, t1, r);          // half x half -> half
      mpf_add(r, t1, t2);
      break;
    }
    prec -= (bits&1);
    bits /=2;
  }
}
コード例 #12
0
ファイル: GmpFloat.cpp プロジェクト: whitwham/libmaus2
libmaus2::math::GmpFloat & libmaus2::math::GmpFloat::operator=(
	GmpFloat const &
	#if defined(LIBMAUS2_HAVE_GMP)
		o
	#endif
)
{
	#if defined(LIBMAUS2_HAVE_GMP)
	if ( this != &o )
	{
		mpf_set_prec(decode(v),mpf_get_prec(decode(o.v)));
		mpf_set(decode(v),decode(o.v));
	}
	#endif
	return *this;
}
コード例 #13
0
void extrapolate(index_t num_samples, index_t start_index,
        SequenceFunc f, mpf_t ans) {
    // Calculate the desired samples, then pass to the other extrapolate
    // function.
    mpf_t *samples = (mpf_t*)malloc(sizeof(mpf_t) * num_samples);
    mpf_t *lim = samples + num_samples;
    mp_bitcnt_t precision = mpf_get_prec(ans);
    for (mpf_t *ptr = samples; ptr < lim; ptr++, start_index <<= 1) {
        mpf_init2(*ptr, precision);
        f(start_index, *ptr);
    }
    extrapolate(num_samples, samples, ans);

    // Clean
    for (mpf_t *ptr = samples; ptr < lim; ptr++)
        mpf_clear(*ptr);
    free(samples);
}
コード例 #14
0
ファイル: exprf.c プロジェクト: AllardJ/Tomato
int
mpf_expr (mpf_ptr res, int base, const char *e, ...)
{
  mpf_srcptr  var[MPEXPR_VARIABLES];
  va_list     ap;
  int         ret;
  va_start (ap, e);

  TRACE (printf ("mpf_expr(): base %d, %s\n", base, e));
  ret = mpexpr_va_to_var ((void **) var, ap);
  va_end (ap);

  if (ret != MPEXPR_RESULT_OK)
    return ret;

  return mpf_expr_a (mpf_expr_standard_table, res, base,
		     mpf_get_prec (res), e, strlen(e), var);
}
コード例 #15
0
static void
mpf_normalize(mpf_t op)
{
    Py_ssize_t size, prec, toclear, temp, i;
    mp_limb_t bit1, rem, carry;

    prec = mpf_get_prec(op);
    size = mpf_size(op);
    toclear = size - ((prec / GMP_NUMB_BITS) + 1);
    if(toclear>0) {
        bit1 = (op->_mp_d[toclear-1] & ((mp_limb_t)1 << (GMP_NUMB_BITS - 1))) ? 1 : 0;
        rem = (op->_mp_d[toclear-1] & (((mp_limb_t)1 << (GMP_NUMB_BITS - 1)) - 1)) ? 1 : 0;
        carry = bit1 && ((op->_mp_d[toclear] & 1) || rem);
    } else {
        carry = 0;
    }
    if(options.debug) {
        fprintf(stderr, "prec %ld size %ld toclear %ld carry %ld\n",
               prec, size, toclear, carry);
        for(i=0; i<size; i++)
            fprintf(stderr,"[%zd]=%lx\n", i, op->_mp_d[i]);
    }
    temp = toclear;
    if(temp>0) {
        op->_mp_d[--temp] = 0;
    }
    if(carry) {
        if(options.debug) {
            fprintf(stderr, "adding carry bit\n");
        }
        carry = mpn_add_1(op->_mp_d + toclear, op->_mp_d + toclear, size-toclear, carry);
        if(carry) {
            if(options.debug) {
                fprintf(stderr, "carry bit extended\n");
            }
            op->_mp_d[size-1] = 1;
            op->_mp_exp++;
        }
    }
    if(options.debug) {
        for(i=0; i<size; i++)
            fprintf(stderr,"[%zd]=%lx\n", i, op->_mp_d[i]);
    }
}
コード例 #16
0
ファイル: pow_ui.c プロジェクト: AllardJ/Tomato
void
mpf_pow_ui (mpf_ptr r, mpf_srcptr b, unsigned long int e)
{
  mpf_t b2;

  mpf_init2 (b2, mpf_get_prec (r));
  mpf_set (b2, b);

  if ((e & 1) != 0)
    mpf_set (r, b);
  else
    mpf_set_ui (r, 1);
  while (e >>= 1)
    {
      mpf_mul (b2, b2, b2);
      if ((e & 1) != 0)
	mpf_mul (r, r, b2);
    }

  mpf_clear (b2);
}
コード例 #17
0
ファイル: pow_ui.c プロジェクト: mahdiz/mpclib
void
mpf_pow_ui (mpf_ptr r, mpf_srcptr b, unsigned long int e)
{
  mpf_t b2;
  unsigned long int e2;

  mpf_init2 (b2, mpf_get_prec (r));
  mpf_set (b2, b);
  mpf_set_ui (r, 1);

  if ((e & 1) != 0)
    mpf_set (r, b2);
  for (e2 = e >> 1; e2 != 0; e2 >>= 1)
    {
      mpf_mul (b2, b2, b2);
      if ((e2 & 1) != 0)
	mpf_mul (r, r, b2);
    }

  mpf_clear (b2);
}
コード例 #18
0
ファイル: main.c プロジェクト: MattiHameister/Mandelbrot
void keyboard(uint8_t key, int32_t x, int32_t y)
{
	FILE *file;
	int32_t base = 10;
	
	switch (key) {
		case 27: // ESC
			stopThreads();
			exit(0);
			break;
			
		case 105: // i
			maxIterations+=iterDelta;
			printf("Iterationen: %u\n",maxIterations);
			restart();
			break;
			
		case 111: // o
			maxIterations-=iterDelta;
			if (maxIterations <= 0) {
				maxIterations+=iterDelta;
			}
			printf("Iterationen: %u\n",maxIterations);
			restart();
			break;
			
		case 115: // s
			printf("Speichere Position\n");
			file = fopen("minRe.val", "w");
			mpf_out_str(file, base, 0, mandelRange.minRe);
			fclose(file);
			file = fopen("maxRe.val", "w");
			mpf_out_str(file, base, 0, mandelRange.maxRe);
			fclose(file);
			file = fopen("minIm.val", "w");
			mpf_out_str(file, base, 0, mandelRange.minIm);
			fclose(file);
			file = fopen("iter.val", "wb");
			fwrite(&maxIterations, sizeof(maxIterations), 1, file);
			fclose(file);
			file = fopen("bits.val", "wb");
			fwrite(&gmpBit, sizeof(gmpBit), 1, file);
			fclose(file);
			printf("Position gespeichert\n");
			break;
			
		case 108: // l
			loadPosition();
			restart();
			break;
			
		case 98: //b
			gmpBit+=1;
			printf("Bit: %i\n",gmpBit);
			setBits(gmpBit);
			restart();
			break;
			
		case 99: // c
			printf("aktuelle Bits: %lu\n",mpf_get_prec(mandelRange.minRe));
			break;
			
			//		case 103: // g
			//			useGMP = useGMP ? 0 : 1;
			//			printf("benutze GMP: %i\n",useGMP);
			//			break;
			
		default:
			printf("%i\n",key);
			break;
	}
}
コード例 #19
0
ファイル: floatbasic.cpp プロジェクト: AnZhg/mU
uint mpfc_getdigits(mpfc_ptr x)
{
	return (uint)(mpf_get_prec(x->Im)/3.3219280948873623478703194294894);
}
コード例 #20
0
ファイル: main.c プロジェクト: GenevaS/Parallel_MPI
int main(int argc, char** argv)
{  
  // Computation parameters
  int maxiter, maxIterStart, maxIterEnd;
  int iterStep;
  int flag;
  int comm_sz, my_rank;
  time_t t1, t2;
  double delta, maxTime;
  int i;
  int *iterations;

  // Video parameters
  unsigned long int width, height;
  int frames, curframe;
  int startframe, endframe;
  int fps, vidLen;
  float zoomx, zoomy;
  mpf_t framezoomx, framezoomy;

  // File name variables
  char *filename;
  char filenum [10];
  char *fileext = ".bmp";
  char *image = "";

  // GMP Floats
  mpf_t cr, ci;
  mpf_init(cr);
  mpf_init(ci);

  mpf_t xcent, ycent;
  mpf_init(xcent);
  mpf_init(ycent);

  mpf_t xrInit, yrInit, xrFin, yrFin;
  mpf_init(xrInit);
  mpf_init(yrInit);
  mpf_init(xrFin);
  mpf_init(yrFin);

  // Get and parse the program parameters and set GMP precision
  getParams(argv, &flag, &cr, &ci, &xcent, &ycent, &xrInit, &yrInit, &xrFin, &yrFin, &width, &height, &maxIterStart, &maxIterEnd, &filename, &fps, &vidLen, &startframe, &endframe);
  mpf_set_default_prec(mpf_get_prec(cr));

  // Calculate number of frames in the video
  frames = fps * vidLen;

  // Calculate number of iterations to add per frame
  iterStep = ceil((2*(double)maxIterEnd - 2*(double)maxIterStart) / (double)frames);

  // Calculate zoom rate based on the number of frames; since the first frame is not zoomed
  // in on, we calculate zoom with frame count (totalframes - 1)
  // x and y zoom are calculated separately to avoid stretching images
  zoomx = pow((float)mpf_get_d(xrInit) / (float)mpf_get_d(xrFin), 1.0/((float)frames - 1));
  mpf_init(framezoomx);
  mpf_set_d(framezoomx, (double)zoomx);

  zoomy = pow((float)mpf_get_d(yrInit) / (float)mpf_get_d(yrFin), 1.0/((float)frames - 1));
  mpf_init(framezoomy);
  mpf_set_d(framezoomy, (double)zoomy);

  /* Start MPI */
  MPI_Init(NULL, NULL);
  MPI_Comm_size(MPI_COMM_WORLD, &comm_sz);
  MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);

  // Debugging output
  int n = 35;
  if (my_rank == 0)
  {
    gmp_printf ("x = %+.*Ff\n", n, xcent);
    gmp_printf ("xr Init = %+.*Ff\n", n, xrInit);
    gmp_printf ("xr Fin = %+.*Ff\n\n", n, xrFin);

    gmp_printf ("y = %+.*Ff\n", n, ycent);
    gmp_printf ("yr Init = %+.*Ff\n", n, yrInit);
    gmp_printf ("yr Fin = %+.*Ff\n\n", n, yrFin);

    printf("Height = %ld\t", height);
    printf("Width = %ld\n", width);
    printf("maxiterStart = %d\t", maxIterStart);
    printf("maxiterEnd = %d\t", maxIterEnd);
    printf("iterStep = %d\n\n", iterStep);

    gmp_printf ("Zoom x (GMP) = %+.*Ff\n", n, framezoomx);
    gmp_printf ("Zoom y (GMP) = %+.*Ff\n", n, framezoomy);
    printf("frames = %d\n\n", frames);
  }

  // Divide frames among processes
  startframe = startframe - 1; // Offset frame divisions
  endframe = endframe - 1;
  frames = endframe - startframe + 1; // Total frames + 1 to include end bound

  int totalframes = frames / comm_sz;
  if (my_rank < (frames % comm_sz)) totalframes++;
  printf("Process %d processess %d frames\n", my_rank, totalframes);

  // Start timer
  time(&t1);

  /* Start OpenMP */
  #pragma omp parallel shared(width, height, xcent, ycent, xrInit, yrInit, maxIterStart, iterStep, framezoomx, framezoomy) private(i, iterations, filenum, image, curframe, maxiter)
  {
    /* Variables and memory declared in this section are private to each thread */

    // Allocate space for the image
    iterations = (int*)calloc( width * height, sizeof(int) );
    assert(iterations != NULL);
 
    // Allocate space for the filenames
    image = malloc(strlen(filename) + 5 + strlen(fileext));

    // GMP variables to stored distance from center point in
    mpf_t xmin, xmax, ymin, ymax;
    mpf_init(xmin);
    mpf_init(xmax);
    mpf_init(ymin);
    mpf_init(ymax);

    /* Start OpenMP parallel FOR */
    #pragma omp for
    for ( i = 0; i < totalframes; i++ )
    {
      curframe = my_rank + (i * comm_sz) + startframe;
      maxiter = maxIterStart + (iterStep * curframe);
      printf("Process %d working on frame %d with thread %d\n", my_rank, curframe + 1, omp_get_thread_num());

      // xmin, xmax, ymin and ymax
      if (curframe == 0)
      {
        // Do not zoom for the first image
        mpf_sub(xmin, xcent, xrInit);
        mpf_add(xmax, xcent, xrInit);

        mpf_sub(ymin, ycent, yrInit);
        mpf_add(ymax, ycent, yrInit);
      }
      else
      {
        // Radius is calculated as r = rinit / (zoom^frame#)
        mpf_pow_ui(xmax, framezoomx, (unsigned long int)curframe);
        mpf_div(xmax, xrInit, xmax);
        mpf_pow_ui(ymax, framezoomy, (unsigned long int)curframe);
        mpf_div(ymax, yrInit, ymax);

        mpf_sub(xmin, xcent, xmax);
        mpf_add(xmax, xcent, xmax);
        mpf_sub(ymin, ycent, ymax);
        mpf_add(ymax, ycent, ymax);
      }

      /* Compute Julia set */
      GMPJulia(xmin, xmax, width, width, 0, ymin, ymax, height, height, 0, cr, ci, flag, maxiter, iterations);

      /* Save image as a bitmap (.bmp) */
      sprintf(filenum, "%05d", curframe + 1);

      strcpy(image, filename);
      strcat(image, filenum);
      strcat(image, fileext);  

      printf("\nProcess %d creating frame %d on thread %d...", my_rank, curframe + 1, omp_get_thread_num());
      saveBMP(image, iterations, width, height);
    }

    // Free thread-reserved memory
    free(iterations);
    free(image);
    mpf_clear(xmin);
    mpf_clear(xmax);
    mpf_clear(ymin);
    mpf_clear(ymax);
  }

  // Stop timer and calculate elapsed time
  time(&t2);
  delta = difftime(t2, t1);

  MPI_Reduce(&delta, &maxTime, 1, MPI_DOUBLE, MPI_MAX, 0, MPI_COMM_WORLD);

  if (my_rank == 0) printf("Computation time = %lf\n", maxTime);

  // Close MPI environment
  MPI_Finalize();

  // Free reserved memory
  //mpf_clears(cr, ci, x, y, xr, yr, xmin, xmax, ymin, ymax, (mpf_t *) 0);
  mpf_clear(cr);
  mpf_clear(ci);
  mpf_clear(xcent);
  mpf_clear(ycent);
  mpf_clear(xrInit);
  mpf_clear(yrInit);
  mpf_clear(xrFin);
  mpf_clear(yrFin);
  mpf_clear(framezoomx);
  mpf_clear(framezoomy);

   return 0;
}