sqrtRatioGeneric<F extends CryptoField<F>> static method

FieldSqrtResult<F> sqrtRatioGeneric<F extends CryptoField<F>>({
  1. required F num,
  2. required F div,
  3. required F zero,
  4. required F rootOfUnity,
})

Implementation

static FieldSqrtResult<F> sqrtRatioGeneric<F extends CryptoField<F>>({
  required F num,
  required F div,
  required F zero,
  required F rootOfUnity,
}) {
  // a = num * inv0(div)
  // inv0(div) = 0 if div == 0
  F a;
  final F? inv = div.invert();
  if (inv == null) {
    a = zero;
  } else {
    a = inv * num;
  }

  // b = a * ROOT_OF_UNITY
  final F b = a * rootOfUnity;

  // sqrt candidates
  final sqrtA = a.sqrt(); // returns null if a is nonsquare
  final sqrtB = b.sqrt(); // returns null if b is nonsquare

  final bool numIsZero = num.isZero();
  final bool divIsZero = div.isZero();
  final bool isSquare = sqrtA.isSquare;
  final bool isNonSquare = sqrtB.isSquare;

  // Safety check from Rust:
  // num == 0  OR div == 0  OR exactly one of a,b is square.
  assert(numIsZero || divIsZero || (isSquare != isNonSquare));

  // Boolean condition:
  // is_square & (num_is_zero || !div_is_zero)
  final bool resultIsSquare = isSquare && (numIsZero || !divIsZero);

  // Pick sqrt: if a is square, pick sqrtA, else pick sqrtB
  final F chosen = isSquare ? sqrtA.result : sqrtB.result;
  return FieldSqrtResult(chosen, resultIsSquare);
}