| 216 | } |
| 217 | |
| 218 | void Num3072::Square() |
| 219 | { |
| 220 | limb_t c0 = 0, c1 = 0, c2 = 0; |
| 221 | Num3072 tmp; |
| 222 | |
| 223 | /* Compute limbs 0..N-2 of this*this into tmp, including one reduction. */ |
| 224 | for (int j = 0; j < LIMBS - 1; ++j) { |
| 225 | limb_t d0 = 0, d1 = 0, d2 = 0; |
| 226 | for (int i = 0; i < (LIMBS - 1 - j) / 2; ++i) muldbladd3(d0, d1, d2, this->limbs[i + j + 1], this->limbs[LIMBS - 1 - i]); |
| 227 | if ((j + 1) & 1) muladd3(d0, d1, d2, this->limbs[(LIMBS - 1 - j) / 2 + j + 1], this->limbs[LIMBS - 1 - (LIMBS - 1 - j) / 2]); |
| 228 | mulnadd3(c0, c1, c2, d0, d1, d2, MAX_PRIME_DIFF); |
| 229 | for (int i = 0; i < (j + 1) / 2; ++i) muldbladd3(c0, c1, c2, this->limbs[i], this->limbs[j - i]); |
| 230 | if ((j + 1) & 1) muladd3(c0, c1, c2, this->limbs[(j + 1) / 2], this->limbs[j - (j + 1) / 2]); |
| 231 | extract3(c0, c1, c2, tmp.limbs[j]); |
| 232 | } |
| 233 | |
| 234 | assert(c2 == 0); |
| 235 | for (int i = 0; i < LIMBS / 2; ++i) muldbladd3(c0, c1, c2, this->limbs[i], this->limbs[LIMBS - 1 - i]); |
| 236 | extract3(c0, c1, c2, tmp.limbs[LIMBS - 1]); |
| 237 | |
| 238 | /* Perform a second reduction. */ |
| 239 | muln2(c0, c1, MAX_PRIME_DIFF); |
| 240 | for (int j = 0; j < LIMBS; ++j) { |
| 241 | addnextract2(c0, c1, tmp.limbs[j], this->limbs[j]); |
| 242 | } |
| 243 | |
| 244 | assert(c1 == 0); |
| 245 | assert(c0 == 0 || c0 == 1); |
| 246 | |
| 247 | /* Perform up to two more reductions if the internal state has already |
| 248 | * overflown the MAX of Num3072 or if it is larger than the modulus or |
| 249 | * if both are the case. |
| 250 | * */ |
| 251 | if (this->IsOverflow()) this->FullReduce(); |
| 252 | if (c0) this->FullReduce(); |
| 253 | } |
| 254 | |
| 255 | void Num3072::SetToOne() |
| 256 | { |
no test coverage detected