referredBlockIndex method

  1. @visibleForTesting
(int, int) referredBlockIndex({
  1. required int iteration,
  2. required int slice,
  3. required int lane,
  4. required int index,
  5. required int j1,
  6. required int j2,
})

Finds a block using rules describes in the specification.

Implementation

@visibleForTesting
(int, int) referredBlockIndex({
  required int iteration,
  required int slice,
  required int lane,
  required int index,
  required int j1,
  required int j2,
}) {
  final blocksPerLane = blockCount ~/ parallelism;
  final blocksPerSegment = blocksPerLane ~/ 4;

  // In the RFC 9106:
  //   l = J_2 mod p
  //
  // During the first segment of the first iteration,
  // the current lane is used.
  var referenceLane = j2 % parallelism;
  if (iteration == 0 && slice == 0) {
    referenceLane = lane;
  }

  // Index of the first possible block.
  var candidatesStart = 0;

  // Number of possible blocks.
  var candidatesLength = 0;

  if (iteration == 0) {
    if (slice == 0 || referenceLane == lane) {
      candidatesLength = slice * blocksPerSegment + index - 1;
    } else {
      candidatesLength = slice * blocksPerSegment;
      if (index == 0) {
        candidatesLength--;
      }
    }
  } else {
    // This is not the first iteration.
    candidatesStart = ((slice + 1) % 4) * blocksPerSegment;
    candidatesLength = 3 * blocksPerSegment;

    // The previous blocks of the same segment are candidates if:
    //   * This is the first slice of the first iteration
    //   * OR the current lane is the reference lane
    if (referenceLane == lane) {
      candidatesLength += index - 1;
    } else if (index == 0) {
      candidatesLength--;
    }
  }
  final zz = referredBlockIndexZZ(j1, candidatesLength);
  final z = (candidatesStart + candidatesLength - 1 - zz) % blocksPerLane;
  return (referenceLane, z);
}