Compute product of two Fq12 elements in normalized form (1 + c J) <- (1 + a J) x (1 + b J). Input a, b and output c. In this form (1 + c J) <- 1 + {(a+b)/(1 + ab J^2)} => c . (1 + ab J^2) =?= (a + b) a, b and c are passed as input to the script and the above equation is validated to show that c is the correct output For invalid input i.e (1 + ab J ^2) == 0, return [a, b, c]
(
a: ark_bn254::Fq6,
b: ark_bn254::Fq6,
)
| 199 | // a, b and c are passed as input to the script and the above equation is validated to show that c is the correct output |
| 200 | // For invalid input i.e (1 + ab J ^2) == 0, return [a, b, c] |
| 201 | pub(crate) fn utils_fq12_dd_mul( |
| 202 | a: ark_bn254::Fq6, |
| 203 | b: ark_bn254::Fq6, |
| 204 | ) -> (ark_bn254::Fq6, bool, Script, Vec<Hint>) { |
| 205 | let mut hints = vec![]; |
| 206 | let mock_value = ark_bn254::Fq6::ONE; |
| 207 | |
| 208 | // compute ab in Script |
| 209 | let (ab_scr, ab_hints) = Fq6::hinted_mul(6, a, 0, b); |
| 210 | hints.extend_from_slice(&ab_hints); |
| 211 | |
| 212 | // calculate denom |
| 213 | let beta_sq = ark_bn254::Fq12Config::NONRESIDUE; |
| 214 | let denom = ark_bn254::Fq6::ONE + a * b * beta_sq; |
| 215 | |
| 216 | // is input valid ? output: mock_output |
| 217 | let (denom_mul_c_scr, c) = if denom != ark_bn254::Fq6::ZERO { |
| 218 | let c = (a + b) / denom; |
| 219 | let res = Fq6::hinted_mul(6, denom, 0, c); |
| 220 | hints.extend_from_slice(&res.1); |
| 221 | (res.0, c) |
| 222 | } else { |
| 223 | let scr = Fq6::hinted_mul(6, ark_bn254::Fq6::ONE, 0, ark_bn254::Fq6::ONE).0; |
| 224 | (scr, mock_value) |
| 225 | }; |
| 226 | |
| 227 | let mul_by_beta_sq_scr = script! { |
| 228 | {Fq6::mul_fq2_by_nonresidue()} |
| 229 | {Fq2::roll(4)} {Fq2::roll(4)} |
| 230 | }; |
| 231 | |
| 232 | let scr = script! { |
| 233 | // [hints a, b, c] [] |
| 234 | {Fq6::toaltstack()} |
| 235 | // [hints a, b] [c] |
| 236 | {Fq12::copy(0)} |
| 237 | // [hints a, b, a, b] [c] |
| 238 | {ab_scr} |
| 239 | // [hints, a, b, ab] |
| 240 | {mul_by_beta_sq_scr} |
| 241 | // [hints, a, b, ab*beta_sq] |
| 242 | {Fq6::push(ark_bn254::Fq6::ONE)} |
| 243 | {Fq6::add(6, 0)} |
| 244 | // [hints, a, b, denom] [c] |
| 245 | {Fq6::copy(0)} |
| 246 | {Fq6::is_zero()} // denom =?= 0 |
| 247 | OP_IF |
| 248 | // [a, b, denom] [c] |
| 249 | {Fq6::drop()} |
| 250 | {Fq6::fromaltstack()} |
| 251 | // [a, b c] [] |
| 252 | {Fq6::drop()} |
| 253 | {Fq6::push(mock_value)} |
| 254 | {0} |
| 255 | // [a, b mock_c, 0] [] |
| 256 | OP_ELSE |
| 257 | {Fq6::fromaltstack()} |
| 258 | // [hints, a, b, denom, c] |
no outgoing calls