00001
00006 #include <cstdlib>
00007 #include <exception>
00008 #include <new>
00009
00010
00012 template <class TNum, class kdefs>
00013 fast_Ring<TNum,kdefs>::fast_Ring( unsigned short _char,
00014 unsigned short _epsPrec) : characteristic(_char),
00015 epsilon(_epsPrec),
00016 generator(getGenerator())
00017 {
00018 assert(TNum::wellDefined(characteristic));
00019 assert( epsilon <= 1 );
00020 init();
00021 assert( wellDefined() );
00022 }
00023
00024
00025 template <class TNum, class kdefs>
00026 bool fast_Ring<TNum,kdefs>::wellDefined()
00027 {
00028 TNum num;
00029 assert (num.wellDefined(characteristic) );
00030 return true;
00031 }
00032
00034 template <class TNum,class kdefs>
00035 inline void fast_Ring< TNum, kdefs>::init()
00036 {
00037 additiveInverseTable =NULL;
00038 multiplicationTable =NULL;
00039 additionTable =NULL;
00040 multiplicativeInverseTable =NULL;
00041
00042 fastAdditionTable =NULL;
00043 elementsToExponentsTab =NULL;
00044 exponentsToElementTab =NULL;
00045
00046 sqrtTable =NULL;
00047
00048 moduloTable = NULL;
00049
00050 try
00051 {
00052 if (additionTable==NULL)
00053 additionTable = createAdditionTable();
00054
00055 if (additiveInverseTable==NULL)
00056 additiveInverseTable = createAdditiveInverseTable();
00057
00058 if (multiplicationTable==NULL)
00059 multiplicationTable = createMultiplicationTable();
00060
00061
00062 if (multiplicativeInverseTable==NULL)
00063 multiplicativeInverseTable = createMultiplicativeInverseTable();
00064
00065 if (fastAdditionTable==NULL)
00066 fastAdditionTable = createFastAdditionTable();
00067
00068 if (elementsToExponentsTab==NULL)
00069 elementsToExponentsTab = initElementsToExponentsTab(generator);
00070
00071 if (exponentsToElementTab==NULL)
00072 exponentsToElementTab = initExponentsToElementTab(generator);
00073
00074 if (sqrtTable==NULL)
00075 sqrtTable = createSqrtTable( );
00076
00077 if (moduloTable==NULL)
00078 moduloTable=createModuloTable();
00079 }
00080 catch(std::bad_alloc &e)
00081 {
00082 std::cerr << "Memory allocation error in fast_Ring::init() " << std::endl;
00083 exit(0);
00084 }
00085 catch(...)
00086 {
00087 std::cerr << "Error in creating ring operation Tables, " << std::endl;
00088 exit(0);
00089 }
00090 }
00091
00092
00093
00094 template <class TNum,class kdefs>
00095 fast_Ring<TNum,kdefs>::~fast_Ring()
00096 {
00097 if (additiveInverseTable!=NULL) { delete[] additiveInverseTable;
00098 additiveInverseTable = NULL; }
00099
00100 if (multiplicationTable!=NULL) { delete[] multiplicationTable;
00101 multiplicationTable = NULL; }
00102
00103 if (additionTable!=NULL) { delete[] additionTable;
00104 additionTable = NULL; }
00105
00106 if (multiplicativeInverseTable!=NULL) { delete[] multiplicativeInverseTable;
00107 multiplicativeInverseTable = NULL; }
00108
00109 if ( fastAdditionTable!=NULL ) { delete[] fastAdditionTable;
00110 fastAdditionTable = NULL; }
00111
00112 if ( elementsToExponentsTab!=NULL ) { delete[] elementsToExponentsTab;
00113 elementsToExponentsTab = NULL; }
00114
00115 if ( exponentsToElementTab!=NULL ) { delete[] exponentsToElementTab;
00116 exponentsToElementTab = NULL; }
00117
00118 if ( sqrtTable!=NULL ) { delete[] sqrtTable;
00119 sqrtTable = NULL; }
00120
00121 if ( moduloTable!=NULL ) { delete[] moduloTable;
00122 moduloTable = NULL; }
00123
00124 }
00125
00126
00127
00128
00129
00130
00131
00132
00140 template <class TNum, class kdefs>
00141 template <class TConvNum >
00142 inline TNum fast_Ring<TNum, kdefs>::Convert(const TConvNum src ) const
00143 {
00144 #ifdef SAFE
00145 assert( getEpsPrecision()<=1 );
00146 #endif
00147
00148 TNum z;
00149
00150 z.setX( ConvertScalar( src.getX() ) );
00151
00152
00153
00154
00155 if ( getEpsPrecision()==1 )
00156 {
00157 z.setEps( ConvertScalar(src.getEps() ) );
00158
00159
00160
00161 }
00162 return z;
00163 }
00164
00165 template <class TNum, class kdefs>
00166 inline TNum fast_Ring<TNum, kdefs>::Convert(const double a) const
00167 {
00168 #ifdef SAFE
00169 assert( getEpsPrecision()<=1 );
00170 #endif
00171
00172 TNum z;
00173
00174 z.setX( ConvertScalar( a ) );
00175
00176 return z;
00177 }
00178
00179 template <class TNum, class kdefs>
00180 inline TNum fast_Ring<TNum, kdefs>::Convert(const int a) const
00181 {
00182 #ifdef SAFE
00183 assert( getEpsPrecision()<=1 );
00184 #endif
00185
00186 TNum z;
00187
00188 z.setX( ConvertScalar( a ) );
00189
00190 return z;
00191 }
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00216 template <class TNum,class kdefs>
00217 template <class TConvNum >
00218 inline void fast_Ring<TNum, kdefs>::ConvertInPlace( TConvNum & a) const
00219 {
00220
00221 assert( a.getEpsPrecision()<=1 );
00222
00223
00224 a.setX( ConvertScalar(a.getX() ) );
00225
00226 if ( getEpsPrecision()==1 )
00227 a.setEps( ConvertScalar(a.getEps() ) );
00228
00229 #ifdef SAFE
00230 assert(a.getX() == ConvertScalar(a.getX() ) );
00231 assert(a.getEps() == ConvertScalar(a.getEps() ) );
00232 #endif
00233
00234 return ;
00235 }
00236
00238 template <class TNum, class kdefs>
00239 inline int fast_Ring<TNum,kdefs>::ConvertScalar(const int a) const
00240 {
00241 int res = a;
00242 while (res<0)
00243 {
00244 res += getCharacteristic();
00245 }
00246 if ( res >= getCharacteristic() )
00247 {
00248 res %= getCharacteristic();
00249 }
00250
00251
00252
00253
00254
00255 return res;
00256 }
00257
00258
00260 template <class TNum,class kdefs>
00261 inline int fast_Ring<TNum,kdefs>::ConvertScalarSpec(const int a) const
00262 {
00263 #ifdef SAFE
00264 assert(a>=0);
00265 #endif
00266 return a % getCharacteristic();
00267 }
00268
00269
00270
00273
00274 template <class TNum,class kdefs>
00275 inline int fast_Ring<TNum,kdefs>::FastConvertScalar(const int a) const
00276 {
00277 return ( a + getCharacteristic() ) % getCharacteristic();
00278 }
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 template <class TNum,class kdefs>
00290 inline TNum fast_Ring< TNum, kdefs>::add( const TNum a, const TNum b) const
00291 {
00292 #ifdef SAFE
00293 assert(Convert(a)==a);
00294 assert(Convert(b)==b);
00295 #endif
00296 return additionTable[ getPairIndex(a, b) ];
00297 }
00298
00299
00300
00301
00302 template <class TNum,class kdefs>
00303 inline TNum fast_Ring< TNum, kdefs>::addRef( const TNum &a, const TNum &b) const
00304 {
00305 #ifdef SAFE
00306 assert(Convert(a)==a);
00307 assert(Convert(b)==b);
00308 #endif
00309 return additionTable[ getPairIndexByRef(a, b) ];
00310 }
00311
00312
00313
00314
00315
00316
00317
00318 template <class TNum,class kdefs>
00319 inline void fast_Ring< TNum, kdefs>::addInPlace(TNum& a, const TNum b) const
00320 {
00321 #ifdef SAFE
00322 assert(Convert(a)==a);
00323 assert(Convert(b)==b);
00324 #endif
00325
00326 a= this->additionTable[ getPairIndex(a, b) ];
00327 return;
00328
00329
00330 }
00331
00332
00333 template <class TNum,class kdefs>
00334 inline void fast_Ring< TNum, kdefs>::addInPlaceRef(TNum& a, const TNum &b) const
00335 {
00336 #ifdef SAFE
00337 assert(Convert(a)==a);
00338 assert(Convert(b)==b);
00339 #endif
00340
00341 a = this->additionTable[ getPairIndexByRef(a, b) ];
00342 return;
00343 }
00344
00345
00346
00347
00348
00349
00350
00351 template <class TNum,class kdefs>
00352 inline TNum fast_Ring< TNum, kdefs>::addInv(const TNum a) const
00353 {
00354 #ifdef SAFE
00355 assert(Convert(a)==a);
00356 #endif
00357 return additiveInverseTable[ getSingleIndex(a) ];
00358 }
00359
00360
00361
00362
00363 template <class TNum,class kdefs>
00364 inline TNum fast_Ring< TNum, kdefs>::addInvRef(const TNum& a) const
00365 {
00366 #ifdef SAFE
00367 assert(Convert(a)==a);
00368 #endif
00369 return additiveInverseTable[ getSingleIndexByRef(a) ];
00370 }
00371
00372
00373
00374 template <class TNum, class kdefs>
00375 inline void fast_Ring< TNum, kdefs>::addInvInPlace( TNum & a) const
00376 {
00377 #ifdef SAFE
00378 assert(Convert(a)==a);
00379 #endif
00380 a=additiveInverseTable[ getSingleIndexByRef(a) ];
00381 return;
00382 }
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395 template <class TNum,class kdefs>
00396 inline TNum fast_Ring< TNum, kdefs>::multiply(const TNum a, const TNum b) const
00397 {
00398 #ifdef SAFE
00399 assert(Convert(a)==a);
00400 assert(Convert(b)==b);
00401 #endif
00402
00403 return multiplicationTable[getPairIndex(a, b)];
00404 }
00405
00406
00407
00408
00410 template <class TNum,class kdefs>
00411 inline TNum fast_Ring< TNum, kdefs>::multiplyRef(const TNum & a, const TNum & b) const
00412 {
00413 #ifdef SAFE
00414 assert(Convert(a)==a);
00415 assert(Convert(b)==b);
00416 #endif
00417
00418 return multiplicationTable[getPairIndexByRef(a, b)];
00419 }
00420
00421
00422
00423
00424
00425
00426
00427 template <class TNum,class kdefs>
00428 inline void fast_Ring< TNum, kdefs>::multiplyInPlace(TNum &a, const TNum b) const
00429 {
00430 #ifdef SAFE
00431 assert(Convert(a)==a);
00432 assert(Convert(b)==b);
00433 #endif
00434 a = multiplicationTable[ getPairIndex(a, b) ];
00435 }
00436
00437
00438 template <class TNum,class kdefs>
00439 inline void fast_Ring< TNum, kdefs>::multiplyInPlaceRef(TNum &a, const TNum & b) const
00440 {
00441 #ifdef SAFE
00442 assert(Convert(a)==a);
00443 assert(Convert(b)==b);
00444 #endif
00445 a = multiplicationTable[ getPairIndexByRef(a, b) ];
00446 }
00447
00448
00449
00450
00451
00452
00453
00454 template <class TNum,class kdefs>
00455 inline TNum
00456 fast_Ring< TNum, kdefs>::scalarMultiply(const FieldType::ElementType a, const TNum b) const
00457 {
00458 #ifdef SAFE
00459 assert(Convert(TNum(a))==a);
00460 assert(Convert(b)==b);
00461 #endif
00462
00463 return multiplicationTable[getPairIndex(a, b)];
00464 }
00465
00466
00467
00468
00470 template <class TNum,class kdefs>
00471 inline TNum
00472 fast_Ring< TNum, kdefs>::scalarMultiplyRef(const FieldType::ElementType & a, const TNum & b) const
00473 {
00474 #ifdef SAFE
00475 assert(Convert(TNum(a))==a);
00476 assert(Convert(b)==b);
00477 #endif
00478
00479 return multiplicationTable[getPairIndexByRef(a, b)];
00480 }
00481
00482
00483
00484
00485
00486
00487 template <class TNum,class kdefs>
00488 inline void
00489 fast_Ring< TNum, kdefs>::scalarMultiplyInPlace(const FieldType::ElementType a,
00490 TNum & b ) const
00491 {
00492 #ifdef SAFE
00493 assert(Convert(TNum(a))==a);
00494 assert(Convert(b)==b);
00495 #endif
00496 b = multiplicationTable[ getPairIndex(a, b) ];
00497 }
00498
00499
00500 template <class TNum,class kdefs>
00501 inline void
00502 fast_Ring< TNum, kdefs>::scalarMultiplyInPlaceRef(const FieldType::ElementType & a,
00503 TNum & b ) const
00504 {
00505 #ifdef SAFE
00506 assert(Convert(TNum(a))==a);
00507 assert(Convert(b)==b);
00508 #endif
00509 b = multiplicationTable[ getPairIndexByRef(a, b) ];
00510 }
00511
00512
00513
00514
00515 template <class TNum,class kdefs>
00516 inline TNum const fast_Ring< TNum, kdefs>::multByExp(const TNum a, const TNum b) const
00517 {
00518 if (a.isZero() || b.isZero() )
00519 return TNum::Zero;
00520
00521 register short res = a.getX()+b.getX();
00522 if ( res>=getCharacteristic() )
00523 return res-getCharacteristic();
00524 return res;
00525 }
00526
00527
00528
00529 template <class TNum,class kdefs>
00530 inline TNum const fast_Ring< TNum, kdefs>::multByExpRef(const TNum & a, const TNum & b) const
00531 {
00532 if (a.isZero() || b.isZero() )
00533 return TNum::Zero;
00534
00535 register short res = a.getX()+b.getX();
00536 if (res>=getCharacteristic())
00537 return res-getCharacteristic();
00538 return res;
00539 }
00540
00541
00542
00543 template <class TNum,class kdefs>
00544 inline void fast_Ring< TNum, kdefs>::multByExpInPlace( TNum & a, const TNum b) const
00545 {
00546 if (a.isZero() || b.isZero() )
00547 a=TNum::Zero;
00548
00549 register short res = a.getX()+b.getX();
00550 if (res>=getCharacteristic())
00551 a=res-getCharacteristic();
00552 a=res;
00553 }
00554
00555
00556
00557 template <class TNum,class kdefs>
00558 inline void fast_Ring< TNum, kdefs>::multByExpInPlaceRef( TNum & a, const TNum & b) const
00559 {
00560 if (a.isZero() ||b.isZero())
00561 a=TNum::Zero;
00562
00563 register unsigned short res = a.getX() + b.getX();
00564 if (res>getCharacteristic()-1)
00565 a= res-getCharacteristic();
00566 return;
00567 }
00568
00569
00570
00571
00572 template <class TNum,class kdefs>
00573 inline TNum fast_Ring< TNum, kdefs>::multInv(const TNum a) const
00574 {
00575 #ifdef SAFE
00576 assert( a==Convert(a) );
00577 #endif
00578 TNum const & res = multiplicativeInverseTable[ getSingleIndex( a)];
00579 if (res.isNotZero() )
00580 {
00581 return res;
00582 }
00583 else
00584 {
00585 std::cerr << "Multiplicative inverse does not exist!" << std::endl;
00586 throw "Multiplicative inverse does not exist!" ;
00587 }
00588 }
00589
00590
00591 template <class TNum,class kdefs>
00592 inline TNum fast_Ring< TNum, kdefs>::multInvRef(const TNum & a) const
00593 {
00594 #ifdef SAFE
00595 assert( a==Convert(a) );
00596 #endif
00597 TNum const & res = multiplicativeInverseTable[ getSingleIndexByRef( a) ];
00598 if (res.isNotZero() )
00599 {
00600 return res;
00601 }
00602 else
00603 {
00604 std::cerr << "Multiplicative inverse does not exist!" << std::endl;
00605 throw "Multiplicative inverse does not exist!" ;
00606 }
00607 }
00608
00609
00610
00611
00612
00613
00614
00615
00616 template <class TNum,class kdefs>
00617 inline void fast_Ring< TNum, kdefs>::multInvInPlace( TNum & a) const
00618 {
00619 #ifdef SAFE
00620 assert( a==Convert(a) );
00621 #endif
00622 TNum const & res = multiplicativeInverseTable[getSingleIndex( a)];
00623 if (res.isNotZero() )
00624 {
00625 a = res;
00626 }
00627 else
00628 {
00629 std::cerr << "Multiplicative inverse does not exist!" << std::endl;
00630 throw "Multiplicative inverse does not exist!" ;
00631 }
00632 }
00633
00634
00635
00636
00637
00638
00639
00640 template <class TNum,class kdefs>
00641 inline void fast_Ring<TNum,kdefs>::accMult( TNum& a ,const TNum b , const TNum c) const
00642 {
00643 #ifdef SAFE
00644 assert(Convert(a)==a);
00645 assert(Convert(b)==b);
00646 assert(Convert(c)==c);
00647 #endif
00648 #ifdef COUNT
00649 accMultCount=accMultCount+1;
00650 #endif
00651 a=additionTable[ getPairIndex (a, multiplicationTable[ getPairIndex(b, c)] ) ];
00652 }
00653
00654
00655 template <class TNum,class kdefs>
00656 inline void fast_Ring<TNum,kdefs>::accMult( TNum* a ,const TNum b , const TNum c) const
00657 {
00658 #ifdef SAFE
00659 assert(Convert(a)==a);
00660 assert(Convert(b)==b);
00661 assert(Convert(c)==c);
00662 #endif
00663 #ifdef COUNT
00664 accMultCount=accMultCount+1;
00665 #endif
00666
00667 *a = additionTable[ getPairIndex( *a,multiplicationTable[ getPairIndex(b, c)] ) ];
00668 }
00669
00670
00671
00672 template <class TNum,class kdefs>
00673 inline void fast_Ring<TNum,kdefs>::accMultRef( TNum& a ,const TNum& b , const TNum& c) const
00674 {
00675 #ifdef SAFE
00676 assert(Convert(a)==a);
00677 assert(Convert(b)==b);
00678 assert(Convert(c)==c);
00679 #endif
00680 #ifdef COUNT
00681 accMultCount=accMultCount+1;
00682 #endif
00683
00684 a=additionTable[ getPairIndexByRef(a, multiplicationTable[ getPairIndex(b, c) ]) ];
00685 }
00686
00687
00688
00696 template <class TNum,class kdefs>
00697 inline void
00698 fast_Ring<TNum,kdefs>::accMultSpec( TNum* const a ,const TNum b , const TNum * const c) const
00699 {
00700 #ifdef SAFE
00701 assert(Convert(*a)==*a);
00702 assert(Convert(b)==b);
00703 assert(Convert(*c)==*c);
00704 #endif
00705
00706 #ifdef COUNT
00707 accMultCount=accMultCount+1;
00708 #endif
00709
00710 *a=additionTable[ getPairIndex(*a, multiplicationTable[ getPairIndex(b, *c)]) ];
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736 }
00737
00738
00739 template <class TNum,class kdefs>
00740 inline typename fast_Ring<TNum,kdefs>::sqrtInf_t fast_Ring<TNum,kdefs>::sqrt ( const TNum a) const
00741 {
00742 #ifdef SAFE
00743 assert(Convert(a)==a);
00744
00745 #endif
00746 assert( a.getEps()==0 );
00747 return sqrtTable[ a.getX() ];
00748 }
00749
00750 template <class TNum,class kdefs>
00751 inline typename fast_Ring<TNum,kdefs>::sqrtInf_t fast_Ring<TNum,kdefs>::sqrtRef ( const TNum &a) const
00752 {
00753 #ifdef SAFE
00754 assert(Convert(*a)==*a);
00755 #endif
00756 assert( a.getEps()==0 );
00757 return sqrtTable[ a.getX() ];
00758 }
00759
00760
00762 template <class TNum,class kdefs>
00763 inline void fast_Ring<TNum,kdefs>::accMultAddr( TNum* a ,const TNum* b , const TNum* c) const
00764 {
00765 #ifdef SAFE
00766 assert(Convert(a)==a);
00767 assert(Convert(b)==b);
00768 assert(Convert(c)==c);
00769 #endif
00770 *a = additionTable[getPairIndex(*a, multiplicationTable[ getPairIndex(*b, *c)]) ];
00771 }
00772
00773
00774
00780 template <class TNum,class kdefs>
00781 TNum fast_Ring<TNum,kdefs>::getGenerator()
00782 {
00783 std::cerr << " getGenerator () " << std::endl;
00784 if (getEpsPrecision()>0)
00785 {
00786 std::cerr << " Warning: getGenerator() is not implemented for epsPrecision>0 !";
00787 std::cerr << std::endl;
00788
00789 return TNum::Zero;
00790 }
00791 for (int m=1; m<getCharacteristic(); m++)
00792 {
00793 TNum erzeuger = m;
00794 TNum tmp = erzeuger;
00795 assert (tmp==erzeuger);
00796
00797 bool erz=true;
00798
00799 for (int n=0; n<getCharacteristic()-1; n++)
00800 {
00801
00802 tmp.setX( (unsigned int )
00803 ( (unsigned int )tmp.getX() * (unsigned int )erzeuger.getX() )
00804 % getCharacteristic()
00805 );
00806
00807 if ( (tmp.getX()==erzeuger.getX()) && (n<( getCharacteristic() - 2 )) )
00808 {
00809 erz=false;
00810 }
00811 }
00812
00813 if (erz)
00814 {
00815 tmp = erzeuger;
00816 return erzeuger;
00817
00818 }
00819 }
00820 std::cerr << " Error: kein Erzeuger gefunden ! - da gibt es einen Fehler! " << std::endl;
00821 exit(0);
00822 return TNum::Zero;
00823 }
00824
00825
00826
00827
00841 template <class TNum,class kdefs>
00842 TNum * fast_Ring<TNum, kdefs>::createAdditionTable()
00843 {
00844
00845 unsigned short i, j, k , l;
00846
00847 TNum * tAdditionTable=0;
00848
00849 size_t tableSize = getMaxPairIndex() + 1;
00850 std::cerr << "createAdditionTable::tableSize = " << tableSize << std::endl;
00851 tAdditionTable = new TNum[tableSize];
00852
00853 for (i=0; i<getCharacteristic(); i++)
00854 for (j=0; j<((getCharacteristic()-1)*getEpsPrecision())+1; j++)
00855 for (k=0; k<getCharacteristic(); k++)
00856 for (l=0; l<((getCharacteristic()-1)*getEpsPrecision())+1; l++)
00857 {
00858 TNum z1(i, j);
00859 TNum z2(k, l);
00860 size_t index = getPairIndex(z1, z2);
00861 assert(index < tableSize && index>=0);
00862
00863 tAdditionTable[index].setX (
00864 ( (int)z1.getX() + (int)z2.getX() )
00865 % getCharacteristic()
00866 );
00867
00868 tAdditionTable[index].setEps (
00869 ((int)z1.getEps() + (int)z2.getEps())
00870 % getCharacteristic()
00871 );
00872 }
00873 return tAdditionTable;
00874 }
00875
00876
00878 template <class TNum,class kdefs>
00879 TNum* fast_Ring<TNum,kdefs>::createFastAdditionTable()
00880 {
00881 TNum * tfastAdditionTable=NULL;
00882
00883 if (getEpsPrecision()==0)
00884 {
00885
00886 tfastAdditionTable = new TNum[ getCharacteristic()*2 ];
00887
00888 for (int m=0; m<getCharacteristic(); m++)
00889 {
00890 tfastAdditionTable[m]=m;
00891 }
00892
00893 for (int m=0; m<getCharacteristic(); m++)
00894 {
00895 tfastAdditionTable[m + getCharacteristic() ]=m;
00896 }
00897 }
00898 return tfastAdditionTable;
00899 }
00900
00902 template <class TNum,class kdefs>
00903 TNum* fast_Ring<TNum,kdefs>::createAdditiveInverseTable()
00904 {
00905 int i, j;
00906
00907 size_t tableSize = getMaxSingleIndex() + 1;
00908
00909 TNum* tadditiveInverseTable = new TNum[ tableSize ];
00910
00911 for (i=0; i<getCharacteristic(); i++)
00912 for (j=0; j<( ( getCharacteristic()-1 )*getEpsPrecision() )+1; j++)
00913 {
00914 TNum z1(i, j);
00915
00916 size_t index = getSingleIndex( z1);
00917 assert(index<tableSize && index>=0);
00918
00919 TNum z2( ( getCharacteristic() - i) % getCharacteristic(),
00920 (getCharacteristic() - j) % getCharacteristic() );
00921
00922 tadditiveInverseTable[ index ] = z2;
00923 }
00924 return tadditiveInverseTable;
00925 }
00926
00927
00928
00929
00931 template <class TNum,class kdefs>
00932 TNum * fast_Ring<TNum, kdefs>::createMultiplicationTable()
00933 {
00934 int i, j, k, l;
00935
00936 TNum * tMultiplicationTable = NULL;
00937
00938 size_t tableSize = getMaxPairIndex() + 1;
00939
00940 tMultiplicationTable = new TNum[tableSize];
00941
00942 for (i=0; i< getCharacteristic(); i++)
00943 for (j=0; j<( (getCharacteristic()-1)*getEpsPrecision() )+1; j++)
00944 for (k=0; k < getCharacteristic(); k++)
00945 for (l=0; l<( (getCharacteristic() - 1)* getEpsPrecision() ) + 1; l++)
00946 {
00947 TNum z1 (i,j);
00948 TNum z2 (k,l);
00949
00950 size_t index = getPairIndex(z1, z2);
00951
00952 assert(index < tableSize && index>=0 );
00953
00954 TNum result;
00955
00956 result.setX ( ((int) z1.getX() * (int)z2.getX() )
00957 % getCharacteristic()
00958 );
00959
00960 result.setEps( ( (int)z1.getX() * (int)z2.getEps()
00961 + (int)z2.getX() * (int)z1.getEps()
00962 ) % getCharacteristic()
00963 );
00964
00965
00966 tMultiplicationTable[ index ] = result;
00967 }
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989 return tMultiplicationTable;
00990 }
00991
00992
00997 template <class TNum,class kdefs>
00998 TNum* fast_Ring<TNum,kdefs>::createMultiplicativeInverseTable()
00999 {
01000 int i, j, k, l;
01001
01002 size_t tableSize = getMaxSingleIndex() + 1;
01003
01004 TNum * inverses1 = new TNum[ tableSize ];
01005
01006 for (i=0; i<getCharacteristic(); i++)
01007
01008 for (j=0; j<((getCharacteristic()-1)*getEpsPrecision())+1; j++)
01009 {
01010 TNum z1(i, j);
01011 size_t index = getSingleIndex( z1 );
01012
01013 assert(index<tableSize && index>=0);
01014
01015 inverses1[ index ] = TNum::Zero;
01016
01017 for (k=0; k<getCharacteristic(); k++)
01018 for (l=0; l<((getCharacteristic()-1)*getEpsPrecision())+1; l++)
01019 {
01020 TNum z2(k, l);
01021 TNum z;
01022 z.setX( ((int)z1.getX() * (int)z2.getX()) % getCharacteristic() );
01023
01024 z.setEps ( ( (int)z1.getX() * (int)z2.getEps()
01025 + (int)z2.getX() * (int)z1.getEps()
01026 ) % getCharacteristic() );
01027
01028 if ( z == TNum::One )
01029 {
01030 size_t index_2 = getSingleIndex( z1);
01031 assert( index_2<tableSize && index_2 >=0);
01032 inverses1 [index_2 ] = z2;
01033 break;
01034 }
01035 }
01036 }
01037 return inverses1;
01038 }
01039
01040
01041
01042
01044 template <class TNum,class kdefs>
01045 TNum* fast_Ring<TNum,kdefs>::initElementsToExponentsTab(TNum erzeuger)
01046 {
01047 TNum * tElementsToExponentsTab=NULL;
01048
01049 size_t tableSize = getMaxSingleIndex() + 1;
01050
01051 tElementsToExponentsTab = new TNum[tableSize];
01052
01053 tElementsToExponentsTab[0]=TNum::Zero;
01054
01055 TNum num=erzeuger;
01056
01057 for (int i=1; i<getCharacteristic(); i++)
01058 {
01059 tElementsToExponentsTab[ num.getX() ] = i;
01060 num.setX( ( (int)num.getX() * (int)erzeuger.getX() ) % getCharacteristic());
01061 }
01062 if (num!=erzeuger)
01063 {
01064 std::cerr << "num " << num << std::endl;
01065 std::cerr << "generator " << erzeuger << std::endl;
01066 num = erzeuger;
01067 for (int i=1; i<getCharacteristic(); i++)
01068 {
01069 std::cerr << "num " << (int)num.getX() * (int)erzeuger.getX() << std::endl;
01070 num.setX( ( (int)num.getX() * (int)erzeuger.getX() ) % getCharacteristic());
01071 std::cerr << "num " << num << std::endl << std::endl;
01072 }
01073
01074 assert( num==erzeuger );
01075 }
01076 return tElementsToExponentsTab;
01077 }
01078
01079
01082 template <class TNum,class kdefs>
01083 TNum* fast_Ring<TNum,kdefs>::initExponentsToElementTab(TNum erzeuger)
01084 {
01085
01086 TNum * tExponentsToElementTab=NULL;
01087
01088 long tableSize=0;
01089
01090 tableSize = getMaxSingleIndex() + 1;
01091
01092 tExponentsToElementTab = new TNum[tableSize];
01093
01094 tExponentsToElementTab[0] = TNum::Zero;
01095
01096 TNum num = erzeuger;
01097
01098 for (int i=1; i<getCharacteristic(); i++)
01099 {
01100
01101 tExponentsToElementTab[ i ] = num;
01102 num.setX( ( (int)num.getX() * (int)erzeuger.getX() ) % getCharacteristic() );
01103 }
01104 assert( num==erzeuger );
01105 return tExponentsToElementTab;
01106 }
01107
01108
01109 template <class TNum,class kdefs>
01110 typename fast_Ring<TNum,kdefs>::FieldType::ElementType* fast_Ring<TNum,kdefs>::createModuloTable()
01111 {
01112 ScalarType * tModuloTable=NULL;
01113
01114
01115
01116
01117
01118 moduloTableSize_m = 15*characteristic*characteristic+characteristic;
01119 tModuloTable= new ScalarType[ moduloTableSize_m ];
01120
01121 long currPos=0;
01122 while( currPos < moduloTableSize_m )
01123 {
01124 for (long j=0; j<characteristic;j++ )
01125 {
01126 tModuloTable[ currPos ] = j;
01127 currPos++;
01128 }
01129 }
01130
01131 return tModuloTable;
01132 }
01133
01134
01135 template <class TNum,class kdefs>
01136 inline int fast_Ring<TNum,kdefs>::getLookupModuloTableSize( ) const
01137 {
01138 return moduloTableSize_m;
01139 }
01140
01141
01142 template <class TNum,class kdefs>
01143 inline typename fast_Ring<TNum,kdefs>::FieldType::ElementType fast_Ring<TNum,kdefs>::lookupModuloTable(int convertee) const
01144 {
01145 #ifdef SAFE
01146 assert(convertee>=0 && convertee<moduloTableSize_m);
01147 #endif
01148
01149 if (convertee>=moduloTableSize_m || convertee<0 )
01150 {
01151
01152 return ConvertScalar(convertee);
01153 }
01154
01155 return moduloTable[convertee];
01156 }
01157
01158
01159 template <class TNum,class kdefs>
01160 typename fast_Ring<TNum,kdefs>::sqrtInf_t* fast_Ring<TNum,kdefs>::createSqrtTable()
01161 {
01162
01163 typename fast_Ring<TNum,kdefs>::sqrtInf_t * tSqrtTable=NULL;
01164
01165 long tableSize=0;
01166
01167 tableSize = getMaxSingleIndex() + 1;
01168
01169 tSqrtTable = new typename fast_Ring<TNum,kdefs>::sqrtInf_t[tableSize];
01170
01171 typename fast_Ring<TNum,kdefs>::sqrtInf_t entry(0,TNum::Zero);
01172
01173 for (int i=0; i<getCharacteristic(); i++)
01174 {
01175 tSqrtTable[ i ] = entry;
01176 }
01177
01178 for (int i=0; i<getCharacteristic(); i++)
01179 {
01180 int res= (i*i) % getCharacteristic();
01181 if (tSqrtTable[ res ].solutions==0)
01182 tSqrtTable[ res ].sqrt =TNum(i);
01183 else
01184 {
01185 assert( getCharacteristic()-i ==tSqrtTable[ res ].sqrt.getX() );
01186 }
01187 tSqrtTable[ res ].solutions ++;
01188
01189 }
01190
01191 for (int i=0; i<getCharacteristic(); i++)
01192 {
01193 assert( tSqrtTable[ i ].solutions==0 ||
01194 tSqrtTable[ i ].solutions==2 || tSqrtTable[ i ].sqrt.getX()==0);
01195
01196
01197 if (tSqrtTable[ i ].solutions>0)
01198 assert( (tSqrtTable[ i ].sqrt.getX() * tSqrtTable[ i ].sqrt.getX() ) % getCharacteristic() == i );
01199 assert( tSqrtTable[ i ].sqrt.getEps()==0);
01200 }
01201
01202 return tSqrtTable;
01203 }
01204
01205
01206
01207
01208
01209
01210 template <class TNum,class kdefs>
01211 inline TNum fast_Ring<TNum,kdefs>::pow(const TNum x,unsigned int exp) const
01212 {
01213 #ifdef SAFE
01214 assert(exp>=0);
01215 #endif
01216
01217
01218 if (exp==1)
01219 return x;
01220 if (exp==0)
01221 return TNum::One;
01222
01223
01224 TNum erg = x;
01225 for (; exp >1; exp--)
01226 {
01227 multiplyInPlaceRef( erg, x ) ;
01228 }
01229 return erg;
01230 }
01231
01232
01233
01234 template <class TNum,class kdefs>
01235 inline void fast_Ring<TNum,kdefs>::powInPlace( TNum & x, unsigned int exp) const
01236 {
01237 #ifdef SAFE
01238 assert(exp>=0);
01239 #endif
01240
01241
01242 if (exp==1)
01243 return ;
01244 if (exp==0)
01245 x = TNum::One;
01246
01247 TNum tmp = x;
01248 for (; exp >1; exp--)
01249 {
01250 multiplyInPlaceRef( x, tmp ) ;
01251 }
01252 return;
01253 }
01254
01255
01256
01257
01258 template <class TNum,class kdefs>
01259 inline size_t fast_Ring<TNum,kdefs>::getMaxSingleIndex() const
01260 {
01261 return TNum::getMaxSingleIndex( getCharacteristic());
01262 }
01263
01264
01265
01266 template <class TNum,class kdefs>
01267 inline size_t fast_Ring<TNum,kdefs>::getMaxPairIndex() const
01268 {
01269 return TNum::getMaxPairIndex( getCharacteristic() );
01270 }
01271
01272
01273
01274 template <class TNum,class kdefs>
01275 inline size_t fast_Ring<TNum,kdefs>::getSingleIndex(const TNum z1) const
01276 {
01277
01278
01279 return TNum::getSingleIndex(z1, getCharacteristic());
01280 }
01281
01282 template <class TNum,class kdefs>
01283 inline size_t fast_Ring<TNum,kdefs>::getSingleIndexByRef(const TNum &z1) const
01284 {
01285 return TNum::getSingleIndexByRef(z1, getCharacteristicRef());
01286 }
01287
01288 template <class TNum,class kdefs>
01289 inline size_t fast_Ring<TNum,kdefs>::getPairIndex(const TNum z1, const TNum z2) const
01290 {
01291 return TNum::getPairIndex(z1, z2, getCharacteristic() );
01292 }
01293
01294
01295 template <class TNum,class kdefs>
01296 inline size_t fast_Ring<TNum,kdefs>::getPairIndexByRef(const TNum & z1, const TNum & z2) const
01297 {
01298 return TNum::getPairIndexByRef(z1, z2, getCharacteristicRef() ) ;
01299 }
01300
01301
01302