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

net.jqwik.engine.properties.arbitraries.randomized.RandomIntegralGenerators 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 java.util.*;
import java.util.function.*;

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

// TODO: Remove duplication with RandomDecimalGenerators
public class RandomIntegralGenerators {

	public static RandomGenerator bigIntegers(
		Range range,
		BigInteger[] partitionPoints,
		Function shrinkingTargetCalculator
	) {
		if (range.isSingular()) {
			return ignored -> Shrinkable.unshrinkable(range.min);
		}
		return partitionedGenerator(range, partitionPoints, shrinkingTargetCalculator);
	}

	private static RandomGenerator partitionedGenerator(
		Range range,
		BigInteger[] partitionPoints,
		Function shrinkingTargetCalculator
	) {
		List> generators = createPartitions(range, partitionPoints, shrinkingTargetCalculator);
		if (generators.size() == 1) {
			return generators.get(0);
		}
		return random -> generators.get(random.nextInt(generators.size())).next(random);
	}

	private static List> createPartitions(
		Range range, BigInteger[] partitionPoints,
		Function shrinkingTargetCalculator
	) {
		List> partitions = new ArrayList<>();
		Arrays.sort(partitionPoints);
		BigInteger lower = range.min;
		for (BigInteger partitionPoint : partitionPoints) {
			BigInteger upper = partitionPoint;
			if (upper.compareTo(lower) <= 0) {
				continue;
			}
			if (upper.compareTo(range.max) >= 0) {
				break;
			}
			partitions.add(createBaseGenerator(lower, upper.subtract(BigInteger.ONE), range, shrinkingTargetCalculator));
			lower = upper;
		}
		partitions.add(createBaseGenerator(lower, range.max, range, shrinkingTargetCalculator));
		return partitions;
	}

	private static RandomGenerator createBaseGenerator(
		BigInteger minGenerate,
		BigInteger maxGenerate,
		Range shrinkingRange,
		Function shrinkingTargetCalculator
	) {
		if (isWithinIntegerRange(minGenerate, maxGenerate)) {
			return createIntegerGenerator(minGenerate, maxGenerate, shrinkingRange, shrinkingTargetCalculator);
		} else {
			return createBigIntegerGenerator(minGenerate, maxGenerate, shrinkingRange, shrinkingTargetCalculator);
		}
	}

	private static RandomGenerator createBigIntegerGenerator(
		BigInteger minGenerate,
		BigInteger maxGenerate,
		Range shrinkingRange,
		Function shrinkingTargetCalculator
	) {
		BigInteger range = maxGenerate.subtract(minGenerate);
		int bits = range.bitLength();
		return random -> {
			while (true) {
				BigInteger rawValue = new BigInteger(bits, random);
				BigInteger value = rawValue.add(minGenerate);
				if (value.compareTo(minGenerate) >= 0 && value.compareTo(maxGenerate) <= 0) {
					return new ShrinkableBigInteger(
						value,
						shrinkingRange,
						shrinkingTargetCalculator.apply(value)
					);
				}
			}
		};
	}

	private static RandomGenerator createIntegerGenerator(
		BigInteger min,
		BigInteger max,
		Range shrinkingRange,
		Function shrinkingTargetCalculator
	) {
		final int _min = Math.min(min.intValue(), max.intValue());
		final int _max = Math.max(min.intValue(), max.intValue());
		return random -> {
			int bound = Math.abs(_max - _min) + 1;
			int value = random.nextInt(bound >= 0 ? bound : Integer.MAX_VALUE) + _min;
			BigInteger bigIntegerValue = BigInteger.valueOf(value);
			return new ShrinkableBigInteger(
				bigIntegerValue,
				shrinkingRange,
				shrinkingTargetCalculator.apply(bigIntegerValue)
			);
		};
	}

	private static boolean isWithinIntegerRange(BigInteger min, BigInteger max) {
		return min.compareTo(BigInteger.valueOf(Integer.MIN_VALUE)) >= 0
				   && max.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) <= 0;
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy