aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/ch/obermuhlner/math/big/stream
diff options
context:
space:
mode:
authorTec <daniel112092@gmail.com>2020-07-18 22:49:35 +0200
committerTec <daniel112092@gmail.com>2020-07-18 22:49:35 +0200
commit11e50eb56f6750d6bdfe15b986eef55e27452211 (patch)
treef6d4e90967e76c2fa2f988a823340fa85b9a604b /src/main/java/ch/obermuhlner/math/big/stream
parent5c68b296e1b499ca83d78f24837768ac3a75df62 (diff)
downloadGT5-Unofficial-11e50eb56f6750d6bdfe15b986eef55e27452211.tar.gz
GT5-Unofficial-11e50eb56f6750d6bdfe15b986eef55e27452211.tar.bz2
GT5-Unofficial-11e50eb56f6750d6bdfe15b986eef55e27452211.zip
Implement big float, transition to molarity
Diffstat (limited to 'src/main/java/ch/obermuhlner/math/big/stream')
-rw-r--r--src/main/java/ch/obermuhlner/math/big/stream/BigDecimalStream.java219
-rw-r--r--src/main/java/ch/obermuhlner/math/big/stream/BigFloatStream.java214
2 files changed, 433 insertions, 0 deletions
diff --git a/src/main/java/ch/obermuhlner/math/big/stream/BigDecimalStream.java b/src/main/java/ch/obermuhlner/math/big/stream/BigDecimalStream.java
new file mode 100644
index 0000000000..05a45fd846
--- /dev/null
+++ b/src/main/java/ch/obermuhlner/math/big/stream/BigDecimalStream.java
@@ -0,0 +1,219 @@
+package ch.obermuhlner.math.big.stream;
+
+import java.math.BigDecimal;
+import java.math.MathContext;
+import java.util.Comparator;
+import java.util.Spliterator;
+import java.util.Spliterators.AbstractSpliterator;
+import java.util.function.Consumer;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+
+import ch.obermuhlner.math.big.BigDecimalMath;
+
+/**
+ * Provides constructor methods for streams of {@link BigDecimal} elements.
+ */
+public class BigDecimalStream {
+
+ /**
+ * Returns a sequential ordered {@code Stream<BigDecimal>} from {@code startInclusive}
+ * (inclusive) to {@code endExclusive} (exclusive) by an incremental {@code step}.
+ *
+ * <p>An equivalent sequence of increasing values can be produced
+ * sequentially using a {@code for} loop as follows:
+ * <pre>for (BigDecimal i = startInclusive; i.compareTo(endExclusive) &lt; 0; i = i.add(step, mathContext)) {
+ // ...
+}</pre>
+ *
+ * @param startInclusive the (inclusive) initial value
+ * @param endExclusive the exclusive upper bound
+ * @param step the step between elements
+ * @param mathContext the {@link MathContext} used for all mathematical operations
+ * @return a sequential {@code Stream<BigDecimal>}
+ */
+ public static Stream<BigDecimal> range(BigDecimal startInclusive, BigDecimal endExclusive, BigDecimal step, MathContext mathContext) {
+ if (step.signum() == 0) {
+ throw new IllegalArgumentException("invalid step: 0");
+ }
+ if (endExclusive.subtract(startInclusive).signum() != step.signum()) {
+ return Stream.empty();
+ }
+ return StreamSupport.stream(new BigDecimalSpliterator(startInclusive, endExclusive, false, step, mathContext), false);
+ }
+
+ /**
+ * Returns a sequential ordered {@code Stream<BigDecimal>} from {@code startInclusive}
+ * (inclusive) to {@code endExclusive} (exclusive) by an incremental {@code step}.
+ *
+ * <p>The {@code long} arguments are converted using {@link BigDecimal#valueOf(long)}.</p>
+ *
+ * @param startInclusive the (inclusive) initial value
+ * @param endExclusive the exclusive upper bound
+ * @param step the step between elements
+ * @param mathContext the {@link MathContext} used for all mathematical operations
+ * @return a sequential {@code Stream<BigDecimal>}
+ * @see #range(BigDecimal, BigDecimal, BigDecimal, MathContext)
+ */
+ public static Stream<BigDecimal> range(long startInclusive, long endExclusive, long step, MathContext mathContext) {
+ return range(BigDecimal.valueOf(startInclusive), BigDecimal.valueOf(endExclusive), BigDecimal.valueOf(step), mathContext);
+ }
+
+ /**
+ * Returns a sequential ordered {@code Stream<BigDecimal>} from {@code startInclusive}
+ * (inclusive) to {@code endExclusive} (exclusive) by an incremental {@code step}.
+ *
+ * <p>The {@code double} arguments are converted using {@link BigDecimal#valueOf(double)}.</p>
+ *
+ * @param startInclusive the (inclusive) initial value
+ * @param endExclusive the exclusive upper bound
+ * @param step the step between elements
+ * @param mathContext the {@link MathContext} used for all mathematical operations
+ * @return a sequential {@code Stream<BigDecimal>}
+ * @see #range(BigDecimal, BigDecimal, BigDecimal, MathContext)
+ */
+ public static Stream<BigDecimal> range(double startInclusive, double endExclusive, double step, MathContext mathContext) {
+ return range(BigDecimal.valueOf(startInclusive), BigDecimal.valueOf(endExclusive), BigDecimal.valueOf(step), mathContext);
+ }
+
+ /**
+ * Returns a sequential ordered {@code Stream<BigDecimal>} from {@code startInclusive}
+ * (inclusive) to {@code endInclusive} (inclusive) by an incremental {@code step}.
+ *
+ * <p>An equivalent sequence of increasing values can be produced
+ * sequentially using a {@code for} loop as follows:
+ * <pre>for (BigDecimal i = startInclusive; i.compareTo(endInclusive) &lt;= 0; i = i.add(step, mathContext)) {
+ // ...
+}</pre>
+ *
+ * @param startInclusive the (inclusive) initial value
+ * @param endInclusive the inclusive upper bound
+ * @param step the step between elements
+ * @param mathContext the {@link MathContext} used for all mathematical operations
+ * @return a sequential {@code Stream<BigDecimal>}
+ * @see #range(BigDecimal, BigDecimal, BigDecimal, MathContext)
+ */
+ public static Stream<BigDecimal> rangeClosed(BigDecimal startInclusive, BigDecimal endInclusive, BigDecimal step, MathContext mathContext) {
+ if (step.signum() == 0) {
+ throw new IllegalArgumentException("invalid step: 0");
+ }
+ if (endInclusive.subtract(startInclusive).signum() == -step.signum()) {
+ return Stream.empty();
+ }
+ return StreamSupport.stream(new BigDecimalSpliterator(startInclusive, endInclusive, true, step, mathContext), false);
+ }
+
+ /**
+ * Returns a sequential ordered {@code Stream<BigDecimal>} from {@code startInclusive}
+ * (inclusive) to {@code endInclusive} (inclusive) by an incremental {@code step}.
+ *
+ * <p>The {@code long} arguments are converted using {@link BigDecimal#valueOf(long)}.</p>
+ *
+ * @param startInclusive the (inclusive) initial value
+ * @param endInclusive the inclusive upper bound
+ * @param step the step between elements
+ * @param mathContext the {@link MathContext} used for all mathematical operations
+ * @return a sequential {@code Stream<BigDecimal>}
+ * @see #rangeClosed(BigDecimal, BigDecimal, BigDecimal, MathContext)
+ */
+ public static Stream<BigDecimal> rangeClosed(long startInclusive, long endInclusive, long step, MathContext mathContext) {
+ return rangeClosed(BigDecimal.valueOf(startInclusive), BigDecimal.valueOf(endInclusive), BigDecimal.valueOf(step), mathContext);
+ }
+
+ /**
+ * Returns a sequential ordered {@code Stream<BigDecimal>} from {@code startInclusive}
+ * (inclusive) to {@code endInclusive} (inclusive) by an incremental {@code step}.
+ *
+ * <p>The {@code double} arguments are converted using {@link BigDecimal#valueOf(double)}.</p>
+ *
+ * @param startInclusive the (inclusive) initial value
+ * @param endInclusive the inclusive upper bound
+ * @param step the step between elements
+ * @param mathContext the {@link MathContext} used for all mathematical operations
+ * @return a sequential {@code Stream<BigDecimal>}
+ * @see #rangeClosed(BigDecimal, BigDecimal, BigDecimal, MathContext)
+ */
+ public static Stream<BigDecimal> rangeClosed(double startInclusive, double endInclusive, double step, MathContext mathContext) {
+ return rangeClosed(BigDecimal.valueOf(startInclusive), BigDecimal.valueOf(endInclusive), BigDecimal.valueOf(step), mathContext);
+ }
+
+ private static class BigDecimalSpliterator extends AbstractSpliterator<BigDecimal> {
+
+ private BigDecimal value;
+ private BigDecimal step;
+ private long count;
+ private MathContext mathContext;
+
+ public BigDecimalSpliterator(BigDecimal startInclusive, BigDecimal step, long count, MathContext mathContext) {
+ super(count,
+ Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.DISTINCT | Spliterator.IMMUTABLE | Spliterator.NONNULL | Spliterator.ORDERED | Spliterator.SORTED);
+
+ this.value = startInclusive;
+ this.step = step;
+ this.count = count;
+ this.mathContext = mathContext;
+ }
+
+ public BigDecimalSpliterator(BigDecimal startInclusive, BigDecimal end, boolean inclusive, BigDecimal step, MathContext mathContext) {
+ this(startInclusive, step, estimatedCount(startInclusive, end, inclusive, step, mathContext), mathContext);
+ }
+
+ private static long estimatedCount(BigDecimal startInclusive, BigDecimal end, boolean inclusive, BigDecimal step, MathContext mathContext) {
+ BigDecimal count = end.subtract(startInclusive).divide(step, mathContext);
+ long result = count.longValue();
+ if (BigDecimalMath.fractionalPart(count).signum() != 0) {
+ result++;
+ } else {
+ if (inclusive) {
+ result++;
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public Comparator<? super BigDecimal> getComparator() {
+ if (step.signum() < 0) {
+ return Comparator.reverseOrder();
+ }
+ return null;
+ }
+
+ @Override
+ public boolean tryAdvance(Consumer<? super BigDecimal> action) {
+ if (count == 0) {
+ return false;
+ }
+
+ action.accept(value);
+ value = value.add(step, mathContext);
+ count--;
+ return true;
+ }
+
+ @Override
+ public void forEachRemaining(Consumer<? super BigDecimal> action) {
+ while (count > 0) {
+ action.accept(value);
+ value = value.add(step, mathContext);
+ count--;
+ }
+ }
+
+ @Override
+ public Spliterator<BigDecimal> trySplit() {
+ long firstHalfCount = count / 2;
+
+ if (firstHalfCount == 0) {
+ return null;
+ }
+
+ long secondHalfCount = count - firstHalfCount;
+
+ count = firstHalfCount;
+ BigDecimal startSecondHalf = value.add(step.multiply(new BigDecimal(firstHalfCount), mathContext), mathContext);
+
+ return new BigDecimalSpliterator(startSecondHalf, step, secondHalfCount, mathContext);
+ }
+ }
+}
diff --git a/src/main/java/ch/obermuhlner/math/big/stream/BigFloatStream.java b/src/main/java/ch/obermuhlner/math/big/stream/BigFloatStream.java
new file mode 100644
index 0000000000..1c982302a6
--- /dev/null
+++ b/src/main/java/ch/obermuhlner/math/big/stream/BigFloatStream.java
@@ -0,0 +1,214 @@
+package ch.obermuhlner.math.big.stream;
+
+import java.util.Comparator;
+import java.util.Spliterator;
+import java.util.Spliterators.AbstractSpliterator;
+import java.util.function.Consumer;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+
+import ch.obermuhlner.math.big.BigFloat;
+import ch.obermuhlner.math.big.BigFloat.Context;
+
+/**
+ * Provides constructor methods for streams of {@link BigFloat} elements.
+ */
+public class BigFloatStream {
+
+ /**
+ * Returns a sequential ordered {@code Stream<BigFloat>} from {@code startInclusive}
+ * (inclusive) to {@code endExclusive} (exclusive) by an incremental {@code step}.
+ *
+ * <p>An equivalent sequence of increasing values can be produced
+ * sequentially using a {@code for} loop as follows:
+ * <pre>for (BigFloat i = startInclusive; i.isLessThan(endExclusive); i = i.add(step)) {
+ // ...
+}</pre>
+ *
+ * @param startInclusive the (inclusive) initial value
+ * @param endExclusive the exclusive upper bound
+ * @param step the step between elements
+ * @return a sequential {@code Stream<BigFloat>}
+ */
+ public static Stream<BigFloat> range(BigFloat startInclusive, BigFloat endExclusive, BigFloat step) {
+ if (step.isZero()) {
+ throw new IllegalArgumentException("invalid step: 0");
+ }
+ if (endExclusive.subtract(startInclusive).signum() != step.signum()) {
+ return Stream.empty();
+ }
+ return StreamSupport.stream(new BigFloatSpliterator(startInclusive, endExclusive, false, step), false);
+ }
+
+ /**
+ * Returns a sequential ordered {@code Stream<BigFloat>} from {@code startInclusive}
+ * (inclusive) to {@code endExclusive} (exclusive) by an incremental {@code step}.
+ *
+ * <p>{@link Context#valueOf(long)} is used to convert the {@code long} values.</p>
+ *
+ * @param startInclusive the (inclusive) initial value
+ * @param endExclusive the exclusive upper bound
+ * @param step the step between elements
+ * @param context the {@link Context} used to convert the {@code long} values
+ * @return a sequential {@code Stream<BigFloat>}
+ * @see #range(BigFloat, BigFloat, BigFloat)
+ */
+ public static Stream<BigFloat> range(long startInclusive, long endExclusive, long step, Context context) {
+ return range(context.valueOf(startInclusive), context.valueOf(endExclusive), context.valueOf(step));
+ }
+
+ /**
+ * Returns a sequential ordered {@code Stream<BigFloat>} from {@code startInclusive}
+ * (inclusive) to {@code endExclusive} (exclusive) by an incremental {@code step}.
+ *
+ * <p>{@link Context#valueOf(double)} is used to convert the {@code double} values.</p>
+ *
+ * @param startInclusive the (inclusive) initial value
+ * @param endExclusive the exclusive upper bound
+ * @param step the step between elements
+ * @param context the {@link Context} used to convert the {@code double} values
+ * @return a sequential {@code Stream<BigFloat>}
+ * @see #range(BigFloat, BigFloat, BigFloat)
+ */
+ public static Stream<BigFloat> range(double startInclusive, double endExclusive, double step, Context context) {
+ return range(context.valueOf(startInclusive), context.valueOf(endExclusive), context.valueOf(step));
+ }
+
+ /**
+ * Returns a sequential ordered {@code Stream<BigFloat>} from {@code startInclusive}
+ * (inclusive) to {@code endInclusive} (inclusive) by an incremental {@code step}.
+ *
+ * <p>An equivalent sequence of increasing values can be produced
+ * sequentially using a {@code for} loop as follows:
+ * <pre>for (BigFloat i = startInclusive; i.isLessThanOrEqual(endInclusive); i = i.add(step)) {
+ //...
+}
+</pre>
+ *
+ * @param startInclusive the (inclusive) initial value
+ * @param endInclusive the inclusive upper bound
+ * @param step the step between elements
+ * @return a sequential {@code Stream<BigFloat>}
+ */
+ public static Stream<BigFloat> rangeClosed(BigFloat startInclusive, BigFloat endInclusive, BigFloat step) {
+ if (step.isZero()) {
+ throw new IllegalArgumentException("invalid step: 0");
+ }
+ if (endInclusive.subtract(startInclusive).signum() == -step.signum()) {
+ return Stream.empty();
+ }
+ return StreamSupport.stream(new BigFloatSpliterator(startInclusive, endInclusive, true, step), false);
+ }
+
+ /**
+ * Returns a sequential ordered {@code Stream<BigFloat>} from {@code startInclusive}
+ * (inclusive) to {@code endInclusive} (inclusive) by an incremental {@code step}.
+ *
+ * <p>{@link Context#valueOf(long)} is used to convert the {@code long} values.</p>
+ *
+ * @param startInclusive the (inclusive) initial value
+ * @param endInclusive the inclusive upper bound
+ * @param step the step between elements
+ * @param context the {@link Context} used to convert the {@code long} values
+ * @return a sequential {@code Stream<BigFloat>}
+ * @see #rangeClosed(BigFloat, BigFloat, BigFloat)
+ */
+ public static Stream<BigFloat> rangeClosed(long startInclusive, long endInclusive, long step, Context context) {
+ return rangeClosed(context.valueOf(startInclusive), context.valueOf(endInclusive), context.valueOf(step));
+ }
+
+ /**
+ * Returns a sequential ordered {@code Stream<BigFloat>} from {@code startInclusive}
+ * (inclusive) to {@code endInclusive} (inclusive) by an incremental {@code step}.
+ *
+ * <p>{@link Context#valueOf(double)} is used to convert the {@code double} values.</p>
+ *
+ * @param startInclusive the (inclusive) initial value
+ * @param endInclusive the inclusive upper bound
+ * @param step the step between elements
+ * @param context the {@link Context} used to convert the {@code double} values
+ * @return a sequential {@code Stream<BigFloat>}
+ * @see #rangeClosed(BigFloat, BigFloat, BigFloat)
+ */
+ public static Stream<BigFloat> rangeClosed(double startInclusive, double endInclusive, double step, Context context) {
+ return rangeClosed(context.valueOf(startInclusive), context.valueOf(endInclusive), context.valueOf(step));
+ }
+
+ private static class BigFloatSpliterator extends AbstractSpliterator<BigFloat> {
+
+ private BigFloat value;
+ private BigFloat step;
+ private long count;
+
+ public BigFloatSpliterator(BigFloat startInclusive, BigFloat step, long count) {
+ super(count,
+ Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.DISTINCT | Spliterator.IMMUTABLE | Spliterator.NONNULL | Spliterator.ORDERED | Spliterator.SORTED);
+
+ this.value = startInclusive;
+ this.step = step;
+ this.count = count;
+ }
+
+ public BigFloatSpliterator(BigFloat startInclusive, BigFloat end, boolean inclusive, BigFloat step) {
+ this(startInclusive, step, estimatedCount(startInclusive, end, inclusive, step));
+ }
+
+ private static long estimatedCount(BigFloat startInclusive, BigFloat end, boolean inclusive, BigFloat step) {
+ BigFloat count = end.subtract(startInclusive).divide(step);
+ long result = count.toLong();
+ if (count.getFractionalPart().signum() != 0) {
+ result++;
+ } else {
+ if (inclusive) {
+ result++;
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public Comparator<? super BigFloat> getComparator() {
+ if (step.signum() < 0) {
+ return Comparator.reverseOrder();
+ }
+ return null;
+ }
+
+ @Override
+ public boolean tryAdvance(Consumer<? super BigFloat> action) {
+ if (count == 0) {
+ return false;
+ }
+
+ action.accept(value);
+ value = value.add(step);
+ count--;
+ return true;
+ }
+
+ @Override
+ public void forEachRemaining(Consumer<? super BigFloat> action) {
+ while (count > 0) {
+ action.accept(value);
+ value = value.add(step);
+ count--;
+ }
+ }
+
+ @Override
+ public Spliterator<BigFloat> trySplit() {
+ long firstHalfCount = count / 2;
+
+ if (firstHalfCount == 0) {
+ return null;
+ }
+
+ long secondHalfCount = count - firstHalfCount;
+
+ count = firstHalfCount;
+ BigFloat startSecondHalf = value.add(step.multiply(firstHalfCount));
+
+ return new BigFloatSpliterator(startSecondHalf, step, secondHalfCount);
+ }
+ }
+}