blob: e80b9bb074229716f4d4bf5698dccfb31d57a08b [file] [log] [blame]
/**
* 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));
}
}