⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vlong.cpp

📁 ecppki-cpp curve
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include "vlong.hpp"

#ifdef topspeed_asm

#pragma call( reg_param=>(bx, cx, si, di ),reg_saved=>() )
inline unsigned dmul( unsigned m, unsigned count, unsigned * src, unsigned * dst )={
0x55,                  //  push ebp
0x29,0xED,             //  sub ebp,ebp
0x67,0xE3,0x14,        //  jcxz 14H
0xAD,                  //  lods dword [esi][0]
0xF7,0xE3,             //  mul ebx
0x01,0xE8,             //  add eax,ebp
0x83,0xD2,0x00,        //  adc edx,0
0x29,0xED,             //  sub ebp,ebp
0x01,0x07,             //  add [edi*1][0],eax
0x11,0xD5,             //  adc ebp,edx
0x83,0xC7,0x04,        //  add edi,4
0x67,0xE2,0xEC,        //  loop -14H
0x89,0xE8,             //  mov eax,ebp
0x5D                   //  pop ebp
};

#endif

static void assert ( int x )
{
  if (!x)
  {
    char * z=0;
    *z=0;
  }
}

unsigned char bittab[256] =
{ 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
  6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 };

unsigned flex_unit::get( unsigned i ) const
{
  if ( i >= n ) return 0;
  return a[i];
}

void flex_unit::clear()
{
   n = 0;
}

flex_unit::flex_unit()
{
  z = 0;
  a = 0;
  n = 0;
}

flex_unit::~flex_unit()
{
  unsigned i=z;
  while (i) { i-=1; a[i] = 0; } // burn
  delete [] a;
}

void flex_unit::reserve( unsigned x )
{
  if (x > z)
  {
    unsigned * na = new unsigned[x];
    for (unsigned i=0;i<n;i+=1) na[i] = a[i];
    delete [] a;
    a = na;
    z = x;
  }
}

void flex_unit::set( unsigned i, unsigned x )
{
  if ( i < n )
  {
    a[i] = x;
    if (x==0) while (n && a[n-1]==0) n-=1; // normalise
  }
  else if ( x )
  {
    reserve(i+1);
    for (unsigned j=n;j<i;j+=1) a[j] = 0;
    a[i] = x;
    n = i+1;
  }
}

// Macros for doing double precision multiply
#define BPU ( 8*sizeof(unsigned) )       // Number of bits in an unsigned
#define lo(x) ( (x) & ((1<<(BPU/2))-1) ) // lower half of unsigned
#define hi(x) ( (x) >> (BPU/2) )         // upper half
#define lh(x) ( (x) << (BPU/2) )         // make upper half

void flex_unit::fast_mul( flex_unit &x, flex_unit &y, unsigned keep )
{
  // *this = (x*y) % (2**keep)
  unsigned i,limit = (keep+BPU-1)/BPU; // size of result in words
  reserve(limit); for (i=0; i<limit; i+=1) a[i] = 0;
  unsigned min = x.n; if (min>limit) min = limit;
  for (i=0; i<min; i+=1)
  {
    unsigned m = x.a[i];
    unsigned min = i+y.n; if (min>limit) min = limit;
#ifdef topspeed_asm
    unsigned c = dmul( m, min-i, y.a, a+i );
    unsigned j = min;
#else
    unsigned c = 0; // carry
    unsigned j;
    for ( j=i; j<min; j+=1 )
    {
      // This is the critical loop
      // Machine dependent code could help here
      // c:a[j] = a[j] + c + m*y.a[j-i];
      unsigned w, v = a[j], p = y.a[j-i];
      v += c; c = ( v < c );
      w = lo(p)*lo(m); v += w; c += ( v < w );
      w = lo(p)*hi(m); c += hi(w); w = lh(w); v += w; c += ( v < w );
      w = hi(p)*lo(m); c += hi(w); w = lh(w); v += w; c += ( v < w );
      c += hi(p) * hi(m);
      a[j] = v;
    }
#endif
    while ( c && j<limit )
    {
      a[j] += c;
      c = a[j] < c;
      j += 1;
    }
  }

  // eliminate unwanted bits
  keep %= BPU; if (keep) a[limit-1] &= (1<<keep)-1;

   // calculate n
  while (limit && a[limit-1]==0) limit-=1;
  n = limit;
};

unsigned vlong_value::to_unsigned()
{
  return get(0);
}

int vlong_value::is_zero() const
{
  return n==0;
}

unsigned vlong_value::bit( unsigned i ) const
{ return ( get(i/BPU) & (1<<(i%BPU)) ) != 0; }

void vlong_value::setbit(unsigned i)
{
  set( i/BPU, get(i/BPU) | (1<<i%BPU) );
}

void vlong_value::clearbit(unsigned i)
{
  set( i/BPU, get(i/BPU) & ~(1<<i%BPU) );
}

unsigned vlong_value::bits() const
{
  // unsigned x = n*BPU;
  // while (x && bit(x-1)==0) x -= 1;

  // slightly more efficient version
  unsigned x = n;
  if (x)
  {
    unsigned msw = get(x-1);
    x = (x-1)*BPU;
    unsigned w = BPU;
    do
    {
      w >>= 1;
      if ( msw>= (1u<<w) )
      {
        x += w;
        msw >>= w;
      }
    } while (w>8);
    x += bittab[msw];
  }
  return x;
}

