| 179 | } |
| 180 | |
| 181 | void Num3072::Multiply(const Num3072& a) |
| 182 | { |
| 183 | limb_t c0 = 0, c1 = 0, c2 = 0; |
| 184 | Num3072 tmp; |
| 185 | |
| 186 | /* Compute limbs 0..N-2 of this*a into tmp, including one reduction. */ |
| 187 | for (int j = 0; j < LIMBS - 1; ++j) { |
| 188 | limb_t d0 = 0, d1 = 0, d2 = 0; |
| 189 | mul(d0, d1, this->limbs[1 + j], a.limbs[LIMBS + j - (1 + j)]); |
| 190 | for (int i = 2 + j; i < LIMBS; ++i) muladd3(d0, d1, d2, this->limbs[i], a.limbs[LIMBS + j - i]); |
| 191 | mulnadd3(c0, c1, c2, d0, d1, d2, MAX_PRIME_DIFF); |
| 192 | for (int i = 0; i < j + 1; ++i) muladd3(c0, c1, c2, this->limbs[i], a.limbs[j - i]); |
| 193 | extract3(c0, c1, c2, tmp.limbs[j]); |
| 194 | } |
| 195 | |
| 196 | /* Compute limb N-1 of a*b into tmp. */ |
| 197 | assert(c2 == 0); |
| 198 | for (int i = 0; i < LIMBS; ++i) muladd3(c0, c1, c2, this->limbs[i], a.limbs[LIMBS - 1 - i]); |
| 199 | extract3(c0, c1, c2, tmp.limbs[LIMBS - 1]); |
| 200 | |
| 201 | /* Perform a second reduction. */ |
| 202 | muln2(c0, c1, MAX_PRIME_DIFF); |
| 203 | for (int j = 0; j < LIMBS; ++j) { |
| 204 | addnextract2(c0, c1, tmp.limbs[j], this->limbs[j]); |
| 205 | } |
| 206 | |
| 207 | assert(c1 == 0); |
| 208 | assert(c0 == 0 || c0 == 1); |
| 209 | |
| 210 | /* Perform up to two more reductions if the internal state has already |
| 211 | * overflown the MAX of Num3072 or if it is larger than the modulus or |
| 212 | * if both are the case. |
| 213 | * */ |
| 214 | if (this->IsOverflow()) this->FullReduce(); |
| 215 | if (c0) this->FullReduce(); |
| 216 | } |
| 217 | |
| 218 | void Num3072::Square() |
| 219 | { |
no test coverage detected