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

net.jqwik.engine.properties.shrinking.ShrinkableBigInteger Maven / Gradle / Ivy

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

import java.math.*;
import java.util.*;
import java.util.stream.*;

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

public class ShrinkableBigInteger extends AbstractValueShrinkable {
	private final Range range;
	private final BigInteger shrinkingTarget;

	public ShrinkableBigInteger(BigInteger value, Range range, BigInteger shrinkingTarget) {
		super(value);
		this.range = range;
		this.shrinkingTarget = shrinkingTarget;
		checkValueInRange(value);
	}

	@Override
	public Stream> shrink() {
		return JqwikStreamSupport.concat(
			shrinkTowardsTarget(this),
			shrinkNegativeToPositive(this)
		);
	}

	@Override
	public Optional> grow(Shrinkable before, Shrinkable after) {
		return new BigIntegerGrower().grow(value(), range, shrinkingTarget, before, after);
	}

	@Override
	public Stream> grow() {
		return new BigIntegerGrower().grow(value(), range, shrinkingTarget);
	}

	private Stream> shrinkNegativeToPositive(Shrinkable shrinkable) {
		if (shrinkable.value().compareTo(BigInteger.ZERO) >= 0) {
			return Stream.empty();
		}
		return Stream.of(shrinkable)
					 .map(s -> shrinkable.value().negate())
					 .filter(range::includes)
					 .map(this::createShrinkable);
	}

	private Stream> shrinkTowardsTarget(Shrinkable shrinkable) {
		return new BigIntegerShrinker(shrinkingTarget)
				   .shrink(shrinkable.value())
				   .map(this::createShrinkable)
				   .sorted(Comparator.comparing(Shrinkable::distance));
	}

	private Shrinkable createShrinkable(BigInteger aBigInteger) {
		return new ShrinkableBigInteger(aBigInteger, range, shrinkingTarget);
	}

	@Override
	public ShrinkingDistance distance() {
		return distanceFor(value(), shrinkingTarget);
	}

	static ShrinkingDistance distanceFor(BigInteger value, BigInteger target) {
		BigInteger distance = value.subtract(target).abs();
		if (distance.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) >= 0) return ShrinkingDistance.of(Long.MAX_VALUE);
		return ShrinkingDistance.of(distance.longValueExact());
	}

	private void checkValueInRange(BigInteger value) {
		if (!range.includes(value)) {
			String message = String.format("Value <%s> is outside allowed range %s", value, range);
			throw new JqwikException(message);
		}
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy