[BACK]Return to N.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib2 / asir2000 / engine

Diff for /OpenXM_contrib2/asir2000/engine/N.c between version 1.11 and 1.12

version 1.11, 2015/08/29 04:15:04 version 1.12, 2018/03/29 01:32:51
Line 45 
Line 45 
  * DEVELOPER SHALL HAVE NO LIABILITY IN CONNECTION WITH THE USE,   * DEVELOPER SHALL HAVE NO LIABILITY IN CONNECTION WITH THE USE,
  * PERFORMANCE OR NON-PERFORMANCE OF THE SOFTWARE.   * PERFORMANCE OR NON-PERFORMANCE OF THE SOFTWARE.
  *   *
  * $OpenXM: OpenXM_contrib2/asir2000/engine/N.c,v 1.10 2009/03/02 16:28:30 ohara Exp $   * $OpenXM: OpenXM_contrib2/asir2000/engine/N.c,v 1.11 2015/08/29 04:15:04 fujimoto Exp $
 */  */
 #include "ca.h"  #include "ca.h"
 #include "base.h"  #include "base.h"
Line 53 
Line 53 
 #if (defined(_M_IX86) || defined(i386)) && !defined(__MINGW32__)  #if (defined(_M_IX86) || defined(i386)) && !defined(__MINGW32__)
 void addn(N n1,N n2,N *nr)  void addn(N n1,N n2,N *nr)
 {  {
         unsigned int *m1,*m2,*mr;    unsigned int *m1,*m2,*mr;
         unsigned int c;    unsigned int c;
         N r;    N r;
         int i,d1,d2;    int i,d1,d2;
         unsigned int tmp;    unsigned int tmp;
   
         if ( !n1 )    if ( !n1 )
                 COPY(n2,*nr);      COPY(n2,*nr);
         else if ( !n2 )    else if ( !n2 )
                 COPY(n1,*nr);      COPY(n1,*nr);
         else {    else {
                 if ( PL(n1) > PL(n2) ) {      if ( PL(n1) > PL(n2) ) {
                         d1 = PL(n1); d2 = PL(n2); m1 = BD(n1); m2 = BD(n2);        d1 = PL(n1); d2 = PL(n2); m1 = BD(n1); m2 = BD(n2);
                 } else {      } else {
                         d1 = PL(n2); d2 = PL(n1); m1 = BD(n2); m2 = BD(n1);        d1 = PL(n2); d2 = PL(n1); m1 = BD(n2); m2 = BD(n1);
                 }      }
                 *nr = r = NALLOC(d1 + 1); INITRC(r); mr = BD(r);      *nr = r = NALLOC(d1 + 1); INITRC(r); mr = BD(r);
   
 #if defined(_M_IX86)  #if defined(_M_IX86)
                 __asm {      __asm {
                 push    esi      push  esi
                 push    edi      push  edi
                 mov esi,m1      mov esi,m1
                 mov edi,m2      mov edi,m2
                 mov ebx,mr      mov ebx,mr
                 mov ecx,d2      mov ecx,d2
                 xor     eax,eax      xor  eax,eax
                 Lstart_addn:      Lstart_addn:
                 mov eax,DWORD PTR [esi]      mov eax,DWORD PTR [esi]
                 mov edx,DWORD PTR [edi]      mov edx,DWORD PTR [edi]
                 adc eax,edx      adc eax,edx
                 mov DWORD PTR [ebx],eax      mov DWORD PTR [ebx],eax
                 lea esi,DWORD PTR [esi+4]      lea esi,DWORD PTR [esi+4]
                 lea edi,DWORD PTR [edi+4]      lea edi,DWORD PTR [edi+4]
                 lea ebx,DWORD PTR [ebx+4]      lea ebx,DWORD PTR [ebx+4]
                 dec ecx      dec ecx
                 jnz Lstart_addn      jnz Lstart_addn
                 pop     edi      pop  edi
                 pop     esi      pop  esi
                 mov eax,0      mov eax,0
                 adc eax,eax      adc eax,eax
                 mov c,eax      mov c,eax
                 }      }
 #else  #else
                 asm volatile("\      asm volatile("\
                 pushl   %%ebx;\      pushl  %%ebx;\
                 movl    %1,%%esi;\      movl  %1,%%esi;\
                 movl    %2,%%edi;\      movl  %2,%%edi;\
                 movl    %3,%%ebx;\      movl  %3,%%ebx;\
                 movl    %4,%%ecx;\      movl  %4,%%ecx;\
                 testl   %%eax,%%eax;\      testl  %%eax,%%eax;\
                 Lstart_addn:;\      Lstart_addn:;\
                 movl    (%%esi),%%eax;\      movl  (%%esi),%%eax;\
                 movl    (%%edi),%%edx;\      movl  (%%edi),%%edx;\
                 adcl    %%edx,%%eax;\      adcl  %%edx,%%eax;\
                 movl    %%eax,(%%ebx);\      movl  %%eax,(%%ebx);\
                 leal    4(%%esi),%%esi;\      leal  4(%%esi),%%esi;\
                 leal    4(%%edi),%%edi;\      leal  4(%%edi),%%edi;\
                 leal    4(%%ebx),%%ebx;\      leal  4(%%ebx),%%ebx;\
                 decl    %%ecx;\      decl  %%ecx;\
                 jnz Lstart_addn;\      jnz Lstart_addn;\
                 movl    $0,%%eax;\      movl  $0,%%eax;\
                 adcl    %%eax,%%eax;\      adcl  %%eax,%%eax;\
                 movl    %%eax,%0;\      movl  %%eax,%0;\
                 popl    %%ebx"\      popl  %%ebx"\
                 :"=m"(c)\      :"=m"(c)\
                 :"m"(m1),"m"(m2),"m"(mr),"m"(d2)\      :"m"(m1),"m"(m2),"m"(mr),"m"(d2)\
                 :"eax","ecx","edx","esi","edi");      :"eax","ecx","edx","esi","edi");
 #endif  #endif
                 for ( i = d2, m1 += d2, mr += d2; (i < d1) && c ; i++ ) {      for ( i = d2, m1 += d2, mr += d2; (i < d1) && c ; i++ ) {
                         tmp = *m1++ + c;        tmp = *m1++ + c;
                         c = tmp < c ? 1 : 0;        c = tmp < c ? 1 : 0;
                         *mr++ = tmp;        *mr++ = tmp;
                 }      }
                 for ( ; i < d1; i++ )      for ( ; i < d1; i++ )
                         *mr++ = *m1++;        *mr++ = *m1++;
                 *mr = c;      *mr = c;
                 PL(r) = (c?d1+1:d1);      PL(r) = (c?d1+1:d1);
         }    }
 }  }
   
 int subn(N n1,N n2,N *nr)  int subn(N n1,N n2,N *nr)
 {  {
         N r;    N r;
         unsigned int *m1,*m2,*mr,br;    unsigned int *m1,*m2,*mr,br;
         unsigned int tmp,t;    unsigned int tmp,t;
         int d1,d2,sgn,i;    int d1,d2,sgn,i;
   
         if ( !n1 ) {    if ( !n1 ) {
                 if ( n2 ) {      if ( n2 ) {
                         COPY(n2,*nr);        COPY(n2,*nr);
                         return -1;        return -1;
                 } else {      } else {
                         *nr = 0;        *nr = 0;
                         return 0;        return 0;
                 }      }
         } else if ( !n2 ) {    } else if ( !n2 ) {
                 COPY(n1,*nr);      COPY(n1,*nr);
                 return 1;      return 1;
         } else {    } else {
                 d1 = PL(n1); d2 = PL(n2);      d1 = PL(n1); d2 = PL(n2);
                 m1 = BD(n1); m2 = BD(n2);      m1 = BD(n1); m2 = BD(n2);
                 if ( (d1 = PL(n1)) > (d2 = PL(n2)) )      if ( (d1 = PL(n1)) > (d2 = PL(n2)) )
                         sgn = 1;        sgn = 1;
                 else if ( d1 < d2 ) {      else if ( d1 < d2 ) {
                         d1 = PL(n2); d2 = PL(n1);        d1 = PL(n2); d2 = PL(n1);
                         m1 = BD(n2); m2 = BD(n1);        m1 = BD(n2); m2 = BD(n1);
                         sgn = -1;        sgn = -1;
                 } else {      } else {
                         for ( i = d1-1; i >= 0 && m1[i] == m2[i]; i-- );        for ( i = d1-1; i >= 0 && m1[i] == m2[i]; i-- );
                         if ( i < 0 ) {        if ( i < 0 ) {
                                 *nr = 0;          *nr = 0;
                                 return 0;          return 0;
                         }        }
                         d1 = d2 = i+1;        d1 = d2 = i+1;
                         if ( m1[i] > m2[i] )        if ( m1[i] > m2[i] )
                                 sgn = 1;          sgn = 1;
                         else {        else {
                                 m1 = BD(n2); m2 = BD(n1);          m1 = BD(n2); m2 = BD(n1);
                                 sgn = -1;          sgn = -1;
                         }        }
                 }      }
                 *nr = r = NALLOC(d1); INITRC(r); mr = BD(r);      *nr = r = NALLOC(d1); INITRC(r); mr = BD(r);
   
 #if defined(_M_IX86)  #if defined(_M_IX86)
                 __asm {      __asm {
                 push    esi      push  esi
                 push    edi      push  edi
                 mov esi,m1      mov esi,m1
                 mov edi,m2      mov edi,m2
                 mov ebx,mr      mov ebx,mr
                 mov ecx,d2      mov ecx,d2
                 xor     eax,eax      xor  eax,eax
                 Lstart_subn:      Lstart_subn:
                 mov eax,DWORD PTR [esi]      mov eax,DWORD PTR [esi]
                 mov edx,DWORD PTR [edi]      mov edx,DWORD PTR [edi]
                 sbb eax,edx      sbb eax,edx
                 mov DWORD PTR [ebx],eax      mov DWORD PTR [ebx],eax
                 lea esi,DWORD PTR [esi+4]      lea esi,DWORD PTR [esi+4]
                 lea edi,DWORD PTR [edi+4]      lea edi,DWORD PTR [edi+4]
                 lea ebx,DWORD PTR [ebx+4]      lea ebx,DWORD PTR [ebx+4]
                 dec ecx      dec ecx
                 jnz Lstart_subn      jnz Lstart_subn
                 pop     edi      pop  edi
                 pop     esi      pop  esi
                 mov eax,0      mov eax,0
                 adc eax,eax      adc eax,eax
                 mov br,eax      mov br,eax
                 }      }
 #else  #else
                 asm volatile("\      asm volatile("\
                 pushl   %%ebx;\      pushl  %%ebx;\
                 movl    %1,%%esi;\      movl  %1,%%esi;\
                 movl    %2,%%edi;\      movl  %2,%%edi;\
                 movl    %3,%%ebx;\      movl  %3,%%ebx;\
                 movl    %4,%%ecx;\      movl  %4,%%ecx;\
                 testl   %%eax,%%eax;\      testl  %%eax,%%eax;\
                 Lstart_subn:;\      Lstart_subn:;\
                 movl    (%%esi),%%eax;\      movl  (%%esi),%%eax;\
                 movl    (%%edi),%%edx;\      movl  (%%edi),%%edx;\
                 sbbl    %%edx,%%eax;\      sbbl  %%edx,%%eax;\
                 movl    %%eax,(%%ebx);\      movl  %%eax,(%%ebx);\
                 leal    4(%%esi),%%esi;\      leal  4(%%esi),%%esi;\
                 leal    4(%%edi),%%edi;\      leal  4(%%edi),%%edi;\
                 leal    4(%%ebx),%%ebx;\      leal  4(%%ebx),%%ebx;\
                 decl    %%ecx;\      decl  %%ecx;\
                 jnz Lstart_subn;\      jnz Lstart_subn;\
                 movl    $0,%%eax;\      movl  $0,%%eax;\
                 adcl    %%eax,%%eax;\      adcl  %%eax,%%eax;\
                 movl    %%eax,%0;\      movl  %%eax,%0;\
                 popl    %%ebx"\      popl  %%ebx"\
                 :"=m"(br)\      :"=m"(br)\
                 :"m"(m1),"m"(m2),"m"(mr),"m"(d2)\      :"m"(m1),"m"(m2),"m"(mr),"m"(d2)\
                 :"eax","ecx","edx","esi","edi");      :"eax","ecx","edx","esi","edi");
 #endif  #endif
                 for ( i = d2, m1 += d2, mr += d2; (i < d1) && br; i++ ) {      for ( i = d2, m1 += d2, mr += d2; (i < d1) && br; i++ ) {
                         t = *m1++;        t = *m1++;
                         tmp = t - br;        tmp = t - br;
                         br = tmp > t ? 1 : 0;        br = tmp > t ? 1 : 0;
                         *mr++ = tmp;        *mr++ = tmp;
                 }      }
                 for ( ; i < d1; i++ )      for ( ; i < d1; i++ )
                         *mr++ = *m1++;        *mr++ = *m1++;
                 for ( i = d1-1, mr--; i >= 0 && !*mr--; i-- );      for ( i = d1-1, mr--; i >= 0 && !*mr--; i-- );
                 PL(r) = i + 1;      PL(r) = i + 1;
                 return sgn;      return sgn;
         }    }
 }  }
   
 void _addn(N n1,N n2,N nr)  void _addn(N n1,N n2,N nr)
 {  {
         unsigned int *m1,*m2,*mr;    unsigned int *m1,*m2,*mr;
         unsigned int c;    unsigned int c;
         int i,d1,d2;    int i,d1,d2;
         unsigned int tmp;    unsigned int tmp;
   
         if ( !n1 || !PL(n1) )    if ( !n1 || !PL(n1) )
                 dupn(n2,nr);      dupn(n2,nr);
         else if ( !n2 || !PL(n2) )    else if ( !n2 || !PL(n2) )
                 dupn(n1,nr);      dupn(n1,nr);
         else {    else {
                 if ( PL(n1) > PL(n2) ) {      if ( PL(n1) > PL(n2) ) {
                         d1 = PL(n1); d2 = PL(n2); m1 = BD(n1); m2 = BD(n2);        d1 = PL(n1); d2 = PL(n2); m1 = BD(n1); m2 = BD(n2);
                 } else {      } else {
                         d1 = PL(n2); d2 = PL(n1); m1 = BD(n2); m2 = BD(n1);        d1 = PL(n2); d2 = PL(n1); m1 = BD(n2); m2 = BD(n1);
                 }      }
                 mr = BD(nr);      mr = BD(nr);
   
 #if defined(_M_IX86)  #if defined(_M_IX86)
                 __asm {      __asm {
                 push    esi      push  esi
                 push    edi      push  edi
                 mov esi,m1      mov esi,m1
                 mov edi,m2      mov edi,m2
                 mov ebx,mr      mov ebx,mr
                 mov ecx,d2      mov ecx,d2
                 xor     eax,eax      xor  eax,eax
                 Lstart__addn:      Lstart__addn:
                 mov eax,DWORD PTR [esi]      mov eax,DWORD PTR [esi]
                 mov edx,DWORD PTR [edi]      mov edx,DWORD PTR [edi]
                 adc eax,edx      adc eax,edx
                 mov DWORD PTR [ebx],eax      mov DWORD PTR [ebx],eax
                 lea esi,DWORD PTR [esi+4]      lea esi,DWORD PTR [esi+4]
                 lea edi,DWORD PTR [edi+4]      lea edi,DWORD PTR [edi+4]
                 lea ebx,DWORD PTR [ebx+4]      lea ebx,DWORD PTR [ebx+4]
                 dec ecx      dec ecx
                 jnz Lstart__addn      jnz Lstart__addn
                 pop     edi      pop  edi
                 pop     esi      pop  esi
                 mov eax,0      mov eax,0
                 adc eax,eax      adc eax,eax
                 mov c,eax      mov c,eax
                 }      }
 #else  #else
                 asm volatile("\      asm volatile("\
                 pushl   %%ebx;\      pushl  %%ebx;\
                 movl    %1,%%esi;\      movl  %1,%%esi;\
                 movl    %2,%%edi;\      movl  %2,%%edi;\
                 movl    %3,%%ebx;\      movl  %3,%%ebx;\
                 movl    %4,%%ecx;\      movl  %4,%%ecx;\
                 testl   %%eax,%%eax;\      testl  %%eax,%%eax;\
                 Lstart__addn:;\      Lstart__addn:;\
                 movl    (%%esi),%%eax;\      movl  (%%esi),%%eax;\
                 movl    (%%edi),%%edx;\      movl  (%%edi),%%edx;\
                 adcl    %%edx,%%eax;\      adcl  %%edx,%%eax;\
                 movl    %%eax,(%%ebx);\      movl  %%eax,(%%ebx);\
                 leal    4(%%esi),%%esi;\      leal  4(%%esi),%%esi;\
                 leal    4(%%edi),%%edi;\      leal  4(%%edi),%%edi;\
                 leal    4(%%ebx),%%ebx;\      leal  4(%%ebx),%%ebx;\
                 decl    %%ecx;\      decl  %%ecx;\
                 jnz Lstart__addn;\      jnz Lstart__addn;\
                 movl    $0,%%eax;\      movl  $0,%%eax;\
                 adcl    %%eax,%%eax;\      adcl  %%eax,%%eax;\
                 movl    %%eax,%0;\      movl  %%eax,%0;\
                 popl    %%ebx"\      popl  %%ebx"\
                 :"=m"(c)\      :"=m"(c)\
                 :"m"(m1),"m"(m2),"m"(mr),"m"(d2)\      :"m"(m1),"m"(m2),"m"(mr),"m"(d2)\
                 :"eax","ecx","edx","esi","edi");      :"eax","ecx","edx","esi","edi");
 #endif  #endif
                 for ( i = d2, m1 += d2, mr += d2; (i < d1) && c ; i++ ) {      for ( i = d2, m1 += d2, mr += d2; (i < d1) && c ; i++ ) {
                         tmp = *m1++ + c;        tmp = *m1++ + c;
                         c = tmp < c ? 1 : 0;        c = tmp < c ? 1 : 0;
                         *mr++ = tmp;        *mr++ = tmp;
                 }      }
                 for ( ; i < d1; i++ )      for ( ; i < d1; i++ )
                         *mr++ = *m1++;        *mr++ = *m1++;
                 *mr = c;      *mr = c;
                 PL(nr) = (c?d1+1:d1);      PL(nr) = (c?d1+1:d1);
         }    }
 }  }
   
 int _subn(N n1,N n2,N nr)  int _subn(N n1,N n2,N nr)
 {  {
         unsigned int *m1,*m2,*mr,br;    unsigned int *m1,*m2,*mr,br;
         unsigned int tmp,t;    unsigned int tmp,t;
         int d1,d2,sgn,i;    int d1,d2,sgn,i;
   
         if ( !n1 || !PL(n1) ) {    if ( !n1 || !PL(n1) ) {
                 if ( n2 && PL(n2) ) {      if ( n2 && PL(n2) ) {
                         dupn(n2,nr);        dupn(n2,nr);
                         return -1;        return -1;
                 } else {      } else {
                         PL(nr) = 0;        PL(nr) = 0;
                         return 0;        return 0;
                 }      }
         } else if ( !n2 || !PL(n2) ) {    } else if ( !n2 || !PL(n2) ) {
                 dupn(n1,nr);      dupn(n1,nr);
                 return 1;      return 1;
         } else {    } else {
                 d1 = PL(n1); d2 = PL(n2);      d1 = PL(n1); d2 = PL(n2);
                 m1 = BD(n1); m2 = BD(n2);      m1 = BD(n1); m2 = BD(n2);
                 if ( (d1 = PL(n1)) > (d2 = PL(n2)) )      if ( (d1 = PL(n1)) > (d2 = PL(n2)) )
                         sgn = 1;        sgn = 1;
                 else if ( d1 < d2 ) {      else if ( d1 < d2 ) {
                         d1 = PL(n2); d2 = PL(n1);        d1 = PL(n2); d2 = PL(n1);
                         m1 = BD(n2); m2 = BD(n1);        m1 = BD(n2); m2 = BD(n1);
                         sgn = -1;        sgn = -1;
                 } else {      } else {
                         for ( i = d1-1; i >= 0 && m1[i] == m2[i]; i-- );        for ( i = d1-1; i >= 0 && m1[i] == m2[i]; i-- );
                         if ( i < 0 ) {        if ( i < 0 ) {
                                 PL(nr) = 0;          PL(nr) = 0;
                                 return 0;          return 0;
                         }        }
                         d1 = d2 = i+1;        d1 = d2 = i+1;
                         if ( m1[i] > m2[i] )        if ( m1[i] > m2[i] )
                                 sgn = 1;          sgn = 1;
                         else {        else {
                                 m1 = BD(n2); m2 = BD(n1);          m1 = BD(n2); m2 = BD(n1);
                                 sgn = -1;          sgn = -1;
                         }        }
                 }      }
                 mr = BD(nr);      mr = BD(nr);
   
 #if defined(_M_IX86)  #if defined(_M_IX86)
                 __asm {      __asm {
                 push    esi      push  esi
                 push    edi      push  edi
                 mov esi,m1      mov esi,m1
                 mov edi,m2      mov edi,m2
                 mov ebx,mr      mov ebx,mr
                 mov ecx,d2      mov ecx,d2
                 xor     eax,eax      xor  eax,eax
                 Lstart__subn:      Lstart__subn:
                 mov eax,DWORD PTR [esi]      mov eax,DWORD PTR [esi]
                 mov edx,DWORD PTR [edi]      mov edx,DWORD PTR [edi]
                 sbb eax,edx      sbb eax,edx
                 mov DWORD PTR [ebx],eax      mov DWORD PTR [ebx],eax
                 lea esi,DWORD PTR [esi+4]      lea esi,DWORD PTR [esi+4]
                 lea edi,DWORD PTR [edi+4]      lea edi,DWORD PTR [edi+4]
                 lea ebx,DWORD PTR [ebx+4]      lea ebx,DWORD PTR [ebx+4]
                 dec ecx      dec ecx
                 jnz Lstart__subn      jnz Lstart__subn
                 pop     edi      pop  edi
                 pop     esi      pop  esi
                 mov eax,0      mov eax,0
                 adc eax,eax      adc eax,eax
                 mov br,eax      mov br,eax
                 }      }
 #else  #else
                 asm volatile("\      asm volatile("\
                 pushl   %%ebx;\      pushl  %%ebx;\
                 movl    %1,%%esi;\      movl  %1,%%esi;\
                 movl    %2,%%edi;\      movl  %2,%%edi;\
                 movl    %3,%%ebx;\      movl  %3,%%ebx;\
                 movl    %4,%%ecx;\      movl  %4,%%ecx;\
                 testl   %%eax,%%eax;\      testl  %%eax,%%eax;\
                 Lstart__subn:;\      Lstart__subn:;\
                 movl    (%%esi),%%eax;\      movl  (%%esi),%%eax;\
                 movl    (%%edi),%%edx;\      movl  (%%edi),%%edx;\
                 sbbl    %%edx,%%eax;\      sbbl  %%edx,%%eax;\
                 movl    %%eax,(%%ebx);\      movl  %%eax,(%%ebx);\
                 leal    4(%%esi),%%esi;\      leal  4(%%esi),%%esi;\
                 leal    4(%%edi),%%edi;\      leal  4(%%edi),%%edi;\
                 leal    4(%%ebx),%%ebx;\      leal  4(%%ebx),%%ebx;\
                 decl    %%ecx;\      decl  %%ecx;\
                 jnz Lstart__subn;\      jnz Lstart__subn;\
                 movl    $0,%%eax;\      movl  $0,%%eax;\
                 adcl    %%eax,%%eax;\      adcl  %%eax,%%eax;\
                 movl    %%eax,%0;\      movl  %%eax,%0;\
                 popl    %%ebx"\      popl  %%ebx"\
                 :"=m"(br)\      :"=m"(br)\
                 :"m"(m1),"m"(m2),"m"(mr),"m"(d2)\      :"m"(m1),"m"(m2),"m"(mr),"m"(d2)\
                 :"eax","ecx","edx","esi","edi");      :"eax","ecx","edx","esi","edi");
 #endif  #endif
                 for ( i = d2, m1 += d2, mr += d2; (i < d1) && br; i++ ) {      for ( i = d2, m1 += d2, mr += d2; (i < d1) && br; i++ ) {
                         t = *m1++;        t = *m1++;
                         tmp = t - br;        tmp = t - br;
                         br = tmp > t ? 1 : 0;        br = tmp > t ? 1 : 0;
                         *mr++ = tmp;        *mr++ = tmp;
                 }      }
                 for ( ; i < d1; i++ )      for ( ; i < d1; i++ )
                         *mr++ = *m1++;        *mr++ = *m1++;
                 for ( i = d1-1, mr--; i >= 0 && !*mr--; i-- );      for ( i = d1-1, mr--; i >= 0 && !*mr--; i-- );
                 PL(nr) = i + 1;      PL(nr) = i + 1;
                 return sgn;      return sgn;
         }    }
 }  }
 #else  #else
   
 void addn(N n1,N n2,N *nr)  void addn(N n1,N n2,N *nr)
 {  {
         unsigned int *m1,*m2,*mr,i,c;    unsigned int *m1,*m2,*mr,i,c;
         N r;    N r;
         int d1,d2;    int d1,d2;
         unsigned int tmp;    unsigned int tmp;
   
         if ( !n1 )    if ( !n1 )
                 COPY(n2,*nr);      COPY(n2,*nr);
         else if ( !n2 )    else if ( !n2 )
                 COPY(n1,*nr);      COPY(n1,*nr);
         else {    else {
                 if ( PL(n1) > PL(n2) ) {      if ( PL(n1) > PL(n2) ) {
                         d1 = PL(n1); d2 = PL(n2); m1 = BD(n1); m2 = BD(n2);        d1 = PL(n1); d2 = PL(n2); m1 = BD(n1); m2 = BD(n2);
                 } else {      } else {
                         d1 = PL(n2); d2 = PL(n1); m1 = BD(n2); m2 = BD(n1);        d1 = PL(n2); d2 = PL(n1); m1 = BD(n2); m2 = BD(n1);
                 }      }
                 *nr = r = NALLOC(d1 + 1); INITRC(r);      *nr = r = NALLOC(d1 + 1); INITRC(r);
                 for ( i = 0, c = 0, mr = BD(r); i < d2; i++, m1++, m2++, mr++ ) {      for ( i = 0, c = 0, mr = BD(r); i < d2; i++, m1++, m2++, mr++ ) {
                         tmp = *m1 + *m2;        tmp = *m1 + *m2;
                         if ( tmp < *m1 ) {        if ( tmp < *m1 ) {
                                 tmp += c;          tmp += c;
                                 c = 1;          c = 1;
                         } else {        } else {
                                 tmp += c;          tmp += c;
                                 c = tmp < c ? 1 : 0;          c = tmp < c ? 1 : 0;
                         }        }
                         *mr = tmp;        *mr = tmp;
                 }      }
                 for ( ; (i < d1) && c ; i++, m1++, mr++ ) {      for ( ; (i < d1) && c ; i++, m1++, mr++ ) {
                         tmp = *m1 + c;        tmp = *m1 + c;
                         c = tmp < c ? 1 : 0;        c = tmp < c ? 1 : 0;
                         *mr = tmp;        *mr = tmp;
                 }      }
                 for ( ; i < d1; i++ )      for ( ; i < d1; i++ )
                         *mr++ = *m1++;        *mr++ = *m1++;
                 *mr = c;      *mr = c;
                 PL(r) = (c?d1+1:d1);      PL(r) = (c?d1+1:d1);
         }    }
 }  }
   
 int subn(N n1,N n2,N *nr)  int subn(N n1,N n2,N *nr)
 {  {
         N r;    N r;
         unsigned int *m1,*m2,*mr,i,br;    unsigned int *m1,*m2,*mr,i,br;
         L tmp;    L tmp;
         int d1,d2,nz,sgn;    int d1,d2,nz,sgn;
   
         if ( !n1 ) {    if ( !n1 ) {
                 if ( n2 ) {      if ( n2 ) {
                         COPY(n2,*nr);        COPY(n2,*nr);
                         return -1;        return -1;
                 } else {      } else {
                         *nr = 0;        *nr = 0;
                         return 0;        return 0;
                 }      }
         } else if ( !n2 ) {    } else if ( !n2 ) {
                 COPY(n1,*nr);      COPY(n1,*nr);
                 return 1;      return 1;
         } else {    } else {
                 switch ( cmpn(n1,n2) ) {      switch ( cmpn(n1,n2) ) {
                         case 1:        case 1:
                                 d1 = PL(n1); d2 = PL(n2); m1 = BD(n1); m2 = BD(n2);          d1 = PL(n1); d2 = PL(n2); m1 = BD(n1); m2 = BD(n2);
                                 sgn = 1; break;          sgn = 1; break;
                         case -1:        case -1:
                                 d1 = PL(n2); d2 = PL(n1); m1 = BD(n2); m2 = BD(n1);          d1 = PL(n2); d2 = PL(n1); m1 = BD(n2); m2 = BD(n1);
                                 sgn = -1; break;          sgn = -1; break;
                         case 0:        case 0:
                         default:        default:
                                 *nr = 0; return ( 0 ); break;          *nr = 0; return ( 0 ); break;
                 }      }
                 *nr = r = NALLOC(d1); INITRC(r);      *nr = r = NALLOC(d1); INITRC(r);
                 for ( i = 0, br = 0, nz = -1, mr = BD(r);      for ( i = 0, br = 0, nz = -1, mr = BD(r);
                         i < d2; i++ ) {        i < d2; i++ ) {
                         if ( (tmp = (L)*m1++ - (L)*m2++ - (L)br) && ( tmp > -LBASE ) )        if ( (tmp = (L)*m1++ - (L)*m2++ - (L)br) && ( tmp > -LBASE ) )
                                 nz = i;          nz = i;
                         if ( tmp < 0 ) {        if ( tmp < 0 ) {
                                 br = 1; *mr++ = (unsigned int)(tmp + LBASE);          br = 1; *mr++ = (unsigned int)(tmp + LBASE);
                         } else {        } else {
                                 br = 0; *mr++ = (unsigned int)tmp;          br = 0; *mr++ = (unsigned int)tmp;
                         }        }
                 }      }
                 for ( ; (i < d1) && br; i++ ) {      for ( ; (i < d1) && br; i++ ) {
                         if ( (tmp = (L)*m1++ - (L)br) && ( tmp > -LBASE ) )        if ( (tmp = (L)*m1++ - (L)br) && ( tmp > -LBASE ) )
                                 nz = i;          nz = i;
                         if ( tmp < 0 ) {        if ( tmp < 0 ) {
                                 br = 1; *mr++ = (unsigned int)(tmp + LBASE);          br = 1; *mr++ = (unsigned int)(tmp + LBASE);
                         } else {        } else {
                                 br = 0; *mr++ = (unsigned int)tmp;          br = 0; *mr++ = (unsigned int)tmp;
                         }        }
                 }      }
                 for ( ; i < d1; i++ )      for ( ; i < d1; i++ )
                         if ( *mr++ = *m1++ )        if ( *mr++ = *m1++ )
                                 nz = i;          nz = i;
                 PL(r) = nz + 1;      PL(r) = nz + 1;
                 return sgn;      return sgn;
         }    }
 }  }
   
 void _addn(N n1,N n2,N nr)  void _addn(N n1,N n2,N nr)
 {  {
         unsigned int *m1,*m2,*mr,i,c;    unsigned int *m1,*m2,*mr,i,c;
         int d1,d2;    int d1,d2;
         unsigned int tmp;    unsigned int tmp;
   
         if ( !n1 || !PL(n1) )    if ( !n1 || !PL(n1) )
                 dupn(n2,nr);      dupn(n2,nr);
         else if ( !n2 || !PL(n2) )    else if ( !n2 || !PL(n2) )
                 dupn(n1,nr);      dupn(n1,nr);
         else {    else {
                 if ( PL(n1) > PL(n2) ) {      if ( PL(n1) > PL(n2) ) {
                         d1 = PL(n1); d2 = PL(n2); m1 = BD(n1); m2 = BD(n2);        d1 = PL(n1); d2 = PL(n2); m1 = BD(n1); m2 = BD(n2);
                 } else {      } else {
                         d1 = PL(n2); d2 = PL(n1); m1 = BD(n2); m2 = BD(n1);        d1 = PL(n2); d2 = PL(n1); m1 = BD(n2); m2 = BD(n1);
                 }      }
                 for ( i = 0, c = 0, mr = BD(nr); i < d2; i++, m1++, m2++, mr++ ) {      for ( i = 0, c = 0, mr = BD(nr); i < d2; i++, m1++, m2++, mr++ ) {
                         tmp = *m1 + *m2;        tmp = *m1 + *m2;
                         if ( tmp < *m1 ) {        if ( tmp < *m1 ) {
                                 tmp += c;          tmp += c;
                                 c = 1;          c = 1;
                         } else {        } else {
                                 tmp += c;          tmp += c;
                                 c = tmp < c ? 1 : 0;          c = tmp < c ? 1 : 0;
                         }        }
                         *mr = tmp;        *mr = tmp;
                 }      }
                 for ( ; (i < d1) && c ; i++, m1++, mr++ ) {      for ( ; (i < d1) && c ; i++, m1++, mr++ ) {
                         tmp = *m1 + c;        tmp = *m1 + c;
                         c = tmp < c ? 1 : 0;        c = tmp < c ? 1 : 0;
                         *mr = tmp;        *mr = tmp;
                 }      }
                 for ( ; i < d1; i++ )      for ( ; i < d1; i++ )
                         *mr++ = *m1++;        *mr++ = *m1++;
                 *mr = c;      *mr = c;
                 PL(nr) = (c?d1+1:d1);      PL(nr) = (c?d1+1:d1);
         }    }
 }  }
   
 int _subn(N n1,N n2,N nr)  int _subn(N n1,N n2,N nr)
 {  {
         N r;    N r;
         unsigned int *m1,*m2,*mr,i,br;    unsigned int *m1,*m2,*mr,i,br;
         L tmp;    L tmp;
         int d1,d2,nz,sgn;    int d1,d2,nz,sgn;
   
         if ( !n1 || !PL(n1) ) {    if ( !n1 || !PL(n1) ) {
                 if ( n2 && PL(n2) ) {      if ( n2 && PL(n2) ) {
                         dupn(n2,nr);        dupn(n2,nr);
                         return -1;        return -1;
                 } else {      } else {
                         PL(nr) = 0;        PL(nr) = 0;
                         return 0;        return 0;
                 }      }
         } else if ( !n2 || !PL(n2) ) {    } else if ( !n2 || !PL(n2) ) {
                 dupn(n1,nr);      dupn(n1,nr);
                 return 1;      return 1;
         } else {    } else {
                 switch ( cmpn(n1,n2) ) {      switch ( cmpn(n1,n2) ) {
                         case 1:        case 1:
                                 d1 = PL(n1); d2 = PL(n2); m1 = BD(n1); m2 = BD(n2);          d1 = PL(n1); d2 = PL(n2); m1 = BD(n1); m2 = BD(n2);
                                 sgn = 1; break;          sgn = 1; break;
                         case -1:        case -1:
                                 d1 = PL(n2); d2 = PL(n1); m1 = BD(n2); m2 = BD(n1);          d1 = PL(n2); d2 = PL(n1); m1 = BD(n2); m2 = BD(n1);
                                 sgn = -1; break;          sgn = -1; break;
                         case 0:        case 0:
                         default:        default:
                                 PL(nr) = 0; return ( 0 ); break;          PL(nr) = 0; return ( 0 ); break;
                 }      }
                 for ( i = 0, br = 0, nz = -1, mr = BD(nr);      for ( i = 0, br = 0, nz = -1, mr = BD(nr);
                         i < d2; i++ ) {        i < d2; i++ ) {
                         if ( (tmp = (L)*m1++ - (L)*m2++ - (L)br) && ( tmp > -LBASE ) )        if ( (tmp = (L)*m1++ - (L)*m2++ - (L)br) && ( tmp > -LBASE ) )
                                 nz = i;          nz = i;
                         if ( tmp < 0 ) {        if ( tmp < 0 ) {
                                 br = 1; *mr++ = (unsigned int)(tmp + LBASE);          br = 1; *mr++ = (unsigned int)(tmp + LBASE);
                         } else {        } else {
                                 br = 0; *mr++ = (unsigned int)tmp;          br = 0; *mr++ = (unsigned int)tmp;
                         }        }
                 }      }
                 for ( ; (i < d1) && br; i++ ) {      for ( ; (i < d1) && br; i++ ) {
                         if ( (tmp = (L)*m1++ - (L)br) && ( tmp > -LBASE ) )        if ( (tmp = (L)*m1++ - (L)br) && ( tmp > -LBASE ) )
                                 nz = i;          nz = i;
                         if ( tmp < 0 ) {        if ( tmp < 0 ) {
                                 br = 1; *mr++ = (unsigned int)(tmp + LBASE);          br = 1; *mr++ = (unsigned int)(tmp + LBASE);
                         } else {        } else {
                                 br = 0; *mr++ = (unsigned int)tmp;          br = 0; *mr++ = (unsigned int)tmp;
                         }        }
                 }      }
                 for ( ; i < d1; i++ )      for ( ; i < d1; i++ )
                         if ( *mr++ = *m1++ )        if ( *mr++ = *m1++ )
                                 nz = i;          nz = i;
                 PL(nr) = nz + 1;      PL(nr) = nz + 1;
                 return sgn;      return sgn;
         }    }
 }  }
 #endif  #endif
   
Line 632  int _subn(N n1,N n2,N nr)
Line 632  int _subn(N n1,N n2,N nr)
   
 void addarray_to(unsigned int *a1,int n1,unsigned int *a2,int n2)  void addarray_to(unsigned int *a1,int n1,unsigned int *a2,int n2)
 {  {
         int i;    int i;
         unsigned int c,tmp;    unsigned int c,tmp;
   
         for ( i = 0, c = 0; i < n2; i++, a1++, a2++ ) {    for ( i = 0, c = 0; i < n2; i++, a1++, a2++ ) {
                 tmp = *a1 + *a2;      tmp = *a1 + *a2;
                 if ( tmp < *a1 ) {      if ( tmp < *a1 ) {
                         tmp += c;        tmp += c;
                         c = 1;        c = 1;
                 } else {      } else {
                         tmp += c;        tmp += c;
                         c = tmp < c ? 1 : 0;        c = tmp < c ? 1 : 0;
                 }      }
                 *a2 = tmp;      *a2 = tmp;
         }    }
         for ( ; (i < n2) && c ; i++, a2++ ) {    for ( ; (i < n2) && c ; i++, a2++ ) {
                 tmp = *a2 + c;      tmp = *a2 + c;
                 c = tmp < c ? 1 : 0;      c = tmp < c ? 1 : 0;
                 *a2 = tmp;      *a2 = tmp;
         }    }
         if ( i == n2 && c )    if ( i == n2 && c )
                 *a2 = c;      *a2 = c;
 }  }
   
 void pwrn(N n,int e,N *nr)  void pwrn(N n,int e,N *nr)
 {  {
         N nw,nw1;    N nw,nw1;
   
         if ( e == 1 ) {    if ( e == 1 ) {
                 COPY(n,*nr);      COPY(n,*nr);
                 return;      return;
         }    }
         pwrn(n,e / 2,&nw);    pwrn(n,e / 2,&nw);
         if ( e % 2 == 0 )    if ( e % 2 == 0 )
                 kmuln(nw,nw,nr);      kmuln(nw,nw,nr);
         else {    else {
                 kmuln(nw,nw,&nw1); kmuln(nw1,n,nr); FREEN(nw1);      kmuln(nw,nw,&nw1); kmuln(nw1,n,nr); FREEN(nw1);
         }    }
         FREEN(nw);    FREEN(nw);
 }  }
   
   
