Package org.jwildfire.create.tina.variation

Source Code of org.jwildfire.create.tina.variation.PolylogarithmFunc$RiemannInt

/*
  JWildfire - an image and animation processor written in Java
  Copyright (C) 1995-2014 Andreas Maschke

  This is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser
  General Public License as published by the Free Software Foundation; either version 2.1 of the
  License, or (at your option) any later version.
  This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public License along with this software;
  if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jwildfire.create.tina.variation;

import static org.jwildfire.base.mathlib.MathLib.pow;

import org.jwildfire.base.Tools;
import org.jwildfire.base.mathlib.Complex;
import org.jwildfire.create.tina.base.Layer;
import org.jwildfire.create.tina.base.XForm;
import org.jwildfire.create.tina.base.XYZPoint;

public class PolylogarithmFunc extends VariationFunc {
  private static final long serialVersionUID = 1L;

  private static final String PARAM_N = "n";
  private static final String PARAM_ZPOW = "zpow";
  private static final String[] paramNames = { PARAM_N, PARAM_ZPOW };

  private int n = 2;
  private double zpow = 1.0;

  @Override
  public void transform(FlameTransformationContext pContext, XForm pXForm, XYZPoint pAffineTP, XYZPoint pVarTP, double pAmount) {
    /* polylogarithm by dark-beam */
    // approx (very good) of Li[n](z) for n > 1
    double vv = pAmount;
    Complex z = new Complex(pAffineTP.x, pAffineTP.y);
    z.Pow(zpow);
    z.Save();
    if (z.Mag2() > 250000.0 || N >= 20) { // no convergence, or N too big... When N is big then Li tends to z
      pVarTP.x += vv * z.re;
      pVarTP.y += vv * z.im;
      return;
    }

    Complex LiN = new Complex();
    int i;
    Complex T = new Complex();
    Complex zPl1 = new Complex(z);

    if (z.Mag2() < 0.07) { // normal series. Li = sum((z^k)/(k^n))
      for (i = 1; i < 20; i++) {
        T.Copy(new Complex(pow(i, N)));
        T.DivR(z);
        LiN.Add(T);
        z.NextPow();
      }
      pVarTP.x += vv * LiN.re;
      pVarTP.y += vv * LiN.im;
      return;
    }
    // Crandall method (very simple and fast!) that uses Erdelyi series
    // from now on we will use ln(z) only so switch to it
    z.Log();
    z.Save();
    z.One();

    for (i = 0; i < 20; i++) {
      double zee = Riem.Z((int) N - i);
      if (zee != 0.0) {
        T.Copy(z);
        T.Scale(zee / (cern.jet.math.Arithmetic.longFactorial(i)));
        LiN.Add(T);
      }
      if (i == N - 1) {
        zPl1.Copy(z);
      }
      z.NextPow();
    }
    z.Restore(); // back to log(z) again...
    z.Neg();
    z.Log();
    z.Neg(); // -log(-log(z)) must be added now...
    z.re += HSTerm;
    T.Copy(z);
    z.Copy(zPl1);
    z.Scale(1.0 / cern.jet.math.Arithmetic.longFactorial((int) N - 1));
    z.Mul(T);
    LiN.Add(z);
    pVarTP.x += vv * LiN.re;
    pVarTP.y += vv * LiN.im;

    if (pContext.isPreserveZCoordinate()) {
      pVarTP.z += pAmount * pAffineTP.z;
    }
  }

  @Override
  public String[] getParameterNames() {
    return paramNames;
  }

  @Override
  public Object[] getParameterValues() {
    return new Object[] { n, zpow };
  }

  @Override
  public void setParameter(String pName, double pValue) {
    if (PARAM_N.equalsIgnoreCase(pName))
      n = Tools.FTOI(pValue);
    else if (PARAM_ZPOW.equalsIgnoreCase(pName))
      zpow = pValue;
    else
      throw new IllegalArgumentException(pName);
  }

  @Override
  public String getName() {
    return "polylogarithm";
  }

  public double HarmonicS(int N) { // Defined in Crandall's paper
    if (N < 1)
      return 0.;
    double Hs = 0.0;
    int i = 1;
    for (; i <= N; i++) {
      Hs += 1.0 / ((double) i);
    }
    return Hs;
  }

  public class RiemannInt { // with table lookups (TLDR) :D
    private double[] RzNegOdd = { -0.08333333333333333, // zeta(-(2n+1)) because zeta (-2), zeta(-4) etc are zero
        0.008333333333333333, // zeta(-3)
        -0.003968253968253968, // zeta(-5)
        0.004166666666666667,
        -0.007575757575757576,
        0.021092796092796094,
        -0.08333333333333333, // they begin to grow from now on!
        0.4432598039215686,
        -3.0539543302701198,
        26.456212121212122,
        -281.46014492753625,
        3607.5105463980462,
        -54827.583333333336,
        974936.8238505747,
        -2.005269579668808e+7,
        4.723848677216299e+8,
        -1.2635724795916667e+10,
        3.8087931125245367e+11,
        -1.2850850499305083e+13,
        4.824144835485017e+14,
        -2.0040310656516253e+16,
        9.167743603195331e+17,
        -4.5979888343656505e+19,
        2.518047192145109e+21,
        -1.500173349215393e+23,
        9.689957887463594e+24,
        -6.764588237929281e+26,
        5.089065946866229e+28,
        -4.114728879255798e+30,
        3.5666582095375554e+32,
        -3.306608987657758e+34,
        3.2715634236478713e+36,
        -3.4473782558278054e+38,
        3.861427983270526e+40,
        -4.589297443245433e+42,
        5.777538634277042e+44,
        -7.691985875950713e+46,
        1.0813635449971654e+49,
        -1.6029364522008965e+51,
        2.501947904156046e+53,
        -4.106705233581021e+55,
        7.079877440849458e+57,
        -1.280454688793951e+60,
        2.4267340392333522e+62,
        -4.8143218874045757e+64,
        9.987557417572751e+66,
        -2.1645634868435182e+69,
        4.8962327039620546e+71,
        -1.1549023923963518e+74,
        2.83822495706937e+76,
        -7.26120088036067e+78,
        1.932351423341981e+81,
        -5.345016042528861e+83,
        1.535602884642242e+86,
        -4.5789872682265786e+88,
        1.4162025212194806e+91,
        -4.540065229609264e+93,
        1.5076656758807855e+96,
        -5.183094914826456e+98,
        1.843564742725653e+101,
        -6.780555475309095e+103,
        2.57733267027546e+106,
        -1.01191128757046e+109,
        4.101634616154228e+111,
        -1.715524453403202e+114,
        7.400342570526908e+116,
        -3.290922535705444e+119,
        1.507983153416477e+122,
        -7.116987918825454e+124,
        3.458042914157776e+127,
        -1.729090760667674e+130,
        8.893699169503295e+132,
        -4.7038470619636e+135,
        2.55719382310602e+138,
        -1.428406750044352e+141,
        8.195215221831376e+143,
        -4.827648542272736e+146,
        2.918961237477031e+149,
        -1.81089321625689e+152,
        1.152357722002117e+155,
        -7.519231195198174e+157,
        5.029401657641103e+160,
        -3.447342044447767e+163,
        2.420745864586851e+166,
        -1.740946592037767e+169,
        1.281948986348224e+172,
        -9.662412110856088e+174,
        7.452691030430086e+177,
        -5.880839331167436e+180,
        4.74627186549076e+183,
        -3.916913259477282e+186,
        3.304507144322603e+189,
        -2.849289055099457e+192,
        2.510332934507758e+195,
        -2.259390199547524e+198,
        2.07691380042876e+201,
        -1.949473217492725e+204,
        1.868073147126591e+207,
        -1.827075266281457e+210,
        1.823538632259567e+213 };

    //From GNU sci lib (thanks) - just few terms
    private double[] RzPosInt = { -0.50000000000000000000000000000, /* zeta(0) */
        0.0, /* zeta(1) is infinite. But we don't care ;) */
        1.64493406684822643647241516665, /* ...     */
        1.20205690315959428539973816151,
        1.08232323371113819151600369654,
        1.03692775514336992633136548646,
        1.01734306198444913971451792979,
        1.00834927738192282683979754985,
        1.00407735619794433937868523851,
        1.00200839282608221441785276923,
        1.00099457512781808533714595890,
        1.00049418860411946455870228253,
        1.00024608655330804829863799805,
        1.00012271334757848914675183653,
        1.00006124813505870482925854511,
        1.00003058823630702049355172851,
        1.00001528225940865187173257149,
        1.00000763719763789976227360029,
        1.00000381729326499983985646164,
        1.00000190821271655393892565696,
        1.00000095396203387279611315204,
        1.00000047693298678780646311672,
        1.00000023845050272773299000365,
        1.00000011921992596531107306779,
        1.00000005960818905125947961244,
        1.00000002980350351465228018606,
        1.00000001490155482836504123466,
        1.00000000745071178983542949198,
        1.00000000372533402478845705482,
        1.00000000186265972351304900640,
        1.00000000093132743241966818287,
        1.00000000046566290650337840730,
        1.00000000023283118336765054920,
        1.00000000011641550172700519776 }; // 33 ... it tends to 1...

    public double Z(int N) {
      if (N > 33)
        return 1.0;
      if (N < -200)
        return 1e250; // don't go over indices just make a bad guess
      int M = N;
      if (M < 0) {
        if (((-M) % 2) == 0)
          return 0.0; // even neg are triv zeros
        M = (-M - 1) / 2;
        return RzNegOdd[M];
      }

      return RzPosInt[M];

    } // END OF Z

  } // END OF RiemannInt

  RiemannInt Riem;
  double HSTerm;
  double N;

  @Override
  public void init(FlameTransformationContext pContext, Layer pLayer, XForm pXForm, double pAmount) {
    N = n;
    Riem = new RiemannInt();
    HSTerm = HarmonicS((int) N - 1);
  }

}
TOP

Related Classes of org.jwildfire.create.tina.variation.PolylogarithmFunc$RiemannInt

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.