random method

SmvType random(
  1. Random rv, {
  2. SignMagnitudeValue? gt,
  3. SignMagnitudeValue? gte,
  4. SignMagnitudeValue? lt,
  5. SignMagnitudeValue? lte,
})

Generate a random SignMagnitudeValue in a signed range.

The range is defined by one of the following combinations of range parameters:

  • gt, lt: generate a value in the range ([gt], [lt])
  • gte, lt: generate a value in the range [[gte], [lt])
  • gt, lte: generate a value in the range ([gt], [lte]]
  • gte, lte: generate a value in the range [[gte], [lte]]
  • gt: generate a value in the range ([gt], ∞)
  • gte: generate a value in the range [[gte], ∞)
  • lt: generate a value in the range (-∞, [lt])
  • lte: generate a value in the range (-∞, [lte]]
  • none: generate a value in the range (-∞, ∞)

Implementation

SmvType random(Random rv,
    {SignMagnitudeValue? gt,
    SignMagnitudeValue? gte,
    SignMagnitudeValue? lt,
    SignMagnitudeValue? lte}) {
  if ((gt != null) & (gte != null)) {
    throw RohdHclException('randomSignMagnitude: cannot have both '
        'gt and gte');
  }
  if ((lt != null) & (lte != null)) {
    throw RohdHclException('randomSignMagnitude: cannot have both '
        'lt and lte');
  }
  final lowerLimitSign = (gt ?? gte)?.sign ?? LogicValue.one;
  final isUpperZero = LogicValue.of((lte ?? lt)?.magnitude.isZero ?? false);
  final isLowerZero = LogicValue.of((gte ?? gt)?.magnitude.isZero ?? false);
  final upperLimitSign =
      ((lt ?? lte)?.sign ?? LogicValue.zero) | (isUpperZero & ~isLowerZero);

  if ((lowerLimitSign == LogicValue.zero) &
      (upperLimitSign == LogicValue.one)) {
    throw RohdHclException('randomSignMagnitude: cannot have positive '
        'lower limit with negative upper limit');
  }

  final one = BigInt.from(1);
  final zero = BigInt.from(0);
  final max = BigInt.two.pow(width) - one;

  final posLowerLimit = (lowerLimitSign == LogicValue.zero)
      ? gte?.magnitude.toBigInt() ?? (gt?.magnitude.toBigInt() ?? -one) + one
      : zero;

  final posUpperLimit = (upperLimitSign == LogicValue.zero)
      ? (lte?.magnitude.toBigInt() ??
          (lt?.magnitude.toBigInt() ?? max + one) - one)
      : zero;

  final negLowerLimit = (upperLimitSign == LogicValue.one)
      ? lte?.magnitude.toBigInt() ?? (lt?.magnitude.toBigInt() ?? -one) + one
      : zero;

  final negUpperLimit = (lowerLimitSign == LogicValue.one)
      ? gte?.magnitude.toBigInt() ??
          ((gt?.magnitude.toBigInt() ?? max + one) - one)
      : zero;

  final sign = (lowerLimitSign == upperLimitSign)
      ? lowerLimitSign
      : (negUpperLimit - negLowerLimit) > zero
          ? (rv.nextBool() ? LogicValue.zero : LogicValue.one)
          : LogicValue.zero;

  final LogicValue magnitude;
  final BigInt limit;
  final BigInt lower;
  if (sign == LogicValue.zero) {
    limit = posUpperLimit - posLowerLimit + one;
    lower = posLowerLimit;
  } else {
    limit = negUpperLimit - negLowerLimit + one;
    lower = negLowerLimit;
  }

  if (lower > max) {
    throw RohdHclException('randomSignMagnitude: invalid range, cannot '
        'generate value');
  }
  if (limit <= zero) {
    throw RohdHclException('randomSignMagnitude: invalid tight range, cannot '
        'generate value');
  }

  magnitude = rv.nextLogicValue(width: width, max: limit) +
      LogicValue.ofBigInt(lower, width);

  return populate(sign: sign, magnitude: magnitude);
}