/* File: Complex.java
 *                             -- A  Java  class  for performing complex
 *                                number arithmetic to double precision.
 *
 * Copyright (c) 1997 - 2001, Alexander Anderson.
 *
 * This  program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published  by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * This program 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
 * General Public License for more details.
 *
 * You  should  have  received  a copy of the GNU General Public License
 * along  with  this  program;  if  not,  write  to  the  Free  Software
 * Foundation,  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA.
 *
 *    Alexandr Korlyukov
 *    korlyukov@grsu.grodno.by
 */

import ORG.netlib.math.complex.Complex;

/**
 *  Class for calculation of number of the happy tickets
 *  through complex numbers.
 *  For example,
 *  123 204 - happy ticket, because the sum 1, 2, 3
 *                      is equal to the sum 2, 0, 4
 *  123 254 - is not the happy ticket, because the sum 1, 2, 3
 *                             is not equal to the sum 2, 5, 4
 */
public class HappyTickets{

    public static final int notation  =  2;
    public static final int lengthTicket  =  6;
    public static final int c28  = (notation-1)*(lengthTicket/2)+1;

    public static int numberSteps  =  1000000;

    public static final Complex Compl1 =  new Complex(1.0, 0.0);
    public static final Complex Compl0 =  new Complex(0.0, 0.0);
    public static final Complex i2pi =  new Complex(0.0, 2.0 * Math.PI);
    public static Complex Compl28 =  new Complex(numberSteps, 0.0);


    /**
      * Calculation of number of the happy tickets
      * through complex numbers.
      * The formula of calculation
      * N =  (1.0 / 2*pi*i) *
      * integral on the closed contour containing number zero,
      * from function
      *    f(z) = ((z^10 - 1) / (z - 1))^6 / z^28
      *  where
      *  10 - basis of a notation,
      *   6 - length of the tickets.
      */
    public static void main (String[] args) {
        Complex res = new Complex(0.0, 0.0);
        for (int it=0; it<5; it++) {
            long start = System.currentTimeMillis();

            res = test(numberSteps);
            res = res.div(i2pi);

            System.out.println("result = "+ res);
            long end = System.currentTimeMillis();
            System.out.println("Total time = "+ (end-start)*0.001);
        }
    }
    

    /**
      * The closed contour is a circle of radius 1
      * with the centre in the beginning of coordinates
      */
    public static Complex test(int numberSteps1) {
        double st = 2.0 * Math.PI / numberSteps1;
        Complex eps = new Complex(Math.cos(st), Math.sin(st));
        Complex res  = new Complex(0.0, 0.0);
        Complex epsr = new Complex(1.0, 0.0);

        for (int it=0; it<numberSteps1; it++) {
            Complex r1 = eps.mul(epsr);
            Complex delta = r1.sub(epsr);
            res = delta.mul(fi(epsr)).add(res);
            epsr = eps.mul(epsr);
        }
        return res;
    }


    /** Calculation f(z)
      * @param x Complex number z
      */
    public static Complex fi(Complex z) {
        Complex ff1 = new Complex( 0.0, 0.0);
        Complex ff2 = new Complex( 1.0, 0.0);
        for (int i=0; i<notation; i++) {
            ff1 = ff1.add(ff2);
            ff2 = ff2.mul(z);
        }
        Complex ff3 = degc(ff1, lengthTicket);
        Complex ff4 = ff3.mul(degc(z, c28).conj());
        return ff4;
    }

    /** Calculation of a degree of complex number 
      * @param ccc complex number
      * @param ddd degree
      */
    public static Complex degc(Complex c, int d) {
        Complex r = new Complex( 1.0, 0.0);
        for (int i =  0; i < d; i++) {
            r = r.mul(c);
        }
        return r;
    }

}