/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.hadoop.examples.pi.math;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;

import org.apache.hadoop.examples.pi.Container;
import org.apache.hadoop.examples.pi.Util;
import org.apache.hadoop.examples.pi.Util.Timer;
import org.apache.hadoop.examples.pi.math.TestModular.Montgomery2;

public class TestSummation extends junit.framework.TestCase {
  static final Random RANDOM = new Random();
  static final BigInteger TWO = BigInteger.valueOf(2);

  private static Summation2 newSummation(final long base, final long range, final long delta) {
    final ArithmeticProgression N = new ArithmeticProgression('n', base+3, delta, base+3+range);
    final ArithmeticProgression E = new ArithmeticProgression('e', base+range, -delta, base);
    return new Summation2(N, E);
  }

  private static void runTestSubtract(Summation sigma, List<Summation> diff) {
//    Util.out.println("diff=" + diff);
    List<Container<Summation>> tmp = new ArrayList<Container<Summation>>(diff.size());
    for(Summation s : diff)
      tmp.add(s);
    final List<Summation> a = sigma.remainingTerms(tmp);
//    Util.out.println("a   =" + a);

    a.addAll(diff);
    for(Summation s : a)
      s.compute();

    final List<Summation> combined = Util.combine(a);
//    Util.out.println("combined=" + combined);
    assertEquals(1, combined.size());
    assertEquals(sigma, combined.get(0));
  }

  public void testSubtract() {
    final Summation sigma = newSummation(3, 10000, 20);
    final int size = 10;
    final List<Summation> parts = Arrays.asList(sigma.partition(size));
    Collections.sort(parts);

    runTestSubtract(sigma, new ArrayList<Summation>());
    runTestSubtract(sigma, parts);

    for(int n = 1; n < size; n++) {
      for(int j = 0; j < 10; j++) {
        final List<Summation> diff = new ArrayList<Summation>(parts);
        for(int i = 0; i < n; i++)
          diff.remove(RANDOM.nextInt(diff.size()));
///        Collections.sort(diff);
        runTestSubtract(sigma, diff);
      }
    }
  }
  
  static class Summation2 extends Summation {
    Summation2(ArithmeticProgression N, ArithmeticProgression E) {
      super(N, E);
    }

    
    final Montgomery2 m2 = new Montgomery2();
    double compute_montgomery2() {
      long e = E.value;
      long n = N.value;
      double s = 0;
      for(; e > E.limit; e += E.delta) {
        m2.set(n);
        s = Modular.addMod(s, m2.mod2(e)/(double)n);
        n += N.delta;
      }
      return s;
    }

    double compute_modBigInteger() {
      long e = E.value;
      long n = N.value;
      double s = 0;
      for(; e > E.limit; e += E.delta) {
        s = Modular.addMod(s, TestModular.modBigInteger(e, n)/(double)n);
        n += N.delta;
      }
      return s;
    }
  
    double compute_modPow() {
      long e = E.value;
      long n = N.value;
      double s = 0;
      for(; e > E.limit; e += E.delta) {
        s = Modular.addMod(s, TWO.modPow(BigInteger.valueOf(e), BigInteger.valueOf(n)).doubleValue()/n);
        n += N.delta;
      }
      return s;
    }
  }

  private static void computeBenchmarks(final Summation2 sigma) {
    final Timer t = new Timer(false);
    t.tick("sigma=" + sigma);
    final double value = sigma.compute();
    t.tick("compute=" + value);
    assertEquals(value, sigma.compute_modular());
    t.tick("compute_modular");
    assertEquals(value, sigma.compute_montgomery());
    t.tick("compute_montgomery");
    assertEquals(value, sigma.compute_montgomery2());
    t.tick("compute_montgomery2");

    assertEquals(value, sigma.compute_modBigInteger());
    t.tick("compute_modBigInteger");
    assertEquals(value, sigma.compute_modPow());
    t.tick("compute_modPow");
  }

  /** Benchmarks */
  public static void main(String[] args) {
    final long delta = 1L << 4;
    final long range = 1L << 20;
    for(int i = 20; i < 40; i += 2) 
      computeBenchmarks(newSummation(1L << i, range, delta));
  }
}