int vlong_value::cf( vlong_value& x ) const
{
  if ( n > x.n ) return +1;
  if ( n < x.n ) return -1;
  unsigned i = n;
  while (i)
  {
    i -= 1;
    if ( get(i) > x.get(i) ) return +1;
    if ( get(i) < x.get(i) ) return -1;
  }
  return 0;
}

void vlong_value::shl()
{
  unsigned carry = 0;
  unsigned N = n; // necessary, since n can change
  for (unsigned i=0;i<=N;i+=1)
  {
    unsigned u = get(i);
    set(i,(u<<1)+carry);
    carry = u>>(BPU-1);
  }
}

int vlong_value::shr()
{
  unsigned carry = 0;
  unsigned i=n;
  while (i)
  {
    i -= 1;
    unsigned u = get(i);
    set(i,(u>>1)+carry);
    carry = u<<(BPU-1);
  }
  return carry != 0;
}

void vlong_value::shr( unsigned x )
{
  unsigned delta = x/BPU; x %= BPU;
  for (unsigned i=0;i<n;i+=1)
  {
    unsigned u = get(i+delta);
    if (x)
    {
      u >>= x;
      u += get(i+delta+1) << (BPU-x);
    }
    set(i,u);
  }
}

void vlong_value::add( vlong_value & x )
{
  unsigned carry = 0;
  unsigned max = n; if (max<x.n) max = x.n;
  reserve(max);
  for (unsigned i=0;i<max+1;i+=1)
  {
    unsigned u = get(i);
    u = u + carry; carry = ( u < carry );
    unsigned ux = x.get(i);
    u = u + ux; carry += ( u < ux );
    set(i,u);
  }
}

void vlong_value::xor( vlong_value & x )
{
  unsigned max = n; if (max<x.n) max = x.n;
  reserve(max);
  for (unsigned i=0;i<max;i+=1)
  {
    set(i,get(i)^x.get(i));
  }
}

void vlong_value::and( vlong_value & x )
{
  unsigned max = n; if (max<x.n) max = x.n;
  reserve(max);
  for (unsigned i=0;i<max;i+=1)
  {
    set(i,get(i)&x.get(i));
  }
}

int vlong_value::product( vlong_value &x ) const
{
  unsigned max = n; if (max<x.n) max = x.n;
  unsigned tmp = 0;
  for (unsigned i=0;i<max;i+=1)
  {
    tmp ^= get(i)&x.get(i);
  }
  unsigned count = 0;
  while (tmp)
  {
    if (tmp&1) count += 1;
    tmp >>= 1;
  }
  return count&1;
}

void vlong_value::subtract( vlong_value & x )
{
  unsigned carry = 0;
  unsigned N = n;
  for (unsigned i=0;i<N;i+=1)
  {
    unsigned ux = x.get(i);
    ux += carry;
    if ( ux >= carry )
    {
      unsigned u = get(i);
      unsigned nu = u - ux;
      carry = nu > u;
      set(i,nu);
    }
  }
}

void vlong_value::init( unsigned x )
{
  clear();
  set(0,x);
}

void vlong_value::copy( vlong_value& x )
{
  clear();
  unsigned i=x.n;
  while (i) { i -= 1; set( i, x.get(i) ); }
}

vlong_value::vlong_value()
{
  share = 0;
}

void vlong_value::mul( vlong_value& x, vlong_value& y )
{
  fast_mul( x, y, x.bits()+y.bits() );
}

void vlong_value::divide( vlong_value& x, vlong_value& y, vlong_value& rem )
{
  init(0);
  rem.copy(x);
  vlong_value m,s;
  m.copy(y);
  s.init(1);
  while ( rem.cf(m) > 0 )
  {
    m.shl();
    s.shl();
  }
  while ( rem.cf(y) >= 0 )
  {
    while ( rem.cf(m) < 0 )
    {
      m.shr();
      s.shr();
    }
    rem.subtract( m );
    add( s );
  }
}

// Implementation of vlong

int operator !=( const vlong& x, const vlong& y ){ return x.cf( y ) != 0; }
int operator ==( const vlong& x, const vlong& y ){ return x.cf( y ) == 0; }
int operator >=( const vlong& x, const vlong& y ){ return x.cf( y ) >= 0; }
int operator <=( const vlong& x, const vlong& y ){ return x.cf( y ) <= 0; }
int operator > ( const vlong& x, const vlong& y ){ return x.cf( y ) > 0; }
int operator < ( const vlong& x, const vlong& y ){ return x.cf( y ) < 0; }

void vlong::load( unsigned * a, unsigned n )
{
  docopy();
  value->clear();
  for (unsigned i=0;i<n;i+=1)
    value->set(i,a[i]);
}

void vlong::store( unsigned * a, unsigned n ) const
{
  for (unsigned i=0;i<n;i+=1)
    a[i] = value->get(i);
}

void vlong::docopy()
{
  if ( value->share )
  {
    value->share -= 1;
    vlong_value * nv = new vlong_value;
    nv->copy(*value);
    value = nv;
  }
}

unsigned vlong::bits() const
{
  return value->bits();
}

unsigned vlong::bit(unsigned i) const

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -