diff --git a/src/com/jwetherell/algorithms/data_structures/FenwickTree.java b/src/com/jwetherell/algorithms/data_structures/FenwickTree.java index 60634d40..04af939e 100644 --- a/src/com/jwetherell/algorithms/data_structures/FenwickTree.java +++ b/src/com/jwetherell/algorithms/data_structures/FenwickTree.java @@ -5,6 +5,8 @@ import java.util.ArrayList; import java.util.List; +import com.jwetherell.algorithms.mathematics.Operations; + /** * A Fenwick tree or binary indexed tree is a data structure providing efficient methods * for calculation and manipulation of the prefix sums of a table of values. Fenwick trees @@ -303,27 +305,7 @@ else if (this.sum != null && data.sum == null) else if (this.sum == null && data.sum != null) this.sum = data.sum; else { - /* TODO: This is ugly and how to handle number overflow? */ - if (this.sum instanceof BigDecimal || data.sum instanceof BigDecimal) { - BigDecimal result = ((BigDecimal)this.sum).add((BigDecimal)data.sum); - this.sum = (N)result; - } else if (this.sum instanceof BigInteger || data.sum instanceof BigInteger) { - BigInteger result = ((BigInteger)this.sum).add((BigInteger)data.sum); - this.sum = (N)result; - } else if (this.sum instanceof Long || data.sum instanceof Long) { - Long result = (this.sum.longValue() + data.sum.longValue()); - this.sum = (N)result; - } else if (this.sum instanceof Double || data.sum instanceof Double) { - Double result = (this.sum.doubleValue() + data.sum.doubleValue()); - this.sum = (N)result; - } else if (this.sum instanceof Float || data.sum instanceof Float) { - Float result = (this.sum.floatValue() + data.sum.floatValue()); - this.sum = (N)result; - } else { - // Integer - Integer result = (this.sum.intValue() + data.sum.intValue()); - this.sum = (N)result; - } + this.sum = (N) Operations.addNumbers(this.sum, data.sum); } } @@ -341,27 +323,7 @@ else if (this.sum != null && data.sum == null) else if (this.sum == null && data.sum != null) this.sum = data.sum; else { - /* TODO: This is ugly and how to handle number overflow? */ - if (this.sum instanceof BigDecimal || data.sum instanceof BigDecimal) { - BigDecimal result = ((BigDecimal)this.sum).subtract((BigDecimal)data.sum); - this.sum = (N)result; - } else if (this.sum instanceof BigInteger || data.sum instanceof BigInteger) { - BigInteger result = ((BigInteger)this.sum).subtract((BigInteger)data.sum); - this.sum = (N)result; - } else if (this.sum instanceof Long || data.sum instanceof Long) { - Long result = (this.sum.longValue() - data.sum.longValue()); - this.sum = (N)result; - } else if (this.sum instanceof Double || data.sum instanceof Double) { - Double result = (this.sum.doubleValue() - data.sum.doubleValue()); - this.sum = (N)result; - } else if (this.sum instanceof Float || data.sum instanceof Float) { - Float result = (this.sum.floatValue() - data.sum.floatValue()); - this.sum = (N)result; - } else { - // Integer - Integer result = (this.sum.intValue() - data.sum.intValue()); - this.sum = (N)result; - } + this.sum = (N) Operations.subtractNumbers(this.sum, data.sum); } } diff --git a/src/com/jwetherell/algorithms/data_structures/Matrix.java b/src/com/jwetherell/algorithms/data_structures/Matrix.java index 0d814e18..270ee532 100644 --- a/src/com/jwetherell/algorithms/data_structures/Matrix.java +++ b/src/com/jwetherell/algorithms/data_structures/Matrix.java @@ -3,6 +3,7 @@ import java.math.BigDecimal; import java.math.BigInteger; import java.util.Comparator; +import com.jwetherell.algorithms.mathematics.Operations; /** * Matrx. This Matrix implementation is designed to be more efficient @@ -26,33 +27,7 @@ public class Matrix { @Override public int compare(T o1, T o2) { /* TODO: What if Java adds new numeric type? */ - int result = 0; - if (o1 instanceof BigDecimal || o2 instanceof BigDecimal) { - BigDecimal c1 = (BigDecimal)o1; - BigDecimal c2 = (BigDecimal)o2; - result = c1.compareTo(c2); - } else if (o1 instanceof BigInteger || o2 instanceof BigInteger) { - BigInteger c1 = (BigInteger)o1; - BigInteger c2 = (BigInteger)o2; - result = c1.compareTo(c2); - } else if (o1 instanceof Long || o2 instanceof Long) { - Long c1 = o1.longValue(); - Long c2 = o2.longValue(); - result = c1.compareTo(c2); - } else if (o1 instanceof Double || o2 instanceof Double) { - Double c1 = o1.doubleValue(); - Double c2 = o2.doubleValue(); - result = c1.compareTo(c2); - } else if (o1 instanceof Float || o2 instanceof Float) { - Float c1 = o1.floatValue(); - Float c2 = o2.floatValue(); - result = c1.compareTo(c2); - } else { - Integer c1 = o1.intValue(); - Integer c2 = o2.intValue(); - result = c1.compareTo(c2); - } - return result; + return Operations.compare(o1, o2); } }; @@ -165,29 +140,7 @@ public Matrix add(Matrix input) { for (int i = 0; i < cols; i++) { T m1 = this.get(r, c); T m2 = input.get(r, c); - T result; - /* TODO: This is ugly and how to handle number overflow? */ - if (m1 instanceof BigDecimal || m2 instanceof BigDecimal) { - BigDecimal result2 = ((BigDecimal)m1).add((BigDecimal)m2); - result = (T)result2; - } else if (m1 instanceof BigInteger || m2 instanceof BigInteger) { - BigInteger result2 = ((BigInteger)m1).add((BigInteger)m2); - result = (T)result2; - } else if (m1 instanceof Long || m2 instanceof Long) { - Long result2 = (m1.longValue() + m2.longValue()); - result = (T)result2; - } else if (m1 instanceof Double || m2 instanceof Double) { - Double result2 = (m1.doubleValue() + m2.doubleValue()); - result = (T)result2; - } else if (m1 instanceof Float || m2 instanceof Float) { - Float result2 = (m1.floatValue() + m2.floatValue()); - result = (T)result2; - } else { - // Integer - Integer result2 = (m1.intValue() + m2.intValue()); - result = (T)result2; - } - output.set(r, c, result); + output.set(r, c, (T) Operations.addNumbers(m1, m2)); } } } @@ -204,29 +157,7 @@ public Matrix subtract(Matrix input) { for (int i = 0; i < cols; i++) { T m1 = this.get(r, c); T m2 = input.get(r, c); - T result; - /* TODO: This is ugly and how to handle number overflow? */ - if (m1 instanceof BigDecimal || m2 instanceof BigDecimal) { - BigDecimal result2 = ((BigDecimal)m1).subtract((BigDecimal)m2); - result = (T)result2; - } else if (m1 instanceof BigInteger || m2 instanceof BigInteger) { - BigInteger result2 = ((BigInteger)m1).subtract((BigInteger)m2); - result = (T)result2; - } else if (m1 instanceof Long || m2 instanceof Long) { - Long result2 = (m1.longValue() - m2.longValue()); - result = (T)result2; - } else if (m1 instanceof Double || m2 instanceof Double) { - Double result2 = (m1.doubleValue() - m2.doubleValue()); - result = (T)result2; - } else if (m1 instanceof Float || m2 instanceof Float) { - Float result2 = (m1.floatValue() - m2.floatValue()); - result = (T)result2; - } else { - // Integer - Integer result2 = (m1.intValue() - m2.intValue()); - result = (T)result2; - } - output.set(r, c, result); + output.set(r, c, (T) Operations.subtractNumbers(m1, m2)); } } } @@ -243,69 +174,7 @@ public Matrix multiply(Matrix input) { T[] row = getRow(r); T[] column = input.getColumn(c); T test = row[0]; - /* TODO: This is ugly and how to handle number overflow? */ - if (test instanceof BigDecimal) { - BigDecimal result = BigDecimal.ZERO; - for (int i = 0; i < cols; i++) { - T m1 = row[i]; - T m2 = column[i]; - - BigDecimal result2 = ((BigDecimal)m1).multiply(((BigDecimal)m2)); - result = result.add(result2); - } - output.set(r, c, (T)result); - } else if (test instanceof BigInteger) { - BigInteger result = BigInteger.ZERO; - for (int i = 0; i < cols; i++) { - T m1 = row[i]; - T m2 = column[i]; - - BigInteger result2 = ((BigInteger)m1).multiply(((BigInteger)m2)); - result = result.add(result2); - } - output.set(r, c, (T)result); - } else if (test instanceof Long) { - Long result = 0l; - for (int i = 0; i < cols; i++) { - T m1 = row[i]; - T m2 = column[i]; - - Long result2 = m1.longValue() * m2.longValue(); - result = result+result2; - } - output.set(r, c, (T)result); - } else if (test instanceof Double) { - Double result = 0d; - for (int i = 0; i < cols; i++) { - T m1 = row[i]; - T m2 = column[i]; - - Double result2 = m1.doubleValue() * m2.doubleValue(); - result = result+result2; - } - output.set(r, c, (T)result); - } else if (test instanceof Float) { - Float result = 0f; - for (int i = 0; i < cols; i++) { - T m1 = row[i]; - T m2 = column[i]; - - Float result2 = m1.floatValue() * m2.floatValue(); - result = result+result2; - } - output.set(r, c, (T)result); - } else { - // Integer - Integer result = 0; - for (int i = 0; i < cols; i++) { - T m1 = row[i]; - T m2 = column[i]; - - Integer result2 = m1.intValue() * m2.intValue(); - result = result+result2; - } - output.set(r, c, (T)result); - } + output.set(r, c, (T) Operations.rowMultiplication(test, row, column, cols)); } } return output; diff --git a/src/com/jwetherell/algorithms/data_structures/SegmentTree.java b/src/com/jwetherell/algorithms/data_structures/SegmentTree.java index fb516d8e..8a223d73 100644 --- a/src/com/jwetherell/algorithms/data_structures/SegmentTree.java +++ b/src/com/jwetherell/algorithms/data_structures/SegmentTree.java @@ -12,6 +12,8 @@ import java.util.Set; import java.util.TreeSet; +import com.jwetherell.algorithms.mathematics.Operations; + /** * Segment tree using objects and pointers. A segment tree is a tree data * structure for storing intervals, or segments. It allows querying which of the @@ -340,26 +342,8 @@ else if (this.maximum != null && data.maximum == null) else if (this.maximum == null && data.maximum != null) this.maximum = data.maximum; else { - /* TODO: This is ugly */ - if (this.maximum instanceof BigDecimal || data.maximum instanceof BigDecimal) { - if (((BigDecimal)data.maximum).compareTo(((BigDecimal)this.maximum))==1) - this.maximum = data.maximum; - } else if (this.maximum instanceof BigInteger || data.maximum instanceof BigInteger) { - if (((BigInteger)data.maximum).compareTo(((BigInteger)this.maximum))==1) - this.maximum = data.maximum; - } else if (this.maximum instanceof Long || data.maximum instanceof Long) { - if (((Long)data.maximum).compareTo(((Long)this.maximum))==1) - this.maximum = data.maximum; - } else if (this.maximum instanceof Double || data.maximum instanceof Double) { - if (((Double)data.maximum).compareTo(((Double)this.maximum))==1) - this.maximum = data.maximum; - } else if (this.maximum instanceof Float || data.maximum instanceof Float) { - if (((Float)data.maximum).compareTo(((Float)this.maximum))==1) - this.maximum = data.maximum; - } else { - // Integer - if (((Integer)data.maximum).compareTo(((Integer)this.maximum))==1) - this.maximum = data.maximum; + if(Operations.compare(data.maximum, this.maximum) == 1){ + this.maximum = data.maximum; } } } @@ -471,26 +455,8 @@ else if (this.minimum != null && data.minimum == null) else if (this.minimum == null && data.minimum != null) this.minimum = data.minimum; else { - /* TODO: This is ugly */ - if (this.minimum instanceof BigDecimal || data.minimum instanceof BigDecimal) { - if (((BigDecimal)data.minimum).compareTo(((BigDecimal)this.minimum))==-1) - this.minimum = data.minimum; - } else if (this.minimum instanceof BigInteger || data.minimum instanceof BigInteger) { - if (((BigInteger)data.minimum).compareTo(((BigInteger)this.minimum))==-1) - this.minimum = data.minimum; - } else if (this.minimum instanceof Long || data.minimum instanceof Long) { - if (((Long)data.minimum).compareTo(((Long)this.minimum))==-1) - this.minimum = data.minimum; - } else if (this.minimum instanceof Double || data.minimum instanceof Double) { - if (((Double)data.minimum).compareTo(((Double)this.minimum))==-1) - this.minimum = data.minimum; - } else if (this.minimum instanceof Float || data.minimum instanceof Float) { - if (((Float)data.minimum).compareTo(((Float)this.minimum))==-1) - this.minimum = data.minimum; - } else { - // Integer - if (((Integer)data.minimum).compareTo(((Integer)this.minimum))==-1) - this.minimum = data.minimum; + if(Operations.compare(data.minimum, this.minimum) == -1){ + this.minimum = data.minimum; } } } @@ -603,27 +569,7 @@ else if (this.sum != null && data.sum == null) else if (this.sum == null && data.sum != null) this.sum = data.sum; else { - /* TODO: This is ugly and how to handle number overflow? */ - if (this.sum instanceof BigDecimal || data.sum instanceof BigDecimal) { - BigDecimal result = ((BigDecimal)this.sum).add((BigDecimal)data.sum); - this.sum = (N)result; - } else if (this.sum instanceof BigInteger || data.sum instanceof BigInteger) { - BigInteger result = ((BigInteger)this.sum).add((BigInteger)data.sum); - this.sum = (N)result; - } else if (this.sum instanceof Long || data.sum instanceof Long) { - Long result = (this.sum.longValue() + data.sum.longValue()); - this.sum = (N)result; - } else if (this.sum instanceof Double || data.sum instanceof Double) { - Double result = (this.sum.doubleValue() + data.sum.doubleValue()); - this.sum = (N)result; - } else if (this.sum instanceof Float || data.sum instanceof Float) { - Float result = (this.sum.floatValue() + data.sum.floatValue()); - this.sum = (N)result; - } else { - // Integer - Integer result = (this.sum.intValue() + data.sum.intValue()); - this.sum = (N)result; - } + this.sum = (N) Operations.addNumbers(this.sum, data.sum); } } diff --git a/src/com/jwetherell/algorithms/mathematics/Operations.java b/src/com/jwetherell/algorithms/mathematics/Operations.java new file mode 100644 index 00000000..ac477310 --- /dev/null +++ b/src/com/jwetherell/algorithms/mathematics/Operations.java @@ -0,0 +1,145 @@ +package com.jwetherell.algorithms.mathematics; + +import java.math.BigDecimal; +import java.math.BigInteger; + +/** + * Mathematical operations adapted to support input of the different numeric types + * Integer, Float, Double, Long, BigDecimal and BigInteger. + */ +public class Operations { + + /* + * Compares two number of the type Integer, Float, Double, Long, BigDecimal or BigInteger + * + * TODO: How to handle number overflow? + */ + public static int compare(Number a, Number b){ + if (a instanceof BigDecimal || b instanceof BigDecimal){ + return ((BigDecimal)a).compareTo((BigDecimal)b); + } + else if (a instanceof BigInteger || b instanceof BigInteger){ + return ((BigInteger)a).compareTo((BigInteger)b); + } + else if (a instanceof Long || b instanceof Long){ + return ((Long)a).compareTo((Long)b); + } + else if (a instanceof Double || b instanceof Double){ + return ((Double)a).compareTo((Double)b); + } + else if (a instanceof Float || b instanceof Float){ + return ((Float)a).compareTo((Float)b); + } + else { + return ((Integer)a).compareTo((Integer)b); + } + } + + /* + * Multiplies two number of the type Integer, Float, Double, Long, BigDecimal or BigInteger in a row + * + * TODO: How to handle number overflow? + */ + public static Number rowMultiplication(Number test, Number[] row, Number[] column, int cols){ + if (test instanceof BigDecimal) { + BigDecimal result = BigDecimal.ZERO; + for (int i = 0; i < cols; i++) { + Number m1 = row[i]; + Number m2 = column[i]; + BigDecimal result2 = ((BigDecimal)m1).multiply(((BigDecimal)m2)); + result = result.add(result2); + } + return result; + } else if (test instanceof BigInteger) { + BigInteger result = BigInteger.ZERO; + for (int i = 0; i < cols; i++) { + Number m1 = row[i]; + Number m2 = column[i]; + BigInteger result2 = ((BigInteger)m1).multiply(((BigInteger)m2)); + result = result.add(result2); + } + return result; + } else if (test instanceof Long) { + Long result = 0l; + for (int i = 0; i < cols; i++) { + Number m1 = row[i]; + Number m2 = column[i]; + Long result2 = m1.longValue() * m2.longValue(); + result = result+result2; + } + return result; + } else if (test instanceof Double) { + Double result = 0d; + for (int i = 0; i < cols; i++) { + Number m1 = row[i]; + Number m2 = column[i]; + Double result2 = m1.doubleValue() * m2.doubleValue(); + result = result+result2; + } + return result; + } else if (test instanceof Float) { + Float result = 0f; + for (int i = 0; i < cols; i++) { + Number m1 = row[i]; + Number m2 = column[i]; + Float result2 = m1.floatValue() * m2.floatValue(); + result = result+result2; + } + return result; + } else { + // Integer + Integer result = 0; + for (int i = 0; i < cols; i++) { + Number m1 = row[i]; + Number m2 = column[i]; + Integer result2 = m1.intValue() * m2.intValue(); + result = result+result2; + } + return result; + } + } + + /* + * Adds two number of the type Integer, Float, Double, Long, BigDecimal or BigInteger + * + * TODO: How to handle number overflow? + */ + public static Number addNumbers(Number m1, Number m2) { + if (m1 instanceof BigDecimal || m2 instanceof BigDecimal) { + return ((BigDecimal)m1).add((BigDecimal)m2); + } else if (m1 instanceof BigInteger || m2 instanceof BigInteger) { + return ((BigInteger)m1).add((BigInteger)m2); + } else if (m1 instanceof Long || m2 instanceof Long) { + return (m1.longValue() + m2.longValue()); + } else if (m1 instanceof Double || m2 instanceof Double) { + return (m1.doubleValue() + m2.doubleValue()); + } else if (m1 instanceof Float || m2 instanceof Float) { + return (m1.floatValue() + m2.floatValue()); + } else { + // Integer + return (m1.intValue() + m2.intValue()); + } + } + + /* + * Subtracts one number from another of the type Integer, Float, Double, Long, BigDecimal or BigInteger + * + * TODO: How to handle number overflow? + */ + public static Number subtractNumbers(Number m1, Number m2) { + if (m1 instanceof BigDecimal || m2 instanceof BigDecimal) { + return ((BigDecimal)m1).subtract((BigDecimal)m2); + } else if (m1 instanceof BigInteger || m2 instanceof BigInteger) { + return ((BigInteger)m1).subtract((BigInteger)m2); + } else if (m1 instanceof Long || m2 instanceof Long) { + return (m1.longValue() - m2.longValue()); + } else if (m1 instanceof Double || m2 instanceof Double) { + return (m1.doubleValue() - m2.doubleValue()); + } else if (m1 instanceof Float || m2 instanceof Float) { + return (m1.floatValue() - m2.floatValue()); + } else { + // Integer + return (m1.intValue() - m2.intValue()); + } + } +} \ No newline at end of file diff --git a/test/com/jwetherell/algorithms/data_structures/test/FenwickTreeTests.java b/test/com/jwetherell/algorithms/data_structures/test/FenwickTreeTests.java index e635398b..e842984a 100644 --- a/test/com/jwetherell/algorithms/data_structures/test/FenwickTreeTests.java +++ b/test/com/jwetherell/algorithms/data_structures/test/FenwickTreeTests.java @@ -1,5 +1,9 @@ package com.jwetherell.algorithms.data_structures.test; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Comparator; + import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -136,4 +140,265 @@ private static final void assertTrue(String msg, Fe toString = "\n"+obj.toString(); Assert.assertTrue(msg+toString, isTrue); } + + // Requirement: + // When FenwickTree consists of data with BigDecimal numbers it should be able to sum them up correctly + @Test + public void testBigDecimalFenwickTree() { + List> segments = new ArrayList>(); + segments.add(new FenwickTree.Data.RangeSumData(0, (BigDecimal) new BigDecimal(1.1))); + segments.add(new FenwickTree.Data.RangeSumData(1, (BigDecimal) new BigDecimal(2.1))); + segments.add(new FenwickTree.Data.RangeSumData(2, (BigDecimal) new BigDecimal(6.1))); + segments.add(new FenwickTree.Data.RangeSumData(3, (BigDecimal) new BigDecimal(7.1))); + + // No matter which order the data is given, all tests should pass + + // Initial order. + testBigDecimalFenwickTree(segments); + + // Randomize it + Collections.shuffle(segments); + testBigDecimalFenwickTree(segments); + + // Try in order + Collections.sort(segments); + testBigDecimalFenwickTree(segments); + + // Try reverse order + Collections.sort(segments,REVERSE); + testBigDecimalFenwickTree(segments); + } + + private void testBigDecimalFenwickTree(List> segments) { // Range Sum Segment tree + FenwickTree> tree = new FenwickTree>(segments); + + FenwickTree.Data.RangeSumData query = tree.query(0, 3); + + query = tree.query(2); + assertTrue("Segment tree query error. query=2 result="+query, tree, query.sum.compareTo(new BigDecimal(6.1)) == 0); + + query = tree.query(0, 1); // stabbing + assertTrue("Segment tree query error. query=0->1 result="+ query, tree, query.sum.compareTo(new BigDecimal(1.1).add(new BigDecimal(2.1))) == 0); + } + + // Requirement: + // When FenwickTree consists of data with BigInteger numbers it should be able to sum them up correctly + @Test + public void testBigIntegerFenwickTree() { + List> segments = new ArrayList>(); + segments.add(new FenwickTree.Data.RangeSumData(0, (BigInteger) BigInteger.valueOf(1))); + segments.add(new FenwickTree.Data.RangeSumData(1, (BigInteger) BigInteger.valueOf(2))); + segments.add(new FenwickTree.Data.RangeSumData(2, (BigInteger) BigInteger.valueOf(6))); + segments.add(new FenwickTree.Data.RangeSumData(3, (BigInteger) BigInteger.valueOf(7))); + + // No matter which order the data is given, all tests should pass + + // Initial order. + testBigIntegerFenwickTree(segments); + + // Randomize it + Collections.shuffle(segments); + testBigIntegerFenwickTree(segments); + + // Try in order + Collections.sort(segments); + testBigIntegerFenwickTree(segments); + + // Try reverse order + Collections.sort(segments,REVERSE); + testBigIntegerFenwickTree(segments); + } + + private void testBigIntegerFenwickTree(List> segments) { // Range Sum Segment tree + FenwickTree> tree = new FenwickTree>(segments); + + FenwickTree.Data.RangeSumData query = tree.query(0, 3); + + query = tree.query(2); + assertTrue("Segment tree query error. query=2 result="+query, tree, query.sum.compareTo(BigInteger.valueOf(6)) == 0); + + query = tree.query(0, 1); // stabbing + assertTrue("Segment tree query error. query=0->1 result="+ query, tree, query.sum.compareTo(BigInteger.valueOf(1).add(BigInteger.valueOf(2))) == 0); + } + + // Requirement: + // When FenwickTree consists of data with Long numbers it should be able to sum them up correctly + @Test + public void testLongFenwickTree() { + List> segments = new ArrayList>(); + segments.add(new FenwickTree.Data.RangeSumData(0, (Long) Long.valueOf(1))); + segments.add(new FenwickTree.Data.RangeSumData(1, (Long) Long.valueOf(2))); + segments.add(new FenwickTree.Data.RangeSumData(2, (Long) Long.valueOf(6))); + segments.add(new FenwickTree.Data.RangeSumData(3, (Long) Long.valueOf(7))); + + // No matter which order the data is given, all tests should pass + + // Initial order. + testLongFenwickTree(segments); + + // Randomize it + Collections.shuffle(segments); + testLongFenwickTree(segments); + + // Try in order + Collections.sort(segments); + testLongFenwickTree(segments); + + // Try reverse order + Collections.sort(segments,REVERSE); + testLongFenwickTree(segments); + } + + private void testLongFenwickTree(List> segments) { // Range Sum Segment tree + FenwickTree> tree = new FenwickTree>(segments); + + FenwickTree.Data.RangeSumData query = tree.query(0, 3); + + query = tree.query(2); + assertTrue("Segment tree query error. query=2 result="+query, tree, query.sum.compareTo(Long.valueOf(6)) == 0); + + query = tree.query(0, 1); // stabbing + assertTrue("Segment tree query error. query=0->1 result="+ query, tree, query.sum.compareTo(Long.sum(Long.valueOf(1), (Long.valueOf(2)))) == 0); + } + + // Requirement: + // When FenwickTree consists of data with Double numbers it should be able to sum them up correctly + @Test + public void testDoubleFenwickTree() { + List> segments = new ArrayList>(); + segments.add(new FenwickTree.Data.RangeSumData(0, (Double) new Double(1.11))); + segments.add(new FenwickTree.Data.RangeSumData(1, (Double) new Double(2.11))); + segments.add(new FenwickTree.Data.RangeSumData(2, (Double) new Double(6.11))); + segments.add(new FenwickTree.Data.RangeSumData(3, (Double) new Double(7.11))); + + // No matter which order the data is given, all tests should pass + + // Initial order. + testDoubleFenwickTree(segments); + + // Randomize it + Collections.shuffle(segments); + testDoubleFenwickTree(segments); + + // Try in order + Collections.sort(segments); + testDoubleFenwickTree(segments); + + // Try reverse order + Collections.sort(segments,REVERSE); + testDoubleFenwickTree(segments); + } + + private void testDoubleFenwickTree(List> segments) { // Range Sum Segment tree + FenwickTree> tree = new FenwickTree>(segments); + + FenwickTree.Data.RangeSumData query = tree.query(0, 3); + + query = tree.query(2); + assertTrue("Segment tree query error. query=2 result="+query, tree, query.sum.compareTo(new Double(6.11)) == 0); + + query = tree.query(0, 1); // stabbing + assertTrue("Segment tree query error. query=0->1 result="+ query, tree, query.sum.compareTo(Double.sum(new Double(1.11),(new Double(2.11)))) == 0); + } + + // Requirement: + // When FenwickTree consists of data with Float numbers it should be able to sum them up correctly + @Test + public void testFloatFenwickTree() { + List> segments = new ArrayList>(); + segments.add(new FenwickTree.Data.RangeSumData(0, (Float) new Float(1.11))); + segments.add(new FenwickTree.Data.RangeSumData(1, (Float) new Float(2.11))); + segments.add(new FenwickTree.Data.RangeSumData(2, (Float) new Float(6.11))); + segments.add(new FenwickTree.Data.RangeSumData(3, (Float) new Float(7.11))); + + // No matter which order the data is given, all tests should pass + + // Initial order. + testFloatFenwickTree(segments); + + // Randomize it + Collections.shuffle(segments); + testFloatFenwickTree(segments); + + // Try in order + Collections.sort(segments); + testFloatFenwickTree(segments); + + // Try reverse order + Collections.sort(segments,REVERSE); + testFloatFenwickTree(segments); + } + + private void testFloatFenwickTree(List> segments) { // Range Sum Segment tree + FenwickTree> tree = new FenwickTree>(segments); + + FenwickTree.Data.RangeSumData query = tree.query(0, 3); + + query = tree.query(2); + assertTrue("Segment tree query error. query=2 result="+query, tree, query.sum.compareTo(new Float(6.11)) == 0); + + query = tree.query(0, 1); // stabbing + assertTrue("Segment tree query error. query=0->1 result="+ query, tree, query.sum.compareTo(Float.sum(new Float(1.11),(new Float(2.11)))) == 0); + } + + + // Requirement: + // Added branch coverage for when an element is null when using the functions combined and separate for every case + // except the case in separate where "this.sum == null && data.sum != null" since it will not be possible to test as + // a separated number supposed to be null (this.sum) from a sum which is not null (data.sum) is equal to 0.0 and not null + // when separated + @Test + public void testNullFenwickTree() { + List> segments = new ArrayList>(); + segments.add(new FenwickTree.Data.RangeSumData(0, null)); + segments.add(new FenwickTree.Data.RangeSumData(1, null)); + segments.add(new FenwickTree.Data.RangeSumData(2, new Float(6.11))); + segments.add(new FenwickTree.Data.RangeSumData(3, null)); + //segments.add(new FenwickTree.Data.RangeSumData(2, (Float) new Float(6.11))); + //segments.add(new FenwickTree.Data.RangeSumData(3, (Float) new Float(7.11))); + + // No matter which order the data is given, all tests should pass + + // Initial order. + testNullFenwickTree(segments); + + // Randomize it + Collections.shuffle(segments); + testNullFenwickTree(segments); + + // Try in order + Collections.sort(segments); + testNullFenwickTree(segments); + + // Try reverse order + Collections.sort(segments,REVERSE); + testNullFenwickTree(segments); + } + + private void testNullFenwickTree(List> segments) { // Range Sum Segment tree + FenwickTree> tree1 = new FenwickTree>(segments); + + FenwickTree.Data.RangeSumData query = tree1.query(0, 3); + + query = tree1.query(1); + assertTrue("Segment tree query error. query=1 result="+query, tree1, query.sum == null); + + query = tree1.query(2); + assertTrue("Segment tree query error. query=2 result="+query, tree1, query.sum.compareTo(new Float(6.11)) == 0); + + query = tree1.query(3); + assertTrue("Segment tree query error. query=3 result="+query, tree1, query.sum == 0.0); + + query = tree1.query(0, 1); // stabbing + assertTrue("Segment tree query error. query=0->1 result="+ query, tree1, query.sum == null); + + query = tree1.query(0, 2); // stabbing + assertTrue("Segment tree query error. query=0->2 result="+ query, tree1, query.sum.compareTo(new Float(6.11)) == 0); + + query = tree1.query(0, 3); // stabbing + assertTrue("Segment tree query error. query=0->3 result="+ query, tree1, query.sum.compareTo(new Float(6.11)) == 0); + + query = tree1.query(2, 3); // stabbing + assertTrue("Segment tree query error. query=2->3 result="+ query, tree1, query.sum.compareTo(new Float(6.11)) == 0); + } } diff --git a/test/com/jwetherell/algorithms/data_structures/test/MatrixTests.java b/test/com/jwetherell/algorithms/data_structures/test/MatrixTests.java index ca0014bf..84fcd51c 100644 --- a/test/com/jwetherell/algorithms/data_structures/test/MatrixTests.java +++ b/test/com/jwetherell/algorithms/data_structures/test/MatrixTests.java @@ -1,5 +1,8 @@ package com.jwetherell.algorithms.data_structures.test; +import java.math.BigDecimal; +import java.math.BigInteger; + import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.junit.Assert.assertArrayEquals; @@ -87,7 +90,407 @@ public void testMatrix() { Matrix matrix9 = matrix7.multiply(matrix8); assertTrue("Matrix multiplication error. matrix9="+matrix9+" result4"+result4, matrix9.equals(result4)); } - + + // Requirement: Matrix addition, subtraction, and multiplication should work correctly with Long values. + @Test + public void testMatrixLongOperations() { + Matrix matrix1 = new Matrix(4, 3); + matrix1.set(0, 0, Long.valueOf(14)); + matrix1.set(0, 1, Long.valueOf(9)); + matrix1.set(0, 2, Long.valueOf(3)); + matrix1.set(1, 0, Long.valueOf(2)); + matrix1.set(1, 1, Long.valueOf(11)); + matrix1.set(1, 2, Long.valueOf(15)); + matrix1.set(2, 0, Long.valueOf(0)); + matrix1.set(2, 1, Long.valueOf(12)); + matrix1.set(2, 2, Long.valueOf(17)); + matrix1.set(3, 0, Long.valueOf(5)); + matrix1.set(3, 1, Long.valueOf(2)); + matrix1.set(3, 2, Long.valueOf(3)); + + Matrix matrix2 = new Matrix(3, 2); + matrix2.set(0, 0, Long.valueOf(12)); + matrix2.set(0, 1, Long.valueOf(25)); + matrix2.set(1, 0, Long.valueOf(9)); + matrix2.set(1, 1, Long.valueOf(10)); + matrix2.set(2, 0, Long.valueOf(8)); + matrix2.set(2, 1, Long.valueOf(5)); + + // Result of multiplication + Long[][] array1 = new Long[][]{{Long.valueOf(273),Long.valueOf(455)}, + {Long.valueOf(243),Long.valueOf(235)}, + {Long.valueOf(244),Long.valueOf(205)}, + {Long.valueOf(102),Long.valueOf(160)}}; + Matrix result1 = new Matrix(4,2,array1); + + Matrix matrix3 = matrix1.multiply(matrix2); + assertTrue("Matrix multiplication error. matrix3="+matrix3+" result1"+result1, matrix3.equals(result1)); + + int rows = 2; + int cols = 2; + int counter = 0; + Matrix matrix4 = new Matrix(rows, cols); + for (int r = 0; r < rows; r++) + for (int c = 0; c < cols; c++) + matrix4.set(r, c, Long.valueOf(counter++)); + + // Result of subtraction + Long[][] array2 = new Long[][]{{Long.valueOf(0),Long.valueOf(0)}, + {Long.valueOf(0),Long.valueOf(0)}}; + Matrix result2 = new Matrix(2,2,array2); + + Matrix matrix5 = matrix4.subtract(matrix4); + assertTrue("Matrix subtraction error. matrix5="+matrix5+" result2"+result2, matrix5.equals(result2)); + + // Result of addition + Long[][] array3 = new Long[][]{{Long.valueOf(0),Long.valueOf(2)}, + {Long.valueOf(4),Long.valueOf(6)}}; + Matrix result3 = new Matrix(2,2,array3); + + Matrix matrix6 = matrix4.add(matrix4); + assertTrue("Matrix addition error. matrix6="+matrix6+" result3"+result3, matrix6.equals(result3)); + + Matrix matrix7 = new Matrix(2, 2); + matrix7.set(0, 0, Long.valueOf(1)); + matrix7.set(0, 1, Long.valueOf(2)); + matrix7.set(1, 0, Long.valueOf(3)); + matrix7.set(1, 1, Long.valueOf(4)); + + Matrix matrix8 = new Matrix(2, 2); + matrix8.set(0, 0, Long.valueOf(1)); + matrix8.set(0, 1, Long.valueOf(2)); + matrix8.set(1, 0, Long.valueOf(3)); + matrix8.set(1, 1, Long.valueOf(4)); + + // Result of multiplication + Long[][] array4 = new Long[][]{{Long.valueOf(7),Long.valueOf(10)}, + {Long.valueOf(15),Long.valueOf(22)}}; + Matrix result4 = new Matrix(2,2,array4); + + Matrix matrix9 = matrix7.multiply(matrix8); + assertTrue("Matrix multiplication error. matrix9="+matrix9+" result4"+result4, matrix9.equals(result4)); + } + + // Requirement: Matrix addition, subtraction, and multiplication should work correctly with Float values. + @Test + public void testMatrixFloatOperations() { + Matrix matrix1 = new Matrix(4, 3); + matrix1.set(0, 0, Float.valueOf(14)); + matrix1.set(0, 1, Float.valueOf(9)); + matrix1.set(0, 2, Float.valueOf(3)); + matrix1.set(1, 0, Float.valueOf(2)); + matrix1.set(1, 1, Float.valueOf(11)); + matrix1.set(1, 2, Float.valueOf(15)); + matrix1.set(2, 0, Float.valueOf(0)); + matrix1.set(2, 1, Float.valueOf(12)); + matrix1.set(2, 2, Float.valueOf(17)); + matrix1.set(3, 0, Float.valueOf(5)); + matrix1.set(3, 1, Float.valueOf(2)); + matrix1.set(3, 2, Float.valueOf(3)); + + Matrix matrix2 = new Matrix(3, 2); + matrix2.set(0, 0, Float.valueOf(12)); + matrix2.set(0, 1, Float.valueOf(25)); + matrix2.set(1, 0, Float.valueOf(9)); + matrix2.set(1, 1, Float.valueOf(10)); + matrix2.set(2, 0, Float.valueOf(8)); + matrix2.set(2, 1, Float.valueOf(5)); + + // Result of multiplication + Float[][] array1 = new Float[][]{{Float.valueOf(273),Float.valueOf(455)}, + {Float.valueOf(243),Float.valueOf(235)}, + {Float.valueOf(244),Float.valueOf(205)}, + {Float.valueOf(102),Float.valueOf(160)}}; + Matrix result1 = new Matrix(4,2,array1); + + Matrix matrix3 = matrix1.multiply(matrix2); + assertTrue("Matrix multiplication error. matrix3="+matrix3+" result1"+result1, matrix3.equals(result1)); + + int rows = 2; + int cols = 2; + int counter = 0; + Matrix matrix4 = new Matrix(rows, cols); + for (int r = 0; r < rows; r++) + for (int c = 0; c < cols; c++) + matrix4.set(r, c, Float.valueOf(counter++)); + + // Result of subtraction + Float[][] array2 = new Float[][]{{Float.valueOf(0),Float.valueOf(0)}, + {Float.valueOf(0),Float.valueOf(0)}}; + Matrix result2 = new Matrix(2,2,array2); + + Matrix matrix5 = matrix4.subtract(matrix4); + assertTrue("Matrix subtraction error. matrix5="+matrix5+" result2"+result2, matrix5.equals(result2)); + + // Result of addition + Float[][] array3 = new Float[][]{{Float.valueOf(0),Float.valueOf(2)}, + {Float.valueOf(4),Float.valueOf(6)}}; + Matrix result3 = new Matrix(2,2,array3); + + Matrix matrix6 = matrix4.add(matrix4); + assertTrue("Matrix addition error. matrix6="+matrix6+" result3"+result3, matrix6.equals(result3)); + + Matrix matrix7 = new Matrix(2, 2); + matrix7.set(0, 0, Float.valueOf(1)); + matrix7.set(0, 1, Float.valueOf(2)); + matrix7.set(1, 0, Float.valueOf(3)); + matrix7.set(1, 1, Float.valueOf(4)); + + Matrix matrix8 = new Matrix(2, 2); + matrix8.set(0, 0, Float.valueOf(1)); + matrix8.set(0, 1, Float.valueOf(2)); + matrix8.set(1, 0, Float.valueOf(3)); + matrix8.set(1, 1, Float.valueOf(4)); + + // Result of multiplication + Float[][] array4 = new Float[][]{{Float.valueOf(7),Float.valueOf(10)}, + {Float.valueOf(15),Float.valueOf(22)}}; + Matrix result4 = new Matrix(2,2,array4); + + Matrix matrix9 = matrix7.multiply(matrix8); + assertTrue("Matrix multiplication error. matrix9="+matrix9+" result4"+result4, matrix9.equals(result4)); + } + + // Requirement: Matrix addition, subtraction, and multiplication should work correctly with Double values. + @Test + public void testMatrixDoubleOperations() { + Matrix matrix1 = new Matrix(4, 3); + matrix1.set(0, 0, Double.valueOf(14)); + matrix1.set(0, 1, Double.valueOf(9)); + matrix1.set(0, 2, Double.valueOf(3)); + matrix1.set(1, 0, Double.valueOf(2)); + matrix1.set(1, 1, Double.valueOf(11)); + matrix1.set(1, 2, Double.valueOf(15)); + matrix1.set(2, 0, Double.valueOf(0)); + matrix1.set(2, 1, Double.valueOf(12)); + matrix1.set(2, 2, Double.valueOf(17)); + matrix1.set(3, 0, Double.valueOf(5)); + matrix1.set(3, 1, Double.valueOf(2)); + matrix1.set(3, 2, Double.valueOf(3)); + + Matrix matrix2 = new Matrix(3, 2); + matrix2.set(0, 0, Double.valueOf(12)); + matrix2.set(0, 1, Double.valueOf(25)); + matrix2.set(1, 0, Double.valueOf(9)); + matrix2.set(1, 1, Double.valueOf(10)); + matrix2.set(2, 0, Double.valueOf(8)); + matrix2.set(2, 1, Double.valueOf(5)); + + // Result of multiplication + Double[][] array1 = new Double[][]{{Double.valueOf(273),Double.valueOf(455)}, + {Double.valueOf(243),Double.valueOf(235)}, + {Double.valueOf(244),Double.valueOf(205)}, + {Double.valueOf(102),Double.valueOf(160)}}; + Matrix result1 = new Matrix(4,2,array1); + + Matrix matrix3 = matrix1.multiply(matrix2); + assertTrue("Matrix multiplication error. matrix3="+matrix3+" result1"+result1, matrix3.equals(result1)); + + int rows = 2; + int cols = 2; + int counter = 0; + Matrix matrix4 = new Matrix(rows, cols); + for (int r = 0; r < rows; r++) + for (int c = 0; c < cols; c++) + matrix4.set(r, c, Double.valueOf(counter++)); + + // Result of subtraction + Double[][] array2 = new Double[][]{{Double.valueOf(0),Double.valueOf(0)}, + {Double.valueOf(0),Double.valueOf(0)}}; + Matrix result2 = new Matrix(2,2,array2); + + Matrix matrix5 = matrix4.subtract(matrix4); + assertTrue("Matrix subtraction error. matrix5="+matrix5+" result2"+result2, matrix5.equals(result2)); + + // Result of addition + Double[][] array3 = new Double[][]{{Double.valueOf(0),Double.valueOf(2)}, + {Double.valueOf(4),Double.valueOf(6)}}; + Matrix result3 = new Matrix(2,2,array3); + + Matrix matrix6 = matrix4.add(matrix4); + assertTrue("Matrix addition error. matrix6="+matrix6+" result3"+result3, matrix6.equals(result3)); + + Matrix matrix7 = new Matrix(2, 2); + matrix7.set(0, 0, Double.valueOf(1)); + matrix7.set(0, 1, Double.valueOf(2)); + matrix7.set(1, 0, Double.valueOf(3)); + matrix7.set(1, 1, Double.valueOf(4)); + + Matrix matrix8 = new Matrix(2, 2); + matrix8.set(0, 0, Double.valueOf(1)); + matrix8.set(0, 1, Double.valueOf(2)); + matrix8.set(1, 0, Double.valueOf(3)); + matrix8.set(1, 1, Double.valueOf(4)); + + // Result of multiplication + Double[][] array4 = new Double[][]{{Double.valueOf(7),Double.valueOf(10)}, + {Double.valueOf(15),Double.valueOf(22)}}; + Matrix result4 = new Matrix(2,2,array4); + + Matrix matrix9 = matrix7.multiply(matrix8); + assertTrue("Matrix multiplication error. matrix9="+matrix9+" result4"+result4, matrix9.equals(result4)); + } + + // Requirement: Matrix addition, subtraction, and multiplication should work correctly with BigDecimal values. + @Test + public void testMatrixBigDecimalOperations() { + Matrix matrix1 = new Matrix(4, 3); + matrix1.set(0, 0, BigDecimal.valueOf(14)); + matrix1.set(0, 1, BigDecimal.valueOf(9)); + matrix1.set(0, 2, BigDecimal.valueOf(3)); + matrix1.set(1, 0, BigDecimal.valueOf(2)); + matrix1.set(1, 1, BigDecimal.valueOf(11)); + matrix1.set(1, 2, BigDecimal.valueOf(15)); + matrix1.set(2, 0, BigDecimal.valueOf(0)); + matrix1.set(2, 1, BigDecimal.valueOf(12)); + matrix1.set(2, 2, BigDecimal.valueOf(17)); + matrix1.set(3, 0, BigDecimal.valueOf(5)); + matrix1.set(3, 1, BigDecimal.valueOf(2)); + matrix1.set(3, 2, BigDecimal.valueOf(3)); + + Matrix matrix2 = new Matrix(3, 2); + matrix2.set(0, 0, BigDecimal.valueOf(12)); + matrix2.set(0, 1, BigDecimal.valueOf(25)); + matrix2.set(1, 0, BigDecimal.valueOf(9)); + matrix2.set(1, 1, BigDecimal.valueOf(10)); + matrix2.set(2, 0, BigDecimal.valueOf(8)); + matrix2.set(2, 1, BigDecimal.valueOf(5)); + + // Result of multiplication + BigDecimal[][] array1 = new BigDecimal[][]{{BigDecimal.valueOf(273),BigDecimal.valueOf(455)}, + {BigDecimal.valueOf(243),BigDecimal.valueOf(235)}, + {BigDecimal.valueOf(244),BigDecimal.valueOf(205)}, + {BigDecimal.valueOf(102),BigDecimal.valueOf(160)}}; + Matrix result1 = new Matrix(4,2,array1); + + Matrix matrix3 = matrix1.multiply(matrix2); + assertTrue("Matrix multiplication error. matrix3="+matrix3+" result1"+result1, matrix3.equals(result1)); + + int rows = 2; + int cols = 2; + int counter = 0; + Matrix matrix4 = new Matrix(rows, cols); + for (int r = 0; r < rows; r++) + for (int c = 0; c < cols; c++) + matrix4.set(r, c, BigDecimal.valueOf(counter++)); + + // Result of subtraction + BigDecimal[][] array2 = new BigDecimal[][]{{BigDecimal.valueOf(0),BigDecimal.valueOf(0)}, + {BigDecimal.valueOf(0),BigDecimal.valueOf(0)}}; + Matrix result2 = new Matrix(2,2,array2); + + Matrix matrix5 = matrix4.subtract(matrix4); + assertTrue("Matrix subtraction error. matrix5="+matrix5+" result2"+result2, matrix5.equals(result2)); + + // Result of addition + BigDecimal[][] array3 = new BigDecimal[][]{{BigDecimal.valueOf(0),BigDecimal.valueOf(2)}, + {BigDecimal.valueOf(4),BigDecimal.valueOf(6)}}; + Matrix result3 = new Matrix(2,2,array3); + + Matrix matrix6 = matrix4.add(matrix4); + assertTrue("Matrix addition error. matrix6="+matrix6+" result3"+result3, matrix6.equals(result3)); + + Matrix matrix7 = new Matrix(2, 2); + matrix7.set(0, 0, BigDecimal.valueOf(1)); + matrix7.set(0, 1, BigDecimal.valueOf(2)); + matrix7.set(1, 0, BigDecimal.valueOf(3)); + matrix7.set(1, 1, BigDecimal.valueOf(4)); + + Matrix matrix8 = new Matrix(2, 2); + matrix8.set(0, 0, BigDecimal.valueOf(1)); + matrix8.set(0, 1, BigDecimal.valueOf(2)); + matrix8.set(1, 0, BigDecimal.valueOf(3)); + matrix8.set(1, 1, BigDecimal.valueOf(4)); + + // Result of multiplication + BigDecimal[][] array4 = new BigDecimal[][]{{BigDecimal.valueOf(7),BigDecimal.valueOf(10)}, + {BigDecimal.valueOf(15),BigDecimal.valueOf(22)}}; + Matrix result4 = new Matrix(2,2,array4); + + Matrix matrix9 = matrix7.multiply(matrix8); + assertTrue("Matrix multiplication error. matrix9="+matrix9+" result4"+result4, matrix9.equals(result4)); + } + + // Requirement: Matrix addition, subtraction, and multiplication should work correctly with BigInteger values. + @Test + public void testMatrixBigIntegerOperations() { + Matrix matrix1 = new Matrix(4, 3); + matrix1.set(0, 0, BigInteger.valueOf(14)); + matrix1.set(0, 1, BigInteger.valueOf(9)); + matrix1.set(0, 2, BigInteger.valueOf(3)); + matrix1.set(1, 0, BigInteger.valueOf(2)); + matrix1.set(1, 1, BigInteger.valueOf(11)); + matrix1.set(1, 2, BigInteger.valueOf(15)); + matrix1.set(2, 0, BigInteger.valueOf(0)); + matrix1.set(2, 1, BigInteger.valueOf(12)); + matrix1.set(2, 2, BigInteger.valueOf(17)); + matrix1.set(3, 0, BigInteger.valueOf(5)); + matrix1.set(3, 1, BigInteger.valueOf(2)); + matrix1.set(3, 2, BigInteger.valueOf(3)); + + Matrix matrix2 = new Matrix(3, 2); + matrix2.set(0, 0, BigInteger.valueOf(12)); + matrix2.set(0, 1, BigInteger.valueOf(25)); + matrix2.set(1, 0, BigInteger.valueOf(9)); + matrix2.set(1, 1, BigInteger.valueOf(10)); + matrix2.set(2, 0, BigInteger.valueOf(8)); + matrix2.set(2, 1, BigInteger.valueOf(5)); + + // Result of multiplication + BigInteger[][] array1 = new BigInteger[][]{{BigInteger.valueOf(273),BigInteger.valueOf(455)}, + {BigInteger.valueOf(243),BigInteger.valueOf(235)}, + {BigInteger.valueOf(244),BigInteger.valueOf(205)}, + {BigInteger.valueOf(102),BigInteger.valueOf(160)}}; + Matrix result1 = new Matrix(4,2,array1); + + Matrix matrix3 = matrix1.multiply(matrix2); + assertTrue("Matrix multiplication error. matrix3="+matrix3+" result1"+result1, matrix3.equals(result1)); + + int rows = 2; + int cols = 2; + int counter = 0; + Matrix matrix4 = new Matrix(rows, cols); + for (int r = 0; r < rows; r++) + for (int c = 0; c < cols; c++) + matrix4.set(r, c, BigInteger.valueOf(counter++)); + + // Result of subtraction + BigInteger[][] array2 = new BigInteger[][]{{BigInteger.valueOf(0),BigInteger.valueOf(0)}, + {BigInteger.valueOf(0),BigInteger.valueOf(0)}}; + Matrix result2 = new Matrix(2,2,array2); + + Matrix matrix5 = matrix4.subtract(matrix4); + assertTrue("Matrix subtraction error. matrix5="+matrix5+" result2"+result2, matrix5.equals(result2)); + + // Result of addition + BigInteger[][] array3 = new BigInteger[][]{{BigInteger.valueOf(0),BigInteger.valueOf(2)}, + {BigInteger.valueOf(4),BigInteger.valueOf(6)}}; + Matrix result3 = new Matrix(2,2,array3); + + Matrix matrix6 = matrix4.add(matrix4); + assertTrue("Matrix addition error. matrix6="+matrix6+" result3"+result3, matrix6.equals(result3)); + + Matrix matrix7 = new Matrix(2, 2); + matrix7.set(0, 0, BigInteger.valueOf(1)); + matrix7.set(0, 1, BigInteger.valueOf(2)); + matrix7.set(1, 0, BigInteger.valueOf(3)); + matrix7.set(1, 1, BigInteger.valueOf(4)); + + Matrix matrix8 = new Matrix(2, 2); + matrix8.set(0, 0, BigInteger.valueOf(1)); + matrix8.set(0, 1, BigInteger.valueOf(2)); + matrix8.set(1, 0, BigInteger.valueOf(3)); + matrix8.set(1, 1, BigInteger.valueOf(4)); + + // Result of multiplication + BigInteger[][] array4 = new BigInteger[][]{{BigInteger.valueOf(7),BigInteger.valueOf(10)}, + {BigInteger.valueOf(15),BigInteger.valueOf(22)}}; + Matrix result4 = new Matrix(2,2,array4); + + Matrix matrix9 = matrix7.multiply(matrix8); + assertTrue("Matrix multiplication error. matrix9="+matrix9+" result4"+result4, matrix9.equals(result4)); + } + @Test public void testIdentityMethod1() { Matrix matrix = new Matrix(2, 2); @@ -111,4 +514,346 @@ public void testIdentityMethod1() { assertArrayEquals(expectedResult.getRow(0), matrix.getRow(0)); assertArrayEquals(expectedResult.getRow(1), matrix.getRow(1)); } + + // Requirement: Matrix addition should work correctly with Long values. + @Test + public void testAddLong() { + Matrix matrix = new Matrix(2, 2); + matrix.set(0, 0, Long.valueOf(1)); + matrix.set(0, 1, Long.valueOf(2)); + matrix.set(1, 0, Long.valueOf(3)); + matrix.set(1, 1, Long.valueOf(4)); + + Matrix actualResult = matrix.add(matrix); + + Matrix expectedResult = new Matrix(2, 2); + expectedResult.set(0, 0, Long.valueOf(2)); + expectedResult.set(0, 1, Long.valueOf(4)); + expectedResult.set(1, 0, Long.valueOf(6)); + expectedResult.set(1, 1, Long.valueOf(8)); + + assertArrayEquals(expectedResult.getRow(0), actualResult.getRow(0)); + assertArrayEquals(expectedResult.getRow(1), actualResult.getRow(1)); + } + + // Requirement: Matrix addition should work correctly with BigInteger values. + @Test + public void testAddBigInteger() { + Matrix matrix = new Matrix(2, 2); + matrix.set(0, 0, BigInteger.valueOf(1)); + matrix.set(0, 1, BigInteger.valueOf(2)); + matrix.set(1, 0, BigInteger.valueOf(3)); + matrix.set(1, 1, BigInteger.valueOf(4)); + + Matrix actualResult = matrix.add(matrix); + + Matrix expectedResult = new Matrix(2, 2); + expectedResult.set(0, 0, BigInteger.valueOf(2)); + expectedResult.set(0, 1, BigInteger.valueOf(4)); + expectedResult.set(1, 0, BigInteger.valueOf(6)); + expectedResult.set(1, 1, BigInteger.valueOf(8)); + + assertArrayEquals(expectedResult.getRow(0), actualResult.getRow(0)); + assertArrayEquals(expectedResult.getRow(1), actualResult.getRow(1)); + } + + // Requirement: Matrix addition should work correctly with Float values. + @Test + public void testAddFloat() { + Matrix matrix = new Matrix(1, 1); + matrix.set(0, 0, new Float(1.1)); + + Matrix actual = matrix.add(matrix); + + Matrix expected = new Matrix(1, 1); + expected.set(0, 0, new Float(2.2)); + + Matrix wrong1 = new Matrix(1, 1); + wrong1.set(0, 0, new Float(2.1)); + + Matrix wrong2 = new Matrix(1, 1); + wrong2.set(0, 0, new Float(2.3)); + + assertTrue(Float.compare(actual.get(0, 0), expected.get(0, 0)) == 0); + assertTrue(Float.compare(actual.get(0, 0), wrong1.get(0, 0)) != 0); + assertTrue(Float.compare(actual.get(0, 0), wrong2.get(0, 0)) != 0); + } + + // Requirement: Matrix addition should work correctly with Double values. + @Test + public void testAddDouble() { + Matrix matrix = new Matrix(1, 1); + matrix.set(0, 0, new Double(1.1)); + + Matrix actual = matrix.add(matrix); + + Matrix expected = new Matrix(1, 1); + expected.set(0, 0, new Double(2.2)); + + Matrix wrong1 = new Matrix(1, 1); + wrong1.set(0, 0, new Double(2.1)); + + Matrix wrong2 = new Matrix(1, 1); + wrong2.set(0, 0, new Double(2.3)); + + assertTrue(Double.compare(actual.get(0, 0), expected.get(0, 0)) == 0); + assertTrue(Double.compare(actual.get(0, 0), wrong1.get(0, 0)) != 0); + assertTrue(Double.compare(actual.get(0, 0), wrong2.get(0, 0)) != 0); + } + + // Requirement: Matrix addition should work correctly with BigDecimal values. + @Test + public void testAddBigDecimal() { + Matrix matrix = new Matrix(1, 1); + matrix.set(0, 0, new BigDecimal(1.1)); + + Matrix actual = matrix.add(matrix); + + Matrix expected = new Matrix(1, 1); + expected.set(0, 0, new BigDecimal(2.2)); + + Matrix wrong1 = new Matrix(1, 1); + wrong1.set(0, 0, new BigDecimal(2.1)); + + Matrix wrong2 = new Matrix(1, 1); + wrong2.set(0, 0, new BigDecimal(2.3)); + + BigDecimal diff = actual.get(0, 0).subtract(expected.get(0, 0)).abs(); + assertTrue((diff.compareTo(new BigDecimal(0.00001)) < 0)); + assertTrue(actual.get(0, 0).compareTo(wrong1.get(0, 0)) != 0); + assertTrue(actual.get(0, 0).compareTo(wrong2.get(0, 0)) != 0); + } + + // Requirement: Matrix subtraction should work correctly with Long values. + @Test + public void testSubtractLong() { + Matrix matrix1 = new Matrix(2, 2); + matrix1.set(0, 0, Long.valueOf(1)); + matrix1.set(0, 1, Long.valueOf(2)); + matrix1.set(1, 0, Long.valueOf(3)); + matrix1.set(1, 1, Long.valueOf(4)); + + Matrix matrix2 = new Matrix(2, 2); + matrix2.set(0, 0, Long.valueOf(1*2)); + matrix2.set(0, 1, Long.valueOf(2*2)); + matrix2.set(1, 0, Long.valueOf(3*2)); + matrix2.set(1, 1, Long.valueOf(4*2)); + + Matrix actualResult = matrix1.subtract(matrix2); + + Matrix expectedResult = new Matrix(2, 2); + expectedResult.set(0, 0, Long.valueOf(-1)); + expectedResult.set(0, 1, Long.valueOf(-2)); + expectedResult.set(1, 0, Long.valueOf(-3)); + expectedResult.set(1, 1, Long.valueOf(-4)); + + assertArrayEquals(expectedResult.getRow(0), actualResult.getRow(0)); + assertArrayEquals(expectedResult.getRow(1), actualResult.getRow(1)); + } + + // Requirement: Matrix subtraction should work correctly with BigInteger values. + @Test + public void testSubtractBigInteger() { + Matrix matrix1 = new Matrix(2, 2); + matrix1.set(0, 0, BigInteger.valueOf(1)); + matrix1.set(0, 1, BigInteger.valueOf(2)); + matrix1.set(1, 0, BigInteger.valueOf(3)); + matrix1.set(1, 1, BigInteger.valueOf(4)); + + Matrix matrix2 = new Matrix(2, 2); + matrix2.set(0, 0, BigInteger.valueOf(1*2)); + matrix2.set(0, 1, BigInteger.valueOf(2*2)); + matrix2.set(1, 0, BigInteger.valueOf(3*2)); + matrix2.set(1, 1, BigInteger.valueOf(4*2)); + + Matrix actualResult = matrix1.subtract(matrix2); + + Matrix expectedResult = new Matrix(2, 2); + expectedResult.set(0, 0, BigInteger.valueOf(-1)); + expectedResult.set(0, 1, BigInteger.valueOf(-2)); + expectedResult.set(1, 0, BigInteger.valueOf(-3)); + expectedResult.set(1, 1, BigInteger.valueOf(-4)); + + assertArrayEquals(expectedResult.getRow(0), actualResult.getRow(0)); + assertArrayEquals(expectedResult.getRow(1), actualResult.getRow(1)); + } + + // Requirement: Matrix subtraction should work correctly with Float values. + @Test + public void testSubtractFloat() { + Matrix matrix1 = new Matrix(1, 1); + matrix1.set(0, 0, new Float(1.1)); + + Matrix matrix2 = new Matrix(1, 1); + matrix2.set(0, 0, new Float(1.1*2)); + + Matrix actual = matrix1.subtract(matrix2); + + Matrix expected = new Matrix(1, 1); + expected.set(0, 0, new Float(-1.1)); + + Matrix wrong1 = new Matrix(1, 1); + wrong1.set(0, 0, new Float(-1.05)); + + Matrix wrong2 = new Matrix(1, 1); + wrong2.set(0, 0, new Float(1.15)); + + assertTrue(Math.abs(actual.get(0, 0) - expected.get(0, 0)) < 0.00001); + assertTrue(Float.compare(actual.get(0, 0), wrong1.get(0, 0)) != 0); + assertTrue(Float.compare(actual.get(0, 0), wrong2.get(0, 0)) != 0); + } + + // Requirement: Matrix subtraction should work correctly with Double values. + @Test + public void testSubtractDouble() { + Matrix matrix1 = new Matrix(1, 1); + matrix1.set(0, 0, new Double(1.1)); + + Matrix matrix2 = new Matrix(1, 1); + matrix2.set(0, 0, new Double(1.1*2)); + + Matrix actual = matrix1.subtract(matrix2); + + Matrix expected = new Matrix(1, 1); + expected.set(0, 0, new Double(-1.1)); + + Matrix wrong1 = new Matrix(1, 1); + wrong1.set(0, 0, new Double(-1.05)); + + Matrix wrong2 = new Matrix(1, 1); + wrong2.set(0, 0, new Double(1.15)); + + assertTrue(Math.abs(actual.get(0, 0) - expected.get(0, 0)) < 0.00001); + assertTrue(Double.compare(actual.get(0, 0), wrong1.get(0, 0)) != 0); + assertTrue(Double.compare(actual.get(0, 0), wrong2.get(0, 0)) != 0); + } + + // Requirement: Matrix subtraction should work correctly with BigDecimal values. + @Test + public void testSubtractBigDecimal() { + Matrix matrix1 = new Matrix(1, 1); + matrix1.set(0, 0, new BigDecimal(1.1)); + + Matrix matrix2 = new Matrix(1, 1); + matrix2.set(0, 0, new BigDecimal(1.1*2)); + + Matrix actual = matrix1.subtract(matrix2); + + Matrix expected = new Matrix(1, 1); + expected.set(0, 0, new BigDecimal(-1.1)); + + Matrix wrong1 = new Matrix(1, 1); + wrong1.set(0, 0, new BigDecimal(-1.05)); + + Matrix wrong2 = new Matrix(1, 1); + wrong2.set(0, 0, new BigDecimal(1.15)); + + BigDecimal diff = actual.get(0, 0).subtract(expected.get(0, 0)).abs(); + assertTrue((diff.compareTo(new BigDecimal(0.00001)) < 0)); + assertTrue(actual.get(0, 0).compareTo(wrong1.get(0, 0)) != 0); + assertTrue(actual.get(0, 0).compareTo(wrong2.get(0, 0)) != 0); + } + + // Requirement: Matrix multiplication should work correctly with Long values. + @Test + public void testMultiplyLong() { + Matrix matrix = new Matrix(1, 1); + matrix.set(0, 0, new Long(2)); + + Matrix actual = matrix.multiply(matrix); + + Matrix expected = new Matrix(1, 1); + expected.set(0, 0, new Long(4)); + + Matrix wrong = new Matrix(1, 1); + wrong.set(0, 0, new Long(3)); + + assertTrue(Long.compare(actual.get(0, 0), expected.get(0, 0)) == 0); + assertTrue(Long.compare(actual.get(0, 0), wrong.get(0, 0)) != 0); + } + + // Requirement: Matrix multiplication should work correctly with BigInteger values. + @Test + public void testMultiplyBigInteger() { + Matrix matrix = new Matrix(1, 1); + matrix.set(0, 0, BigInteger.valueOf(2)); + + Matrix actual = matrix.multiply(matrix); + + Matrix expected = new Matrix(1, 1); + expected.set(0, 0, BigInteger.valueOf(4)); + + Matrix wrong = new Matrix(1, 1); + wrong.set(0, 0, BigInteger.valueOf(3)); + + assertTrue(actual.get(0, 0).compareTo(expected.get(0, 0)) == 0); + assertTrue(actual.get(0, 0).compareTo(wrong.get(0, 0)) != 0); + } + + // Requirement: Matrix multiplication should work correctly with Float values + @Test + public void testMultiplyFloat() { + Matrix matrix = new Matrix(1, 1); + matrix.set(0, 0, new Float(1.1)); + + Matrix actual = matrix.multiply(matrix); + + Matrix expected = new Matrix(1, 1); + expected.set(0, 0, new Float(1.21)); + + Matrix wrong1 = new Matrix(1, 1); + wrong1.set(0, 0, new Float(1.2)); + + Matrix wrong2 = new Matrix(1, 1); + wrong2.set(0, 0, new Float(1.22)); + + assertTrue(Math.abs(actual.get(0, 0) - expected.get(0, 0)) < 0.00001); + assertTrue(Float.compare(actual.get(0, 0), wrong1.get(0, 0)) != 0); + assertTrue(Float.compare(actual.get(0, 0), wrong2.get(0, 0)) != 0); + } + + // Requirement: Matrix multiplication should work correctly with Double values + @Test + public void testMultiplyDouble() { + Matrix matrix = new Matrix(1, 1); + matrix.set(0, 0, new Double(1.1)); + + Matrix actual = matrix.multiply(matrix); + + Matrix expected = new Matrix(1, 1); + expected.set(0, 0, new Double(1.21)); + + Matrix wrong1 = new Matrix(1, 1); + wrong1.set(0, 0, new Double(1.2)); + + Matrix wrong2 = new Matrix(1, 1); + wrong2.set(0, 0, new Double(1.22)); + + assertTrue(Math.abs(actual.get(0, 0) - expected.get(0, 0)) < 0.00001); + assertTrue(Double.compare(actual.get(0, 0), wrong1.get(0, 0)) != 0); + assertTrue(Double.compare(actual.get(0, 0), wrong2.get(0, 0)) != 0); + } + + // Requirement: Matrix multiplication should work correctly with BigDecimal values + @Test + public void testMultiplyBigDecimal() { + Matrix matrix = new Matrix(1, 1); + matrix.set(0, 0, new BigDecimal(1.1)); + + Matrix actual = matrix.multiply(matrix); + + Matrix expected = new Matrix(1, 1); + expected.set(0, 0, new BigDecimal(1.21)); + + Matrix wrong1 = new Matrix(1, 1); + wrong1.set(0, 0, new BigDecimal(1.2)); + + Matrix wrong2 = new Matrix(1, 1); + wrong2.set(0, 0, new BigDecimal(1.22)); + + BigDecimal diff = actual.get(0, 0).subtract(expected.get(0, 0)).abs(); + assertTrue((diff.compareTo(new BigDecimal(0.00001)) < 0)); + assertTrue(actual.get(0, 0).compareTo(wrong1.get(0, 0)) != 0); + assertTrue(actual.get(0, 0).compareTo(wrong2.get(0, 0)) != 0); + } } diff --git a/test/com/jwetherell/algorithms/data_structures/test/SegmentTreeTests.java b/test/com/jwetherell/algorithms/data_structures/test/SegmentTreeTests.java index d15d93f8..2187d415 100644 --- a/test/com/jwetherell/algorithms/data_structures/test/SegmentTreeTests.java +++ b/test/com/jwetherell/algorithms/data_structures/test/SegmentTreeTests.java @@ -15,6 +15,8 @@ import com.jwetherell.algorithms.data_structures.SegmentTree.DynamicSegmentTree; import com.jwetherell.algorithms.data_structures.SegmentTree.FlatSegmentTree; +import java.math.BigDecimal; +import java.math.BigInteger; public class SegmentTreeTests { @Test @@ -57,7 +59,7 @@ private void testQuadrantSegmentTree(java.util.List> segments = new ArrayList>(); segments.add(new SegmentTree.Data.RangeMaximumData(0, (Integer) 4)); segments.add(new SegmentTree.Data.RangeMaximumData(1, (Integer) 2)); @@ -72,22 +74,22 @@ public void testRangeMaxSegmentTree() { // No matter which order the data is given, all tests should pass // Initial order. - testRangeMaxSegmentTree(segments); + testRangeMaxSegmentTreeInteger(segments); // Randomize it Collections.shuffle(segments); - testRangeMaxSegmentTree(segments); + testRangeMaxSegmentTreeInteger(segments); // Try in order Collections.sort(segments); - testRangeMaxSegmentTree(segments); + testRangeMaxSegmentTreeInteger(segments); // Try reverse order Collections.sort(segments,REVERSE); - testRangeMaxSegmentTree(segments); + testRangeMaxSegmentTreeInteger(segments); } - private void testRangeMaxSegmentTree(java.util.List> segments) { // Range Maximum Segment tree + private void testRangeMaxSegmentTreeInteger(java.util.List> segments) { // Range Maximum Segment tree FlatSegmentTree> tree = new FlatSegmentTree>(segments, 3); SegmentTree.Data.RangeMaximumData query = tree.query(0, 7); @@ -116,7 +118,303 @@ private void testRangeMaxSegmentTree(java.util.List> segments = new ArrayList>(); + segments.add(new SegmentTree.Data.RangeMaximumData(0, (BigInteger.valueOf(4)))); + segments.add(new SegmentTree.Data.RangeMaximumData(1, (BigInteger.valueOf(2)))); + segments.add(new SegmentTree.Data.RangeMaximumData(2, (BigInteger.valueOf(6)))); + segments.add(new SegmentTree.Data.RangeMaximumData(3, (BigInteger.valueOf(3)))); + segments.add(new SegmentTree.Data.RangeMaximumData(4, (BigInteger.valueOf(1)))); + segments.add(new SegmentTree.Data.RangeMaximumData(5, (BigInteger.valueOf(5)))); + segments.add(new SegmentTree.Data.RangeMaximumData(6, (BigInteger.valueOf(0)))); + segments.add(new SegmentTree.Data.RangeMaximumData(7, 17, (BigInteger.valueOf(7)))); + segments.add(new SegmentTree.Data.RangeMaximumData(21, (BigInteger.valueOf(10)))); + + // No matter which order the data is given, all tests should pass + + // Initial order. + testRangeMaxSegmentTreeBigInteger(segments); + + // Randomize it + Collections.shuffle(segments); + testRangeMaxSegmentTreeBigInteger(segments); + + // Try in order + Collections.sort(segments); + testRangeMaxSegmentTreeBigInteger(segments); + + // Try reverse order + Collections.sort(segments,REVERSE); + testRangeMaxSegmentTreeBigInteger(segments); + } + + private void testRangeMaxSegmentTreeBigInteger(java.util.List> segments) { // Range Maximum Segment tree + FlatSegmentTree> tree = new FlatSegmentTree>(segments, 3); + + SegmentTree.Data.RangeMaximumData query = tree.query(0, 7); + assertTrue("Segment tree query error. query=0->7 result="+query, tree, query.maximum==BigInteger.valueOf(7)); + + query = tree.query(0, 21); + assertTrue("Segment tree query error. query=0->21 result="+query, tree, query.maximum==BigInteger.valueOf(10)); + + // bounds checking + { + // max is first + query = tree.query(2, 4); + assertTrue("Segment tree query error. query=2->4 result="+query, tree, query.maximum==BigInteger.valueOf(6)); + + // max is middle + query = tree.query(4, 6); + assertTrue("Segment tree query error. query=4->6 result="+query, tree, query.maximum==BigInteger.valueOf(5)); + + // max is last + query = tree.query(5, 7); + assertTrue("Segment tree query error. query=5->7 result="+query, tree, query.maximum==BigInteger.valueOf(7)); + } + + query = tree.query(7); // stabbing + assertTrue("Segment tree query error. query=7 result="+query, tree, query.maximum==BigInteger.valueOf(7)); + } + + @Test + public void testRangeMaxSegmentTreeBigDecimal() { + java.util.List> segments = new ArrayList>(); + segments.add(new SegmentTree.Data.RangeMaximumData(0, BigDecimal.valueOf(4))); + segments.add(new SegmentTree.Data.RangeMaximumData(1, BigDecimal.valueOf(2))); + segments.add(new SegmentTree.Data.RangeMaximumData(2, BigDecimal.valueOf(6))); + segments.add(new SegmentTree.Data.RangeMaximumData(3, BigDecimal.valueOf(3))); + segments.add(new SegmentTree.Data.RangeMaximumData(4, BigDecimal.valueOf(1))); + segments.add(new SegmentTree.Data.RangeMaximumData(5, BigDecimal.valueOf(5))); + segments.add(new SegmentTree.Data.RangeMaximumData(6, BigDecimal.valueOf(0))); + segments.add(new SegmentTree.Data.RangeMaximumData(7, 17, BigDecimal.valueOf(7))); + segments.add(new SegmentTree.Data.RangeMaximumData(21, BigDecimal.valueOf(10))); + + // No matter which order the data is given, all tests should pass + + // Initial order. + testRangeMaxSegmentTreeBigDecimal(segments); + + // Randomize it + Collections.shuffle(segments); + testRangeMaxSegmentTreeBigDecimal(segments); + + // Try in order + Collections.sort(segments); + testRangeMaxSegmentTreeBigDecimal(segments); + + // Try reverse order + Collections.sort(segments,REVERSE); + testRangeMaxSegmentTreeBigDecimal(segments); + } + + private void testRangeMaxSegmentTreeBigDecimal(java.util.List> segments) { // Range Maximum Segment tree + FlatSegmentTree> tree = new FlatSegmentTree>(segments, 3); + + SegmentTree.Data.RangeMaximumData query = tree.query(0, 7); + assertTrue("Segment tree query error. query=0->7 result="+query, tree, query.maximum==BigDecimal.valueOf(7)); + + query = tree.query(0, 21); + assertTrue("Segment tree query error. query=0->21 result="+query, tree, query.maximum==BigDecimal.valueOf(10)); + + // bounds checking + { + // max is first + query = tree.query(2, 4); + assertTrue("Segment tree query error. query=2->4 result="+query, tree, query.maximum==BigDecimal.valueOf(6)); + + // max is middle + query = tree.query(4, 6); + assertTrue("Segment tree query error. query=4->6 result="+query, tree, query.maximum==BigDecimal.valueOf(5)); + + // max is last + query = tree.query(5, 7); + assertTrue("Segment tree query error. query=5->7 result="+query, tree, query.maximum==BigDecimal.valueOf(7)); + } + + query = tree.query(7); // stabbing + assertTrue("Segment tree query error. query=7 result="+query, tree, query.maximum==BigDecimal.valueOf(7)); + } + + @Test + public void testRangeMaxSegmentTreeLong() { + java.util.List> segments = new ArrayList>(); + segments.add(new SegmentTree.Data.RangeMaximumData(0, Long.valueOf(4))); + segments.add(new SegmentTree.Data.RangeMaximumData(1, Long.valueOf(2))); + segments.add(new SegmentTree.Data.RangeMaximumData(2, Long.valueOf(6))); + segments.add(new SegmentTree.Data.RangeMaximumData(3, Long.valueOf(3))); + segments.add(new SegmentTree.Data.RangeMaximumData(4, Long.valueOf(1))); + segments.add(new SegmentTree.Data.RangeMaximumData(5, Long.valueOf(5))); + segments.add(new SegmentTree.Data.RangeMaximumData(6, Long.valueOf(0))); + segments.add(new SegmentTree.Data.RangeMaximumData(7, 17, Long.valueOf(7))); + segments.add(new SegmentTree.Data.RangeMaximumData(21, Long.valueOf(10))); + + // No matter which order the data is given, all tests should pass + + // Initial order. + testRangeMaxSegmentTreeLong(segments); + + // Randomize it + Collections.shuffle(segments); + testRangeMaxSegmentTreeLong(segments); + + // Try in order + Collections.sort(segments); + testRangeMaxSegmentTreeLong(segments); + + // Try reverse order + Collections.sort(segments,REVERSE); + testRangeMaxSegmentTreeLong(segments); + } + + private void testRangeMaxSegmentTreeLong(java.util.List> segments) { // Range Maximum Segment tree + FlatSegmentTree> tree = new FlatSegmentTree>(segments, 3); + + SegmentTree.Data.RangeMaximumData query = tree.query(0, 7); + assertTrue("Segment tree query error. query=0->7 result="+query, tree, query.maximum==7); + + query = tree.query(0, 21); + assertTrue("Segment tree query error. query=0->21 result="+query, tree, query.maximum==10); + + // bounds checking + { + // max is first + query = tree.query(2, 4); + assertTrue("Segment tree query error. query=2->4 result="+query, tree, query.maximum==6); + + // max is middle + query = tree.query(4, 6); + assertTrue("Segment tree query error. query=4->6 result="+query, tree, query.maximum==5); + + // max is last + query = tree.query(5, 7); + assertTrue("Segment tree query error. query=5->7 result="+query, tree, query.maximum==7); + } + + query = tree.query(7); // stabbing + assertTrue("Segment tree query error. query=7 result="+query, tree, query.maximum==7); + } + + @Test + public void testRangeMaxSegmentTreeDouble() { + java.util.List> segments = new ArrayList>(); + segments.add(new SegmentTree.Data.RangeMaximumData(0, Double.valueOf(4))); + segments.add(new SegmentTree.Data.RangeMaximumData(1, Double.valueOf(2))); + segments.add(new SegmentTree.Data.RangeMaximumData(2, Double.valueOf(6))); + segments.add(new SegmentTree.Data.RangeMaximumData(3, Double.valueOf(3))); + segments.add(new SegmentTree.Data.RangeMaximumData(4, Double.valueOf(1))); + segments.add(new SegmentTree.Data.RangeMaximumData(5, Double.valueOf(5))); + segments.add(new SegmentTree.Data.RangeMaximumData(6, Double.valueOf(0))); + segments.add(new SegmentTree.Data.RangeMaximumData(7, 17, Double.valueOf(7))); + segments.add(new SegmentTree.Data.RangeMaximumData(21, Double.valueOf(10))); + + // No matter which order the data is given, all tests should pass + + // Initial order. + testRangeMaxSegmentTreeDouble(segments); + + // Randomize it + Collections.shuffle(segments); + testRangeMaxSegmentTreeDouble(segments); + + // Try in order + Collections.sort(segments); + testRangeMaxSegmentTreeDouble(segments); + + // Try reverse order + Collections.sort(segments,REVERSE); + testRangeMaxSegmentTreeDouble(segments); + } + + private void testRangeMaxSegmentTreeDouble(java.util.List> segments) { // Range Maximum Segment tree + FlatSegmentTree> tree = new FlatSegmentTree>(segments, 3); + + SegmentTree.Data.RangeMaximumData query = tree.query(0, 7); + assertTrue("Segment tree query error. query=0->7 result="+query, tree, query.maximum==7); + + query = tree.query(0, 21); + assertTrue("Segment tree query error. query=0->21 result="+query, tree, query.maximum==10); + + // bounds checking + { + // max is first + query = tree.query(2, 4); + assertTrue("Segment tree query error. query=2->4 result="+query, tree, query.maximum==6); + + // max is middle + query = tree.query(4, 6); + assertTrue("Segment tree query error. query=4->6 result="+query, tree, query.maximum==5); + + // max is last + query = tree.query(5, 7); + assertTrue("Segment tree query error. query=5->7 result="+query, tree, query.maximum==7); + } + + query = tree.query(7); // stabbing + assertTrue("Segment tree query error. query=7 result="+query, tree, query.maximum==7); + } + + + @Test + public void testRangeMaxSegmentTreeFloat() { + java.util.List> segments = new ArrayList>(); + segments.add(new SegmentTree.Data.RangeMaximumData(0, Float.valueOf(4))); + segments.add(new SegmentTree.Data.RangeMaximumData(1, Float.valueOf(2))); + segments.add(new SegmentTree.Data.RangeMaximumData(2, Float.valueOf(6))); + segments.add(new SegmentTree.Data.RangeMaximumData(3, Float.valueOf(3))); + segments.add(new SegmentTree.Data.RangeMaximumData(4, Float.valueOf(1))); + segments.add(new SegmentTree.Data.RangeMaximumData(5, Float.valueOf(5))); + segments.add(new SegmentTree.Data.RangeMaximumData(6, Float.valueOf(0))); + segments.add(new SegmentTree.Data.RangeMaximumData(7, 17, Float.valueOf(7))); + segments.add(new SegmentTree.Data.RangeMaximumData(21, Float.valueOf(10))); + + // No matter which order the data is given, all tests should pass + + // Initial order. + testRangeMaxSegmentTreeFloat(segments); + + // Randomize it + Collections.shuffle(segments); + testRangeMaxSegmentTreeFloat(segments); + + // Try in order + Collections.sort(segments); + testRangeMaxSegmentTreeFloat(segments); + + // Try reverse order + Collections.sort(segments,REVERSE); + testRangeMaxSegmentTreeFloat(segments); + } + + private void testRangeMaxSegmentTreeFloat(java.util.List> segments) { // Range Maximum Segment tree + FlatSegmentTree> tree = new FlatSegmentTree>(segments, 3); + + SegmentTree.Data.RangeMaximumData query = tree.query(0, 7); + assertTrue("Segment tree query error. query=0->7 result="+query, tree, query.maximum==7); + + query = tree.query(0, 21); + assertTrue("Segment tree query error. query=0->21 result="+query, tree, query.maximum==10); + + // bounds checking + { + // max is first + query = tree.query(2, 4); + assertTrue("Segment tree query error. query=2->4 result="+query, tree, query.maximum==6); + + // max is middle + query = tree.query(4, 6); + assertTrue("Segment tree query error. query=4->6 result="+query, tree, query.maximum==5); + + // max is last + query = tree.query(5, 7); + assertTrue("Segment tree query error. query=5->7 result="+query, tree, query.maximum==7); + } + + query = tree.query(7); // stabbing + assertTrue("Segment tree query error. query=7 result="+query, tree, query.maximum==7); + } + + @Test + public void testRangeMinSegmentTreeInteger() { java.util.List> segments = new ArrayList>(); segments.add(new SegmentTree.Data.RangeMinimumData(0, (Integer) 4)); segments.add(new SegmentTree.Data.RangeMinimumData(1, (Integer) 2)); @@ -130,22 +428,22 @@ public void testRangeMinSegmentTree() { // No matter which order the data is given, all tests should pass // Initial order. - testRangeMinSegmentTree(segments); + testRangeMinSegmentTreeInteger(segments); // Randomize it Collections.shuffle(segments); - testRangeMinSegmentTree(segments); + testRangeMinSegmentTreeInteger(segments); // Try in order Collections.sort(segments); - testRangeMinSegmentTree(segments); + testRangeMinSegmentTreeInteger(segments); // Try reverse order Collections.sort(segments,REVERSE); - testRangeMinSegmentTree(segments); + testRangeMinSegmentTreeInteger(segments); } - private void testRangeMinSegmentTree(java.util.List> segments) { // Range Minimum Segment tree + private void testRangeMinSegmentTreeInteger(java.util.List> segments) { // Range Minimum Segment tree FlatSegmentTree> tree = new FlatSegmentTree>(segments, 5); SegmentTree.Data.RangeMinimumData query = tree.query(0, 7); @@ -174,39 +472,589 @@ private void testRangeMinSegmentTree(java.util.List> segments = new ArrayList>(); - segments.add(new SegmentTree.Data.RangeSumData(0, (Integer) 4)); - segments.add(new SegmentTree.Data.RangeSumData(1, (Integer) 2)); - segments.add(new SegmentTree.Data.RangeSumData(2, (Integer) 6)); - segments.add(new SegmentTree.Data.RangeSumData(3, (Integer) 3)); - segments.add(new SegmentTree.Data.RangeSumData(4, (Integer) 1)); - segments.add(new SegmentTree.Data.RangeSumData(5, (Integer) 5)); - segments.add(new SegmentTree.Data.RangeSumData(6, (Integer) 0)); - segments.add(new SegmentTree.Data.RangeSumData(17, (Integer) 7)); + public void testRangeMinSegmentTreeBigInteger() { + java.util.List> segments = new ArrayList>(); + segments.add(new SegmentTree.Data.RangeMinimumData(0, BigInteger.valueOf(4))); + segments.add(new SegmentTree.Data.RangeMinimumData(1, BigInteger.valueOf(2))); + segments.add(new SegmentTree.Data.RangeMinimumData(2, BigInteger.valueOf(6))); + segments.add(new SegmentTree.Data.RangeMinimumData(3, BigInteger.valueOf(3))); + segments.add(new SegmentTree.Data.RangeMinimumData(4, BigInteger.valueOf(1))); + segments.add(new SegmentTree.Data.RangeMinimumData(5, BigInteger.valueOf(5))); + segments.add(new SegmentTree.Data.RangeMinimumData(6, BigInteger.valueOf(0))); + segments.add(new SegmentTree.Data.RangeMinimumData(17, BigInteger.valueOf(7))); // No matter which order the data is given, all tests should pass // Initial order. - testRangeSumSegmentTree(segments); + testRangeMinSegmentTreeBigInteger(segments); // Randomize it Collections.shuffle(segments); - testRangeSumSegmentTree(segments); + testRangeMinSegmentTreeBigInteger(segments); // Try in order Collections.sort(segments); - testRangeSumSegmentTree(segments); + testRangeMinSegmentTreeBigInteger(segments); // Try reverse order Collections.sort(segments,REVERSE); - testRangeSumSegmentTree(segments); + testRangeMinSegmentTreeBigInteger(segments); } - private void testRangeSumSegmentTree(java.util.List> segments) { // Range Sum Segment tree - FlatSegmentTree> tree = new FlatSegmentTree>(segments, 10); + private void testRangeMinSegmentTreeBigInteger(java.util.List> segments) { // Range Minimum Segment tree + FlatSegmentTree> tree = new FlatSegmentTree>(segments, 5); - SegmentTree.Data.RangeSumData query = tree.query(0, 8); + SegmentTree.Data.RangeMinimumData query = tree.query(0, 7); + assertTrue("Segment tree query error. query=0->7 result="+query, tree, query.minimum==BigInteger.valueOf(0)); + + query = tree.query(0, 17); + assertTrue("Segment tree query error. query=0->17 result="+query, tree, query.minimum==BigInteger.valueOf(0)); + + // bounds checking + { + // min is first + query = tree.query(1, 3); + assertTrue("Segment tree query error. query=1->3 result="+query, tree, query.minimum==BigInteger.valueOf(2)); + + // min is middle + query = tree.query(3, 5); + assertTrue("Segment tree query error. query=3->5 result="+query, tree, query.minimum==BigInteger.valueOf(1)); + + // min is last + query = tree.query(1, 4); + assertTrue("Segment tree query error. query=5->7 result="+query, tree, query.minimum==BigInteger.valueOf(1)); + } + + query = tree.query(7); // stabbing + assertTrue("Segment tree query error. query=7 result="+query, tree, query.minimum==null); + } + + @Test + public void testRangeMinSegmentTreeBigDecimal() { + java.util.List> segments = new ArrayList>(); + segments.add(new SegmentTree.Data.RangeMinimumData(0, BigDecimal.valueOf(4))); + segments.add(new SegmentTree.Data.RangeMinimumData(1, BigDecimal.valueOf(2))); + segments.add(new SegmentTree.Data.RangeMinimumData(2, BigDecimal.valueOf(6))); + segments.add(new SegmentTree.Data.RangeMinimumData(3, BigDecimal.valueOf(3))); + segments.add(new SegmentTree.Data.RangeMinimumData(4, BigDecimal.valueOf(1))); + segments.add(new SegmentTree.Data.RangeMinimumData(5, BigDecimal.valueOf(5))); + segments.add(new SegmentTree.Data.RangeMinimumData(6, BigDecimal.valueOf(0))); + segments.add(new SegmentTree.Data.RangeMinimumData(17, BigDecimal.valueOf(7))); + + // No matter which order the data is given, all tests should pass + + // Initial order. + testRangeMinSegmentTreeBigDecimal(segments); + + // Randomize it + Collections.shuffle(segments); + testRangeMinSegmentTreeBigDecimal(segments); + + // Try in order + Collections.sort(segments); + testRangeMinSegmentTreeBigDecimal(segments); + + // Try reverse order + Collections.sort(segments,REVERSE); + testRangeMinSegmentTreeBigDecimal(segments); + } + + private void testRangeMinSegmentTreeBigDecimal(java.util.List> segments) { // Range Minimum Segment tree + FlatSegmentTree> tree = new FlatSegmentTree>(segments, 5); + + SegmentTree.Data.RangeMinimumData query = tree.query(0, 7); + assertTrue("Segment tree query error. query=0->7 result="+query, tree, query.minimum==BigDecimal.valueOf(0)); + + query = tree.query(0, 17); + assertTrue("Segment tree query error. query=0->17 result="+query, tree, query.minimum==BigDecimal.valueOf(0)); + + // bounds checking + { + // min is first + query = tree.query(1, 3); + assertTrue("Segment tree query error. query=1->3 result="+query, tree, query.minimum==BigDecimal.valueOf(2)); + + // min is middle + query = tree.query(3, 5); + assertTrue("Segment tree query error. query=3->5 result="+query, tree, query.minimum==BigDecimal.valueOf(1)); + + // min is last + query = tree.query(1, 4); + assertTrue("Segment tree query error. query=5->7 result="+query, tree, query.minimum==BigDecimal.valueOf(1)); + } + + query = tree.query(7); // stabbing + assertTrue("Segment tree query error. query=7 result="+query, tree, query.minimum==null); + } + + @Test + public void testRangeMinSegmentTreeLong() { + java.util.List> segments = new ArrayList>(); + segments.add(new SegmentTree.Data.RangeMinimumData(0, Long.valueOf(4))); + segments.add(new SegmentTree.Data.RangeMinimumData(1, Long.valueOf(2))); + segments.add(new SegmentTree.Data.RangeMinimumData(2, Long.valueOf(6))); + segments.add(new SegmentTree.Data.RangeMinimumData(3, Long.valueOf(3))); + segments.add(new SegmentTree.Data.RangeMinimumData(4, Long.valueOf(1))); + segments.add(new SegmentTree.Data.RangeMinimumData(5, Long.valueOf(5))); + segments.add(new SegmentTree.Data.RangeMinimumData(6, Long.valueOf(0))); + segments.add(new SegmentTree.Data.RangeMinimumData(17, Long.valueOf(7))); + + // No matter which order the data is given, all tests should pass + + // Initial order. + testRangeMinSegmentTreeLong(segments); + + // Randomize it + Collections.shuffle(segments); + testRangeMinSegmentTreeLong(segments); + + // Try in order + Collections.sort(segments); + testRangeMinSegmentTreeLong(segments); + + // Try reverse order + Collections.sort(segments,REVERSE); + testRangeMinSegmentTreeLong(segments); + } + + private void testRangeMinSegmentTreeLong(java.util.List> segments) { // Range Minimum Segment tree + FlatSegmentTree> tree = new FlatSegmentTree>(segments, 5); + + SegmentTree.Data.RangeMinimumData query = tree.query(0, 7); + assertTrue("Segment tree query error. query=0->7 result="+query, tree, query.minimum==Long.valueOf(0)); + + query = tree.query(0, 17); + assertTrue("Segment tree query error. query=0->17 result="+query, tree, query.minimum==Long.valueOf(0)); + + // bounds checking + { + // min is first + query = tree.query(1, 3); + assertTrue("Segment tree query error. query=1->3 result="+query, tree, query.minimum==Long.valueOf(2)); + + // min is middle + query = tree.query(3, 5); + assertTrue("Segment tree query error. query=3->5 result="+query, tree, query.minimum==Long.valueOf(1)); + + // min is last + query = tree.query(1, 4); + assertTrue("Segment tree query error. query=5->7 result="+query, tree, query.minimum==Long.valueOf(1)); + } + + query = tree.query(7); // stabbing + assertTrue("Segment tree query error. query=7 result="+query, tree, query.minimum==null); + } + + @Test + public void testRangeMinSegmentTreeDouble() { + java.util.List> segments = new ArrayList>(); + segments.add(new SegmentTree.Data.RangeMinimumData(0, Double.valueOf(4))); + segments.add(new SegmentTree.Data.RangeMinimumData(1, Double.valueOf(2))); + segments.add(new SegmentTree.Data.RangeMinimumData(2, Double.valueOf(6))); + segments.add(new SegmentTree.Data.RangeMinimumData(3, Double.valueOf(3))); + segments.add(new SegmentTree.Data.RangeMinimumData(4, Double.valueOf(1))); + segments.add(new SegmentTree.Data.RangeMinimumData(5, Double.valueOf(5))); + segments.add(new SegmentTree.Data.RangeMinimumData(6, Double.valueOf(0))); + segments.add(new SegmentTree.Data.RangeMinimumData(17, Double.valueOf(7))); + + // No matter which order the data is given, all tests should pass + + // Initial order. + testRangeMinSegmentTreeDouble(segments); + + // Randomize it + Collections.shuffle(segments); + testRangeMinSegmentTreeDouble(segments); + + // Try in order + Collections.sort(segments); + testRangeMinSegmentTreeDouble(segments); + + // Try reverse order + Collections.sort(segments,REVERSE); + testRangeMinSegmentTreeDouble(segments); + } + + private void testRangeMinSegmentTreeDouble(java.util.List> segments) { // Range Minimum Segment tree + FlatSegmentTree> tree = new FlatSegmentTree>(segments, 5); + + SegmentTree.Data.RangeMinimumData query = tree.query(0, 7); + assertTrue("Segment tree query error. query=0->7 result="+query, tree, query.minimum==0); + + query = tree.query(0, 17); + assertTrue("Segment tree query error. query=0->17 result="+query, tree, query.minimum==0); + + // bounds checking + { + // min is first + query = tree.query(1, 3); + assertTrue("Segment tree query error. query=1->3 result="+query, tree, query.minimum==2); + + // min is middle + query = tree.query(3, 5); + assertTrue("Segment tree query error. query=3->5 result="+query, tree, query.minimum==1); + + // min is last + query = tree.query(1, 4); + assertTrue("Segment tree query error. query=5->7 result="+query, tree, query.minimum==1); + } + + query = tree.query(7); // stabbing + assertTrue("Segment tree query error. query=7 result="+query, tree, query.minimum==null); + } + + @Test + public void testRangeMinSegmentTreeFloat() { + java.util.List> segments = new ArrayList>(); + segments.add(new SegmentTree.Data.RangeMinimumData(0, Float.valueOf(4))); + segments.add(new SegmentTree.Data.RangeMinimumData(1, Float.valueOf(2))); + segments.add(new SegmentTree.Data.RangeMinimumData(2, Float.valueOf(6))); + segments.add(new SegmentTree.Data.RangeMinimumData(3, Float.valueOf(3))); + segments.add(new SegmentTree.Data.RangeMinimumData(4, Float.valueOf(1))); + segments.add(new SegmentTree.Data.RangeMinimumData(5, Float.valueOf(5))); + segments.add(new SegmentTree.Data.RangeMinimumData(6, Float.valueOf(0))); + segments.add(new SegmentTree.Data.RangeMinimumData(17, Float.valueOf(7))); + + // No matter which order the data is given, all tests should pass + + // Initial order. + testRangeMinSegmentTreeFloat(segments); + + // Randomize it + Collections.shuffle(segments); + testRangeMinSegmentTreeFloat(segments); + + // Try in order + Collections.sort(segments); + testRangeMinSegmentTreeFloat(segments); + + // Try reverse order + Collections.sort(segments,REVERSE); + testRangeMinSegmentTreeFloat(segments); + } + + private void testRangeMinSegmentTreeFloat(java.util.List> segments) { // Range Minimum Segment tree + FlatSegmentTree> tree = new FlatSegmentTree>(segments, 5); + + SegmentTree.Data.RangeMinimumData query = tree.query(0, 7); + assertTrue("Segment tree query error. query=0->7 result="+query, tree, query.minimum==0); + + query = tree.query(0, 17); + assertTrue("Segment tree query error. query=0->17 result="+query, tree, query.minimum==0); + + // bounds checking + { + // min is first + query = tree.query(1, 3); + assertTrue("Segment tree query error. query=1->3 result="+query, tree, query.minimum== 2); + + // min is middle + query = tree.query(3, 5); + assertTrue("Segment tree query error. query=3->5 result="+query, tree, query.minimum== 1); + + // min is last + query = tree.query(1, 4); + assertTrue("Segment tree query error. query=5->7 result="+query, tree, query.minimum== 1); + } + + query = tree.query(7); // stabbing + assertTrue("Segment tree query error. query=7 result="+query, tree, query.minimum==null); + } + + @Test + public void testRangeSumSegmentTreeInteger() { + java.util.List> segments = new ArrayList>(); + segments.add(new SegmentTree.Data.RangeSumData(0, (Integer) 4)); + segments.add(new SegmentTree.Data.RangeSumData(1, (Integer) 2)); + segments.add(new SegmentTree.Data.RangeSumData(2, (Integer) 6)); + segments.add(new SegmentTree.Data.RangeSumData(3, (Integer) 3)); + segments.add(new SegmentTree.Data.RangeSumData(4, (Integer) 1)); + segments.add(new SegmentTree.Data.RangeSumData(5, (Integer) 5)); + segments.add(new SegmentTree.Data.RangeSumData(6, (Integer) 0)); + segments.add(new SegmentTree.Data.RangeSumData(17, (Integer) 7)); + + // No matter which order the data is given, all tests should pass + + // Initial order. + testRangeSumSegmentTreeInteger(segments); + + // Randomize it + Collections.shuffle(segments); + testRangeSumSegmentTreeInteger(segments); + + // Try in order + Collections.sort(segments); + testRangeSumSegmentTreeInteger(segments); + + // Try reverse order + Collections.sort(segments,REVERSE); + testRangeSumSegmentTreeInteger(segments); + } + + private void testRangeSumSegmentTreeInteger(java.util.List> segments) { // Range Sum Segment tree + FlatSegmentTree> tree = new FlatSegmentTree>(segments, 10); + + SegmentTree.Data.RangeSumData query = tree.query(0, 8); + assertTrue("Segment tree query error. query=0->8 result="+query, tree, query.sum==21); + + query = tree.query(0, 17); + assertTrue("Segment tree query error. query=0->17 result="+query, tree, query.sum==28); + + query = tree.query(2, 5); + assertTrue("Segment tree query error. query=2->5 result="+query, tree, query.sum==15); + + query = tree.query(10, 17); + assertTrue("Segment tree query error. query=10->17 result="+query, tree, query.sum==7); + + query = tree.query(16); // stabbing + assertTrue("Segment tree query error. query=16 result="+query, tree, query.sum==null); + + query = tree.query(17); // stabbing + assertTrue("Segment tree query error. query=17 result="+query, tree, query.sum==7); + } + + @Test + public void testRangeSumSegmentTreeBigInteger() { + java.util.List> segments = new ArrayList>(); + segments.add(new SegmentTree.Data.RangeSumData(0, BigInteger.valueOf(4))); + segments.add(new SegmentTree.Data.RangeSumData(1, BigInteger.valueOf(2))); + segments.add(new SegmentTree.Data.RangeSumData(2, BigInteger.valueOf(6))); + segments.add(new SegmentTree.Data.RangeSumData(3, BigInteger.valueOf(3))); + segments.add(new SegmentTree.Data.RangeSumData(4, BigInteger.valueOf(1))); + segments.add(new SegmentTree.Data.RangeSumData(5, BigInteger.valueOf(5))); + segments.add(new SegmentTree.Data.RangeSumData(6, BigInteger.valueOf(0))); + segments.add(new SegmentTree.Data.RangeSumData(17, BigInteger.valueOf(7))); + + // No matter which order the data is given, all tests should pass + + // Initial order. + testRangeSumSegmentTreeBigInteger(segments); + + // Randomize it + Collections.shuffle(segments); + testRangeSumSegmentTreeBigInteger(segments); + + // Try in order + Collections.sort(segments); + testRangeSumSegmentTreeBigInteger(segments); + + // Try reverse order + Collections.sort(segments,REVERSE); + testRangeSumSegmentTreeBigInteger(segments); + } + + private void testRangeSumSegmentTreeBigInteger(java.util.List> segments) { // Range Sum Segment tree + FlatSegmentTree> tree = new FlatSegmentTree>(segments, 10); + + SegmentTree.Data.RangeSumData query = tree.query(0, 8); + assertTrue("Segment tree query error. query=0->8 result="+query, tree, query.sum.compareTo(BigInteger.valueOf(21)) ==0); + + query = tree.query(0, 17); + assertTrue("Segment tree query error. query=0->17 result="+query, tree, query.sum.compareTo(BigInteger.valueOf(28))==0); + + query = tree.query(2, 5); + assertTrue("Segment tree query error. query=2->5 result="+query, tree, query.sum.compareTo(BigInteger.valueOf(15))==0); + + query = tree.query(10, 17); + assertTrue("Segment tree query error. query=10->17 result="+query, tree, query.sum.compareTo(BigInteger.valueOf(7))==0); + + query = tree.query(16); // stabbing + assertTrue("Segment tree query error. query=16 result="+query, tree, query.sum==null); + + query = tree.query(17); // stabbing + assertTrue("Segment tree query error. query=17 result="+query, tree, query.sum.compareTo(BigInteger.valueOf(7))==0); + } + + @Test + public void testRangeSumSegmentTreeBigDecimal() { + java.util.List> segments = new ArrayList>(); + segments.add(new SegmentTree.Data.RangeSumData(0, BigDecimal.valueOf(4))); + segments.add(new SegmentTree.Data.RangeSumData(1, BigDecimal.valueOf(2))); + segments.add(new SegmentTree.Data.RangeSumData(2, BigDecimal.valueOf(6))); + segments.add(new SegmentTree.Data.RangeSumData(3, BigDecimal.valueOf(3))); + segments.add(new SegmentTree.Data.RangeSumData(4, BigDecimal.valueOf(1))); + segments.add(new SegmentTree.Data.RangeSumData(5, BigDecimal.valueOf(5))); + segments.add(new SegmentTree.Data.RangeSumData(6, BigDecimal.valueOf(0))); + segments.add(new SegmentTree.Data.RangeSumData(17, BigDecimal.valueOf(7))); + + // No matter which order the data is given, all tests should pass + + // Initial order. + testRangeSumSegmentTreeBigDecimal(segments); + + // Randomize it + Collections.shuffle(segments); + testRangeSumSegmentTreeBigDecimal(segments); + + // Try in order + Collections.sort(segments); + testRangeSumSegmentTreeBigDecimal(segments); + + // Try reverse order + Collections.sort(segments,REVERSE); + testRangeSumSegmentTreeBigDecimal(segments); + } + + private void testRangeSumSegmentTreeBigDecimal(java.util.List> segments) { // Range Sum Segment tree + FlatSegmentTree> tree = new FlatSegmentTree>(segments, 10); + + SegmentTree.Data.RangeSumData query = tree.query(0, 8); + assertTrue("Segment tree query error. query=0->8 result="+query, tree, query.sum.compareTo(BigDecimal.valueOf(21))==0); + + query = tree.query(0, 17); + assertTrue("Segment tree query error. query=0->17 result="+query, tree, query.sum.compareTo(BigDecimal.valueOf(28))==0); + + query = tree.query(2, 5); + assertTrue("Segment tree query error. query=2->5 result="+query, tree, query.sum.compareTo(BigDecimal.valueOf(15))==0); + + query = tree.query(10, 17); + assertTrue("Segment tree query error. query=10->17 result="+query, tree, query.sum.compareTo(BigDecimal.valueOf(7))==0); + + query = tree.query(16); // stabbing + assertTrue("Segment tree query error. query=16 result="+query, tree, query.sum==null); + + query = tree.query(17); // stabbing + assertTrue("Segment tree query error. query=17 result="+query, tree, query.sum.compareTo(BigDecimal.valueOf(7))==0); + } + + @Test + public void testRangeSumSegmentTreeLong() { + java.util.List> segments = new ArrayList>(); + segments.add(new SegmentTree.Data.RangeSumData(0, Long.valueOf(4))); + segments.add(new SegmentTree.Data.RangeSumData(1, Long.valueOf(2))); + segments.add(new SegmentTree.Data.RangeSumData(2, Long.valueOf(6))); + segments.add(new SegmentTree.Data.RangeSumData(3, Long.valueOf(3))); + segments.add(new SegmentTree.Data.RangeSumData(4, Long.valueOf(1))); + segments.add(new SegmentTree.Data.RangeSumData(5, Long.valueOf(5))); + segments.add(new SegmentTree.Data.RangeSumData(6, Long.valueOf(0))); + segments.add(new SegmentTree.Data.RangeSumData(17, Long.valueOf(7))); + + // No matter which order the data is given, all tests should pass + + // Initial order. + testRangeSumSegmentTreeLong(segments); + + // Randomize it + Collections.shuffle(segments); + testRangeSumSegmentTreeLong(segments); + + // Try in order + Collections.sort(segments); + testRangeSumSegmentTreeLong(segments); + + // Try reverse order + Collections.sort(segments,REVERSE); + testRangeSumSegmentTreeLong(segments); + } + + private void testRangeSumSegmentTreeLong(java.util.List> segments) { // Range Sum Segment tree + FlatSegmentTree> tree = new FlatSegmentTree>(segments, 10); + + SegmentTree.Data.RangeSumData query = tree.query(0, 8); + assertTrue("Segment tree query error. query=0->8 result="+query, tree, query.sum==Long.valueOf(21)); + + query = tree.query(0, 17); + assertTrue("Segment tree query error. query=0->17 result="+query, tree, query.sum==Long.valueOf(28)); + + query = tree.query(2, 5); + assertTrue("Segment tree query error. query=2->5 result="+query, tree, query.sum==Long.valueOf(15)); + + query = tree.query(10, 17); + assertTrue("Segment tree query error. query=10->17 result="+query, tree, query.sum==Long.valueOf(7)); + + query = tree.query(16); // stabbing + assertTrue("Segment tree query error. query=16 result="+query, tree, query.sum==null); + + query = tree.query(17); // stabbing + assertTrue("Segment tree query error. query=17 result="+query, tree, query.sum==Long.valueOf(7)); + } + + @Test + public void testRangeSumSegmentTreeDouble() { + java.util.List> segments = new ArrayList>(); + segments.add(new SegmentTree.Data.RangeSumData(0, Double.valueOf(4))); + segments.add(new SegmentTree.Data.RangeSumData(1, Double.valueOf(2))); + segments.add(new SegmentTree.Data.RangeSumData(2, Double.valueOf(6))); + segments.add(new SegmentTree.Data.RangeSumData(3, Double.valueOf(3))); + segments.add(new SegmentTree.Data.RangeSumData(4, Double.valueOf(1))); + segments.add(new SegmentTree.Data.RangeSumData(5, Double.valueOf(5))); + segments.add(new SegmentTree.Data.RangeSumData(6, Double.valueOf(0))); + segments.add(new SegmentTree.Data.RangeSumData(17, Double.valueOf(7))); + + // No matter which order the data is given, all tests should pass + + // Initial order. + testRangeSumSegmentTreeDouble(segments); + + // Randomize it + Collections.shuffle(segments); + testRangeSumSegmentTreeDouble(segments); + + // Try in order + Collections.sort(segments); + testRangeSumSegmentTreeDouble(segments); + + // Try reverse order + Collections.sort(segments,REVERSE); + testRangeSumSegmentTreeDouble(segments); + } + + private void testRangeSumSegmentTreeDouble(java.util.List> segments) { // Range Sum Segment tree + FlatSegmentTree> tree = new FlatSegmentTree>(segments, 10); + + SegmentTree.Data.RangeSumData query = tree.query(0, 8); + assertTrue("Segment tree query error. query=0->8 result="+query, tree, query.sum==21); + + query = tree.query(0, 17); + assertTrue("Segment tree query error. query=0->17 result="+query, tree, query.sum==28); + + query = tree.query(2, 5); + assertTrue("Segment tree query error. query=2->5 result="+query, tree, query.sum==15); + + query = tree.query(10, 17); + assertTrue("Segment tree query error. query=10->17 result="+query, tree, query.sum==7); + + query = tree.query(16); // stabbing + assertTrue("Segment tree query error. query=16 result="+query, tree, query.sum==null); + + query = tree.query(17); // stabbing + assertTrue("Segment tree query error. query=17 result="+query, tree, query.sum==7); + } + + @Test + public void testRangeSumSegmentTreeBigFloat() { + java.util.List> segments = new ArrayList>(); + segments.add(new SegmentTree.Data.RangeSumData(0, Float.valueOf(4))); + segments.add(new SegmentTree.Data.RangeSumData(1, Float.valueOf(2))); + segments.add(new SegmentTree.Data.RangeSumData(2, Float.valueOf(6))); + segments.add(new SegmentTree.Data.RangeSumData(3, Float.valueOf(3))); + segments.add(new SegmentTree.Data.RangeSumData(4, Float.valueOf(1))); + segments.add(new SegmentTree.Data.RangeSumData(5, Float.valueOf(5))); + segments.add(new SegmentTree.Data.RangeSumData(6, Float.valueOf(0))); + segments.add(new SegmentTree.Data.RangeSumData(17, Float.valueOf(7))); + + // No matter which order the data is given, all tests should pass + + // Initial order. + testRangeSumSegmentTreeFloat(segments); + + // Randomize it + Collections.shuffle(segments); + testRangeSumSegmentTreeFloat(segments); + + // Try in order + Collections.sort(segments); + testRangeSumSegmentTreeFloat(segments); + + // Try reverse order + Collections.sort(segments,REVERSE); + testRangeSumSegmentTreeFloat(segments); + } + + private void testRangeSumSegmentTreeFloat(java.util.List> segments) { // Range Sum Segment tree + FlatSegmentTree> tree = new FlatSegmentTree>(segments, 10); + + SegmentTree.Data.RangeSumData query = tree.query(0, 8); assertTrue("Segment tree query error. query=0->8 result="+query, tree, query.sum==21); query = tree.query(0, 17);