Changeset 3004

Show
Ignore:
Timestamp:
07/03/08 11:43:21 (2 months ago)
Author:
aniau
Message:

=

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • trunk/linbox/linbox/algorithms/rational-reconstruction-base.h

    r2995 r3004  
    11/* -*- mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ 
    2  
    3 #include <iostream> 
    4 #include <deque> 
    52 
    63#ifndef __LINBOXX__RECONSTRUCTION_BASE_H__ 
    74#define __LINBOXX__RECONSTRUCTION_BASE_H__ 
    85 
    9 //#define __FASTRR_DEFAULT_THRESHOLD 9223372036854775807 //2^63-1 
    10 //#define __FASTRR_DEFAULT_THRESHOLD 2147483647 //2^31-1  
    11 #define __FASTRR_DEFAULT_THRESHOLD 7  
    12 //max int=2^32 4294967295 
    13 //max int=2^64 18446744073709551616 
    14 //__FASTRR_DEFAULT_THRESHOLD > 4 
     6#include <iostream> 
     7#include <deque> 
    158 
    169using namespace std; 
     
    108101class RationalReconstructionBase 
    109102{ 
    110 protected: 
     103public: 
    111104        Ring _Z; 
    112105        OpCounter C; 
    113 public: 
    114         //Ring _Z; 
    115106        typedef typename Ring::Element Element; 
    116107         
     
    130121        } 
    131122}; 
    132 /* 
    133 template <class Ring> 
    134 class WangRationalReconstruction: public RationalReconstructionBase<Ring>  
    135 { 
    136 protected: 
    137         bool _reduce; 
    138         bool _recursive; 
    139         Ring _Z; 
    140         OpCounter C; 
    141 public: 
    142         Ring _Z; 
    143         typedef typename Ring::Element Element; 
    144          
    145         OpCounter C; 
    146  
    147         WangRationalReconstruction(const Ring& Z, const bool reduce = true, const bool recursive = false): RationalReconstructionBase<Ring>(Z) { 
    148                 _reduce = reduce; _recursive = recursive; 
    149         } 
    150  
    151         WangRationalReconstruction<Ring> (const WangClassicRationalReconstruction<Ring>& RR): RationalReconstructionBase<Ring>(RR._Z) { 
    152                 _reduce = RR._reduce; _recursive = RR._recursive; 
    153         } 
    154  
    155         bool reconstructRational(Element& a, Element& b, const Element& x, const Element& m)=0 { 
    156                 Element a_bound; _Z.sqrt(a_bound, m/2); 
    157                 bool res = rationalReconstruction(a,b,x,m,a_bound); 
    158                 res = res && (b <= a_bound); 
    159                 return res; 
    160         } 
    161  
    162         bool reconstructRational(Element& a, Element& b, const Element& x, const Element& m, const Element& a_bound) { 
    163                 bool res; 
    164  
    165                 if (x == 0) { 
    166                     a = 0; 
    167                     b = 1; 
    168                 } else { 
    169                         bool res = ratrecon(a,b,x,m,a_bound); 
    170                         if (_recursive) 
    171                         for(Element newbound = a_bound + 1; (!res) && (newbound<x) ; ++newbound) 
    172                             res = ratrecon(a,b,x,m,newbound); 
    173                 } 
    174                 if (!res) { 
    175                         a = x> m/2? x-m: x;  
    176                         b = 1; 
    177                         if (a > 0) res = (a < a_bound); 
    178                         else res = (-a < a_bound); 
    179                 } 
    180                  
    181                 return res;              
    182         } 
    183  
    184         virtual ~WangRationalReconstruction() {} 
    185 protected: 
    186  
    187 // m> x> 0  
    188         bool ratrecon(Element& a,Element& b,const Element& x,const Element& m,const Element& a_bound) { 
    189  
    190                 Element  r0, t0, q, u; 
    191                 r0=m; 
    192                 t0=0; 
    193                 a=x; 
    194                 b=1; 
    195                 //Element s0,s; s0=1,s=0;//test time gcdex; 
    196                 while(a>=a_bound) 
    197                 { 
    198  
    199                     q = r0; 
    200                     _Z.divin(q,a);        // r0/num 
    201 ++C.div_counter;                     
    202  
    203                     u = a; 
    204                     a = r0;      
    205                     r0 = u;     // r0 <-- num 
    206                                                             
    207                     _Z.axmyin(a,u,q); // num <-- r0-q*num 
    208 ++C.mul_counter; 
    209                     //if (a == 0) return false; 
    210                      
    211                     u = b; 
    212                     b = t0;      
    213                     t0 = u;     // t0 <-- den 
    214                                 
    215                     _Z.axmyin(b,u,q); // den <-- t0-q*den 
    216 ++C.mul_counter; 
    217                 }  
    218  
    219 //                        if (den < 0) { 
    220 //                                _Z.negin(num); 
    221 //                                _Z.negin(den); 
    222 //                        } 
    223  
    224                 if ((a>0) && (_reduce)) { 
    225  
    226                         // [GG, MCA, 1999] Theorem 5.26 
    227                         // (ii) 
    228                     Element gg; 
    229 ++C.gcd_counter; 
    230                     if (_Z.gcd(gg,a,b) != 1) { 
    231                          
    232                         Element ganum, gar2; 
    233                         for( q = 1, ganum = r0-a, gar2 = r0 ; (ganum >= a_bound) || (gar2<a_bound); ++q ) { 
    234                             ganum -= a; 
    235                             gar2 -= a; 
    236                         } 
    237                                          
    238                         //_Z.axmyin(r0,q,a); 
    239                         r0 = ganum; 
    240                         _Z.axmyin(t0,q,b); 
    241 ++C.mul_counter;++C.mul_counter;                         
    242                         if (t0 < 0) { 
    243                             a = -r0; 
    244                             b = -t0; 
    245                         } else { 
    246                             a = r0; 
    247                             b = t0; 
    248                         } 
    249                          
    250 //                                if (t0 > m/k) { 
    251                         if ((double)b > (double)m/(double)a_bound) { 
    252                                 if (!_recursive) { 
    253                                         std::cerr  
    254                                                 << "*** Error *** No rational reconstruction of "  
    255                                                 << x  
    256                                                 << " modulo "  
    257                                                 << m  
    258                                                 << " with denominator <= "  
    259                                                 << (m/a_bound) 
    260                                                 << std::endl;  
    261                                 } 
    262                                 return false; 
    263                         } 
    264                         if (_Z.gcd(gg,a,b) != 1) { 
    265                             if (!_recursive)  
    266                                 std::cerr  
    267                                     << "*** Error *** There exists no rational reconstruction of "  
    268                                     << x  
    269                                     << " modulo "  
    270                                     << m  
    271                                     << " with |numerator| < "  
    272                                     << a_bound 
    273                                     << std::endl 
    274                                     << "*** Error *** But "  
    275                                     << a 
    276                                     << " = " 
    277                                     << b 
    278                                     << " * " 
    279                                     << x 
    280                                     << " modulo "  
    281                                     << m  
    282                                     << std::endl; 
    283                             return false; 
    284                         } 
    285                     } 
    286                 } 
    287                // (i) 
    288                if (b < 0) { 
    289                        _Z.negin(a); 
    290                        _Z.negin(b); 
    291                } 
    292  
    293 // std::cerr << "RatRecon End " << num << "/" << den << std::endl; 
    294                 return true;     
    295         } 
    296 }; 
    297 */ 
    298 template <class Ring> 
    299 class QMatrix { 
    300 public: 
    301         Ring _Z; 
    302         typedef typename Ring::Element Element; 
    303  
    304         Element a,b,c,d; 
    305         Element q; 
    306  
    307         QMatrix(const Ring Z): _Z(Z) { 
    308                 a=1;b=0;c=0;d=1;q=0; 
    309         } 
    310  
    311         QMatrix(const QMatrix& Q): _Z(Q._Z) { 
    312                 a = Q.a; 
    313                 b = Q.b; 
    314                 c = Q.c; 
    315                 d = Q.d; 
    316                 q = Q.q; 
    317         } 
    318  
    319         QMatrix(Ring Z,const Element& ai, const Element& bi, const Element& ci, const Element& di, const Element& qi=0): _Z(Z) { 
    320                 a = ai; 
    321                 b = bi; 
    322                 c = ci; 
    323                 d = di; 
    324                 q = qi;          
    325         } 
    326  
    327         QMatrix& operator=(const QMatrix& Q) { 
    328                 a = Q.a; 
    329                 b = Q.b; 
    330                 c = Q.c; 
    331                 d = Q.d; 
    332                 q = Q.q; 
    333                 return *this; 
    334         } 
    335  
    336         void leftmultiply(const QMatrix Q) { 
    337                 leftmultiply(Q.a,Q.b, Q.c,Q.d); 
    338         } 
    339  
    340         void leftmultiply(const Element& ai,const Element& bi,const Element& ci,const Element& di) { 
    341                 Element tmpa,tmpb,tmpc,tmpd; 
    342                 _Z.mul(tmpa,ai,a); 
    343                 _Z.axpyin(tmpa,bi,c); 
    344  
    345                 _Z.mul(tmpb,ai,b); 
    346                 _Z.axpyin(tmpb,bi,d); 
    347  
    348                 _Z.mul(tmpc,ci,a); 
    349                 _Z.axpyin(tmpc,di,c); 
    350                  
    351                 _Z.mul(tmpd,ci,b); 
    352                 _Z.axpyin(tmpd,di,d);            
    353  
    354                 a = tmpa; b = tmpb; c = tmpc; d = tmpd; 
    355         } 
    356          
    357         QMatrix& max(const QMatrix& max1, const QMatrix max2) { 
    358                 if (max1.q >= max2.q) return QMatrix(max1); 
    359                 else return QMatrix(max2);       
    360         } 
    361  
    362         bool maxin(const QMatrix max2) { 
    363                 if (q >= max2.q) return true; 
    364                 else { 
    365                         a = max2.a; 
    366                         b = max2.b; 
    367                         c = max2.c; 
    368                         d = max2.d; 
    369                         q = max2.q; 
    370                         return false; 
    371                 } 
    372         } 
    373 }; 
    374  
    375 template <class Ring> 
    376 class myQueue: public deque<QMatrix<Ring > > { 
    377 public: 
    378         typedef typename Ring::Element Element; 
    379         typedef QMatrix<Ring> QMatrix; 
    380  
    381         size_t _maxSize; 
    382         size_t _size; 
    383  
    384         myQueue(const size_t K=0) { 
    385                 _maxSize = K; 
    386                 _size = 0; 
    387         } 
    388  
    389         bool pushpop(QMatrix& top, const QMatrix& bottom) { 
    390                 if (_size+1 < _maxSize) { 
    391                         push_back(bottom); 
    392                         return false; 
    393                         ++_size; 
    394                 } else { 
    395                         if (!this->empty()) { 
    396                                 top = this->front(); 
    397                                 this->pop_front(); 
    398                                 push_back(bottom); 
    399                                  
    400                         } else { 
    401                                 top=bottom;  
    402                         } 
    403                         return true;                                     
    404                 } 
    405         } 
    406          
    407         QMatrix& clearmax(QMatrix& max1) { 
    408                 while (!this->empty()) { 
    409                         QMatrix max2(this->front()); 
    410                         if (max2.q > max1.q) return max1=max2; 
    411                         this->pop_front(); 
    412                 } 
    413         } 
    414 }; 
    415  
    416 template <class Ring> 
    417 class MaxQFastRationalReconstruction: public RationalReconstructionBase<Ring> 
    418 { 
    419 protected: 
    420         size_t _threshold; 
    421         Ring _Z; 
    422         OpCounter C;     
    423  
    424 typedef typename Ring::Element Element; 
    425 public: 
    426  
    427         MaxQFastRationalReconstruction(const Ring& Z): RationalReconstructionBase<Ring>(Z), _Z(Z) {              
    428                 _threshold = __FASTRR_DEFAULT_THRESHOLD; 
    429                 if (_threshold <5) _threshold=5;  
    430         } 
    431  
    432         ~MaxQFastRationalReconstruction() {} 
    433  
    434         bool reconstructRational(Element& a, Element& b, const Element& x, const Element& m) {   
    435                 //reconstructRational(a,b,x,m,1); 
    436                 return fastQMaxReconstructRational(a,b,x,m); 
    437         } 
    438  
    439         bool reconstructRational(Element& a, Element& b, const Element& x, const Element& m, const Element& a_bound) { 
    440                 bool res = reconstructRational(a,b,x,m); 
    441                 return res && (a < a_bound); 
    442         } 
    443  
    444 protected: 
    445  
    446         Element cur_ri; 
    447         Element cur_rinext; 
    448         Element cur_ainext; 
    449         Element cur_qinext; 
    450  
    451         //QMatrix max; 
    452  
    453         Element& powtwo(Element& h, const Element& log_h) { 
    454                 h = 1; 
    455                 //cout << "max" << ULONG_MAX << "x" << x << "?" << (x < ULONG_MAX); 
    456                 if (log_h < ULONG_MAX) { 
    457                         h<<=log_h; 
    458                         //cout << "z"<< z; 
    459                         return h; 
    460                 } else { 
    461                         Element n,m; 
    462                         quoRem(n,m,log_h,(Element)(ULONG_MAX-1)); 
    463                         for (int i=0; i < n; ++i) { 
    464                                 h <<=(long int)(ULONG_MAX-1); 
    465                         } 
    466                         h <= (long int)m; 
    467                         return h; 
    468                 } 
    469         } 
    470  
    471         Element& powtwo(Element& h, const size_t log_h) { 
    472                 h = 1; 
    473                 h<<=log_h; 
    474                 return h; 
    475         } 
    476  
    477         bool fastQMaxReconstructRational(Element& n, Element& d, const Element& x, const Element& m) { 
    478                  
    479                 size_t log_m = m.bitsize()-1; //true unless m = 2^k 
    480                  
    481                 Element ai, bi, ci, di; 
    482                 ai=1;bi=0;ci=0;di=1; 
    483                  
    484                 cur_ri = m; 
    485                 cur_rinext = x; 
    486                 _Z.quo(cur_ainext, cur_ri, cur_rinext); 
    487                 cur_qinext = cur_ainext;//  ri/ri_next 
    488  
    489                 Element powh; 
    490                 myQueue<Ring > queueMax(0); 
    491                 QMatrix<Ring > maxQ(_Z); 
    492                  
    493                 if (!fastQMaxEEA (ai,bi,ci,di,m,log_m,x,powtwo(powh,log_m+1), log_m+1,queueMax,maxQ)) { 
    494                         //cout << "false\n" << flush; 
    495                         return false; 
    496                 } 
    497                  
    498                 if (cur_rinext != 0) { 
    499                         cout << "bad bounds - should not happen\n" << flush; 
    500                 } 
    501  
    502                 if (!queueMax.empty()) { 
    503                         cout << "Queue is empty\n - sth wrong" << flush; 
    504                 } 
    505                  
    506                 _Z.mul(n,x, maxQ.a); 
    507                 _Z.axmyin(n,m,maxQ.c); 
    508                 //n = x_in*ai-m*ci; 
    509                 d = maxQ.a; 
    510  
    511 /* 
    512                 _Z.mul(n, maxQ.d, m); 
    513                 _Z.axmyin(n, maxQ.b, n); 
    514                 d = maxQ.b;      
    515 */ 
    516                 Element _gcd; 
    517                 if (_Z.gcd(_gcd, n,d) > 1) { 
    518                 /* solution not implemented */ 
    519                         cout << "Solution pair is not coprime\n"; 
    520                         return false; 
    521                 } 
    522  
    523                 return true; 
    524         }                
    525  
    526         bool classicQMaxEEA(Element& ai, Element& bi, Element& ci, Element& di, const Element& r0, const Element& r1,const Element& powh, myQueue<Ring >&  queueMax, QMatrix<Ring>& maxQ) { 
    527                 Element ri, rinext; 
    528                 ri = r0; rinext = r1; 
    529                 ai =di = 1; 
    530                 bi =ci = 0; 
    531                 if (rinext==0) return true; 
    532                 Element ainext,cinext; 
    533                 Element qinext; 
    534                 _Z.quo(qinext,ri,rinext); 
    535 ++C.div_counter; 
    536  
    537                 ainext =qinext;  
    538                 //_Z.axpy(ainext, ai,qinext,bi); 
    539                 while (ainext <= powh) { 
    540  
    541                         //_Z.quo(qinext,ri,rinext); 
    542 ++C.div_counter; 
    543                         QMatrix<Ring> newQ(_Z,ai,bi,ci,di,qinext); 
    544                         QMatrix<Ring> top(_Z); 
    545                         if (queueMax.pushpop(top, newQ)) { 
    546                                 //cout << "1new max " << top.q << "\n" << flush; 
    547                                 if (maxQ.q < top.q) maxQ = top; 
    548                         } 
    549                         //cout << "EEA" << qinext << ","; 
    550                         //++i; 
    551                         //ainext = ai*qinext + bi; 
    552                         //_Z.axpy(ainext, ai,qinext,bi); 
    553 ++C.mul_counter; 
    554  
    555                         Element tmpbi = bi; 
    556                         Element tmpdi = di;  
    557                         bi = ai; 
    558                         ai = ainext; 
    559                         Element temp = ci; 
    560                         _Z.axpy(ci, temp,qinext,di); 
    561 ++C.mul_counter; 
    562                         di = temp; 
    563  
    564                         temp = ri; 
    565                         ri=rinext; 
    566                         _Z.axpy(rinext, -qinext,ri,temp);//rinext = ri-qinext*rinext 
    567  
    568 ++C.mul_counter; 
    569                         if (rinext==0) { 
    570                                 //ainext = infinity 
    571                                 cur_ri = ri; 
    572                                 cur_rinext = rinext; 
    573                                 cur_ainext = r0+1; 
    574                                 cur_qinext = cur_ainext;//infinity 
    575                                 //cout << "->1E:" << cur_ri << " " << cur_rinext <<" " <<  cur_ainext << "\n"<< flush; 
    576                                 return true; 
    577                         } 
    578  
    579                         _Z.quo(qinext,ri,rinext); 
    580 ++C.div_counter;                         
    581                         _Z.axpy(ainext, ai,qinext,bi); 
    582                          
    583                 } 
    584                 cur_ri = ri; 
    585                 cur_rinext = rinext; 
    586                 cur_ainext = ainext; 
    587                 cur_qinext = qinext;     
    588                 //cout << "->2E:" << cur_ri << " " << cur_rinext <<" " <<  cur_ainext << "\n"<< flush; 
    589                 return true; 
    590         } 
    591          
    592         bool fastQMaxEEA(Element& ai,Element& bi, Element& ci, Element& di, const Element& m, const size_t d, const Element& n, const Element& powh, const size_t& h, myQueue<Ring >&  queueMax, QMatrix<Ring>& maxQ) { 
    593                  
    594                 //cout << m << " " << n << " " << powh << "\n" << flush; 
    595                  
    596                 ai=Element(1); 
    597                 di=Element(1); 
    598                 bi=Element(0); 
    599                 ci=Element(0); //Q(0)=Id 
    600  
    601                 if (m==n) { 
    602                         cur_ri = n; 
    603                         cur_rinext = 0; 
    604                         cur_ainext = m+1;//infinity 
    605                         cur_qinext = m+1; 
    606                         ai=1; bi=1; ci=1; di=0; 
    607                         QMatrix<Ring> newQ(_Z,1,0,0,1,1); 
    608                         //QMatrix<Ring> newQ(_Z,1,1,1,0,1); 
    609                         QMatrix<Ring> top(_Z); 
    610                         if (queueMax.pushpop(top, newQ)) { 
    611                                 //cout << "2new max " << top.q << "\n"<< flush; 
    612                                 if (maxQ.q < top.q) maxQ = top; 
    613                         } 
    614                         //cout << "m=n1" << ","; 
    615                         return true; 
    616                 } 
    617  
    618                 if (powh < 1) return false; //should not happen 
    619                 if (n < 2) { 
    620                         //cout << "n=1\n"<< flush; 
    621                                          //n==1 -> Q1=(m,1//1,0) 
    622                                          //n==0 -> Q1=infinity 
    623                         cur_ri = m; 
    624                         cur_rinext = 1; 
    625                         cur_ainext = m;//infinity 
    626                         cur_qinext = m; 
    627                         if (cur_ainext > powh) { 
    628                                 //we do not have to treat identity; 
    629                                 return true; 
    630                         } 
    631                         else { 
    632                                 ai=m; bi=1; ci=1; di=0; 
    633                                 cur_ri = 1; 
    634                                 cur_rinext = 0; 
    635                                 cur_ainext = m+1; 
    636                                 cur_qinext = m+1; 
    637                                 QMatrix<Ring> newQ(_Z,1,0,0,1,m); 
    638                                 //QMatrix<Ring> newQ(_Z,m,1,1,0,m); 
    639                                 QMatrix<Ring> top(_Z); 
    640                                 if (queueMax.pushpop(top, newQ)) { 
    641                                 //      cout << "3new max " << top.q << "\n"<< flush; 
    642                                         if (maxQ.q < top.q) maxQ = top; 
    643                                 } 
    644                                 //cout << "n=1" << m << ","; 
    645                                  
    646                                 return true; 
    647                         } 
    648                         return true; 
    649                 } 
    650  
    651                 if (h < 1) { 
    652                         //cout << "h < 1" << flush; 
    653                         //quo(qinext,m,n);  
    654                         //if (qinext==1) { return (1,1,1,0) or (1,0,0,1) 
    655                         if ((n << 1) > m) { 
    656                                 cur_ri = n; 
    657                                 cur_rinext = m-n; 
    658                                 _Z.quo(cur_qinext, cur_ri, cur_rinext); 
    659 ++C.div_counter; 
    660                                 cur_ainext = cur_qinext + 1; 
    661                                 ai=1; bi=1; ci=1; di=0; 
    662                                 QMatrix<Ring> newQ(_Z,1,0,0,1,1); 
    663                                 //QMatrix<Ring> newQ(_Z,1,1,1,0,1); 
    664                                 QMatrix<Ring> top(_Z); 
    665                                 if (queueMax.pushpop(top, newQ)) { 
    666                                         //cout << "4new max " << top.q << "\n"<< flush; 
    667                                         if (maxQ.q < top.q) maxQ = top; 
    668                                 } 
    669                                 //cout << "h=01" << ","; 
    670  
    671                         } else { 
    672                                 //we do not have to treat identity; 
    673                                 cur_ri = m; 
    674                                 cur_rinext = n; 
    675                                 _Z.quo(cur_ainext,m,n); 
    676 ++C.div_counter; 
    677                                 cur_qinext = cur_ainext; 
    678                         } 
    679                         return true; 
    680                 } 
    681  
    682                 if (n < _threshold) {       //what about m? 
    683                         return classicQMaxEEA(ai,bi,ci,di,m,n,powh,queueMax,maxQ); 
    684                 } 
    685  
    686                 //size_t log_n = n.bitsize()-1; 
    687  
    688                 //              cout << d << " " << log_n << " "  << h << "\n"<< flush; 
    689  
    690                 if (2*h+1 < d) { 
    691                         //cout << "choice1"<< flush; 
    692                         //if (2*h+1 <= log_n) { 
    693                   if (true) {    
    694                         //cout << ".1\n"<< flush; 
    695                         size_t lambda = d-2*h-1; 
    696  
    697                         Element aistar, bistar, cistar, distar; 
    698                         aistar=distar=1; 
    699                         bistar=cistar=0; 
    700  
    701                         Element mstar = m >> (long unsigned int) lambda; 
    702                         Element nstar = n >> (long unsigned int) lambda; 
    703  
    704                         size_t log_mstar = 2*h+1; 
    705  
    706                         queueMax._maxSize +=2; 
    707                         if (nstar > 0) if (!fastQMaxEEA(aistar, bistar, cistar, distar, mstar, log_mstar,nstar, powh, h, queueMax, maxQ)) return false; 
    708  
    709                         if (queueMax._size > 1) { 
    710                                 queueMax.pop_back(); 
    711                                 QMatrix<Ring> Q_i_2 (queueMax.back());  
    712                                 queueMax.pop_back();//pop Q*(i-1) q*(i) 
    713                                 --queueMax._size ; 
    714                                 --queueMax._size ; 
    715                                 ai = Q_i_2.a; 
    716                                 bi = Q_i_2.b; 
    717                                 ci = Q_i_2.c; 
    718                                 di = Q_i_2.d;// Q(i-2)= Q*(i-2) q*(i-1) 
    719                         }  else { 
    720                                 queueMax.clear(); 
    721                         } 
    722                         queueMax._maxSize -=2; 
    723                          
    724                         _Z.mul(cur_ri,m,di); 
    725                         _Z.axmyin(cur_ri,n,bi); 
    726                         _Z.mul(cur_rinext,n,ai); 
    727                         _Z.axmyin(cur_rinext,m,ci); 
    728 C.mul_counter+=4; 
    729                         //ri = m*di - n*bi; 
    730                         //rinext = -m*ci + n*ai;  
    731   
    732                         if (cur_ri < 0) { 
    733                                 cur_ri = -cur_ri; 
    734