Line 680  void gcdEuclidn(), gcdn_HMEXT();
Line 680  void gcdEuclidn(), gcdn_HMEXT();
   
 void lcmn(N n1,N n2,N *nr)  void lcmn(N n1,N n2,N *nr)
 {  {
         N g,t;    N g,t;
   
         gcdn(n1,n2,&g);    gcdn(n1,n2,&g);
         divsn(n1,g,&t);    divsn(n1,g,&t);
         muln(t,n2,nr);    muln(t,n2,nr);
 }  }
   
 void gcdn(N n1,N n2,N *nr)  void gcdn(N n1,N n2,N *nr)
 {  {
         if ( !igcd_algorithm )    if ( !igcd_algorithm )
                 gcdEuclidn(n1,n2,nr);      gcdEuclidn(n1,n2,nr);
         else {    else {
                 gcdn_HMEXT(n1,n2,nr);      gcdn_HMEXT(n1,n2,nr);
         }    }
 }  }
   
 #include "Ngcd.c"  #include "Ngcd.c"
   
 void gcdEuclidn(N n1,N n2,N *nr)  void gcdEuclidn(N n1,N n2,N *nr)
 {  {
         N m1,m2,q,r;    N m1,m2,q,r;
         unsigned int i1,i2,ir;    unsigned int i1,i2,ir;
   
         if ( !n1 )    if ( !n1 )
                 COPY(n2,*nr);      COPY(n2,*nr);
         else if ( !n2 )    else if ( !n2 )
                 COPY(n1,*nr);      COPY(n1,*nr);
         else {    else {
                 if ( PL(n1) > PL(n2) ) {      if ( PL(n1) > PL(n2) ) {
                         COPY(n1,m1); COPY(n2,m2);        COPY(n1,m1); COPY(n2,m2);
                 } else {      } else {
                         COPY(n1,m2); COPY(n2,m1);        COPY(n1,m2); COPY(n2,m1);
                 }      }
                 while ( PL(m1) > 1 ) {      while ( PL(m1) > 1 ) {
                         divn(m1,m2,&q,&r); FREEN(m1); FREEN(q);        divn(m1,m2,&q,&r); FREEN(m1); FREEN(q);
                         if ( !r ) {        if ( !r ) {
                                 *nr = m2;          *nr = m2;
                                 return;          return;
                         } else {        } else {
                                 m1 = m2; m2 = r;          m1 = m2; m2 = r;
                         }        }
                 }      }
                 for ( i1 = BD(m1)[0], i2 = BD(m2)[0]; ir = i1 % i2; i2 = ir )      for ( i1 = BD(m1)[0], i2 = BD(m2)[0]; ir = i1 % i2; i2 = ir )
                         i1 = i2;        i1 = i2;
                 if ( i2 == 1 )      if ( i2 == 1 )
                         COPY(ONEN,*nr);        COPY(ONEN,*nr);
                 else {      else {
                         *nr = r = NALLOC(1); INITRC(r); PL(r) = 1; BD(r)[0] = i2;        *nr = r = NALLOC(1); INITRC(r); PL(r) = 1; BD(r)[0] = i2;
                 }      }
         }    }
 }  }
   
 int cmpn(N n1,N n2)  int cmpn(N n1,N n2)
 {  {
         int i;    int i;
         unsigned int *m1,*m2;    unsigned int *m1,*m2;
   
         if ( !n1 )    if ( !n1 )
                 if ( !n2 )      if ( !n2 )
                         return 0;        return 0;
                 else      else
                         return -1;        return -1;
         else if ( !n2 )    else if ( !n2 )
                 return 1;      return 1;
         else if ( PL(n1) > PL(n2) )    else if ( PL(n1) > PL(n2) )
                 return 1;      return 1;
         else if ( PL(n1) < PL(n2) )    else if ( PL(n1) < PL(n2) )
                 return -1;      return -1;
         else {    else {
                 for ( i = PL(n1)-1, m1 = BD(n1)+i, m2 = BD(n2)+i;      for ( i = PL(n1)-1, m1 = BD(n1)+i, m2 = BD(n2)+i;
                         i >= 0; i--, m1--, m2-- )        i >= 0; i--, m1--, m2-- )
                         if ( *m1 > *m2 )        if ( *m1 > *m2 )
                                 return 1;          return 1;
                         else if ( *m1 < *m2 )        else if ( *m1 < *m2 )
                                 return -1;          return -1;
                 return 0;      return 0;
         }    }
 }  }
   
 void bshiftn(N n,int b,N *r)  void bshiftn(N n,int b,N *r)
 {  {
         int w,l,nl,i,j;    int w,l,nl,i,j;
         N z;    N z;
         unsigned int msw;    unsigned int msw;
         unsigned int *p,*pz;    unsigned int *p,*pz;
   
         if ( b == 0 ) {    if ( b == 0 ) {
                 COPY(n,*r); return;      COPY(n,*r); return;
         }    }
         if ( b > 0 ) { /* >> */    if ( b > 0 ) { /* >> */
                 w = b / BSH; l = PL(n)-w;      w = b / BSH; l = PL(n)-w;
                 if ( l <= 0 ) {      if ( l <= 0 ) {
                         *r = 0; return;        *r = 0; return;
                 }      }
                 b %= BSH; p = BD(n)+w;      b %= BSH; p = BD(n)+w;
                 if ( !b ) {      if ( !b ) {
                         *r = z = NALLOC(l); INITRC(z); PL(z) = l;        *r = z = NALLOC(l); INITRC(z); PL(z) = l;
                         bcopy(p,BD(z),l*sizeof(unsigned int));        bcopy(p,BD(z),l*sizeof(unsigned int));
                         return;        return;
                 }      }
                 msw = p[l-1];      msw = p[l-1];
                 for ( i = BSH-1; !(msw&(((unsigned int)1)<<i)); i-- ); i++;      for ( i = BSH-1; !(msw&(((unsigned int)1)<<i)); i-- ); i++;
                 if ( b >= i ) {      if ( b >= i ) {
                         l--;        l--;
                         if ( !l ) {        if ( !l ) {
                                 *r = 0; return;          *r = 0; return;
                         }        }
                         *r = z = NALLOC(l); INITRC(z); PL(z) = l; pz = BD(z);        *r = z = NALLOC(l); INITRC(z); PL(z) = l; pz = BD(z);
                         for ( j = 0; j < l; j++, p++ )        for ( j = 0; j < l; j++, p++ )
                                 *pz++ = (*(p+1)<<(BSH-b))|(*p>>b);          *pz++ = (*(p+1)<<(BSH-b))|(*p>>b);
                 } else {      } else {
                         *r = z = NALLOC(l); INITRC(z); PL(z) = l; pz = BD(z);        *r = z = NALLOC(l); INITRC(z); PL(z) = l; pz = BD(z);
                         for ( j = 1; j < l; j++, p++ )        for ( j = 1; j < l; j++, p++ )
                                 *pz++ = (*(p+1)<<(BSH-b))|(*p>>b);          *pz++ = (*(p+1)<<(BSH-b))|(*p>>b);
                         *pz = *p>>b;        *pz = *p>>b;
                 }      }
         } else { /* << */    } else { /* << */
                 b = -b;      b = -b;
                 w = b / BSH; b %= BSH; l = PL(n); p = BD(n);      w = b / BSH; b %= BSH; l = PL(n); p = BD(n);
                 if ( !b ) {      if ( !b ) {
                         nl = l+w; *r = z = NALLOC(nl); INITRC(z); PL(z) = nl;        nl = l+w; *r = z = NALLOC(nl); INITRC(z); PL(z) = nl;
                         bzero((char *)BD(z),w*sizeof(unsigned int));        bzero((char *)BD(z),w*sizeof(unsigned int));
                         bcopy(p,BD(z)+w,l*sizeof(unsigned int));        bcopy(p,BD(z)+w,l*sizeof(unsigned int));
                         return;        return;
                 }      }
                 msw = p[l-1];      msw = p[l-1];
                 for ( i = BSH-1; !(msw&(((unsigned int)1)<<i)); i-- ); i++;      for ( i = BSH-1; !(msw&(((unsigned int)1)<<i)); i-- ); i++;
                 if ( b + i > BSH ) {      if ( b + i > BSH ) {
                         nl = l+w+1;        nl = l+w+1;
                         *r = z = NALLOC(nl); INITRC(z); PL(z) = nl; pz = BD(z)+w;        *r = z = NALLOC(nl); INITRC(z); PL(z) = nl; pz = BD(z)+w;
                         bzero((char *)BD(z),w*sizeof(unsigned int));        bzero((char *)BD(z),w*sizeof(unsigned int));
                         *pz++ = *p++<<b;        *pz++ = *p++<<b;
                         for ( j = 1; j < l; j++, p++ )        for ( j = 1; j < l; j++, p++ )
                                 *pz++ = (*p<<b)|(*(p-1)>>(BSH-b));          *pz++ = (*p<<b)|(*(p-1)>>(BSH-b));
                         *pz = *(p-1)>>(BSH-b);        *pz = *(p-1)>>(BSH-b);
                 } else {      } else {
                         nl = l+w;        nl = l+w;
                         *r = z = NALLOC(nl); INITRC(z); PL(z) = nl; pz = BD(z)+w;        *r = z = NALLOC(nl); INITRC(z); PL(z) = nl; pz = BD(z)+w;
                         bzero((char *)BD(z),w*sizeof(unsigned int));        bzero((char *)BD(z),w*sizeof(unsigned int));
                         *pz++ = *p++<<b;        *pz++ = *p++<<b;
                         for ( j = 1; j < l; j++, p++ )        for ( j = 1; j < l; j++, p++ )
                                 *pz++ = (*p<<b)|(*(p-1)>>(BSH-b));          *pz++ = (*p<<b)|(*(p-1)>>(BSH-b));
                 }      }
         }    }
 }  }
   
 #if 0  #if 0
 void _bshiftn(N n,int b,N z)  void _bshiftn(N n,int b,N z)
 {  {
         int w,l,nl,i,j;    int w,l,nl,i,j;
         unsigned int msw;    unsigned int msw;
         unsigned int *p,*pz;    unsigned int *p,*pz;
   
         if ( b == 0 ) {    if ( b == 0 ) {
                 copyn(n,PL(n),BD(z)); PL(z) = PL(n); return;      copyn(n,PL(n),BD(z)); PL(z) = PL(n); return;
         }    }
         if ( b > 0 ) { /* >> */    if ( b > 0 ) { /* >> */
                 w = b / BSH; l = PL(n)-w;      w = b / BSH; l = PL(n)-w;
                 if ( l <= 0 ) {      if ( l <= 0 ) {
                         PL(z) = 0; return;        PL(z) = 0; return;
                 }      }
                 b %= BSH; p = BD(n)+w;      b %= BSH; p = BD(n)+w;
                 if ( !b ) {      if ( !b ) {
                         PL(z) = l;        PL(z) = l;
                         bcopy(p,BD(z),l*sizeof(unsigned int));        bcopy(p,BD(z),l*sizeof(unsigned int));
                         return;        return;
                 }      }
                 msw = p[l-1];      msw = p[l-1];
                 for ( i = BSH-1; !(msw&(((unsigned int)1)<<i)); i-- ); i++;      for ( i = BSH-1; !(msw&(((unsigned int)1)<<i)); i-- ); i++;
                 if ( b >= i ) {      if ( b >= i ) {
                         l--;        l--;
                         if ( !l ) {        if ( !l ) {
                                 PL(z) = 0; return;          PL(z) = 0; return;
                         }        }
                         PL(z) = l; pz = BD(z);        PL(z) = l; pz = BD(z);
                         for ( j = 0; j < l; j++, p++ )        for ( j = 0; j < l; j++, p++ )
                                 *pz++ = (*(p+1)<<(BSH-b))|(*p>>b);          *pz++ = (*(p+1)<<(BSH-b))|(*p>>b);
                 } else {      } else {
                         PL(z) = l; pz = BD(z);        PL(z) = l; pz = BD(z);
                         for ( j = 1; j < l; j++, p++ )        for ( j = 1; j < l; j++, p++ )
                                 *pz++ = (*(p+1)<<(BSH-b))|(*p>>b);          *pz++ = (*(p+1)<<(BSH-b))|(*p>>b);
                         *pz = *p>>b;        *pz = *p>>b;
                 }      }
         } else { /* << */    } else { /* << */
                 b = -b;      b = -b;
                 w = b / BSH; b %= BSH; l = PL(n); p = BD(n);      w = b / BSH; b %= BSH; l = PL(n); p = BD(n);
                 if ( !b ) {      if ( !b ) {
                         nl = l+w; PL(z) = nl;        nl = l+w; PL(z) = nl;
                         bzero((char *)BD(z),w*sizeof(unsigned int));        bzero((char *)BD(z),w*sizeof(unsigned int));
                         bcopy(p,BD(z)+w,l*sizeof(unsigned int));        bcopy(p,BD(z)+w,l*sizeof(unsigned int));
                         return;        return;
                 }      }
                 msw = p[l-1];      msw = p[l-1];
                 for ( i = BSH-1; !(msw&(((unsigned int)1)<<i)); i-- ); i++;      for ( i = BSH-1; !(msw&(((unsigned int)1)<<i)); i-- ); i++;
                 if ( b + i > BSH ) {      if ( b + i > BSH ) {
                         nl = l+w+1;        nl = l+w+1;
                         PL(z) = nl; pz = BD(z)+w;        PL(z) = nl; pz = BD(z)+w;
                         bzero((char *)BD(z),w*sizeof(unsigned int));        bzero((char *)BD(z),w*sizeof(unsigned int));
                         *pz++ = *p++<<b;        *pz++ = *p++<<b;
                         for ( j = 1; j < l; j++, p++ )        for ( j = 1; j < l; j++, p++ )
                                 *pz++ = (*p<<b)|(*(p-1)>>(BSH-b));          *pz++ = (*p<<b)|(*(p-1)>>(BSH-b));
                         *pz = *(p-1)>>(BSH-b);        *pz = *(p-1)>>(BSH-b);
                 } else {      } else {
                         nl = l+w;        nl = l+w;
                         PL(z) = nl; pz = BD(z)+w;        PL(z) = nl; pz = BD(z)+w;
                         bzero((char *)BD(z),w*sizeof(unsigned int));        bzero((char *)BD(z),w*sizeof(unsigned int));
                         *pz++ = *p++<<b;        *pz++ = *p++<<b;
                         for ( j = 1; j < l; j++, p++ )        for ( j = 1; j < l; j++, p++ )
                                 *pz++ = (*p<<b)|(*(p-1)>>(BSH-b));          *pz++ = (*p<<b)|(*(p-1)>>(BSH-b));
                 }      }
         }    }
 }  }
 #endif  #endif
   
 void shiftn(N n,int w,N *r)  void shiftn(N n,int w,N *r)
 {  {
         int l,nl;    int l,nl;
         N z;    N z;
   
         if ( w == 0 )    if ( w == 0 )
                 COPY(n,*r);      COPY(n,*r);
         else if ( w > 0 ) { /* >> */    else if ( w > 0 ) { /* >> */
                 l = PL(n)-w;      l = PL(n)-w;
                 if ( l <= 0 )      if ( l <= 0 )
                         *r = 0;        *r = 0;
                 else {      else {
                         *r = z = NALLOC(l); INITRC(z); PL(z) = l;        *r = z = NALLOC(l); INITRC(z); PL(z) = l;
                         bcopy(BD(n)+w,BD(z),l*sizeof(unsigned int));        bcopy(BD(n)+w,BD(z),l*sizeof(unsigned int));
                 }      }
         } else { /* << */    } else { /* << */
                 w = -w;      w = -w;
                 l = PL(n); nl = l+w;      l = PL(n); nl = l+w;
                 *r = z = NALLOC(nl); INITRC(z); PL(z) = nl;      *r = z = NALLOC(nl); INITRC(z); PL(z) = nl;
                 bzero((char *)BD(z),w*sizeof(unsigned int));      bzero((char *)BD(z),w*sizeof(unsigned int));
                 bcopy(BD(n),BD(z)+w,l*sizeof(unsigned int));      bcopy(BD(n),BD(z)+w,l*sizeof(unsigned int));
         }    }
 }  }
   
 void randomn(int bits,N *r)  void randomn(int bits,N *r)
 {  {
         int l,i;    int l,i;
         unsigned int *tb;    unsigned int *tb;
         N t;    N t;
   
         l = (bits+31)>>5; /* word length */    l = (bits+31)>>5; /* word length */
         *r = t = NALLOC(l);    *r = t = NALLOC(l);
         tb = BD(t);    tb = BD(t);
         for ( i = 0; i < l; i++ )    for ( i = 0; i < l; i++ )
                 tb[i] = mt_genrand();      tb[i] = mt_genrand();
         if ( bits&31 )    if ( bits&31 )
                 tb[l-1] &= (1<<(bits&31))-1;      tb[l-1] &= (1<<(bits&31))-1;
         for ( i = l-1; i >= 0 && !tb[i]; i-- );    for ( i = l-1; i >= 0 && !tb[i]; i-- );
         if ( i < 0 )    if ( i < 0 )
                 *r = 0;      *r = 0;
         else    else
                 PL(t) = i+1;      PL(t) = i+1;
 }  }
   
 void freen(N n)  void freen(N n)
 {  {
         if ( n && (n != ONEN) )    if ( n && (n != ONEN) )
                 free(n);      free(n);
 }  }
   
 /* accepts Z */  /* accepts Z */
 int n_bits(N n)  int n_bits(N n)
 {  {
         unsigned int i,t;    unsigned int i,t;
         int l;    int l;
   
         if ( !n )    if ( !n )
                 return 0;      return 0;
         l = PL(n);    l = PL(n);
         if ( l < 0 ) l = -l;    if ( l < 0 ) l = -l;
         t = BD(n)[l-1];    t = BD(n)[l-1];
         for ( i = 0; t; t>>=1, i++);    for ( i = 0; t; t>>=1, i++);
         return i + (l-1)*BSH;    return i + (l-1)*BSH;
 }  }

Legend:
Removed from v.1.11  
changed lines
  Added in v.1.12

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>