00001
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #ifndef LIBECC_POLYNOMIAL_H
00032 #define LIBECC_POLYNOMIAL_H
00033
00034 #include <libecc/bitset.h>
00035 #if ECC_DEBUGOUTPUT
00036 #include <libcw/cwprint.h>
00037 #endif
00038
00039 namespace libecc {
00040
00277 template<unsigned int m, unsigned int k>
00278 class polynomial {
00279 public:
00280
00281 static size_t const offsetof_vector = bitset<m>::offsetof_vector;
00282
00283 private:
00284 bitset<m> M_coefficients;
00285 static polynomial<m, k> const one;
00286
00287 public:
00291 static polynomial const& unity(void) { return one; }
00292
00293 public:
00297 polynomial(void) { }
00298
00302 explicit polynomial(bitset_digit_t coefficients) : M_coefficients(coefficients) { }
00303
00307 polynomial(polynomial const& p) : M_coefficients(p.M_coefficients) { }
00308
00312 explicit polynomial(bitset<m> const& coefficients) : M_coefficients(coefficients) { }
00313
00317 polynomial(std::string const& coefficients) : M_coefficients(coefficients) { }
00318
00332 polynomial(Operator::bitsetExpression<m, false, false, Operator::bitsetXOR> const& expression) : M_coefficients(expression) { }
00333
00337 polynomial& operator=(polynomial const& p) { M_coefficients = p.M_coefficients; return *this; }
00338
00342 polynomial& operator=(bitset<m> const& coefficients) { M_coefficients = coefficients; return *this; }
00343
00348 polynomial& operator=(Operator::bitsetExpression<m, false, false, Operator::bitsetXOR> const& expression);
00349
00353 polynomial(polynomial const& b, polynomial const& c);
00354
00358 static unsigned int const square_digits = 2 * bitset_base<m>::digits + 4;
00359
00375 polynomial& square(bitset_digit_t* tmpbuf) const;
00376
00380 bool sqrt(void);
00381
00382
00386 polynomial& operator+=(polynomial const& p) { M_coefficients ^= p.M_coefficients; return *this; }
00387
00391 polynomial& operator-=(polynomial const& p) { M_coefficients ^= p.M_coefficients; return *this; }
00392
00396 polynomial& operator*=(polynomial const& p);
00397
00401 polynomial& operator/=(polynomial const& p);
00402
00409 friend Operator::bitsetExpression<m, false, false, Operator::bitsetXOR> operator+ <>(polynomial const& p1, polynomial const& p2);
00410
00417 friend Operator::bitsetExpression<m, false, false, Operator::bitsetXOR> operator- <>(polynomial const& p1, polynomial const& p2);
00418
00422 friend polynomial operator* <>(polynomial const& p1, polynomial const& p2);
00423
00427 friend polynomial operator/ <>(polynomial const& p1, polynomial const& p2);
00428
00432 friend bool operator== <>(polynomial const& p1, polynomial const& p2);
00433
00437 friend bool operator!= <>(polynomial const& p1, polynomial const& p2);
00438
00444 friend std::ostream& operator<< <>(std::ostream& os, polynomial const& p);
00445
00449 bitset<m> const& get_bitset(void) const { return M_coefficients; }
00450
00454 bitset<m>& get_bitset(void) { return M_coefficients; }
00455
00456 private:
00457 static void reduce(bitset_digit_t* buf);
00458 static bitset_digit_t reducea(bitset_digit_t const* a, bitset_digit_t* b, bitset_digit_t* c);
00459
00460 void multiply_with(polynomial const& p1, bitset<m>& result) const;
00461 };
00462
00463 template<unsigned int m, unsigned int k>
00464 polynomial<m, k> const polynomial<m, k>::one(1);
00465
00466 template<unsigned int m, unsigned int k>
00467 bool polynomial<m, k>::sqrt(void)
00468 {
00469 bitset<m> highbits;
00470 highbits.reset();
00471
00472
00473 if ((m & 1) == 1)
00474 {
00475 if ((k & 1) == 1)
00476 {
00477 for(unsigned int bit = 1; bit < m; bit += 2)
00478 {
00479 if (M_coefficients.test(bit))
00480 {
00481 if (bit >= m - k)
00482 highbits.flip(bit + k - m);
00483 else
00484 M_coefficients.flip(bit + k);
00485 highbits.flip(bit);
00486 }
00487 }
00488 }
00489 else
00490 {
00491 for(unsigned int bit = 1; bit < m; bit += 2)
00492 {
00493 if (M_coefficients.test(bit))
00494 {
00495 if (bit >= m - k)
00496 {
00497 M_coefficients.flip(bit + 2 * k - m);
00498 M_coefficients.flip(bit + k - m);
00499 }
00500 else
00501 M_coefficients.flip(bit + k);
00502 highbits.flip(bit);
00503 }
00504 }
00505 }
00506 }
00507 else if ((k & 1) == 1)
00508 {
00509 for(unsigned int bit = 1; bit < m; bit += 2)
00510 {
00511 if (M_coefficients.test(bit))
00512 {
00513 if (bit < k)
00514 {
00515 M_coefficients.flip(bit + k);
00516 M_coefficients.flip(bit + m - k);
00517 highbits.flip(bit + m - k);
00518 }
00519 else
00520 {
00521 M_coefficients.flip(bit - k);
00522 highbits.flip(bit - k);
00523 }
00524 }
00525 }
00526 }
00527 else
00528 {
00529 for(unsigned int bit = 1; bit < m; bit += 2)
00530 if (M_coefficients.test(bit))
00531 return false;
00532 }
00533
00534
00535 unsigned int bit_to = 1;
00536 for(unsigned int bit = 2; bit < m; bit += 2)
00537 {
00538 if (M_coefficients.test(bit))
00539 M_coefficients.set(bit_to);
00540 else
00541 M_coefficients.clear(bit_to);
00542 ++bit_to;
00543 }
00544 for(unsigned int bit = m % 2; bit < m; bit += 2)
00545 {
00546 if (highbits.test(bit))
00547 M_coefficients.set(bit_to);
00548 else
00549 M_coefficients.clear(bit_to);
00550 ++bit_to;
00551 }
00552 return true;
00553 }
00554
00555 template<unsigned int m, unsigned int k>
00556 polynomial<m, k>&
00557 polynomial<m, k>::operator*=(polynomial const& e1)
00558 {
00559 multiply_with(e1, M_coefficients);
00560 return *this;
00561 }
00562
00563 template<unsigned int m, unsigned int k>
00564 inline polynomial<m, k>&
00565 polynomial<m, k>::operator=(Operator::bitsetExpression<m, false, false, Operator::bitsetXOR> const& expression)
00566 {
00567 M_coefficients = expression;
00568 return *this;
00569 }
00570
00571 template<unsigned int m, unsigned int k>
00572 void
00573 polynomial<m, k>::multiply_with(polynomial const& p1, bitset<m>& result) const
00574 {
00575 bitset_digit_t output[bitset<m>::digits * 2] __attribute__ ((aligned (8)));
00576
00577
00578 unsigned int digit = 0;
00579 while(M_coefficients.digit(digit) == 0)
00580 {
00581 output[digit] = 0;
00582 if (++digit == bitset<m>::digits)
00583 {
00584 result.reset();
00585 return;
00586 }
00587 }
00588 unsigned int uninitialized_digit = digit;
00589
00590 for(; digit < bitset<m>::digits; ++digit)
00591 {
00592 if ((M_coefficients.digit(digit) & 1))
00593 {
00594
00595 for (unsigned int d = 0; d < bitset<m>::digits; ++d)
00596 output[d + digit] = p1.get_bitset().digit(d);
00597 uninitialized_digit = bitset<m>::digits + digit;
00598 ++digit;
00599 break;
00600 }
00601 output[digit] = 0;
00602 ++uninitialized_digit;
00603 }
00604
00605 for(unsigned int remaining_digit = uninitialized_digit; remaining_digit < sizeof(output) / sizeof(bitset_digit_t); ++remaining_digit)
00606 output[remaining_digit] = 0;
00607
00608 for(; digit < bitset<m>::digits; ++digit)
00609 if ((M_coefficients.digit(digit) & 1))
00610 {
00611
00612 for (unsigned int d = 0; d < bitset<m>::digits; ++d)
00613 output[d + digit] ^= p1.get_bitset().digit(d);
00614 }
00615
00616 bitset<m + bitset_digit_bits - 1> shifted_p1;
00617
00618 bitset_digit_t carry = 0;
00619 unsigned int d = 0;
00620 for(bitset_digit_t const* ptr = p1.get_bitset().digits_ptr(); ptr < p1.get_bitset().digits_ptr() + bitset<m>::digits; ++ptr, ++d)
00621 {
00622 shifted_p1.rawdigit(d) = (*ptr << 1) | carry;
00623 carry = *ptr >> (8 * sizeof(bitset_digit_t) - 1);
00624 }
00625 if (d < bitset<m + bitset_digit_bits - 1>::digits)
00626 shifted_p1.rawdigit(d) = carry;
00627 for(bitset_digit_t bitmask = 2;;)
00628 {
00629 for(unsigned int digit = 0; digit < bitset<m>::digits; ++digit)
00630 if ((M_coefficients.digit(digit) & bitmask))
00631 {
00632 for (unsigned int d = 0; d < shifted_p1.digits; ++d)
00633 output[d + digit] ^= shifted_p1.digit(d);
00634 }
00635 bitmask <<= 1;
00636 if (bitmask == 0)
00637 break;
00638
00639 shifted_p1.template shift_op<1, left, assign>(shifted_p1);
00640 }
00641
00642 reduce(output);
00643
00644 std::memcpy(result.digits_ptr(), output, bitset<m>::digits * sizeof(bitset_digit_t));
00645 }
00646
00647 #if ECC_DEBUG
00648 template<unsigned int m>
00649 struct div_tct {
00650 bitset_digit_t const* M_p;
00651 int M_deg;
00652 int M_low;
00653 div_tct(bitset<m> const& b, int deg, int low) : M_p(b.digits_ptr()), M_deg(deg), M_low(low) { }
00654 void print_on(std::ostream& os) const
00655 {
00656 int lowbit = (M_low >> bitset_digit_bits_log2) * bitset_digit_bits;
00657 if (lowbit > 0)
00658 lowbit = 0;
00659 for (int b = 2 * m - 1; b >= lowbit; --b)
00660 {
00661 if (b == M_deg)
00662 os << "\e[31m";
00663 int digitoffset = (b >> bitset_digit_bits_log2);
00664 bitset_digit_t mask = 1 << (b & (bitset_digit_bits - 1));
00665 if (M_p[digitoffset] & mask)
00666 os << '1';
00667 else
00668 os << '0';
00669 if (b == M_low)
00670 os << "\e[0m";
00671 if (b == 0)
00672 os << '.';
00673 }
00674 }
00675 };
00676 #endif
00677
00678 template<unsigned int m, unsigned int k>
00679 polynomial<m, k>&
00680 polynomial<m, k>::operator/=(polynomial const& e1)
00681 {
00682 #if ECC_DEBUG
00683 Dout(dc::polynomial|noprefix_cf, "");
00684 Dout(dc::polynomial, "Entering polynomial<" << m << ", " << k << ">::operator/=()");
00685 polynomial<m, k> x(e1.get_bitset());
00686 polynomial<m, k> y(M_coefficients);
00687 Dout(dc::polynomial, "x(t) = " << x);
00688 Dout(dc::polynomial|flush_cf, "y(t) = " << y);
00689 #endif
00690
00691
00692
00693
00694
00695
00696
00697 static unsigned int const digit_offset_UV = ((sizeof(bitset<m>) * 8 - 1) / bitset_digit_bits + 1);
00698 static unsigned int const offset_UV = digit_offset_UV * bitset_digit_bits;
00699
00700 static unsigned int const digit_size_UV = 3 * digit_offset_UV;
00701
00702 static unsigned int const digit_size_AB = bitset<m>::digits;
00703
00704 static unsigned int const padding_digit_size = 1;
00705
00706
00707 bitset_digit_t bitpool [5 * padding_digit_size + 2 * digit_size_AB + 2 * digit_size_UV]
00708 __attribute__ ((__aligned__ (32)));
00709 std::memset((char*)bitpool, 0, sizeof(bitpool));
00710
00711 bitset<m>& A(*(bitset<m>*)&bitpool[padding_digit_size]);
00712 bitset<m>& B(*(bitset<m>*)&bitpool[2 * padding_digit_size + digit_size_AB]);
00713 bitset<m>& U(*(bitset<m>*)&bitpool[3 * padding_digit_size + 2 * digit_size_AB + digit_offset_UV]);
00714 bitset<m>& V(*(bitset<m>*)&bitpool[4 * padding_digit_size + 2 * digit_size_AB + digit_size_UV + digit_offset_UV]);
00715
00716
00717
00718
00719
00720
00721 #if ECC_DEBUG
00722 polynomial<m + 1, 1> M("1");
00723 M.get_bitset().set(k);
00724 M.get_bitset().set(m);
00725 #endif
00726
00727
00728 Dout(dc::polynomial|flush_cf, "U <- y");
00729 U = M_coefficients;
00730
00731
00732 int degU = m - 1;
00733 int lowU = 0;
00734
00735
00736 Dout(dc::polynomial|flush_cf, "A <- x");
00737 A = e1.get_bitset();
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751 typename bitset<m>::const_reverse_iterator degA = A.rbegin();
00752 degA.find1();
00753 Dout(dc::polynomial|flush_cf, "deg(A) == " << degA);
00754
00755
00756 typename bitset<m>::const_iterator lowA = A.begin();
00757 lowA.find1();
00758 Dout(dc::polynomial|flush_cf, "low(A) == " << lowA);
00759
00760 unsigned int sizeA = static_cast<unsigned int>(degA) - static_cast<unsigned int>(lowA);
00761
00762
00763 unsigned int n = m - static_cast<unsigned int>(degA);
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774 Dout(dc::polynomial|flush_cf, "B <- A * t^" << n << " + " << M);
00775 B.xor_with_zero_padded(A, lowA, static_cast<unsigned int>(degA), n);
00776 B.template flip<m>();
00777 B.template flip<k>();
00778 B.template flip<0>();
00779
00780
00781 typename bitset<m>::const_reverse_iterator degB = B.rbegin();
00782 degB.find1();
00783 Dout(dc::polynomial|flush_cf, "deg(B) == " << degB);
00784
00785
00786 typename bitset<m>::const_iterator lowB = B.begin();
00787 lowB.find1();
00788 Dout(dc::polynomial|flush_cf, "low(B) == " << lowB);
00789
00790
00791 Dout(dc::polynomial|flush_cf, "V <- U * t^" << n << " [mod " << M << "]");
00792 V.xor_with_zero_padded(U, 0, m - 1, n);
00793
00794 int degV = degU + n;
00795 int lowV = lowU + n;
00796
00797 unsigned int sizeB = static_cast<unsigned int>(degB) - static_cast<unsigned int>(lowB);
00798
00799 if (sizeA > 0 && sizeB > 0)
00800 for(;;)
00801 {
00802 Dout(dc::polynomial|flush_cf, "A = " << cwprint(div_tct<m>(A, degA, lowA)));
00803 Dout(dc::polynomial|flush_cf, "B = " << cwprint(div_tct<m>(B, degB, lowB)));
00804 Dout(dc::polynomial|flush_cf, "U = " << cwprint(div_tct<m>(U, degU, lowU)));
00805 Dout(dc::polynomial|flush_cf, "V = " << cwprint(div_tct<m>(V, degV, lowV)));
00806 if (sizeA < sizeB)
00807 {
00808 int left_shift = static_cast<unsigned int>(lowB) - static_cast<unsigned int>(lowA);
00809 Dout(dc::polynomial|flush_cf, "B <- B + A * t^" << left_shift);
00810 B.xor_with_zero_padded(A, lowA, degA, left_shift);
00811 degB.find1();
00812 lowB.find1();
00813 sizeB = static_cast<unsigned int>(degB) - static_cast<unsigned int>(lowB);
00814 Dout(dc::polynomial|flush_cf, "V <- V + U * t^" << left_shift);
00815 V.xor_with_zero_padded(U, lowU, degU, left_shift);
00816 degV = std::max(degV, degU + left_shift);
00817 lowV = std::min(lowV, lowU + left_shift);
00818 if (sizeB == 0)
00819 break;
00820 }
00821 else
00822 {
00823 int left_shift = static_cast<unsigned int>(lowA) - static_cast<unsigned int>(lowB);
00824 Dout(dc::polynomial|flush_cf, "A <- A + B * t^" << left_shift);
00825 A.xor_with_zero_padded(B, lowB, degB, left_shift);
00826 degA.find1();
00827 lowA.find1();
00828 sizeA = static_cast<unsigned int>(degA) - static_cast<unsigned int>(lowA);
00829 Dout(dc::polynomial|flush_cf, "U <- U + V * t^" << left_shift);
00830 U.xor_with_zero_padded(V, lowV, degV, left_shift);
00831 degU = std::max(degU, degV + left_shift);
00832 lowU = std::min(lowU, lowV + left_shift);
00833 if (sizeA == 0)
00834 break;
00835 }
00836 }
00837
00838 Dout(dc::polynomial|flush_cf, "A = " << cwprint(div_tct<m>(A, degA, lowA)));
00839 Dout(dc::polynomial|flush_cf, "B = " << cwprint(div_tct<m>(B, degB, lowB)));
00840 Dout(dc::polynomial|flush_cf, "U = " << cwprint(div_tct<m>(U, degU, lowU)));
00841 Dout(dc::polynomial|flush_cf, "V = " << cwprint(div_tct<m>(V, degV, lowV)));
00842
00843 bitset<m>* R;
00844
00845
00846
00847 static unsigned int const offset_F = 2 * offset_UV;
00848 static unsigned int const size_F = 2 * m + offset_F;
00849 bitset<size_F>* F;
00850 int low1, lowR;
00851 #if ECC_DEBUG
00852 int degR;
00853 #endif
00854 if (sizeA == 0)
00855 {
00856 Dout(dc::polynomial|flush_cf, "R = U");
00857 R = &U;
00858 F = (bitset<size_F>*)&bitpool[3 * padding_digit_size + 2 * digit_size_AB - digit_offset_UV];
00859 low1 = lowA;
00860 lowR = lowU;
00861 #if ECC_DEBUG
00862 degR = degU;
00863 #endif
00864 }
00865 else if (sizeB == 0)
00866 {
00867 Dout(dc::polynomial|flush_cf, "R = V");
00868 R = &V;
00869 F = (bitset<size_F>*)&bitpool[4 * padding_digit_size + 2 * digit_size_AB + digit_size_UV - digit_offset_UV];
00870 low1 = lowB;
00871 lowR = lowV;
00872 #if ECC_DEBUG
00873 degR = degV;
00874 #endif
00875 }
00876
00877 *F >>= low1;
00878 lowR -= low1;
00879 #if ECC_DEBUG
00880 degR -= low1;
00881 #endif
00882
00883 Dout(dc::polynomial|flush_cf, "lowR = " << lowR);
00884 Dout(dc::polynomial|flush_cf, "R = " << cwprint(div_tct<m>(*R, degR, lowR)));
00885 if (k >= 32)
00886 {
00887 static int const digit_shift_k = k >> bitset_digit_bits_log2;
00888 static int const bit_shift_k = k & (bitset_digit_bits - 1);
00889 static int const digit_shift_m = m >> bitset_digit_bits_log2;
00890 static int const bit_shift_m = m & (bitset_digit_bits - 1);
00891 int first_digit = (lowR + offset_F) >> bitset_digit_bits_log2;
00892 bitset_digit_t* ptr = F->digits_ptr() + first_digit;
00893 bitset_digit_t* ptr1 = R->digits_ptr();
00894 while(ptr < ptr1)
00895 {
00896 ptr[digit_shift_k] ^= (*ptr) << bit_shift_k;
00897 if (bit_shift_k != 0)
00898 ptr[digit_shift_k + 1] ^= (*ptr) >> (32 - bit_shift_k);
00899 ptr[digit_shift_m] ^= (*ptr) << bit_shift_m;
00900 if (bit_shift_m != 0)
00901 ptr[digit_shift_m + 1] ^= (*ptr) >> (32 - bit_shift_m);
00902 ++ptr;
00903 }
00904 }
00905 else
00906 {
00907 for (int i = lowR + offset_F; i < offset_F; ++i)
00908 {
00909 if (F->test(i))
00910 {
00911 #if ECC_DEBUG
00912 F->flip(i);
00913 #endif
00914 F->flip(i + k);
00915 F->flip(i + m);
00916 }
00917 }
00918 }
00919 #if ECC_DEBUG
00920 lowR = 0;
00921 degR = 2 * m - 1;
00922 #endif
00923 Dout(dc::polynomial|flush_cf, "R = " << cwprint(div_tct<m>(*R, degR, lowR)));
00924 reduce(R->digits_ptr());
00925 #if ECC_DEBUG
00926 degR = m - 1;
00927 #endif
00928 Dout(dc::polynomial|flush_cf, "R = " << cwprint(div_tct<m>(*R, degR, lowR)));
00929 M_coefficients = *R;
00930
00931 return *this;
00932 }
00933
00934
00935
00936
00937
00938
00939
00940
00941 template<unsigned int m, unsigned int k>
00942 polynomial<m, k>::polynomial(polynomial<m, k> const& b, polynomial<m, k> const& c) : M_coefficients(c.M_coefficients)
00943 {
00944 using namespace libecc;
00945
00946 bitset<m> reverse_b;
00947 reverse_b.reset();
00948 int bits_in_b = 0;
00949 short b_row;
00950 for (short i = m - 1; i >= 0; --i)
00951 if (b.M_coefficients.test(i))
00952 {
00953 reverse_b.set(m - 1 - i);
00954 ++bits_in_b;
00955 b_row = i;
00956 }
00957 if (bits_in_b == 0)
00958 {
00959 sqrt();
00960 return;
00961 }
00962 else if (bits_in_b != 1)
00963 b_row = -1;
00964
00965 bitset<m> matrix[m];
00966 reverse_b.template shift_op<k + 1, libecc::left, libecc::assign>(matrix[k]);
00967 reverse_b.template shift_op<m - (k + 1), libecc::right, libecc::exor>(matrix[k]);
00968 reverse_b.template shift_op<1, libecc::left, libecc::exor>(matrix[k]);
00969 reverse_b.template shift_op<m - (k - 1), libecc::left, libecc::exor>(matrix[k]);
00970 unsigned short i = k;
00971 for (unsigned short j = i + 1; j != k; j = (j + 1) % m)
00972 {
00973 matrix[i].template shift_op<1, libecc::left, libecc::assign>(matrix[j]);
00974 if (b.M_coefficients.test(j))
00975 matrix[j].template set<0>();
00976 i = j;
00977 }
00978
00979 #if ECC_DEBUGOUTPUT
00980 LibEccDout(dc::polynomial, "b Matrix =");
00981 for (short row2 = m - 1; row2 >= 0; --row2)
00982 LibEccDout(dc::polynomial, cwprint_using(*static_cast<libecc::bitset_invertible<m, false>*>(&matrix[row2]),
00983 &bitset<m>::base2_print_on) << " x" << row2 << " " << M_coefficients.test(row2) ? '1' : '0');
00984 #endif
00985
00986 for (unsigned int col = 0; col < m; ++col)
00987 {
00988 unsigned int r = 2 * col;
00989 while(r >= m)
00990 {
00991 matrix[r - m].flip(col);
00992 r -= m - k;
00993 }
00994 matrix[r].flip(col);
00995 }
00996
00997 #if ECC_DEBUGOUTPUT
00998 LibEccDout(dc::polynomial, "Matrix =");
00999 for (short row2 = m - 1; row2 >= 0; --row2)
01000 LibEccDout(dc::polynomial, cwprint_using(*static_cast<libecc::bitset_invertible<m, false>*>(&matrix[row2]),
01001 &bitset<m>::base2_print_on) << " x" << row2 << " " << M_coefficients.test(row2) ? '1' : '0');
01002 #endif
01003
01004 unsigned short rows[m];
01005 for (unsigned short i = 0; i < m; ++i)
01006 rows[i] = i;
01007
01008 if (bits_in_b == 1)
01009 {
01010 for (short row2 = m - 1; row2 >= 0; --row2)
01011 {
01012 if (!matrix[row2].any())
01013 {
01014 if (row2 != b_row)
01015 {
01016 rows[b_row] = row2;
01017 rows[row2] = b_row;
01018 if (M_coefficients.test(b_row) != M_coefficients.test(row2))
01019 {
01020 M_coefficients.flip(b_row);
01021 M_coefficients.flip(row2);
01022 }
01023 }
01024 }
01025 }
01026 }
01027
01028 #if ECC_DEBUGOUTPUT
01029 LibEccDout(dc::polynomial, "After swap: Matrix =");
01030 for (short row2 = m - 1; row2 >= 0; --row2)
01031 LibEccDout(dc::polynomial, cwprint_using(*static_cast<libecc::bitset_invertible<m, false>*>(&matrix[rows[row2]]),
01032 &bitset<m>::base2_print_on)
01033 << " x" << row2 << " " << (M_coefficients.test(row2) ? '1' : '0')
01034 << " " << (b.get_bitset().test(row2) ? '1' : '0'));
01035 #endif
01036
01037 for (unsigned short col = 0; col < m; ++col)
01038 {
01039 unsigned short row = col;
01040 for (; row < m; ++row)
01041 {
01042 unsigned short mr = rows[row];
01043 if (matrix[mr].test(col))
01044 {
01045 for (unsigned short row2 = row + 1; row2 < m; ++row2)
01046 {
01047 unsigned short mr2 = rows[row2];
01048 if (matrix[mr2].test(col))
01049 {
01050 matrix[mr2] ^= matrix[mr];
01051 if (!b.get_bitset().test(row2) && !matrix[mr2].any())
01052 {
01053
01054 matrix[mr2] = matrix[mr];
01055 matrix[mr].reset();
01056
01057 if (M_coefficients.test(row) != M_coefficients.test(row2))
01058 for (unsigned short row3 = row + 1; row3 < row2; ++row3)
01059 M_coefficients.flip(row3);
01060 if (M_coefficients.test(row2))
01061 M_coefficients.flip(row);
01062
01063 row = row2;
01064 mr = mr2;
01065 }
01066 else if (M_coefficients.test(row))
01067 M_coefficients.flip(row2);
01068 }
01069 }
01070
01071 #if ECC_DEBUGOUTPUT
01072 LibEccDout(dc::polynomial, "After wipe: Matrix =");
01073 for (short row2 = m - 1; row2 >= 0; --row2)
01074 LibEccDout(dc::polynomial, cwprint_using(*static_cast<libecc::bitset_invertible<m, false>*>(&matrix[rows[row2]]),
01075 &bitset<m>::base2_print_on)
01076 << " x" << row2 << " " << (M_coefficients.test(row2) ? '1' : '0')
01077 << " " << (b.get_bitset().test(row2) ? '1' : '0'));
01078 #endif
01079
01080 if (row != col)
01081 {
01082 unsigned short mc = rows[col];
01083 rows[col] = mr;
01084 rows[row] = mc;
01085 if (M_coefficients.test(row) != M_coefficients.test(col))
01086 {
01087 M_coefficients.flip(row);
01088 M_coefficients.flip(col);
01089 }
01090 }
01091
01092 #if ECC_DEBUGOUTPUT
01093 LibEccDout(dc::polynomial, "After swap: Matrix =");
01094 for (short row2 = m - 1; row2 >= 0; --row2)
01095 LibEccDout(dc::polynomial, cwprint_using(*static_cast<libecc::bitset_invertible<m, false>*>(&matrix[rows[row2]]),
01096 &bitset<m>::base2_print_on)
01097 << " x" << row2 << " " << (M_coefficients.test(row2) ? '1' : '0')
01098 << " " << (b.get_bitset().test(row2) ? '1' : '0'));
01099 #endif
01100
01101 break;
01102 }
01103 }
01104 if (row == m)
01105 {
01106 if (b_row == -1)
01107 {
01108
01109
01110
01111 LibEccDout(dc::polynomial, "Setting b_row to " << col);
01112 b_row = col;
01113 }
01114 else
01115 {
01116 LibEccDout(dc::polynomial, "Swapping row " << col << " with row " << b_row);
01117
01118
01119 unsigned short mc = rows[b_row];
01120 rows[b_row] = rows[col];
01121 rows[col] = mc;
01122 if (M_coefficients.test(b_row) != M_coefficients.test(col))
01123 {
01124 M_coefficients.flip(b_row);
01125 M_coefficients.flip(col);
01126 }
01127
01128 #if ECC_DEBUGOUTPUT
01129 LibEccDout(dc::polynomial, "After swap: Matrix =");
01130 for (short row2 = m - 1; row2 >= 0; --row2)
01131 LibEccDout(dc::polynomial, cwprint_using(*static_cast<libecc::bitset_invertible<m, false>*>(&matrix[rows[row2]]),
01132 &bitset<m>::base2_print_on)
01133 << " x" << row2 << " " << (M_coefficients.test(row2) ? '1' : '0')
01134 << " " << (b.get_bitset().test(row2) ? '1' : '0'));
01135 #endif
01136
01137
01138 for (unsigned short col2 = b_row + 1; col2 < col; ++col2)
01139 if (matrix[mc].test(col2))
01140 {
01141 matrix[mc] ^= matrix[rows[col2]];
01142 if (M_coefficients.test(col2))
01143 M_coefficients.flip(col);
01144
01145 #if ECC_DEBUGOUTPUT
01146 LibEccDout(dc::polynomial, "After wipe of row " << col << " with row " << col2 << ": Matrix =");
01147 for (short row2 = m - 1; row2 >= 0; --row2)
01148 LibEccDout(dc::polynomial, cwprint_using(*static_cast<libecc::bitset_invertible<m, false>*>(&matrix[rows[row2]]),
01149 &bitset<m>::base2_print_on)
01150 << " x" << row2 << " " << (M_coefficients.test(row2) ? '1' : '0')
01151 << " " << (b.get_bitset().test(row2) ? '1' : '0'));
01152 #endif
01153
01154 }
01155 }
01156 }
01157 }
01158
01159 for (short i = m - 1; i >= 0; --i)
01160 {
01161 bitset<m> temp = M_coefficients & matrix[rows[i]];
01162 for (short j = m - 1; j > i; --j)
01163 if (temp.test(j))
01164 M_coefficients.flip(i);
01165 }
01166 }
01167
01168 template<unsigned int m, unsigned int k>
01169 inline bool
01170 operator==(polynomial<m, k> const& p1, polynomial<m, k> const& p2)
01171 {
01172 return p1.M_coefficients == p2.M_coefficients;
01173 }
01174
01175 template<unsigned int m, unsigned int k>
01176 inline bool
01177 operator!=(polynomial<m, k> const& p1, polynomial<m, k> const& p2)
01178 {
01179 return p1.M_coefficients != p2.M_coefficients;
01180 }
01181
01182 template<unsigned int m, unsigned int k>
01183 inline Operator::bitsetExpression<m, false, false, Operator::bitsetXOR>
01184 operator+(polynomial<m, k> const& p1, polynomial<m, k> const& p2)
01185 {
01186 return Operator::bitsetExpression<m, false, false, Operator::bitsetXOR>(p1.M_coefficients, p2.M_coefficients);
01187 }
01188
01189 template<unsigned int m, unsigned int k>
01190 inline Operator::bitsetExpression<m, false, false, Operator::bitsetXOR>
01191 operator-(polynomial<m, k> const& p1, polynomial<m, k> const& p2)
01192 {
01193 return Operator::bitsetExpression<m, false, false, Operator::bitsetXOR>(p1.M_coefficients, p2.M_coefficients);
01194 }
01195
01196 template<unsigned int m, unsigned int k>
01197 inline polynomial<m, k>
01198 operator*(polynomial<m, k> const& p1, polynomial<m, k> const& p2)
01199 {
01200 polynomial<m, k> result;
01201 p1.multiply_with(p2, result.M_coefficients);
01202 return result;
01203 }
01204
01205 template<unsigned int m, unsigned int k>
01206 inline polynomial<m, k>
01207 operator/(polynomial<m, k> const& e1, polynomial<m, k> const& e2)
01208 {
01209 polynomial<m, k> tmp(e1);
01210 tmp /= e2;
01211 return tmp;
01212 }
01213
01214 template<unsigned int m, unsigned int k>
01215 std::ostream& operator<<(std::ostream& os, polynomial<m, k> const& p)
01216 {
01217 p.M_coefficients.base2_print_on(os);
01218 return os;
01219 }
01220
01221 }
01222
01223 #include <libecc/square.hcc>
01224
01225 #endif // LIBECC_POLYNOMIAL_H