00001
00002
00003
00004
00005
00006 #include "pch.h"
00007 #include "polynomi.h"
00008
00009 #include <strstream>
00010 #include <iostream>
00011
00012 NAMESPACE_BEGIN(CryptoPP)
00013
00014 template <class T>
00015 void PolynomialOver<T>::Randomize(RandomNumberGenerator &rng, const RandomizationParameter ¶meter, const Ring &ring)
00016 {
00017 m_coefficients.resize(parameter.m_coefficientCount);
00018 for (unsigned int i=0; i<m_coefficients.size(); ++i)
00019 m_coefficients[i] = ring.RandomElement(rng, parameter.m_coefficientParameter);
00020 }
00021
00022 template <class T>
00023 void PolynomialOver<T>::FromStr(const char *str, const Ring &ring)
00024 {
00025 std::istrstream in((char *)str);
00026 bool positive = true;
00027 CoefficientType coef;
00028 unsigned int power;
00029
00030 while (in)
00031 {
00032 std::ws(in);
00033 if (in.peek() == 'x')
00034 coef = ring.One();
00035 else
00036 in >> coef;
00037
00038 std::ws(in);
00039 if (in.peek() == 'x')
00040 {
00041 in.get();
00042 std::ws(in);
00043 if (in.peek() == '^')
00044 {
00045 in.get();
00046 in >> power;
00047 }
00048 else
00049 power = 1;
00050 }
00051 else
00052 power = 0;
00053
00054 if (!positive)
00055 coef = ring.Inverse(coef);
00056
00057 SetCoefficient(power, coef, ring);
00058
00059 std::ws(in);
00060 switch (in.get())
00061 {
00062 case '+':
00063 positive = true;
00064 break;
00065 case '-':
00066 positive = false;
00067 break;
00068 default:
00069 return;
00070 }
00071 }
00072 }
00073
00074 template <class T>
00075 unsigned int PolynomialOver<T>::CoefficientCount(const Ring &ring) const
00076 {
00077 unsigned count = m_coefficients.size();
00078 while (count && ring.Equal(m_coefficients[count-1], ring.Zero()))
00079 count--;
00080 const_cast<std::vector<CoefficientType> &>(m_coefficients).resize(count);
00081 return count;
00082 }
00083
00084 template <class T>
00085 PolynomialOver<T>::CoefficientType PolynomialOver<T>::GetCoefficient(unsigned int i, const Ring &ring) const
00086 {
00087 return (i < m_coefficients.size()) ? m_coefficients[i] : ring.Zero();
00088 }
00089
00090 template <class T>
00091 PolynomialOver<T>& PolynomialOver<T>::operator=(const PolynomialOver<T>& t)
00092 {
00093 if (this != &t)
00094 {
00095 m_coefficients.resize(t.m_coefficients.size());
00096 for (unsigned int i=0; i<m_coefficients.size(); i++)
00097 m_coefficients[i] = t.m_coefficients[i];
00098 }
00099 return *this;
00100 }
00101
00102 template <class T>
00103 PolynomialOver<T>& PolynomialOver<T>::Accumulate(const PolynomialOver<T>& t, const Ring &ring)
00104 {
00105 unsigned int count = t.CoefficientCount(ring);
00106
00107 if (count > CoefficientCount(ring))
00108 m_coefficients.resize(count, ring.Zero());
00109
00110 for (unsigned int i=0; i<count; i++)
00111 ring.Accumulate(m_coefficients[i], t.GetCoefficient(i, ring));
00112
00113 return *this;
00114 }
00115
00116 template <class T>
00117 PolynomialOver<T>& PolynomialOver<T>::Reduce(const PolynomialOver<T>& t, const Ring &ring)
00118 {
00119 unsigned int count = t.CoefficientCount(ring);
00120
00121 if (count > CoefficientCount(ring))
00122 m_coefficients.resize(count, ring.Zero());
00123
00124 for (unsigned int i=0; i<count; i++)
00125 ring.Reduce(m_coefficients[i], t.GetCoefficient(i, ring));
00126
00127 return *this;
00128 }
00129
00130 template <class T>
00131 PolynomialOver<T>::CoefficientType PolynomialOver<T>::EvaluateAt(const CoefficientType &x, const Ring &ring) const
00132 {
00133 int degree = Degree(ring);
00134
00135 if (degree < 0)
00136 return ring.Zero();
00137
00138 CoefficientType result = m_coefficients[degree];
00139 for (int j=degree-1; j>=0; j--)
00140 {
00141 result = ring.Multiply(result, x);
00142 ring.Accumulate(result, m_coefficients[j]);
00143 }
00144 return result;
00145 }
00146
00147 template <class T>
00148 PolynomialOver<T>& PolynomialOver<T>::ShiftLeft(unsigned int n, const Ring &ring)
00149 {
00150 unsigned int i = CoefficientCount(ring) + n;
00151 m_coefficients.resize(i, ring.Zero());
00152 while (i > n)
00153 {
00154 i--;
00155 m_coefficients[i] = m_coefficients[i-n];
00156 }
00157 while (i)
00158 {
00159 i--;
00160 m_coefficients[i] = ring.Zero();
00161 }
00162 return *this;
00163 }
00164
00165 template <class T>
00166 PolynomialOver<T>& PolynomialOver<T>::ShiftRight(unsigned int n, const Ring &ring)
00167 {
00168 unsigned int count = CoefficientCount(ring);
00169 if (count > n)
00170 {
00171 for (unsigned int i=0; i<count-n; i++)
00172 m_coefficients[i] = m_coefficients[i+n];
00173 m_coefficients.resize(count-n, ring.Zero());
00174 }
00175 else
00176 m_coefficients.resize(0, ring.Zero());
00177 return *this;
00178 }
00179
00180 template <class T>
00181 void PolynomialOver<T>::SetCoefficient(unsigned int i, const CoefficientType &value, const Ring &ring)
00182 {
00183 if (i >= m_coefficients.size())
00184 m_coefficients.resize(i+1, ring.Zero());
00185 m_coefficients[i] = value;
00186 }
00187
00188 template <class T>
00189 void PolynomialOver<T>::Negate(const Ring &ring)
00190 {
00191 unsigned int count = CoefficientCount(ring);
00192 for (unsigned int i=0; i<count; i++)
00193 m_coefficients[i] = ring.Inverse(m_coefficients[i]);
00194 }
00195
00196 template <class T>
00197 void PolynomialOver<T>::swap(PolynomialOver<T> &t)
00198 {
00199 m_coefficients.swap(t.m_coefficients);
00200 }
00201
00202 template <class T>
00203 bool PolynomialOver<T>::Equals(const PolynomialOver<T>& t, const Ring &ring) const
00204 {
00205 unsigned int count = CoefficientCount(ring);
00206
00207 if (count != t.CoefficientCount(ring))
00208 return false;
00209
00210 for (unsigned int i=0; i<count; i++)
00211 if (!ring.Equal(m_coefficients[i], t.m_coefficients[i]))
00212 return false;
00213
00214 return true;
00215 }
00216
00217 template <class T>
00218 PolynomialOver<T> PolynomialOver<T>::Plus(const PolynomialOver<T>& t, const Ring &ring) const
00219 {
00220 unsigned int i;
00221 unsigned int count = CoefficientCount(ring);
00222 unsigned int tCount = t.CoefficientCount(ring);
00223
00224 if (count > tCount)
00225 {
00226 PolynomialOver<T> result(ring, count);
00227
00228 for (i=0; i<tCount; i++)
00229 result.m_coefficients[i] = ring.Add(m_coefficients[i], t.m_coefficients[i]);
00230 for (; i<count; i++)
00231 result.m_coefficients[i] = m_coefficients[i];
00232
00233 return result;
00234 }
00235 else
00236 {
00237 PolynomialOver<T> result(ring, tCount);
00238
00239 for (i=0; i<count; i++)
00240 result.m_coefficients[i] = ring.Add(m_coefficients[i], t.m_coefficients[i]);
00241 for (; i<tCount; i++)
00242 result.m_coefficients[i] = t.m_coefficients[i];
00243
00244 return result;
00245 }
00246 }
00247
00248 template <class T>
00249 PolynomialOver<T> PolynomialOver<T>::Minus(const PolynomialOver<T>& t, const Ring &ring) const
00250 {
00251 unsigned int i;
00252 unsigned int count = CoefficientCount(ring);
00253 unsigned int tCount = t.CoefficientCount(ring);
00254
00255 if (count > tCount)
00256 {
00257 PolynomialOver<T> result(ring, count);
00258
00259 for (i=0; i<tCount; i++)
00260 result.m_coefficients[i] = ring.Subtract(m_coefficients[i], t.m_coefficients[i]);
00261 for (; i<count; i++)
00262 result.m_coefficients[i] = m_coefficients[i];
00263
00264 return result;
00265 }
00266 else
00267 {
00268 PolynomialOver<T> result(ring, tCount);
00269
00270 for (i=0; i<count; i++)
00271 result.m_coefficients[i] = ring.Subtract(m_coefficients[i], t.m_coefficients[i]);
00272 for (; i<tCount; i++)
00273 result.m_coefficients[i] = ring.Inverse(t.m_coefficients[i]);
00274
00275 return result;
00276 }
00277 }
00278
00279 template <class T>
00280 PolynomialOver<T> PolynomialOver<T>::Inverse(const Ring &ring) const
00281 {
00282 unsigned int count = CoefficientCount(ring);
00283 PolynomialOver<T> result(ring, count);
00284
00285 for (unsigned int i=0; i<count; i++)
00286 result.m_coefficients[i] = ring.Inverse(m_coefficients[i]);
00287
00288 return result;
00289 }
00290
00291 template <class T>
00292 PolynomialOver<T> PolynomialOver<T>::Times(const PolynomialOver<T>& t, const Ring &ring) const
00293 {
00294 if (IsZero(ring) || t.IsZero(ring))
00295 return PolynomialOver<T>();
00296
00297 unsigned int count1 = CoefficientCount(ring), count2 = t.CoefficientCount(ring);
00298 PolynomialOver<T> result(ring, count1 + count2 - 1);
00299
00300 for (unsigned int i=0; i<count1; i++)
00301 for (unsigned int j=0; j<count2; j++)
00302 ring.Accumulate(result.m_coefficients[i+j], ring.Multiply(m_coefficients[i], t.m_coefficients[j]));
00303
00304 return result;
00305 }
00306
00307 template <class T>
00308 PolynomialOver<T> PolynomialOver<T>::DividedBy(const PolynomialOver<T>& t, const Ring &ring) const
00309 {
00310 PolynomialOver<T> remainder, quotient;
00311 Divide(remainder, quotient, *this, t, ring);
00312 return quotient;
00313 }
00314
00315 template <class T>
00316 PolynomialOver<T> PolynomialOver<T>::Modulo(const PolynomialOver<T>& t, const Ring &ring) const
00317 {
00318 PolynomialOver<T> remainder, quotient;
00319 Divide(remainder, quotient, *this, t, ring);
00320 return remainder;
00321 }
00322
00323 template <class T>
00324 PolynomialOver<T> PolynomialOver<T>::MultiplicativeInverse(const Ring &ring) const
00325 {
00326 return Degree(ring)==0 ? ring.MultiplicativeInverse(m_coefficients[0]) : ring.Zero();
00327 }
00328
00329 template <class T>
00330 bool PolynomialOver<T>::IsUnit(const Ring &ring) const
00331 {
00332 return Degree(ring)==0 && ring.IsUnit(m_coefficients[0]);
00333 }
00334
00335 template <class T>
00336 std::istream& PolynomialOver<T>::Input(std::istream &in, const Ring &ring)
00337 {
00338 char c;
00339 unsigned int length = 0;
00340 SecBlock<char> str(length + 16);
00341 bool paren = false;
00342
00343 std::ws(in);
00344
00345 if (in.peek() == '(')
00346 {
00347 paren = true;
00348 in.get();
00349 }
00350
00351 do
00352 {
00353 in.read(&c, 1);
00354 str[length++] = c;
00355 if (length >= str.size)
00356 str.Grow(length + 16);
00357 }
00358
00359
00360 while (in && ((paren && c != ')') || (!paren && c != '\n')));
00361
00362 str[length-1] = '\0';
00363 *this = PolynomialOver<T>(str, ring);
00364
00365 return in;
00366 }
00367
00368 template <class T>
00369 std::ostream& PolynomialOver<T>::Output(std::ostream &out, const Ring &ring) const
00370 {
00371 unsigned int i = CoefficientCount(ring);
00372 if (i)
00373 {
00374 bool firstTerm = true;
00375
00376 while (i--)
00377 {
00378 if (m_coefficients[i] != ring.Zero())
00379 {
00380 if (firstTerm)
00381 {
00382 firstTerm = false;
00383 if (!i || !ring.Equal(m_coefficients[i], ring.One()))
00384 out << m_coefficients[i];
00385 }
00386 else
00387 {
00388 CoefficientType inverse = ring.Inverse(m_coefficients[i]);
00389 ostrstream pstr, nstr;
00390
00391 pstr << m_coefficients[i];
00392 nstr << inverse;
00393
00394 if (pstr.pcount() <= nstr.pcount())
00395 {
00396 out << " + ";
00397 if (!i || !ring.Equal(m_coefficients[i], ring.One()))
00398 out << m_coefficients[i];
00399 }
00400 else
00401 {
00402 out << " - ";
00403 if (!i || !ring.Equal(inverse, ring.One()))
00404 out << inverse;
00405 }
00406 }
00407
00408 switch (i)
00409 {
00410 case 0:
00411 break;
00412 case 1:
00413 out << "x";
00414 break;
00415 default:
00416 out << "x^" << i;
00417 }
00418 }
00419 }
00420 }
00421 else
00422 {
00423 out << ring.Zero();
00424 }
00425 return out;
00426 }
00427
00428 template <class T>
00429 void PolynomialOver<T>::Divide(PolynomialOver<T> &r, PolynomialOver<T> &q, const PolynomialOver<T> &a, const PolynomialOver<T> &d, const Ring &ring)
00430 {
00431 unsigned int i = a.CoefficientCount(ring);
00432 const int dDegree = d.Degree(ring);
00433
00434 if (dDegree < 0)
00435 throw DivideByZero();
00436
00437 r = a;
00438 q.m_coefficients.resize(STDMAX(0, int(i - dDegree)));
00439
00440 while (i > (unsigned int)dDegree)
00441 {
00442 --i;
00443 q.m_coefficients[i-dDegree] = ring.Divide(r.m_coefficients[i], d.m_coefficients[dDegree]);
00444 for (int j=0; j<=dDegree; j++)
00445 ring.Reduce(r.m_coefficients[i-dDegree+j], ring.Multiply(q.m_coefficients[i-dDegree], d.m_coefficients[j]));
00446 }
00447
00448 r.CoefficientCount(ring);
00449 }
00450
00451
00452
00453
00454 template <class T>
00455 void RingOfPolynomialsOver<T>::CalculateAlpha(std::vector<CoefficientType> &alpha, const CoefficientType x[], const CoefficientType y[], unsigned int n) const
00456 {
00457 for (unsigned int j=0; j<n; ++j)
00458 alpha[j] = y[j];
00459
00460 for (unsigned int k=1; k<n; ++k)
00461 {
00462 for (unsigned int j=n-1; j>=k; --j)
00463 {
00464 m_ring.Reduce(alpha[j], alpha[j-1]);
00465
00466 CoefficientType d = m_ring.Subtract(x[j], x[j-k]);
00467 if (!m_ring.IsUnit(d))
00468 throw InterpolationFailed();
00469 alpha[j] = m_ring.Divide(alpha[j], d);
00470 }
00471 }
00472 }
00473
00474 template <class T>
00475 RingOfPolynomialsOver<T>::Element RingOfPolynomialsOver<T>::Interpolate(const CoefficientType x[], const CoefficientType y[], unsigned int n) const
00476 {
00477 assert(n > 0);
00478
00479 std::vector<CoefficientType> alpha(n);
00480 CalculateAlpha(alpha, x, y, n);
00481
00482 std::vector<CoefficientType> coefficients((size_t)n, m_ring.Zero());
00483 coefficients[0] = alpha[n-1];
00484
00485 for (int j=n-2; j>=0; --j)
00486 {
00487 for (unsigned int i=n-j-1; i>0; i--)
00488 coefficients[i] = m_ring.Subtract(coefficients[i-1], m_ring.Multiply(coefficients[i], x[j]));
00489
00490 coefficients[0] = m_ring.Subtract(alpha[j], m_ring.Multiply(coefficients[0], x[j]));
00491 }
00492
00493 return PolynomialOver<T>(coefficients.begin(), coefficients.end());
00494 }
00495
00496 template <class T>
00497 RingOfPolynomialsOver<T>::CoefficientType RingOfPolynomialsOver<T>::InterpolateAt(const CoefficientType &position, const CoefficientType x[], const CoefficientType y[], unsigned int n) const
00498 {
00499 assert(n > 0);
00500
00501 std::vector<CoefficientType> alpha(n);
00502 CalculateAlpha(alpha, x, y, n);
00503
00504 CoefficientType result = alpha[n-1];
00505 for (int j=n-2; j>=0; --j)
00506 {
00507 result = m_ring.Multiply(result, m_ring.Subtract(position, x[j]));
00508 m_ring.Accumulate(result, alpha[j]);
00509 }
00510 return result;
00511 }
00512
00513 template <class Ring, class Element>
00514 void PrepareBulkPolynomialInterpolation(const Ring &ring, Element *w, const Element x[], unsigned int n)
00515 {
00516 for (unsigned int i=0; i<n; i++)
00517 {
00518 Element t = ring.One();
00519 for (unsigned int j=0; j<n; j++)
00520 if (i != j)
00521 t = ring.Multiply(t, ring.Subtract(x[i], x[j]));
00522 w[i] = ring.MultiplicativeInverse(t);
00523 }
00524 }
00525
00526 template <class Ring, class Element>
00527 void PrepareBulkPolynomialInterpolationAt(const Ring &ring, Element *v, const Element &position, const Element x[], const Element w[], unsigned int n)
00528 {
00529 assert(n > 0);
00530
00531 std::vector<Element> a(2*n-1);
00532 unsigned int i;
00533
00534 for (i=0; i<n; i++)
00535 a[n-1+i] = ring.Subtract(position, x[i]);
00536
00537 for (i=n-1; i>1; i--)
00538 a[i-1] = ring.Multiply(a[2*i], a[2*i-1]);
00539
00540 a[0] = ring.One();
00541
00542 for (i=0; i<n-1; i++)
00543 {
00544 std::swap(a[2*i+1], a[2*i+2]);
00545 a[2*i+1] = ring.Multiply(a[i], a[2*i+1]);
00546 a[2*i+2] = ring.Multiply(a[i], a[2*i+2]);
00547 }
00548
00549 for (i=0; i<n; i++)
00550 v[i] = ring.Multiply(a[n-1+i], w[i]);
00551 }
00552
00553 template <class Ring, class Element>
00554 Element BulkPolynomialInterpolateAt(const Ring &ring, const Element y[], const Element v[], unsigned int n)
00555 {
00556 Element result = ring.Zero();
00557 for (unsigned int i=0; i<n; i++)
00558 ring.Accumulate(result, ring.Multiply(y[i], v[i]));
00559 return result;
00560 }
00561
00562
00563
00564 template <class T, int instance>
00565 const PolynomialOverFixedRing<T, instance> &PolynomialOverFixedRing<T, instance>::Zero()
00566 {
00567 static const PolynomialOverFixedRing<T, instance> zero;
00568 return zero;
00569 }
00570
00571 template <class T, int instance>
00572 const PolynomialOverFixedRing<T, instance> &PolynomialOverFixedRing<T, instance>::One()
00573 {
00574 static const PolynomialOverFixedRing<T, instance> one = fixedRing.One();
00575 return one;
00576 }
00577
00578 NAMESPACE_END