IntegerSlowAlgo

Files CCore/inc/math/IntegerSlowAlgo.h CCore/src/math/IntegerSlowAlgo.cpp

IntegerSlowAlgo is a reference implementation of the proper integer algorithm package. You can use this package for algorithm definitions and for comparative testing. IntegerSlowAlgo is a template, its template parameter is the unit type.


template <class UInt>
struct IntegerSlowAlgo
 {
  // types and consts
  
  using Unit = UInt ;

  static const unsigned UnitBits = Meta::UIntBits<Unit> ;

  static const Unit MaxUnit = Unit(-1) ;
  
  static const Unit MSBit = Unit( MaxUnit^(MaxUnit>>1) );
  
  // functions
  
  static Unit SignExt(Unit a);
   
  static Unit SignExt(const Unit *a,ulen na);
  
  static CmpResult SignCmp(Unit a,Unit b);
  
  static unsigned CountZeroMSB(Unit a);
  
  static unsigned CountZeroLSB(Unit a);
   
  static UInt DoubleUDiv(UInt hi,UInt lo,UInt den); // hi<den 

  // private functions
  
  static Unit/* c */ Add(Unit &b,Unit a,Unit carry); // carry = 0,1 
   
  static Unit/* c */ Sub(Unit &b,Unit a,Unit carry); // carry = 0,1 
  
  static Unit/* c */ RevSub(Unit &b,Unit a,Unit carry); // carry = 0,1
   
  static Unit LShift(Unit hi,Unit lo,unsigned shift); // 0<shift<UnitBits
 
  static Unit RShift(Unit hi,Unit lo,unsigned shift); // 0<shift<UnitBits
  
  // private operators
  
  static CmpResult UCmp(Unit a,Unit b);
  
  static CmpResult UCmp_(const Unit *a,ulen na,const Unit *b,ulen nb); // na>=nb
  
  static CmpResult Cmp_(const Unit *a,ulen na,const Unit *b,ulen nb); // na>=nb
  
  // const operators
  
  static CmpResult USign(const Unit *a,ulen na);
  
  static CmpResult Sign(const Unit *a,ulen na);
  
  static CmpResult UCmp(const Unit *a,const Unit *b,ulen nab);
  
  static CmpResult UCmp(const Unit *a,ulen na,const Unit *b,ulen nb);
  
  static CmpResult Cmp(const Unit *a,const Unit *b,ulen nab);
  
  static CmpResult Cmp(const Unit *a,ulen na,const Unit *b,ulen nb);
  
  static ulen UNormalize(const Unit *a,ulen na);
  
  static ulen Normalize(const Unit *a,ulen na);
  
  // additive operators
  
  static Unit/* c */ UNeg(Unit *a,ulen na);
  
  static Unit/* msu */ Neg(Unit *a,ulen na);
  
  static Unit/* c */ UAddUnit(Unit *a,ulen na,Unit b);
  
  static Unit/* msu */ AddUnit(Unit *a,ulen na,Unit b);
  
  static Unit/* c */ USubUnit(Unit *a,ulen na,Unit b);
  
  static Unit/* msu */ SubUnit(Unit *a,ulen na,Unit b);
  
  static Unit/* c */ UNegAddUnit(Unit *a,ulen na,Unit b);
  
  static Unit/* msu */ NegAddUnit(Unit *a,ulen na,Unit b);
  
  static Unit/* c */ UAdd(Unit *restrict b,const Unit *a,ulen nab);
  
  static Unit/* msu */ Add(Unit *restrict b,ulen nb,const Unit *a,ulen na); // nb>=na

  static Unit/* c */ USub(Unit *restrict b,const Unit *a,ulen nab);
  
  static Unit/* msu */ Sub(Unit *restrict b,ulen nb,const Unit *a,ulen na); // nb>=na
  
  static Unit/* c */ URevSub(Unit *restrict b,const Unit *a,ulen nab);
  
  static Unit/* msu */ RevSub(Unit *restrict b,ulen nb,const Unit *a,ulen na); // nb>=na
  
  // shift operators
  
  static Unit/* msu */ ULShift(Unit *a,ulen na,unsigned shift); // 0<shift<UnitBits
  
  static Unit/* msu */ LShift(Unit *restrict b,const Unit *a,ulen nab,unsigned shift); // 0<shift<UnitBits
  
  static Unit/* msu */ UShiftUp(Unit *a,ulen na,ulen delta,unsigned shift); // a[na+delta] , 0<shift<UnitBits
  
  static Unit/* msu */ ShiftUp(Unit *a,ulen na,ulen delta,unsigned shift); // a[na+delta] , 0<shift<UnitBits
  
  static void URShift(Unit *a,ulen na,unsigned shift); // 0<shift<UnitBits
  
  static void RShift(Unit *restrict b,const Unit *a,ulen nab,unsigned shift); // 0<shift<UnitBits
  
  static void UShiftDown(Unit *a,ulen na,ulen delta,unsigned shift); // a[na+delta] , 0<shift<UnitBits
  
  static void ShiftDown(Unit *a,ulen na,ulen delta,unsigned shift); // a[na+delta] , 0<shift<UnitBits
  
  // private multiplicative functions
  
  struct DoubleUMul
   {
    UInt hi;
    UInt lo;
    
    DoubleUMul(UInt a,UInt b);
   };
  
  struct MulAcc
   {
    Unit lo;
    Unit hi;
    ulen hi2;
  
    MulAcc(Unit a,Unit b);
  
    void mac(Unit a,Unit b);
  
    void mac2(Unit a,Unit b);
  
    Unit shift();
   };
  
  // multiplicative operators

  static void UMul(Unit *restrict c,const Unit *a,ulen na,const Unit *b,ulen nb); // nc==na+nb
  
  static Unit/* c */ UMac(Unit *restrict c,const Unit *a,ulen na,const Unit *b,ulen nb); // nc==na+nb
  
  static void UMulLo(Unit *restrict c,ulen nc,const Unit *a,ulen na,const Unit *b,ulen nb); // nc<=na+nb
  
  static void USq(Unit *restrict c,const Unit *a,ulen na); // nc==2*na
  
  static void Mul(Unit *restrict c,const Unit *a,ulen na,const Unit *b,ulen nb); // nc==na+nb
  
  static void Sq(Unit *restrict c,const Unit *a,ulen na); // nc==2*na
  
  // data functions  

  static void Null(Unit *a,ulen na);

  static void MoveUp(Unit *a,ulen na,ulen delta); // a[na+delta]
  
  static void MoveDown(Unit *a,ulen na,ulen delta); // a[na+delta]
 };