All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.jqwik.engine.properties.arbitraries.randomized.RandomDecimalGenerators Maven / Gradle / Ivy

There is a newer version: 1.9.1
Show newest version
package net.jqwik.engine.properties.arbitraries.randomized;

import java.math.*;

import net.jqwik.api.*;
import net.jqwik.engine.properties.*;

public class RandomDecimalGenerators {

	public static RandomGenerator bigDecimals(
		int genSize,
		Range range,
		int scale,
		RandomDistribution distribution,
		BigDecimal shrinkingTarget
	) {
		checkRangeIsSound(range, scale);

		if (scale < 0) {
			throw new JqwikException(String.format("Scale [%s] must be positive.", scale));
		}

		if (range.isSingular()) {
			return ignored -> Shrinkable.unshrinkable(range.min);
		}

		Range unscaledRange = unscaledBigIntegerRange(range, scale);
		BigInteger unscaledShrinkingTarget = unscaledBigInteger(shrinkingTarget, scale);
		RandomGenerator unscaledBigIntegerGenerator =
			RandomIntegralGenerators.bigIntegers(genSize, unscaledRange.min, unscaledRange.max, unscaledShrinkingTarget, distribution);

		return scaledBigDecimalGenerator(unscaledBigIntegerGenerator, scale);
	}

	private static void checkRangeIsSound(Range range, int scale) {
		if (range.minIncluded || range.maxIncluded) {
			return;
		}
		BigDecimal minimumDifference = BigDecimal.ONE.movePointLeft(scale);
		if (range.min.add(minimumDifference).compareTo(range.max) >= 0) {
			String message = String.format("No number with scale <%s> can be generated in %s", scale, range);
			throw new JqwikException(message);
		}
	}

	private static RandomGenerator scaledBigDecimalGenerator(
		final RandomGenerator scaledBigIntegerGenerator,
		final int scale
	) {
		return scaledBigIntegerGenerator.map(value -> scaledBigDecimal(value, scale));
	}

	public static Range unscaledBigIntegerRange(final Range range, final int scale) {
		BigInteger minScaled = range.minIncluded
									   ? unscaledBigInteger(range.min, scale)
									   : unscaledBigInteger(range.min, scale).add(BigInteger.ONE);
		BigInteger maxScaled = range.maxIncluded
									   ? unscaledBigInteger(range.max, scale)
									   : unscaledBigInteger(range.max, scale).subtract(BigInteger.ONE);
		return Range.of(minScaled, true, maxScaled, true);
	}

	public static BigDecimal scaledBigDecimal(final BigInteger value, final int scale) {
		return new BigDecimal(value, scale);
	}

	public static BigInteger unscaledBigInteger(final BigDecimal bigDecimal, final int scale) {
		return bigDecimal.setScale(scale, RoundingMode.HALF_UP).unscaledValue();
	}

	public static BigDecimal defaultShrinkingTarget(Range range, int scale) {
		if (range.includes(BigDecimal.ZERO))
			return BigDecimal.ZERO;
		else {
			if (range.max.compareTo(BigDecimal.ZERO) <= 0) {
				if (range.maxIncluded) {
					return range.max;
				} else {
					BigDecimal minimumDifference = BigDecimal.ONE.movePointLeft(scale);
					return range.max.subtract(minimumDifference);
				}
			}
			if (range.min.compareTo(BigDecimal.ZERO) >= 0) {
				if (range.minIncluded) {
					return range.min;
				} else {
					BigDecimal minimumDifference = BigDecimal.ONE.movePointLeft(scale);
					return range.min.add(minimumDifference);
				}
			}
		}
		throw new RuntimeException("This should not be possible");
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy