diff options
author | Tec <daniel112092@gmail.com> | 2020-07-18 22:49:35 +0200 |
---|---|---|
committer | Tec <daniel112092@gmail.com> | 2020-07-18 22:49:35 +0200 |
commit | 11e50eb56f6750d6bdfe15b986eef55e27452211 (patch) | |
tree | f6d4e90967e76c2fa2f988a823340fa85b9a604b /src/main/java/ch/obermuhlner/math/big/stream | |
parent | 5c68b296e1b499ca83d78f24837768ac3a75df62 (diff) | |
download | GT5-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.java | 219 | ||||
-rw-r--r-- | src/main/java/ch/obermuhlner/math/big/stream/BigFloatStream.java | 214 |
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) < 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) <= 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); + } + } +} |