/*
* Copyright 2011 Uwe Krueger.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mandelsoft.mand;
import com.mandelsoft.mand.tools.Mand;
import java.math.BigDecimal;
import com.mandelsoft.mand.util.MandArith;
/**
*
* @author Uwe Krueger
*/
public class MandIter extends MandArith {
static private BigDecimal br=new BigDecimal(5.e-16);
static public PixelIterator createPixelIterator(MandelSpec mi)
{
BigDecimal x0=mi.getXMin();
BigDecimal y0=mi.getYMax();
BigDecimal dx=mi.getDX();
BigDecimal dy=mi.getDY();
int rx=mi.getRX();
int ry=mi.getRY();
return createPixelIterator(x0,y0,dx,dy,rx,ry,
mi.getLimitIt());
}
static public PixelIterator createPixelIterator(BigDecimal x0,
BigDecimal y0,
BigDecimal dx,
BigDecimal dy,
int rx,
int ry,
int limit)
{
if (div(dx,rx).compareTo(br)>0 && div(dy,ry).compareTo(br)>0) {
System.out.println("double iteration mode");
return new DoubleMandIterator(x0,y0,dx,dy,rx,ry,limit);
}
if (useDLL) {
System.out.println("long double iteration mode");
return new LongDoubleMandIterator(x0,y0,dx,dy,rx,ry,limit);
}
System.out.println("big decimal iteration mode");
return new BigDecimalMandIterator(x0,y0,dx,dy,rx,ry,limit);
}
private static abstract class MandPixelIterator implements PixelIterator {
protected int limit;
protected int rx;
protected int ry;
protected int precision;
protected int magnification;
public MandPixelIterator(MandelInfo mi)
{
this(mi.getRX(),mi.getRY(),mi.getLimitIt(),
mi.getDX(),mi.getDY());
}
public MandPixelIterator(int rx, int ry, int limit,
BigDecimal dx, BigDecimal dy)
{
this.limit=limit;
this.rx=rx;
this.ry=ry;
setPrecision(dx,dy);
}
protected void setPrecision(BigDecimal dx, BigDecimal dy)
{
BigDecimal dX=div(dx,rx);
BigDecimal dY=div(dy,ry);
BigDecimal d=dX;
if (dX.compareTo(dY)>0) d=dY;
int p=0;
while (d.compareTo(BigDecimal.ONE)<0) {
p++;
d=mul(d,BigDecimal.TEN);
}
int prec=((p+2)/3)*10;
precision=(int)((p+2)/Math.log10(2));
d=dx;
if (dx.compareTo(dy)>0) d=dy;
p=0;
while (d.compareTo(BigDecimal.ONE)<0) {
p++;
d=mul(d,BigDecimal.TEN);
}
magnification=p;
}
public int getPrecision()
{
return precision;
}
public int getMagnification()
{
return magnification;
}
}
/////////////////////////////////////////////////////////////////////////
// double iterator
/////////////////////////////////////////////////////////////////////////
private static class DoubleMandIterator extends MandPixelIterator {
//parameters
private double bound;
private double dx;
private double dy;
private double x0;
private double y0;
private double drx;
private double dry;
// iteration point
private double cx;
private double cy;
public DoubleMandIterator(BigDecimal x0,
BigDecimal y0,
BigDecimal dx,
BigDecimal dy,
int rx,
int ry,
int limit)
{
super(rx,ry,limit,dx,dy);
bound=Mand.BOUND;
this.dx=dx.doubleValue();
this.dy=dy.doubleValue();
this.x0=x0.doubleValue();
this.y0=y0.doubleValue();
this.drx=rx;
this.dry=ry;
}
public boolean isFast()
{ return true;
}
public void setX(int x)
{
cx=x0+(x*dx)/drx;
}
public void setY(int y)
{
cy=y0-(y*dy)/dry;
}
public BigDecimal getCX()
{
return new BigDecimal(cx);
}
public BigDecimal getCY()
{
return new BigDecimal(cy);
}
public double getX(BigDecimal x)
{
double xd=x.doubleValue();
return (xd-x0)*drx/dx;
}
public double getY(BigDecimal y)
{
double yd=y.doubleValue();
return (y0-yd)*dry/dy;
}
public int iter()
{
return iter(0.0, 0.0, cx, cy, bound, limit);
}
private static int iter(double x, double y, double px, double py,
double bound, int limit)
{
double x2=x*x;
double y2=y*y;
int it=0;
while (x2+y2<bound&&++it<=limit) {
double xn=x2-y2+px;
double yn=2*x*y+py;
x=xn;
x2=x*x;
y=yn;
y2=y*y;
}
return it;
}
}
/////////////////////////////////////////////////////////////////////////
// big decimal iterator support
/////////////////////////////////////////////////////////////////////////
public static abstract class BigDecimalIterator extends MandPixelIterator {
protected BigDecimal dx;
protected BigDecimal dy;
protected BigDecimal drx;
protected BigDecimal dry;
protected BigDecimal x0;
protected BigDecimal y0;
protected BigDecimal cx;
protected BigDecimal cy;
public BigDecimalIterator(MandelSpec spec)
{
this(spec.getXMin(),spec.getYMax(),spec.getDX(),spec.getDY(),
spec.getRX(),spec.getRY(),spec.getLimitIt());
}
public BigDecimalIterator(BigDecimal x0,
BigDecimal y0,
BigDecimal dx,
BigDecimal dy,
int rx,
int ry,
int limit)
{
super(rx,ry,limit,dx,dy);
this.dx=dx;
this.dy=dy;
this.drx=new BigDecimal(rx);
this.dry=new BigDecimal(ry);
this.x0=x0;
this.y0=y0;
}
public boolean isFast()
{ return false;
}
public void setX(int x)
{
cx=add(x0, div(mul(dx, x), drx));
}
public void setY(int y)
{
cy=sub(y0, div(mul(dy, y), dry));
}
public BigDecimal getCX()
{
return cx;
}
public BigDecimal getCY()
{
return cy;
}
public double getX(BigDecimal x)
{
return div(mul(sub(x,x0),drx),dx).doubleValue();
}
public double getY(BigDecimal y)
{
return div(mul(sub(y0,y),dry),dy).doubleValue();
}
}
/////////////////////////////////////////////////////////////////////////
// long double iterator
/////////////////////////////////////////////////////////////////////////
private static class LongDoubleMandIterator extends BigDecimalIterator {
protected String bound;
protected String scx;
protected String scy;
public LongDoubleMandIterator(BigDecimal x0,
BigDecimal y0,
BigDecimal dx,
BigDecimal dy,
int rx,
int ry,
int limit)
{
super(x0,y0,dx,dy,rx,ry,limit);
bound=new BigDecimal(Mand.BOUND).toString();
System.out.println("prec: "+precision);
}
@Override
public void setX(int x)
{
super.setX(x);
scx=cx.toString();
}
@Override
public void setY(int y)
{
super.setY(y);
scy=cy.toString();
}
public int iter()
{
return MandIter.iterP("0.0", "0.0", scx, scy, bound, limit, precision);
}
}
/////////////////////////////////////////////////////////////////////////
// big decimal iterator
/////////////////////////////////////////////////////////////////////////
private static class BigDecimalMandIterator extends BigDecimalIterator {
private int cnt;
private BigDecimal bound;
public BigDecimalMandIterator(BigDecimal x0,
BigDecimal y0,
BigDecimal dx,
BigDecimal dy,
int rx,
int ry,
int limit)
{
super(x0,y0,dx,dy,rx,ry,limit);
bound=new BigDecimal(Mand.BOUND);
}
public int iter()
{
cnt++;
if (cnt%100==0) {
System.out.print(".");
System.out.flush();
}
return iter(BigDecimal.ZERO, BigDecimal.ZERO, cx, cy,
bound, limit);
}
static public int iter(BigDecimal sx, BigDecimal sy,
BigDecimal cx, BigDecimal cy,
BigDecimal bound, int limit)
{
BigDecimal x=sx;
BigDecimal y=sy;
BigDecimal x2=mul(x, x);
BigDecimal y2=mul(y, y);
int it=0;
while (add(x2, y2).compareTo(bound)<0&&++it<=limit) {
BigDecimal xn=add(sub(x2, y2), cx);
BigDecimal yn=add(mul(mul(b2, x), y), cy);
x=xn;
x2=mul(x, x);
y=yn;
y2=mul(y, y);
}
return it;
}
}
/////////////////////////////////////////////////////////////////////////
// native support
/////////////////////////////////////////////////////////////////////////
native static public int iter(String sx, String sy, String cx, String cy,
String bound, int limit);
native static public int iterP(String sx, String sy, String cx, String cy,
String bound, int limit, int prec);
public static boolean useDLL;
static {
try {
System.loadLibrary("gmp");
System.loadLibrary("Mandelbrot");
useDLL=true;
//useDLL=false;
}
catch (UnsatisfiedLinkError le) {
System.out.println("failed:"+le);
useDLL=false;
}
}
/////////////////////////////////////////////////////////////////////////
// test
/////////////////////////////////////////////////////////////////////////
static private int iter(BigDecimal sx, BigDecimal sy,
BigDecimal cx, BigDecimal cy,
BigDecimal bound, int limit)
{
if (useDLL) {
System.out.println("using native(dll) mode");
return iterP(sx.toString(), sy.toString(),
cx.toString(), cy.toString(),
bound.toString(), limit,100);
}
else {
System.out.println("using BigDecimal mode");
return BigDecimalMandIterator.iter(sx, sy, cx, cy, bound, limit);
}
}
static public void main(String[] args)
{
int i;
System.out.println("calling iter");
i=iter(b0, b0, new BigDecimal(0.5), b0, b10, 128000);
System.out.println("got "+i);
}
}