Home | History | Annotate | Download | only in libyasm
      1 #include "util.h"
      2 
      3 #include "coretype.h"
      4 
      5 /*****************************************************************************/
      6 /*  MODULE NAME:  BitVector.c                           MODULE TYPE:  (adt)  */
      7 /*****************************************************************************/
      8 /*  MODULE IMPORTS:                                                          */
      9 /*****************************************************************************/
     10 #include <ctype.h>                                  /*  MODULE TYPE:  (sys)  */
     11 #include <limits.h>                                 /*  MODULE TYPE:  (sys)  */
     12 #include <string.h>                                 /*  MODULE TYPE:  (sys)  */
     13 /*****************************************************************************/
     14 /*  MODULE INTERFACE:                                                        */
     15 /*****************************************************************************/
     16 #include "bitvect.h"
     17 
     18 /* ToolBox.h */
     19 #define and         &&      /* logical (boolean) operators: lower case */
     20 #define or          ||
     21 #define not         !
     22 
     23 #define AND         &       /* binary (bitwise) operators: UPPER CASE */
     24 #define OR          |
     25 #define XOR         ^
     26 #define NOT         ~
     27 #define SHL         <<
     28 #define SHR         >>
     29 
     30 #ifdef ENABLE_MODULO
     31 #define mod         %       /* arithmetic operators */
     32 #endif
     33 
     34 #define blockdef(name,size)         unsigned char name[size]
     35 #define blocktypedef(name,size)     typedef unsigned char name[size]
     36 
     37 /*****************************************************************************/
     38 /*  MODULE RESOURCES:                                                        */
     39 /*****************************************************************************/
     40 
     41 #define bits_(BitVector) *(BitVector-3)
     42 #define size_(BitVector) *(BitVector-2)
     43 #define mask_(BitVector) *(BitVector-1)
     44 
     45 #define  ERRCODE_TYPE  "sizeof(word) > sizeof(size_t)"
     46 #define  ERRCODE_BITS  "bits(word) != sizeof(word)*8"
     47 #define  ERRCODE_WORD  "bits(word) < 16"
     48 #define  ERRCODE_LONG  "bits(word) > bits(long)"
     49 #define  ERRCODE_POWR  "bits(word) != 2^x"
     50 #define  ERRCODE_LOGA  "bits(word) != 2^ld(bits(word))"
     51 #define  ERRCODE_NULL  "unable to allocate memory"
     52 #define  ERRCODE_INDX  "index out of range"
     53 #define  ERRCODE_ORDR  "minimum > maximum index"
     54 #define  ERRCODE_SIZE  "bit vector size mismatch"
     55 #define  ERRCODE_PARS  "input string syntax error"
     56 #define  ERRCODE_OVFL  "numeric overflow error"
     57 #define  ERRCODE_SAME  "result vector(s) must be distinct"
     58 #define  ERRCODE_EXPO  "exponent must be positive"
     59 #define  ERRCODE_ZERO  "division by zero error"
     60 #define  ERRCODE_OOPS  "unexpected internal error - please contact author"
     61 
     62 const N_int BitVector_BYTENORM[256] =
     63 {
     64     0x00, 0x01, 0x01, 0x02,  0x01, 0x02, 0x02, 0x03,
     65     0x01, 0x02, 0x02, 0x03,  0x02, 0x03, 0x03, 0x04, /* 0x00 */
     66     0x01, 0x02, 0x02, 0x03,  0x02, 0x03, 0x03, 0x04,
     67     0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05, /* 0x10 */
     68     0x01, 0x02, 0x02, 0x03,  0x02, 0x03, 0x03, 0x04,
     69     0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05, /* 0x20 */
     70     0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05,
     71     0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06, /* 0x30 */
     72     0x01, 0x02, 0x02, 0x03,  0x02, 0x03, 0x03, 0x04,
     73     0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05, /* 0x40 */
     74     0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05,
     75     0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06, /* 0x50 */
     76     0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05,
     77     0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06, /* 0x60 */
     78     0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06,
     79     0x04, 0x05, 0x05, 0x06,  0x05, 0x06, 0x06, 0x07, /* 0x70 */
     80     0x01, 0x02, 0x02, 0x03,  0x02, 0x03, 0x03, 0x04,
     81     0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05, /* 0x80 */
     82     0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05,
     83     0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06, /* 0x90 */
     84     0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05,
     85     0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06, /* 0xA0 */
     86     0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06,
     87     0x04, 0x05, 0x05, 0x06,  0x05, 0x06, 0x06, 0x07, /* 0xB0 */
     88     0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05,
     89     0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06, /* 0xC0 */
     90     0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06,
     91     0x04, 0x05, 0x05, 0x06,  0x05, 0x06, 0x06, 0x07, /* 0xD0 */
     92     0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06,
     93     0x04, 0x05, 0x05, 0x06,  0x05, 0x06, 0x06, 0x07, /* 0xE0 */
     94     0x04, 0x05, 0x05, 0x06,  0x05, 0x06, 0x06, 0x07,
     95     0x05, 0x06, 0x06, 0x07,  0x06, 0x07, 0x07, 0x08  /* 0xF0 */
     96 };
     97 
     98 /*****************************************************************************/
     99 /*  MODULE IMPLEMENTATION:                                                   */
    100 /*****************************************************************************/
    101 
    102     /**********************************************/
    103     /* global implementation-intrinsic constants: */
    104     /**********************************************/
    105 
    106 #define BIT_VECTOR_HIDDEN_WORDS 3
    107 
    108     /*****************************************************************/
    109     /* global machine-dependent constants (set by "BitVector_Boot"): */
    110     /*****************************************************************/
    111 
    112 static N_word BITS;     /* = # of bits in machine word (must be power of 2)  */
    113 static N_word MODMASK;  /* = BITS - 1 (mask for calculating modulo BITS)     */
    114 static N_word LOGBITS;  /* = ld(BITS) (logarithmus dualis)                   */
    115 static N_word FACTOR;   /* = ld(BITS / 8) (ld of # of bytes)                 */
    116 
    117 static N_word LSB = 1;  /* = mask for least significant bit                  */
    118 static N_word MSB;      /* = mask for most significant bit                   */
    119 
    120 static N_word LONGBITS; /* = # of bits in unsigned long                      */
    121 
    122 static N_word LOG10;    /* = logarithm to base 10 of BITS - 1                */
    123 static N_word EXP10;    /* = largest possible power of 10 in signed int      */
    124 
    125     /********************************************************************/
    126     /* global bit mask table for fast access (set by "BitVector_Boot"): */
    127     /********************************************************************/
    128 
    129 static wordptr BITMASKTAB;
    130 
    131     /*****************************/
    132     /* global macro definitions: */
    133     /*****************************/
    134 
    135 #define BIT_VECTOR_ZERO_WORDS(target,count) \
    136     while (count-- > 0) *target++ = 0;
    137 
    138 #define BIT_VECTOR_FILL_WORDS(target,fill,count) \
    139     while (count-- > 0) *target++ = fill;
    140 
    141 #define BIT_VECTOR_FLIP_WORDS(target,flip,count) \
    142     while (count-- > 0) *target++ ^= flip;
    143 
    144 #define BIT_VECTOR_COPY_WORDS(target,source,count) \
    145     while (count-- > 0) *target++ = *source++;
    146 
    147 #define BIT_VECTOR_BACK_WORDS(target,source,count) \
    148     { target += count; source += count; while (count-- > 0) *--target = *--source; }
    149 
    150 #define BIT_VECTOR_CLR_BIT(address,index) \
    151     *(address+(index>>LOGBITS)) &= NOT BITMASKTAB[index AND MODMASK];
    152 
    153 #define BIT_VECTOR_SET_BIT(address,index) \
    154     *(address+(index>>LOGBITS)) |= BITMASKTAB[index AND MODMASK];
    155 
    156 #define BIT_VECTOR_TST_BIT(address,index) \
    157     ((*(address+(index>>LOGBITS)) AND BITMASKTAB[index AND MODMASK]) != 0)
    158 
    159 #define BIT_VECTOR_FLP_BIT(address,index,mask) \
    160     (mask = BITMASKTAB[index AND MODMASK]), \
    161     (((*(addr+(index>>LOGBITS)) ^= mask) AND mask) != 0)
    162 
    163 #define BIT_VECTOR_DIGITIZE(type,value,digit) \
    164     value = (type) ((digit = value) / 10); \
    165     digit -= value * 10; \
    166     digit += (type) '0';
    167 
    168     /*********************************************************/
    169     /* private low-level functions (potentially dangerous!): */
    170     /*********************************************************/
    171 
    172 static N_word power10(N_word x)
    173 {
    174     N_word y = 1;
    175 
    176     while (x-- > 0) y *= 10;
    177     return(y);
    178 }
    179 
    180 static void BIT_VECTOR_zro_words(wordptr addr, N_word count)
    181 {
    182     BIT_VECTOR_ZERO_WORDS(addr,count)
    183 }
    184 
    185 static void BIT_VECTOR_cpy_words(wordptr target, wordptr source, N_word count)
    186 {
    187     BIT_VECTOR_COPY_WORDS(target,source,count)
    188 }
    189 
    190 static void BIT_VECTOR_mov_words(wordptr target, wordptr source, N_word count)
    191 {
    192     if (target != source)
    193     {
    194         if (target < source) BIT_VECTOR_COPY_WORDS(target,source,count)
    195         else                 BIT_VECTOR_BACK_WORDS(target,source,count)
    196     }
    197 }
    198 
    199 static void BIT_VECTOR_ins_words(wordptr addr, N_word total, N_word count,
    200                                  boolean clear)
    201 {
    202     N_word length;
    203 
    204     if ((total > 0) and (count > 0))
    205     {
    206         if (count > total) count = total;
    207         length = total - count;
    208         if (length > 0) BIT_VECTOR_mov_words(addr+count,addr,length);
    209         if (clear)      BIT_VECTOR_zro_words(addr,count);
    210     }
    211 }
    212 
    213 static void BIT_VECTOR_del_words(wordptr addr, N_word total, N_word count,
    214                                  boolean clear)
    215 {
    216     N_word length;
    217 
    218     if ((total > 0) and (count > 0))
    219     {
    220         if (count > total) count = total;
    221         length = total - count;
    222         if (length > 0) BIT_VECTOR_mov_words(addr,addr+count,length);
    223         if (clear)      BIT_VECTOR_zro_words(addr+length,count);
    224     }
    225 }
    226 
    227 static void BIT_VECTOR_reverse(charptr string, N_word length)
    228 {
    229     charptr last;
    230     N_char  temp;
    231 
    232     if (length > 1)
    233     {
    234         last = string + length - 1;
    235         while (string < last)
    236         {
    237             temp = *string;
    238             *string = *last;
    239             *last = temp;
    240             string++;
    241             last--;
    242         }
    243     }
    244 }
    245 
    246 static N_word BIT_VECTOR_int2str(charptr string, N_word value)
    247 {
    248     N_word  length;
    249     N_word  digit;
    250     charptr work;
    251 
    252     work = string;
    253     if (value > 0)
    254     {
    255         length = 0;
    256         while (value > 0)
    257         {
    258             BIT_VECTOR_DIGITIZE(N_word,value,digit)
    259             *work++ = (N_char) digit;
    260             length++;
    261         }
    262         BIT_VECTOR_reverse(string,length);
    263     }
    264     else
    265     {
    266         length = 1;
    267         *work++ = (N_char) '0';
    268     }
    269     return(length);
    270 }
    271 
    272 static N_word BIT_VECTOR_str2int(charptr string, N_word *value)
    273 {
    274     N_word  length;
    275     N_word  digit;
    276 
    277     *value = 0;
    278     length = 0;
    279     digit = (N_word) *string++;
    280     /* separate because isdigit() is likely a macro! */
    281     while (isdigit((int)digit) != 0)
    282     {
    283         length++;
    284         digit -= (N_word) '0';
    285         if (*value) *value *= 10;
    286         *value += digit;
    287         digit = (N_word) *string++;
    288     }
    289     return(length);
    290 }
    291 
    292     /********************************************/
    293     /* routine to convert error code to string: */
    294     /********************************************/
    295 
    296 const char * BitVector_Error(ErrCode error)
    297 {
    298     switch (error)
    299     {
    300         case ErrCode_Ok:   return(     NULL     ); break;
    301         case ErrCode_Type: return( ERRCODE_TYPE ); break;
    302         case ErrCode_Bits: return( ERRCODE_BITS ); break;
    303         case ErrCode_Word: return( ERRCODE_WORD ); break;
    304         case ErrCode_Long: return( ERRCODE_LONG ); break;
    305         case ErrCode_Powr: return( ERRCODE_POWR ); break;
    306         case ErrCode_Loga: return( ERRCODE_LOGA ); break;
    307         case ErrCode_Null: return( ERRCODE_NULL ); break;
    308         case ErrCode_Indx: return( ERRCODE_INDX ); break;
    309         case ErrCode_Ordr: return( ERRCODE_ORDR ); break;
    310         case ErrCode_Size: return( ERRCODE_SIZE ); break;
    311         case ErrCode_Pars: return( ERRCODE_PARS ); break;
    312         case ErrCode_Ovfl: return( ERRCODE_OVFL ); break;
    313         case ErrCode_Same: return( ERRCODE_SAME ); break;
    314         case ErrCode_Expo: return( ERRCODE_EXPO ); break;
    315         case ErrCode_Zero: return( ERRCODE_ZERO ); break;
    316         default:           return( ERRCODE_OOPS ); break;
    317     }
    318 }
    319 
    320     /*****************************************/
    321     /* automatic self-configuration routine: */
    322     /*****************************************/
    323 
    324     /*******************************************************/
    325     /*                                                     */
    326     /*   MUST be called once prior to any other function   */
    327     /*   to initialize the machine dependent constants     */
    328     /*   of this package! (But call only ONCE, or you      */
    329     /*   will suffer memory leaks!)                        */
    330     /*                                                     */
    331     /*******************************************************/
    332 
    333 ErrCode BitVector_Boot(void)
    334 {
    335     N_long longsample = 1L;
    336     N_word sample = LSB;
    337     N_word lsb;
    338 
    339     if (sizeof(N_word) > sizeof(size_t)) return(ErrCode_Type);
    340 
    341     BITS = 1;
    342     while (sample <<= 1) BITS++;    /* determine # of bits in a machine word */
    343 
    344     if (BITS != (sizeof(N_word) << 3)) return(ErrCode_Bits);
    345 
    346     if (BITS < 16) return(ErrCode_Word);
    347 
    348     LONGBITS = 1;
    349     while (longsample <<= 1) LONGBITS++;  /* = # of bits in an unsigned long */
    350 
    351     if (BITS > LONGBITS) return(ErrCode_Long);
    352 
    353     LOGBITS = 0;
    354     sample = BITS;
    355     lsb = (sample AND LSB);
    356     while ((sample >>= 1) and (not lsb))
    357     {
    358         LOGBITS++;
    359         lsb = (sample AND LSB);
    360     }
    361 
    362     if (sample) return(ErrCode_Powr);      /* # of bits is not a power of 2! */
    363 
    364     if (BITS != (LSB << LOGBITS)) return(ErrCode_Loga);
    365 
    366     MODMASK = BITS - 1;
    367     FACTOR = LOGBITS - 3;  /* ld(BITS / 8) = ld(BITS) - ld(8) = ld(BITS) - 3 */
    368     MSB = (LSB << MODMASK);
    369 
    370     BITMASKTAB = (wordptr) yasm_xmalloc((size_t) (BITS << FACTOR));
    371 
    372     if (BITMASKTAB == NULL) return(ErrCode_Null);
    373 
    374     for ( sample = 0; sample < BITS; sample++ )
    375     {
    376         BITMASKTAB[sample] = (LSB << sample);
    377     }
    378 
    379     LOG10 = (N_word) (MODMASK * 0.30103); /* = (BITS - 1) * ( ln 2 / ln 10 ) */
    380     EXP10 = power10(LOG10);
    381 
    382     return(ErrCode_Ok);
    383 }
    384 
    385 void BitVector_Shutdown(void)
    386 {
    387     if (BITMASKTAB) yasm_xfree(BITMASKTAB);
    388 }
    389 
    390 N_word BitVector_Size(N_int bits)           /* bit vector size (# of words)  */
    391 {
    392     N_word size;
    393 
    394     size = bits >> LOGBITS;
    395     if (bits AND MODMASK) size++;
    396     return(size);
    397 }
    398 
    399 N_word BitVector_Mask(N_int bits)           /* bit vector mask (unused bits) */
    400 {
    401     N_word mask;
    402 
    403     mask = bits AND MODMASK;
    404     if (mask) mask = (N_word) ~(~0L << mask); else mask = (N_word) ~0L;
    405     return(mask);
    406 }
    407 
    408 const char * BitVector_Version(void)
    409 {
    410     return("6.4");
    411 }
    412 
    413 N_int BitVector_Word_Bits(void)
    414 {
    415     return(BITS);
    416 }
    417 
    418 N_int BitVector_Long_Bits(void)
    419 {
    420     return(LONGBITS);
    421 }
    422 
    423 /********************************************************************/
    424 /*                                                                  */
    425 /*  WARNING: Do not "free()" constant character strings, i.e.,      */
    426 /*           don't call "BitVector_Dispose()" for strings returned  */
    427 /*           by "BitVector_Error()" or "BitVector_Version()"!       */
    428 /*                                                                  */
    429 /*  ONLY call this function for strings allocated with "malloc()",  */
    430 /*  i.e., the strings returned by the functions "BitVector_to_*()"  */
    431 /*  and "BitVector_Block_Read()"!                                   */
    432 /*                                                                  */
    433 /********************************************************************/
    434 
    435 void BitVector_Dispose(charptr string)                      /* free string   */
    436 {
    437     if (string != NULL) yasm_xfree((voidptr) string);
    438 }
    439 
    440 void BitVector_Destroy(wordptr addr)                        /* free bitvec   */
    441 {
    442     if (addr != NULL)
    443     {
    444         addr -= BIT_VECTOR_HIDDEN_WORDS;
    445         yasm_xfree((voidptr) addr);
    446     }
    447 }
    448 
    449 void BitVector_Destroy_List(listptr list, N_int count)      /* free list     */
    450 {
    451     listptr slot;
    452 
    453     if (list != NULL)
    454     {
    455         slot = list;
    456         while (count-- > 0)
    457         {
    458             BitVector_Destroy(*slot++);
    459         }
    460         free((voidptr) list);
    461     }
    462 }
    463 
    464 wordptr BitVector_Create(N_int bits, boolean clear)         /* malloc        */
    465 {
    466     N_word  size;
    467     N_word  mask;
    468     N_word  bytes;
    469     wordptr addr;
    470     wordptr zero;
    471 
    472     size = BitVector_Size(bits);
    473     mask = BitVector_Mask(bits);
    474     bytes = (size + BIT_VECTOR_HIDDEN_WORDS) << FACTOR;
    475     addr = (wordptr) yasm_xmalloc((size_t) bytes);
    476     if (addr != NULL)
    477     {
    478         *addr++ = bits;
    479         *addr++ = size;
    480         *addr++ = mask;
    481         if (clear)
    482         {
    483             zero = addr;
    484             BIT_VECTOR_ZERO_WORDS(zero,size)
    485         }
    486     }
    487     return(addr);
    488 }
    489 
    490 listptr BitVector_Create_List(N_int bits, boolean clear, N_int count)
    491 {
    492     listptr list = NULL;
    493     listptr slot;
    494     wordptr addr;
    495     N_int   i;
    496 
    497     if (count > 0)
    498     {
    499         list = (listptr) malloc(sizeof(wordptr) * count);
    500         if (list != NULL)
    501         {
    502             slot = list;
    503             for ( i = 0; i < count; i++ )
    504             {
    505                 addr = BitVector_Create(bits,clear);
    506                 if (addr == NULL)
    507                 {
    508                     BitVector_Destroy_List(list,i);
    509                     return(NULL);
    510                 }
    511                 *slot++ = addr;
    512             }
    513         }
    514     }
    515     return(list);
    516 }
    517 
    518 wordptr BitVector_Resize(wordptr oldaddr, N_int bits)       /* realloc       */
    519 {
    520     N_word  bytes;
    521     N_word  oldsize;
    522     N_word  oldmask;
    523     N_word  newsize;
    524     N_word  newmask;
    525     wordptr newaddr;
    526     wordptr source;
    527     wordptr target;
    528 
    529     oldsize = size_(oldaddr);
    530     oldmask = mask_(oldaddr);
    531     newsize = BitVector_Size(bits);
    532     newmask = BitVector_Mask(bits);
    533     if (oldsize > 0) *(oldaddr+oldsize-1) &= oldmask;
    534     if (newsize <= oldsize)
    535     {
    536         newaddr = oldaddr;
    537         bits_(newaddr) = bits;
    538         size_(newaddr) = newsize;
    539         mask_(newaddr) = newmask;
    540         if (newsize > 0) *(newaddr+newsize-1) &= newmask;
    541     }
    542     else
    543     {
    544         bytes = (newsize + BIT_VECTOR_HIDDEN_WORDS) << FACTOR;
    545         newaddr = (wordptr) yasm_xmalloc((size_t) bytes);
    546         if (newaddr != NULL)
    547         {
    548             *newaddr++ = bits;
    549             *newaddr++ = newsize;
    550             *newaddr++ = newmask;
    551             target = newaddr;
    552             source = oldaddr;
    553             newsize -= oldsize;
    554             BIT_VECTOR_COPY_WORDS(target,source,oldsize)
    555             BIT_VECTOR_ZERO_WORDS(target,newsize)
    556         }
    557         BitVector_Destroy(oldaddr);
    558     }
    559     return(newaddr);
    560 }
    561 
    562 wordptr BitVector_Shadow(wordptr addr)     /* makes new, same size but empty */
    563 {
    564     return( BitVector_Create(bits_(addr),true) );
    565 }
    566 
    567 wordptr BitVector_Clone(wordptr addr)               /* makes exact duplicate */
    568 {
    569     N_word  bits;
    570     wordptr twin;
    571 
    572     bits = bits_(addr);
    573     twin = BitVector_Create(bits,false);
    574     if ((twin != NULL) and (bits > 0))
    575         BIT_VECTOR_cpy_words(twin,addr,size_(addr));
    576     return(twin);
    577 }
    578 
    579 wordptr BitVector_Concat(wordptr X, wordptr Y)      /* returns concatenation */
    580 {
    581     /* BEWARE that X = most significant part, Y = least significant part! */
    582 
    583     N_word  bitsX;
    584     N_word  bitsY;
    585     N_word  bitsZ;
    586     wordptr Z;
    587 
    588     bitsX = bits_(X);
    589     bitsY = bits_(Y);
    590     bitsZ = bitsX + bitsY;
    591     Z = BitVector_Create(bitsZ,false);
    592     if ((Z != NULL) and (bitsZ > 0))
    593     {
    594         BIT_VECTOR_cpy_words(Z,Y,size_(Y));
    595         BitVector_Interval_Copy(Z,X,bitsY,0,bitsX);
    596         *(Z+size_(Z)-1) &= mask_(Z);
    597     }
    598     return(Z);
    599 }
    600 
    601 void BitVector_Copy(wordptr X, wordptr Y)                           /* X = Y */
    602 {
    603     N_word  sizeX = size_(X);
    604     N_word  sizeY = size_(Y);
    605     N_word  maskX = mask_(X);
    606     N_word  maskY = mask_(Y);
    607     N_word  fill  = 0;
    608     wordptr lastX;
    609     wordptr lastY;
    610 
    611     if ((X != Y) and (sizeX > 0))
    612     {
    613         lastX = X + sizeX - 1;
    614         if (sizeY > 0)
    615         {
    616             lastY = Y + sizeY - 1;
    617             if ( (*lastY AND (maskY AND NOT (maskY >> 1))) == 0 ) *lastY &= maskY;
    618             else
    619             {
    620                 fill = (N_word) ~0L;
    621                 *lastY |= NOT maskY;
    622             }
    623             while ((sizeX > 0) and (sizeY > 0))
    624             {
    625                 *X++ = *Y++;
    626                 sizeX--;
    627                 sizeY--;
    628             }
    629             *lastY &= maskY;
    630         }
    631         while (sizeX-- > 0) *X++ = fill;
    632         *lastX &= maskX;
    633     }
    634 }
    635 
    636 void BitVector_Empty(wordptr addr)                        /* X = {}  clr all */
    637 {
    638     N_word size = size_(addr);
    639 
    640     BIT_VECTOR_ZERO_WORDS(addr,size)
    641 }
    642 
    643 void BitVector_Fill(wordptr addr)                         /* X = ~{} set all */
    644 {
    645     N_word size = size_(addr);
    646     N_word mask = mask_(addr);
    647     N_word fill = (N_word) ~0L;
    648 
    649     if (size > 0)
    650     {
    651         BIT_VECTOR_FILL_WORDS(addr,fill,size)
    652         *(--addr) &= mask;
    653     }
    654 }
    655 
    656 void BitVector_Flip(wordptr addr)                         /* X = ~X flip all */
    657 {
    658     N_word size = size_(addr);
    659     N_word mask = mask_(addr);
    660     N_word flip = (N_word) ~0L;
    661 
    662     if (size > 0)
    663     {
    664         BIT_VECTOR_FLIP_WORDS(addr,flip,size)
    665         *(--addr) &= mask;
    666     }
    667 }
    668 
    669 void BitVector_Primes(wordptr addr)
    670 {
    671     N_word  bits = bits_(addr);
    672     N_word  size = size_(addr);
    673     wordptr work;
    674     N_word  temp;
    675     N_word  i,j;
    676 
    677     if (size > 0)
    678     {
    679         temp = 0xAAAA;
    680         i = BITS >> 4;
    681         while (--i > 0)
    682         {
    683             temp <<= 16;
    684             temp |= 0xAAAA;
    685         }
    686         i = size;
    687         work = addr;
    688         *work++ = temp XOR 0x0006;
    689         while (--i > 0) *work++ = temp;
    690         for ( i = 3; (j = i * i) < bits; i += 2 )
    691         {
    692             for ( ; j < bits; j += i ) BIT_VECTOR_CLR_BIT(addr,j)
    693         }
    694         *(addr+size-1) &= mask_(addr);
    695     }
    696 }
    697 
    698 void BitVector_Reverse(wordptr X, wordptr Y)
    699 {
    700     N_word bits = bits_(X);
    701     N_word mask;
    702     N_word bit;
    703     N_word value;
    704 
    705     if (bits > 0)
    706     {
    707         if (X == Y) BitVector_Interval_Reverse(X,0,bits-1);
    708         else if (bits == bits_(Y))
    709         {
    710 /*          mask = mask_(Y);  */
    711 /*          mask &= NOT (mask >> 1);  */
    712             mask = BITMASKTAB[(bits-1) AND MODMASK];
    713             Y += size_(Y) - 1;
    714             value = 0;
    715             bit = LSB;
    716             while (bits-- > 0)
    717             {
    718                 if ((*Y AND mask) != 0)
    719                 {
    720                     value |= bit;
    721                 }
    722                 if (not (mask >>= 1))
    723                 {
    724                     Y--;
    725                     mask = MSB;
    726                 }
    727                 if (not (bit <<= 1))
    728                 {
    729                     *X++ = value;
    730                     value = 0;
    731                     bit = LSB;
    732                 }
    733             }
    734             if (bit > LSB) *X = value;
    735         }
    736     }
    737 }
    738 
    739 void BitVector_Interval_Empty(wordptr addr, N_int lower, N_int upper)
    740 {                                                  /* X = X \ [lower..upper] */
    741     N_word  bits = bits_(addr);
    742     N_word  size = size_(addr);
    743     wordptr loaddr;
    744     wordptr hiaddr;
    745     N_word  lobase;
    746     N_word  hibase;
    747     N_word  lomask;
    748     N_word  himask;
    749     N_word  diff;
    750 
    751     if ((size > 0) and (lower < bits) and (upper < bits) and (lower <= upper))
    752     {
    753         lobase = lower >> LOGBITS;
    754         hibase = upper >> LOGBITS;
    755         diff = hibase - lobase;
    756         loaddr = addr + lobase;
    757         hiaddr = addr + hibase;
    758 
    759         lomask = (N_word)   (~0L << (lower AND MODMASK));
    760         himask = (N_word) ~((~0L << (upper AND MODMASK)) << 1);
    761 
    762         if (diff == 0)
    763         {
    764             *loaddr &= NOT (lomask AND himask);
    765         }
    766         else
    767         {
    768             *loaddr++ &= NOT lomask;
    769             while (--diff > 0)
    770             {
    771                 *loaddr++ = 0;
    772             }
    773             *hiaddr &= NOT himask;
    774         }
    775     }
    776 }
    777 
    778 void BitVector_Interval_Fill(wordptr addr, N_int lower, N_int upper)
    779 {                                                  /* X = X + [lower..upper] */
    780     N_word  bits = bits_(addr);
    781     N_word  size = size_(addr);
    782     N_word  fill = (N_word) ~0L;
    783     wordptr loaddr;
    784     wordptr hiaddr;
    785     N_word  lobase;
    786     N_word  hibase;
    787     N_word  lomask;
    788     N_word  himask;
    789     N_word  diff;
    790 
    791     if ((size > 0) and (lower < bits) and (upper < bits) and (lower <= upper))
    792     {
    793         lobase = lower >> LOGBITS;
    794         hibase = upper >> LOGBITS;
    795         diff = hibase - lobase;
    796         loaddr = addr + lobase;
    797         hiaddr = addr + hibase;
    798 
    799         lomask = (N_word)   (~0L << (lower AND MODMASK));
    800         himask = (N_word) ~((~0L << (upper AND MODMASK)) << 1);
    801 
    802         if (diff == 0)
    803         {
    804             *loaddr |= (lomask AND himask);
    805         }
    806         else
    807         {
    808             *loaddr++ |= lomask;
    809             while (--diff > 0)
    810             {
    811                 *loaddr++ = fill;
    812             }
    813             *hiaddr |= himask;
    814         }
    815         *(addr+size-1) &= mask_(addr);
    816     }
    817 }
    818 
    819 void BitVector_Interval_Flip(wordptr addr, N_int lower, N_int upper)
    820 {                                                  /* X = X ^ [lower..upper] */
    821     N_word  bits = bits_(addr);
    822     N_word  size = size_(addr);
    823     N_word  flip = (N_word) ~0L;
    824     wordptr loaddr;
    825     wordptr hiaddr;
    826     N_word  lobase;
    827     N_word  hibase;
    828     N_word  lomask;
    829     N_word  himask;
    830     N_word  diff;
    831 
    832     if ((size > 0) and (lower < bits) and (upper < bits) and (lower <= upper))
    833     {
    834         lobase = lower >> LOGBITS;
    835         hibase = upper >> LOGBITS;
    836         diff = hibase - lobase;
    837         loaddr = addr + lobase;
    838         hiaddr = addr + hibase;
    839 
    840         lomask = (N_word)   (~0L << (lower AND MODMASK));
    841         himask = (N_word) ~((~0L << (upper AND MODMASK)) << 1);
    842 
    843         if (diff == 0)
    844         {
    845             *loaddr ^= (lomask AND himask);
    846         }
    847         else
    848         {
    849             *loaddr++ ^= lomask;
    850             while (--diff > 0)
    851             {
    852                 *loaddr++ ^= flip;
    853             }
    854             *hiaddr ^= himask;
    855         }
    856         *(addr+size-1) &= mask_(addr);
    857     }
    858 }
    859 
    860 void BitVector_Interval_Reverse(wordptr addr, N_int lower, N_int upper)
    861 {
    862     N_word  bits = bits_(addr);
    863     wordptr loaddr;
    864     wordptr hiaddr;
    865     N_word  lomask;
    866     N_word  himask;
    867 
    868     if ((bits > 0) and (lower < bits) and (upper < bits) and (lower < upper))
    869     {
    870         loaddr = addr + (lower >> LOGBITS);
    871         hiaddr = addr + (upper >> LOGBITS);
    872         lomask = BITMASKTAB[lower AND MODMASK];
    873         himask = BITMASKTAB[upper AND MODMASK];
    874         for ( bits = upper - lower + 1; bits > 1; bits -= 2 )
    875         {
    876             if (((*loaddr AND lomask) != 0) XOR ((*hiaddr AND himask) != 0))
    877             {
    878                 *loaddr ^= lomask;  /* swap bits only if they differ! */
    879                 *hiaddr ^= himask;
    880             }
    881             if (not (lomask <<= 1))
    882             {
    883                 lomask = LSB;
    884                 loaddr++;
    885             }
    886             if (not (himask >>= 1))
    887             {
    888                 himask = MSB;
    889                 hiaddr--;
    890             }
    891         }
    892     }
    893 }
    894 
    895 boolean BitVector_interval_scan_inc(wordptr addr, N_int start,
    896                                     N_intptr min, N_intptr max)
    897 {
    898     N_word  size = size_(addr);
    899     N_word  mask = mask_(addr);
    900     N_word  offset;
    901     N_word  bitmask;
    902     N_word  value;
    903     boolean empty;
    904 
    905     if ((size == 0) or (start >= bits_(addr))) return(FALSE);
    906 
    907     *min = start;
    908     *max = start;
    909 
    910     offset = start >> LOGBITS;
    911 
    912     *(addr+size-1) &= mask;
    913 
    914     addr += offset;
    915     size -= offset;
    916 
    917     bitmask = BITMASKTAB[start AND MODMASK];
    918     mask = NOT (bitmask OR (bitmask - 1));
    919 
    920     value = *addr++;
    921     if ((value AND bitmask) == 0)
    922     {
    923         value &= mask;
    924         if (value == 0)
    925         {
    926             offset++;
    927             empty = TRUE;
    928             while (empty and (--size > 0))
    929             {
    930                 if ((value = *addr++)) empty = false; else offset++;
    931             }
    932             if (empty) return(FALSE);
    933         }
    934         start = offset << LOGBITS;
    935         bitmask = LSB;
    936         mask = value;
    937         while (not (mask AND LSB))
    938         {
    939             bitmask <<= 1;
    940             mask >>= 1;
    941             start++;
    942         }
    943         mask = NOT (bitmask OR (bitmask - 1));
    944         *min = start;
    945         *max = start;
    946     }
    947     value = NOT value;
    948     value &= mask;
    949     if (value == 0)
    950     {
    951         offset++;
    952         empty = TRUE;
    953         while (empty and (--size > 0))
    954         {
    955             if ((value = NOT *addr++)) empty = false; else offset++;
    956         }
    957         if (empty) value = LSB;
    958     }
    959     start = offset << LOGBITS;
    960     while (not (value AND LSB))
    961     {
    962         value >>= 1;
    963         start++;
    964     }
    965     *max = --start;
    966     return(TRUE);
    967 }
    968 
    969 boolean BitVector_interval_scan_dec(wordptr addr, N_int start,
    970                                     N_intptr min, N_intptr max)
    971 {
    972     N_word  size = size_(addr);
    973     N_word  mask = mask_(addr);
    974     N_word offset;
    975     N_word bitmask;
    976     N_word value;
    977     boolean empty;
    978 
    979     if ((size == 0) or (start >= bits_(addr))) return(FALSE);
    980 
    981     *min = start;
    982     *max = start;
    983 
    984     offset = start >> LOGBITS;
    985 
    986     if (offset >= size) return(FALSE);
    987 
    988     *(addr+size-1) &= mask;
    989 
    990     addr += offset;
    991     size = ++offset;
    992 
    993     bitmask = BITMASKTAB[start AND MODMASK];
    994     mask = (bitmask - 1);
    995 
    996     value = *addr--;
    997     if ((value AND bitmask) == 0)
    998     {
    999         value &= mask;
   1000         if (value == 0)
   1001         {
   1002             offset--;
   1003             empty = TRUE;
   1004             while (empty and (--size > 0))
   1005             {
   1006                 if ((value = *addr--)) empty = false; else offset--;
   1007             }
   1008             if (empty) return(FALSE);
   1009         }
   1010         start = offset << LOGBITS;
   1011         bitmask = MSB;
   1012         mask = value;
   1013         while (not (mask AND MSB))
   1014         {
   1015             bitmask >>= 1;
   1016             mask <<= 1;
   1017             start--;
   1018         }
   1019         mask = (bitmask - 1);
   1020         *max = --start;
   1021         *min = start;
   1022     }
   1023     value = NOT value;
   1024     value &= mask;
   1025     if (value == 0)
   1026     {
   1027         offset--;
   1028         empty = TRUE;
   1029         while (empty and (--size > 0))
   1030         {
   1031             if ((value = NOT *addr--)) empty = false; else offset--;
   1032         }
   1033         if (empty) value = MSB;
   1034     }
   1035     start = offset << LOGBITS;
   1036     while (not (value AND MSB))
   1037     {
   1038         value <<= 1;
   1039         start--;
   1040     }
   1041     *min = start;
   1042     return(TRUE);
   1043 }
   1044 
   1045 void BitVector_Interval_Copy(wordptr X, wordptr Y, N_int Xoffset,
   1046                              N_int Yoffset, N_int length)
   1047 {
   1048     N_word  bitsX = bits_(X);
   1049     N_word  bitsY = bits_(Y);
   1050     N_word  source = 0;        /* silence compiler warning */
   1051     N_word  target = 0;        /* silence compiler warning */
   1052     N_word  s_lo_base;
   1053     N_word  s_hi_base;
   1054     N_word  s_lo_bit;
   1055     N_word  s_hi_bit;
   1056     N_word  s_base;
   1057     N_word  s_lower = 0;       /* silence compiler warning */
   1058     N_word  s_upper = 0;       /* silence compiler warning */
   1059     N_word  s_bits;
   1060     N_word  s_min;
   1061     N_word  s_max;
   1062     N_word  t_lo_base;
   1063     N_word  t_hi_base;
   1064     N_word  t_lo_bit;
   1065     N_word  t_hi_bit;
   1066     N_word  t_base;
   1067     N_word  t_lower = 0;       /* silence compiler warning */
   1068     N_word  t_upper = 0;       /* silence compiler warning */
   1069     N_word  t_bits;
   1070     N_word  t_min;
   1071     N_word  mask;
   1072     N_word  bits;
   1073     N_word  sel;
   1074     boolean ascending;
   1075     boolean notfirst;
   1076     wordptr Z = X;
   1077 
   1078     if ((length > 0) and (Xoffset < bitsX) and (Yoffset < bitsY))
   1079     {
   1080         if ((Xoffset + length) > bitsX) length = bitsX - Xoffset;
   1081         if ((Yoffset + length) > bitsY) length = bitsY - Yoffset;
   1082 
   1083         ascending = (Xoffset <= Yoffset);
   1084 
   1085         s_lo_base = Yoffset >> LOGBITS;
   1086         s_lo_bit = Yoffset AND MODMASK;
   1087         Yoffset += --length;
   1088         s_hi_base = Yoffset >> LOGBITS;
   1089         s_hi_bit = Yoffset AND MODMASK;
   1090 
   1091         t_lo_base = Xoffset >> LOGBITS;
   1092         t_lo_bit = Xoffset AND MODMASK;
   1093         Xoffset += length;
   1094         t_hi_base = Xoffset >> LOGBITS;
   1095         t_hi_bit = Xoffset AND MODMASK;
   1096 
   1097         if (ascending)
   1098         {
   1099             s_base = s_lo_base;
   1100             t_base = t_lo_base;
   1101         }
   1102         else
   1103         {
   1104             s_base = s_hi_base;
   1105             t_base = t_hi_base;
   1106         }
   1107         s_bits = 0;
   1108         t_bits = 0;
   1109         Y += s_base;
   1110         X += t_base;
   1111         notfirst = FALSE;
   1112         while (TRUE)
   1113         {
   1114             if (t_bits == 0)
   1115             {
   1116                 if (notfirst)
   1117                 {
   1118                     *X = target;
   1119                     if (ascending)
   1120                     {
   1121                         if (t_base == t_hi_base) break;
   1122                         t_base++;
   1123                         X++;
   1124                     }
   1125                     else
   1126                     {
   1127                         if (t_base == t_lo_base) break;
   1128                         t_base--;
   1129                         X--;
   1130                     }
   1131                 }
   1132                 sel = ((t_base == t_hi_base) << 1) OR (t_base == t_lo_base);
   1133                 switch (sel)
   1134                 {
   1135                     case 0:
   1136                         t_lower = 0;
   1137                         t_upper = BITS - 1;
   1138                         t_bits = BITS;
   1139                         target = 0;
   1140                         break;
   1141                     case 1:
   1142                         t_lower = t_lo_bit;
   1143                         t_upper = BITS - 1;
   1144                         t_bits = BITS - t_lo_bit;
   1145                         mask = (N_word) (~0L << t_lower);
   1146                         target = *X AND NOT mask;
   1147                         break;
   1148                     case 2:
   1149                         t_lower = 0;
   1150                         t_upper = t_hi_bit;
   1151                         t_bits = t_hi_bit + 1;
   1152                         mask = (N_word) ((~0L << t_upper) << 1);
   1153                         target = *X AND mask;
   1154                         break;
   1155                     case 3:
   1156                         t_lower = t_lo_bit;
   1157                         t_upper = t_hi_bit;
   1158                         t_bits = t_hi_bit - t_lo_bit + 1;
   1159                         mask = (N_word) (~0L << t_lower);
   1160                         mask &= (N_word) ~((~0L << t_upper) << 1);
   1161                         target = *X AND NOT mask;
   1162                         break;
   1163                 }
   1164             }
   1165             if (s_bits == 0)
   1166             {
   1167                 if (notfirst)
   1168                 {
   1169                     if (ascending)
   1170                     {
   1171                         if (s_base == s_hi_base) break;
   1172                         s_base++;
   1173                         Y++;
   1174                     }
   1175                     else
   1176                     {
   1177                         if (s_base == s_lo_base) break;
   1178                         s_base--;
   1179                         Y--;
   1180                     }
   1181                 }
   1182                 source = *Y;
   1183                 sel = ((s_base == s_hi_base) << 1) OR (s_base == s_lo_base);
   1184                 switch (sel)
   1185                 {
   1186                     case 0:
   1187                         s_lower = 0;
   1188                         s_upper = BITS - 1;
   1189                         s_bits = BITS;
   1190                         break;
   1191                     case 1:
   1192                         s_lower = s_lo_bit;
   1193                         s_upper = BITS - 1;
   1194                         s_bits = BITS - s_lo_bit;
   1195                         break;
   1196                     case 2:
   1197                         s_lower = 0;
   1198                         s_upper = s_hi_bit;
   1199                         s_bits = s_hi_bit + 1;
   1200                         break;
   1201                     case 3:
   1202                         s_lower = s_lo_bit;
   1203                         s_upper = s_hi_bit;
   1204                         s_bits = s_hi_bit - s_lo_bit + 1;
   1205                         break;
   1206                 }
   1207             }
   1208             notfirst = TRUE;
   1209             if (s_bits > t_bits)
   1210             {
   1211                 bits = t_bits - 1;
   1212                 if (ascending)
   1213                 {
   1214                     s_min = s_lower;
   1215                     s_max = s_lower + bits;
   1216                 }
   1217                 else
   1218                 {
   1219                     s_max = s_upper;
   1220                     s_min = s_upper - bits;
   1221                 }
   1222                 t_min = t_lower;
   1223             }
   1224             else
   1225             {
   1226                 bits = s_bits - 1;
   1227                 if (ascending) t_min = t_lower;
   1228                 else           t_min = t_upper - bits;
   1229                 s_min = s_lower;
   1230                 s_max = s_upper;
   1231             }
   1232             bits++;
   1233             mask = (N_word) (~0L << s_min);
   1234             mask &= (N_word) ~((~0L << s_max) << 1);
   1235             if (s_min == t_min) target |= (source AND mask);
   1236             else
   1237             {
   1238                 if (s_min < t_min) target |= (source AND mask) << (t_min-s_min);
   1239                 else               target |= (source AND mask) >> (s_min-t_min);
   1240             }
   1241             if (ascending)
   1242             {
   1243                 s_lower += bits;
   1244                 t_lower += bits;
   1245             }
   1246             else
   1247             {
   1248                 s_upper -= bits;
   1249                 t_upper -= bits;
   1250             }
   1251             s_bits -= bits;
   1252             t_bits -= bits;
   1253         }
   1254         *(Z+size_(Z)-1) &= mask_(Z);
   1255     }
   1256 }
   1257 
   1258 
   1259 wordptr BitVector_Interval_Substitute(wordptr X, wordptr Y,
   1260                                       N_int Xoffset, N_int Xlength,
   1261                                       N_int Yoffset, N_int Ylength)
   1262 {
   1263     N_word Xbits = bits_(X);
   1264     N_word Ybits = bits_(Y);
   1265     N_word limit;
   1266     N_word diff;
   1267 
   1268     if ((Xoffset <= Xbits) and (Yoffset <= Ybits))
   1269     {
   1270         limit = Xoffset + Xlength;
   1271         if (limit > Xbits)
   1272         {
   1273             limit = Xbits;
   1274             Xlength = Xbits - Xoffset;
   1275         }
   1276         if ((Yoffset + Ylength) > Ybits)
   1277         {
   1278             Ylength = Ybits - Yoffset;
   1279         }
   1280         if (Xlength == Ylength)
   1281         {
   1282             if ((Ylength > 0) and ((X != Y) or (Xoffset != Yoffset)))
   1283             {
   1284                 BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
   1285             }
   1286         }
   1287         else /* Xlength != Ylength */
   1288         {
   1289             if (Xlength > Ylength)
   1290             {
   1291                 diff = Xlength - Ylength;
   1292                 if (Ylength > 0) BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
   1293                 if (limit < Xbits) BitVector_Delete(X,Xoffset+Ylength,diff,FALSE);
   1294                 if ((X = BitVector_Resize(X,Xbits-diff)) == NULL) return(NULL);
   1295             }
   1296             else /* Ylength > Xlength  ==>  Ylength > 0 */
   1297             {
   1298                 diff = Ylength - Xlength;
   1299                 if (X != Y)
   1300                 {
   1301                     if ((X = BitVector_Resize(X,Xbits+diff)) == NULL) return(NULL);
   1302                     if (limit < Xbits) BitVector_Insert(X,limit,diff,FALSE);
   1303                     BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
   1304                 }
   1305                 else /* in-place */
   1306                 {
   1307                     if ((Y = X = BitVector_Resize(X,Xbits+diff)) == NULL) return(NULL);
   1308                     if (limit >= Xbits)
   1309                     {
   1310                         BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
   1311                     }
   1312                     else /* limit < Xbits */
   1313                     {
   1314                         BitVector_Insert(X,limit,diff,FALSE);
   1315                         if ((Yoffset+Ylength) <= limit)
   1316                         {
   1317                             BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
   1318                         }
   1319                         else /* overlaps or lies above critical area */
   1320                         {
   1321                             if (limit <= Yoffset)
   1322                             {
   1323                                 Yoffset += diff;
   1324                                 BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
   1325                             }
   1326                             else /* Yoffset < limit */
   1327                             {
   1328                                 Xlength = limit - Yoffset;
   1329                                 BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Xlength);
   1330                                 Yoffset = Xoffset + Ylength; /* = limit + diff */
   1331                                 Xoffset += Xlength;
   1332                                 Ylength -= Xlength;
   1333                                 BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
   1334                             }
   1335                         }
   1336                     }
   1337                 }
   1338             }
   1339         }
   1340     }
   1341     return(X);
   1342 }
   1343 
   1344 boolean BitVector_is_empty(wordptr addr)                    /* X == {} ?     */
   1345 {
   1346     N_word  size = size_(addr);
   1347     boolean r = TRUE;
   1348 
   1349     if (size > 0)
   1350     {
   1351         *(addr+size-1) &= mask_(addr);
   1352         while (r and (size-- > 0)) r = ( *addr++ == 0 );
   1353     }
   1354     return(r);
   1355 }
   1356 
   1357 boolean BitVector_is_full(wordptr addr)                     /* X == ~{} ?    */
   1358 {
   1359     N_word  size = size_(addr);
   1360     N_word  mask = mask_(addr);
   1361     boolean r = FALSE;
   1362     wordptr last;
   1363 
   1364     if (size > 0)
   1365     {
   1366         r = TRUE;
   1367         last = addr + size - 1;
   1368         *last |= NOT mask;
   1369         while (r and (size-- > 0)) r = ( NOT *addr++ == 0 );
   1370         *last &= mask;
   1371     }
   1372     return(r);
   1373 }
   1374 
   1375 boolean BitVector_equal(wordptr X, wordptr Y)               /* X == Y ?      */
   1376 {
   1377     N_word  size = size_(X);
   1378     N_word  mask = mask_(X);
   1379     boolean r = FALSE;
   1380 
   1381     if (bits_(X) == bits_(Y))
   1382     {
   1383         r = TRUE;
   1384         if (size > 0)
   1385         {
   1386             *(X+size-1) &= mask;
   1387             *(Y+size-1) &= mask;
   1388             while (r and (size-- > 0)) r = (*X++ == *Y++);
   1389         }
   1390     }
   1391     return(r);
   1392 }
   1393 
   1394 Z_int BitVector_Lexicompare(wordptr X, wordptr Y)           /* X <,=,> Y ?   */
   1395 {                                                           /*  unsigned     */
   1396     N_word  bitsX = bits_(X);
   1397     N_word  bitsY = bits_(Y);
   1398     N_word  size  = size_(X);
   1399     boolean r = TRUE;
   1400 
   1401     if (bitsX == bitsY)
   1402     {
   1403         if (size > 0)
   1404         {
   1405             X += size;
   1406             Y += size;
   1407             while (r and (size-- > 0)) r = (*(--X) == *(--Y));
   1408         }
   1409         if (r) return((Z_int) 0);
   1410         else
   1411         {
   1412             if (*X < *Y) return((Z_int) -1); else return((Z_int) 1);
   1413         }
   1414     }
   1415     else
   1416     {
   1417         if (bitsX < bitsY) return((Z_int) -1); else return((Z_int) 1);
   1418     }
   1419 }
   1420 
   1421 Z_int BitVector_Compare(wordptr X, wordptr Y)               /* X <,=,> Y ?   */
   1422 {                                                           /*   signed      */
   1423     N_word  bitsX = bits_(X);
   1424     N_word  bitsY = bits_(Y);
   1425     N_word  size  = size_(X);
   1426     N_word  mask  = mask_(X);
   1427     N_word  sign;
   1428     boolean r = TRUE;
   1429 
   1430     if (bitsX == bitsY)
   1431     {
   1432         if (size > 0)
   1433         {
   1434             X += size;
   1435             Y += size;
   1436             mask &= NOT (mask >> 1);
   1437             if ((sign = (*(X-1) AND mask)) != (*(Y-1) AND mask))
   1438             {
   1439                 if (sign) return((Z_int) -1); else return((Z_int) 1);
   1440             }
   1441             while (r and (size-- > 0)) r = (*(--X) == *(--Y));
   1442         }
   1443         if (r) return((Z_int) 0);
   1444         else
   1445         {
   1446             if (*X < *Y) return((Z_int) -1); else return((Z_int) 1);
   1447         }
   1448     }
   1449     else
   1450     {
   1451         if (bitsX < bitsY) return((Z_int) -1); else return((Z_int) 1);
   1452     }
   1453 }
   1454 
   1455 charptr BitVector_to_Hex(wordptr addr)
   1456 {
   1457     N_word  bits = bits_(addr);
   1458     N_word  size = size_(addr);
   1459     N_word  value;
   1460     N_word  count;
   1461     N_word  digit;
   1462     N_word  length;
   1463     charptr string;
   1464 
   1465     length = bits >> 2;
   1466     if (bits AND 0x0003) length++;
   1467     string = (charptr) yasm_xmalloc((size_t) (length+1));
   1468     if (string == NULL) return(NULL);
   1469     string += length;
   1470     *string = (N_char) '\0';
   1471     if (size > 0)
   1472     {
   1473         *(addr+size-1) &= mask_(addr);
   1474         while ((size-- > 0) and (length > 0))
   1475         {
   1476             value = *addr++;
   1477             count = BITS >> 2;
   1478             while ((count-- > 0) and (length > 0))
   1479             {
   1480                 digit = value AND 0x000F;
   1481                 if (digit > 9) digit += (N_word) 'A' - 10;
   1482                 else           digit += (N_word) '0';
   1483                 *(--string) = (N_char) digit; length--;
   1484                 if ((count > 0) and (length > 0)) value >>= 4;
   1485             }
   1486         }
   1487     }
   1488     return(string);
   1489 }
   1490 
   1491 ErrCode BitVector_from_Hex(wordptr addr, charptr string)
   1492 {
   1493     N_word  size = size_(addr);
   1494     N_word  mask = mask_(addr);
   1495     boolean ok = TRUE;
   1496     size_t  length;
   1497     N_word  value;
   1498     N_word  count;
   1499     int     digit;
   1500 
   1501     if (size > 0)
   1502     {
   1503         length = strlen((char *) string);
   1504         string += length;
   1505         while (size-- > 0)
   1506         {
   1507             value = 0;
   1508             for ( count = 0; (ok and (length > 0) and (count < BITS)); count += 4 )
   1509             {
   1510                 digit = (int) *(--string); length--;
   1511                 /* separate because toupper() is likely a macro! */
   1512                 digit = toupper(digit);
   1513                 if (digit == '_')
   1514                     count -= 4;
   1515                 else if ((ok = (isxdigit(digit) != 0)))
   1516                 {
   1517                     if (digit >= (int) 'A') digit -= (int) 'A' - 10;
   1518                     else                    digit -= (int) '0';
   1519                     value |= (((N_word) digit) << count);
   1520                 }
   1521             }
   1522             *addr++ = value;
   1523         }
   1524         *(--addr) &= mask;
   1525     }
   1526     if (ok) return(ErrCode_Ok);
   1527     else    return(ErrCode_Pars);
   1528 }
   1529 
   1530 ErrCode BitVector_from_Oct(wordptr addr, charptr string)
   1531 {
   1532     N_word  size = size_(addr);
   1533     N_word  mask = mask_(addr);
   1534     boolean ok = TRUE;
   1535     size_t  length;
   1536     N_word  value;
   1537     N_word  value_fill = 0;
   1538     N_word  count;
   1539     Z_word  count_fill = 0;
   1540     int     digit = 0;
   1541 
   1542     if (size > 0)
   1543     {
   1544         length = strlen((char *) string);
   1545         string += length;
   1546         while (size-- > 0)
   1547         {
   1548             value = value_fill;
   1549             for ( count = count_fill; (ok and (length > 0) and (count < BITS)); count += 3 )
   1550             {
   1551                 digit = (int) *(--string); length--;
   1552                 if (digit == '_')
   1553                     count -= 3;
   1554                 else if ((ok = (isdigit(digit) && digit != '8' && digit != '9')) != 0)
   1555                 {
   1556                     digit -= (int) '0';
   1557                     value |= (((N_word) digit) << count);
   1558                 }
   1559             }
   1560             count_fill = (Z_word)count-(Z_word)BITS;
   1561             if (count_fill > 0)
   1562                 value_fill = (((N_word) digit) >> (3-count_fill));
   1563             else
   1564                 value_fill = 0;
   1565             *addr++ = value;
   1566         }
   1567         *(--addr) &= mask;
   1568     }
   1569     if (ok) return(ErrCode_Ok);
   1570     else    return(ErrCode_Pars);
   1571 }
   1572 
   1573 charptr BitVector_to_Bin(wordptr addr)
   1574 {
   1575     N_word  size = size_(addr);
   1576     N_word  value;
   1577     N_word  count;
   1578     N_word  digit;
   1579     N_word  length;
   1580     charptr string;
   1581 
   1582     length = bits_(addr);
   1583     string = (charptr) yasm_xmalloc((size_t) (length+1));
   1584     if (string == NULL) return(NULL);
   1585     string += length;
   1586     *string = (N_char) '\0';
   1587     if (size > 0)
   1588     {
   1589         *(addr+size-1) &= mask_(addr);
   1590         while (size-- > 0)
   1591         {
   1592             value = *addr++;
   1593             count = BITS;
   1594             if (count > length) count = length;
   1595             while (count-- > 0)
   1596             {
   1597                 digit = value AND 0x0001;
   1598                 digit += (N_word) '0';
   1599                 *(--string) = (N_char) digit; length--;
   1600                 if (count > 0) value >>= 1;
   1601             }
   1602         }
   1603     }
   1604     return(string);
   1605 }
   1606 
   1607 ErrCode BitVector_from_Bin(wordptr addr, charptr string)
   1608 {
   1609     N_word  size = size_(addr);
   1610     N_word  mask = mask_(addr);
   1611     boolean ok = TRUE;
   1612     size_t  length;
   1613     N_word  value;
   1614     N_word  count;
   1615     int     digit;
   1616 
   1617     if (size > 0)
   1618     {
   1619         length = strlen((char *) string);
   1620         string += length;
   1621         while (size-- > 0)
   1622         {
   1623             value = 0;
   1624             for ( count = 0; (ok and (length > 0) and (count < BITS)); count++ )
   1625             {
   1626                 digit = (int) *(--string); length--;
   1627                 switch (digit)
   1628                 {
   1629                     case (int) '0':
   1630                         break;
   1631                     case (int) '1':
   1632                         value |= BITMASKTAB[count];
   1633                         break;
   1634                     case (int) '_':
   1635                         count--;
   1636                         break;
   1637                     default:
   1638                         ok = FALSE;
   1639                         break;
   1640                 }
   1641             }
   1642             *addr++ = value;
   1643         }
   1644         *(--addr) &= mask;
   1645     }
   1646     if (ok) return(ErrCode_Ok);
   1647     else    return(ErrCode_Pars);
   1648 }
   1649 
   1650 charptr BitVector_to_Dec(wordptr addr)
   1651 {
   1652     N_word  bits = bits_(addr);
   1653     N_word  length;
   1654     N_word  digits;
   1655     N_word  count;
   1656     N_word  q;
   1657     N_word  r;
   1658     boolean loop;
   1659     charptr result;
   1660     charptr string;
   1661     wordptr quot;
   1662     wordptr rest;
   1663     wordptr temp;
   1664     wordptr base;
   1665     Z_int   sign;
   1666 
   1667     length = (N_word) (bits / 3.3);        /* digits = bits * ln(2) / ln(10) */
   1668     length += 2; /* compensate for truncating & provide space for minus sign */
   1669     result = (charptr) yasm_xmalloc((size_t) (length+1));   /* remember the '\0'! */
   1670     if (result == NULL) return(NULL);
   1671     string = result;
   1672     sign = BitVector_Sign(addr);
   1673     if ((bits < 4) or (sign == 0))
   1674     {
   1675         if (bits > 0) digits = *addr; else digits = (N_word) 0;
   1676         if (sign < 0) digits = ((N_word)(-((Z_word)digits))) AND mask_(addr);
   1677         *string++ = (N_char) digits + (N_char) '0';
   1678         digits = 1;
   1679     }
   1680     else
   1681     {
   1682         quot = BitVector_Create(bits,FALSE);
   1683         if (quot == NULL)
   1684         {
   1685             BitVector_Dispose(result);
   1686             return(NULL);
   1687         }
   1688         rest = BitVector_Create(bits,FALSE);
   1689         if (rest == NULL)
   1690         {
   1691             BitVector_Dispose(result);
   1692             BitVector_Destroy(quot);
   1693             return(NULL);
   1694         }
   1695         temp = BitVector_Create(bits,FALSE);
   1696         if (temp == NULL)
   1697         {
   1698             BitVector_Dispose(result);
   1699             BitVector_Destroy(quot);
   1700             BitVector_Destroy(rest);
   1701             return(NULL);
   1702         }
   1703         base = BitVector_Create(bits,TRUE);
   1704         if (base == NULL)
   1705         {
   1706             BitVector_Dispose(result);
   1707             BitVector_Destroy(quot);
   1708             BitVector_Destroy(rest);
   1709             BitVector_Destroy(temp);
   1710             return(NULL);
   1711         }
   1712         if (sign < 0) BitVector_Negate(quot,addr);
   1713         else           BitVector_Copy(quot,addr);
   1714         digits = 0;
   1715         *base = EXP10;
   1716         loop = (bits >= BITS);
   1717         do
   1718         {
   1719             if (loop)
   1720             {
   1721                 BitVector_Copy(temp,quot);
   1722                 if (BitVector_Div_Pos(quot,temp,base,rest))
   1723                 {
   1724                     BitVector_Dispose(result); /* emergency exit */
   1725                     BitVector_Destroy(quot);
   1726                     BitVector_Destroy(rest);   /* should never occur */
   1727                     BitVector_Destroy(temp);   /* under normal operation */
   1728                     BitVector_Destroy(base);
   1729                     return(NULL);
   1730                 }
   1731                 loop = not BitVector_is_empty(quot);
   1732                 q = *rest;
   1733             }
   1734             else q = *quot;
   1735             count = LOG10;
   1736             while (((loop and (count-- > 0)) or ((not loop) and (q != 0))) and
   1737                 (digits < length))
   1738             {
   1739                 if (q != 0)
   1740                 {
   1741                     BIT_VECTOR_DIGITIZE(N_word,q,r)
   1742                 }
   1743                 else r = (N_word) '0';
   1744                 *string++ = (N_char) r;
   1745                 digits++;
   1746             }
   1747         }
   1748         while (loop and (digits < length));
   1749         BitVector_Destroy(quot);
   1750         BitVector_Destroy(rest);
   1751         BitVector_Destroy(temp);
   1752         BitVector_Destroy(base);
   1753     }
   1754     if ((sign < 0) and (digits < length))
   1755     {
   1756         *string++ = (N_char) '-';
   1757         digits++;
   1758     }
   1759     *string = (N_char) '\0';
   1760     BIT_VECTOR_reverse(result,digits);
   1761     return(result);
   1762 }
   1763 
   1764 struct BitVector_from_Dec_static_data {
   1765     wordptr term;
   1766     wordptr base;
   1767     wordptr prod;
   1768     wordptr rank;
   1769     wordptr temp;
   1770 };
   1771 
   1772 BitVector_from_Dec_static_data *BitVector_from_Dec_static_Boot(N_word bits)
   1773 {
   1774     BitVector_from_Dec_static_data *data;
   1775 
   1776     data = yasm_xmalloc(sizeof(BitVector_from_Dec_static_data));
   1777 
   1778     if (bits > 0)
   1779     {
   1780         data->term = BitVector_Create(BITS,FALSE);
   1781         data->base = BitVector_Create(BITS,FALSE);
   1782         data->prod = BitVector_Create(bits,FALSE);
   1783         data->rank = BitVector_Create(bits,FALSE);
   1784         data->temp = BitVector_Create(bits,FALSE);
   1785     } else {
   1786         data->term = NULL;
   1787         data->base = NULL;
   1788         data->prod = NULL;
   1789         data->rank = NULL;
   1790         data->temp = NULL;
   1791     }
   1792     return data;
   1793 }
   1794 
   1795 void BitVector_from_Dec_static_Shutdown(BitVector_from_Dec_static_data *data)
   1796 {
   1797     if (data) {
   1798         BitVector_Destroy(data->term);
   1799         BitVector_Destroy(data->base);
   1800         BitVector_Destroy(data->prod);
   1801         BitVector_Destroy(data->rank);
   1802         BitVector_Destroy(data->temp);
   1803     }
   1804     yasm_xfree(data);
   1805 }
   1806 
   1807 ErrCode BitVector_from_Dec_static(BitVector_from_Dec_static_data *data,
   1808                                   wordptr addr, charptr string)
   1809 {
   1810     ErrCode error = ErrCode_Ok;
   1811     N_word  bits = bits_(addr);
   1812     N_word  mask = mask_(addr);
   1813     boolean init = (bits > BITS);
   1814     boolean minus;
   1815     boolean shift;
   1816     boolean carry;
   1817     wordptr term;
   1818     wordptr base;
   1819     wordptr prod;
   1820     wordptr rank;
   1821     wordptr temp;
   1822     N_word  accu;
   1823     N_word  powr;
   1824     N_word  count;
   1825     size_t  length;
   1826     int     digit;
   1827 
   1828     if (bits > 0)
   1829     {
   1830         term = data->term;
   1831         base = data->base;
   1832         prod = data->prod;
   1833         rank = data->rank;
   1834         temp = data->temp;
   1835 
   1836         length = strlen((char *) string);
   1837         if (length == 0) return(ErrCode_Pars);
   1838         digit = (int) *string;
   1839         if ((minus = (digit == (int) '-')) or
   1840                      (digit == (int) '+'))
   1841         {
   1842             string++;
   1843             if (--length == 0) return(ErrCode_Pars);
   1844         }
   1845         string += length;
   1846         if (init)
   1847         {
   1848             BitVector_Empty(prod);
   1849             BitVector_Empty(rank);
   1850         }
   1851         BitVector_Empty(addr);
   1852         *base = EXP10;
   1853         shift = FALSE;
   1854         while ((not error) and (length > 0))
   1855         {
   1856             accu = 0;
   1857             powr = 1;
   1858             count = LOG10;
   1859             while ((not error) and (length > 0) and (count-- > 0))
   1860             {
   1861                 digit = (int) *(--string); length--;
   1862                 /* separate because isdigit() is likely a macro! */
   1863                 if (isdigit(digit) != 0)
   1864                 {
   1865                     accu += ((N_word) digit - (N_word) '0') * powr;
   1866                     powr *= 10;
   1867                 }
   1868                 else error = ErrCode_Pars;
   1869             }
   1870             if (not error)
   1871             {
   1872                 if (shift)
   1873                 {
   1874                     *term = accu;
   1875                     BitVector_Copy(temp,rank);
   1876                     error = BitVector_Mul_Pos(prod,temp,term,FALSE);
   1877                 }
   1878                 else
   1879                 {
   1880                     *prod = accu;
   1881                     if ((not init) and ((accu AND NOT mask) != 0)) error = ErrCode_Ovfl;
   1882                 }
   1883                 if (not error)
   1884                 {
   1885                     carry = FALSE;
   1886                     BitVector_compute(addr,addr,prod,FALSE,&carry);
   1887                     /* ignores sign change (= overflow) but not */
   1888                     /* numbers too large (= carry) for resulting bit vector */
   1889                     if (carry) error = ErrCode_Ovfl;
   1890                     else
   1891                     {
   1892                         if (length > 0)
   1893                         {
   1894                             if (shift)
   1895                             {
   1896                                 BitVector_Copy(temp,rank);
   1897                                 error = BitVector_Mul_Pos(rank,temp,base,FALSE);
   1898                             }
   1899                             else
   1900                             {
   1901                                 *rank = *base;
   1902                                 shift = TRUE;
   1903                             }
   1904                         }
   1905                     }
   1906                 }
   1907             }
   1908         }
   1909         if (not error and minus)
   1910         {
   1911             BitVector_Negate(addr,addr);
   1912             if ((*(addr + size_(addr) - 1) AND mask AND NOT (mask >> 1)) == 0)
   1913                 error = ErrCode_Ovfl;
   1914         }
   1915     }
   1916     return(error);
   1917 }
   1918 
   1919 ErrCode BitVector_from_Dec(wordptr addr, charptr string)
   1920 {
   1921     ErrCode error = ErrCode_Ok;
   1922     N_word  bits = bits_(addr);
   1923     N_word  mask = mask_(addr);
   1924     boolean init = (bits > BITS);
   1925     boolean minus;
   1926     boolean shift;
   1927     boolean carry;
   1928     wordptr term;
   1929     wordptr base;
   1930     wordptr prod;
   1931     wordptr rank;
   1932     wordptr temp;
   1933     N_word  accu;
   1934     N_word  powr;
   1935     N_word  count;
   1936     size_t  length;
   1937     int     digit;
   1938 
   1939     if (bits > 0)
   1940     {
   1941         length = strlen((char *) string);
   1942         if (length == 0) return(ErrCode_Pars);
   1943         digit = (int) *string;
   1944         if ((minus = (digit == (int) '-')) or
   1945                      (digit == (int) '+'))
   1946         {
   1947             string++;
   1948             if (--length == 0) return(ErrCode_Pars);
   1949         }
   1950         string += length;
   1951         term = BitVector_Create(BITS,FALSE);
   1952         if (term == NULL)
   1953         {
   1954             return(ErrCode_Null);
   1955         }
   1956         base = BitVector_Create(BITS,FALSE);
   1957         if (base == NULL)
   1958         {
   1959             BitVector_Destroy(term);
   1960             return(ErrCode_Null);
   1961         }
   1962         prod = BitVector_Create(bits,init);
   1963         if (prod == NULL)
   1964         {
   1965             BitVector_Destroy(term);
   1966             BitVector_Destroy(base);
   1967             return(ErrCode_Null);
   1968         }
   1969         rank = BitVector_Create(bits,init);
   1970         if (rank == NULL)
   1971         {
   1972             BitVector_Destroy(term);
   1973             BitVector_Destroy(base);
   1974             BitVector_Destroy(prod);
   1975             return(ErrCode_Null);
   1976         }
   1977         temp = BitVector_Create(bits,FALSE);
   1978         if (temp == NULL)
   1979         {
   1980             BitVector_Destroy(term);
   1981             BitVector_Destroy(base);
   1982             BitVector_Destroy(prod);
   1983             BitVector_Destroy(rank);
   1984             return(ErrCode_Null);
   1985         }
   1986         BitVector_Empty(addr);
   1987         *base = EXP10;
   1988         shift = FALSE;
   1989         while ((not error) and (length > 0))
   1990         {
   1991             accu = 0;
   1992             powr = 1;
   1993             count = LOG10;
   1994             while ((not error) and (length > 0) and (count-- > 0))
   1995             {
   1996                 digit = (int) *(--string); length--;
   1997                 /* separate because isdigit() is likely a macro! */
   1998                 if (isdigit(digit) != 0)
   1999                 {
   2000                     accu += ((N_word) digit - (N_word) '0') * powr;
   2001                     powr *= 10;
   2002                 }
   2003                 else error = ErrCode_Pars;
   2004             }
   2005             if (not error)
   2006             {
   2007                 if (shift)
   2008                 {
   2009                     *term = accu;
   2010                     BitVector_Copy(temp,rank);
   2011                     error = BitVector_Mul_Pos(prod,temp,term,FALSE);
   2012                 }
   2013                 else
   2014                 {
   2015                     *prod = accu;
   2016                     if ((not init) and ((accu AND NOT mask) != 0)) error = ErrCode_Ovfl;
   2017                 }
   2018                 if (not error)
   2019                 {
   2020                     carry = FALSE;
   2021                     BitVector_compute(addr,addr,prod,FALSE,&carry);
   2022                     /* ignores sign change (= overflow) but not */
   2023                     /* numbers too large (= carry) for resulting bit vector */
   2024                     if (carry) error = ErrCode_Ovfl;
   2025                     else
   2026                     {
   2027                         if (length > 0)
   2028                         {
   2029                             if (shift)
   2030                             {
   2031                                 BitVector_Copy(temp,rank);
   2032                                 error = BitVector_Mul_Pos(rank,temp,base,FALSE);
   2033                             }
   2034                             else
   2035                             {
   2036                                 *rank = *base;
   2037                                 shift = TRUE;
   2038                             }
   2039                         }
   2040                     }
   2041                 }
   2042             }
   2043         }
   2044         BitVector_Destroy(term);
   2045         BitVector_Destroy(base);
   2046         BitVector_Destroy(prod);
   2047         BitVector_Destroy(rank);
   2048         BitVector_Destroy(temp);
   2049         if (not error and minus)
   2050         {
   2051             BitVector_Negate(addr,addr);
   2052             if ((*(addr + size_(addr) - 1) AND mask AND NOT (mask >> 1)) == 0)
   2053                 error = ErrCode_Ovfl;
   2054         }
   2055     }
   2056     return(error);
   2057 }
   2058 
   2059 charptr BitVector_to_Enum(wordptr addr)
   2060 {
   2061     N_word  bits = bits_(addr);
   2062     N_word  sample;
   2063     N_word  length;
   2064     N_word  digits;
   2065     N_word  factor;
   2066     N_word  power;
   2067     N_word  start;
   2068     N_word  min;
   2069     N_word  max;
   2070     charptr string;
   2071     charptr target;
   2072     boolean comma;
   2073 
   2074     if (bits > 0)
   2075     {
   2076         sample = bits - 1;  /* greatest possible index */
   2077         length = 2;         /* account for index 0 and terminating '\0' */
   2078         digits = 1;         /* account for intervening dashes and commas */
   2079         factor = 1;
   2080         power = 10;
   2081         while (sample >= (power-1))
   2082         {
   2083             length += ++digits * factor * 6;  /* 9,90,900,9000,... (9*2/3 = 6) */
   2084             factor = power;
   2085             power *= 10;
   2086         }
   2087         if (sample > --factor)
   2088         {
   2089             sample -= factor;
   2090             factor = (N_word) ( sample / 3 );
   2091             factor = (factor << 1) + (sample - (factor * 3));
   2092             length += ++digits * factor;
   2093         }
   2094     }
   2095     else length = 1;
   2096     string = (charptr) yasm_xmalloc((size_t) length);
   2097     if (string == NULL) return(NULL);
   2098     start = 0;
   2099     comma = FALSE;
   2100     target = string;
   2101     while ((start < bits) and BitVector_interval_scan_inc(addr,start,&min,&max))
   2102     {
   2103         start = max + 2;
   2104         if (comma) *target++ = (N_char) ',';
   2105         if (min == max)
   2106         {
   2107             target += BIT_VECTOR_int2str(target,min);
   2108         }
   2109         else
   2110         {
   2111             if (min+1 == max)
   2112             {
   2113                 target += BIT_VECTOR_int2str(target,min);
   2114                 *target++ = (N_char) ',';
   2115                 target += BIT_VECTOR_int2str(target,max);
   2116             }
   2117             else
   2118             {
   2119                 target += BIT_VECTOR_int2str(target,min);
   2120                 *target++ = (N_char) '-';
   2121                 target += BIT_VECTOR_int2str(target,max);
   2122             }
   2123         }
   2124         comma = TRUE;
   2125     }
   2126     *target = (N_char) '\0';
   2127     return(string);
   2128 }
   2129 
   2130 ErrCode BitVector_from_Enum(wordptr addr, charptr string)
   2131 {
   2132     ErrCode error = ErrCode_Ok;
   2133     N_word  bits = bits_(addr);
   2134     N_word  state = 1;
   2135     N_word  token;
   2136     N_word  indx = 0;          /* silence compiler warning */
   2137     N_word  start = 0;         /* silence compiler warning */
   2138 
   2139     if (bits > 0)
   2140     {
   2141         BitVector_Empty(addr);
   2142         while ((not error) and (state != 0))
   2143         {
   2144             token = (N_word) *string;
   2145             /* separate because isdigit() is likely a macro! */
   2146             if (isdigit((int)token) != 0)
   2147             {
   2148                 string += BIT_VECTOR_str2int(string,&indx);
   2149                 if (indx < bits) token = (N_word) '0';
   2150                 else error = ErrCode_Indx;
   2151             }
   2152             else string++;
   2153             if (not error)
   2154             switch (state)
   2155             {
   2156                 case 1:
   2157                     switch (token)
   2158                     {
   2159                         case (N_word) '0':
   2160                             state = 2;
   2161                             break;
   2162                         case (N_word) '\0':
   2163                             state = 0;
   2164                             break;
   2165                         default:
   2166                             error = ErrCode_Pars;
   2167                             break;
   2168                     }
   2169                     break;
   2170                 case 2:
   2171                     switch (token)
   2172                     {
   2173                         case (N_word) '-':
   2174                             start = indx;
   2175                             state = 3;
   2176                             break;
   2177                         case (N_word) ',':
   2178                             BIT_VECTOR_SET_BIT(addr,indx)
   2179                             state = 5;
   2180                             break;
   2181                         case (N_word) '\0':
   2182                             BIT_VECTOR_SET_BIT(addr,indx)
   2183                             state = 0;
   2184                             break;
   2185                         default:
   2186                             error = ErrCode_Pars;
   2187                             break;
   2188                     }
   2189                     break;
   2190                 case 3:
   2191                     switch (token)
   2192                     {
   2193                         case (N_word) '0':
   2194                             if (start < indx)
   2195                                 BitVector_Interval_Fill(addr,start,indx);
   2196                             else if (start == indx)
   2197                                 BIT_VECTOR_SET_BIT(addr,indx)
   2198                             else error = ErrCode_Ordr;
   2199                             state = 4;
   2200                             break;
   2201                         default:
   2202                             error = ErrCode_Pars;
   2203                             break;
   2204                     }
   2205                     break;
   2206                 case 4:
   2207                     switch (token)
   2208                     {
   2209                         case (N_word) ',':
   2210                             state = 5;
   2211                             break;
   2212                         case (N_word) '\0':
   2213                             state = 0;
   2214                             break;
   2215                         default:
   2216                             error = ErrCode_Pars;
   2217                             break;
   2218                     }
   2219                     break;
   2220                 case 5:
   2221                     switch (token)
   2222                     {
   2223                         case (N_word) '0':
   2224                             state = 2;
   2225                             break;
   2226                         default:
   2227                             error = ErrCode_Pars;
   2228                             break;
   2229                     }
   2230                     break;
   2231             }
   2232         }
   2233     }
   2234     return(error);
   2235 }
   2236 
   2237 void BitVector_Bit_Off(wordptr addr, N_int indx)            /* X = X \ {x}   */
   2238 {
   2239     if (indx < bits_(addr)) BIT_VECTOR_CLR_BIT(addr,indx)
   2240 }
   2241 
   2242 void BitVector_Bit_On(wordptr addr, N_int indx)             /* X = X + {x}   */
   2243 {
   2244     if (indx < bits_(addr)) BIT_VECTOR_SET_BIT(addr,indx)
   2245 }
   2246 
   2247 boolean BitVector_bit_flip(wordptr addr, N_int indx)    /* X=(X+{x})\(X*{x}) */
   2248 {
   2249     N_word mask;
   2250 
   2251     if (indx < bits_(addr)) return( BIT_VECTOR_FLP_BIT(addr,indx,mask) );
   2252     else                    return( FALSE );
   2253 }
   2254 
   2255 boolean BitVector_bit_test(wordptr addr, N_int indx)        /* {x} in X ?    */
   2256 {
   2257     if (indx < bits_(addr)) return( BIT_VECTOR_TST_BIT(addr,indx) );
   2258     else                    return( FALSE );
   2259 }
   2260 
   2261 void BitVector_Bit_Copy(wordptr addr, N_int indx, boolean bit)
   2262 {
   2263     if (indx < bits_(addr))
   2264     {
   2265         if (bit) BIT_VECTOR_SET_BIT(addr,indx)
   2266         else     BIT_VECTOR_CLR_BIT(addr,indx)
   2267     }
   2268 }
   2269 
   2270 void BitVector_LSB(wordptr addr, boolean bit)
   2271 {
   2272     if (bits_(addr) > 0)
   2273     {
   2274         if (bit) *addr |= LSB;
   2275         else     *addr &= NOT LSB;
   2276     }
   2277 }
   2278 
   2279 void BitVector_MSB(wordptr addr, boolean bit)
   2280 {
   2281     N_word size = size_(addr);
   2282     N_word mask = mask_(addr);
   2283 
   2284     if (size-- > 0)
   2285     {
   2286         if (bit) *(addr+size) |= mask AND NOT (mask >> 1);
   2287         else     *(addr+size) &= NOT mask OR (mask >> 1);
   2288     }
   2289 }
   2290 
   2291 boolean BitVector_lsb_(wordptr addr)
   2292 {
   2293     if (size_(addr) > 0) return( (*addr AND LSB) != 0 );
   2294     else                 return( FALSE );
   2295 }
   2296 
   2297 boolean BitVector_msb_(wordptr addr)
   2298 {
   2299     N_word size = size_(addr);
   2300     N_word mask = mask_(addr);
   2301 
   2302     if (size-- > 0)
   2303         return( (*(addr+size) AND (mask AND NOT (mask >> 1))) != 0 );
   2304     else
   2305         return( FALSE );
   2306 }
   2307 
   2308 boolean BitVector_rotate_left(wordptr addr)
   2309 {
   2310     N_word  size = size_(addr);
   2311     N_word  mask = mask_(addr);
   2312     N_word  msb;
   2313     boolean carry_in;
   2314     boolean carry_out = FALSE;
   2315 
   2316     if (size > 0)
   2317     {
   2318         msb = mask AND NOT (mask >> 1);
   2319         carry_in = ((*(addr+size-1) AND msb) != 0);
   2320         while (size-- > 1)
   2321         {
   2322             carry_out = ((*addr AND MSB) != 0);
   2323             *addr <<= 1;
   2324             if (carry_in) *addr |= LSB;
   2325             carry_in = carry_out;
   2326             addr++;
   2327         }
   2328         carry_out = ((*addr AND msb) != 0);
   2329         *addr <<= 1;
   2330         if (carry_in) *addr |= LSB;
   2331         *addr &= mask;
   2332     }
   2333     return(carry_out);
   2334 }
   2335 
   2336 boolean BitVector_rotate_right(wordptr addr)
   2337 {
   2338     N_word  size = size_(addr);
   2339     N_word  mask = mask_(addr);
   2340     N_word  msb;
   2341     boolean carry_in;
   2342     boolean carry_out = FALSE;
   2343 
   2344     if (size > 0)
   2345     {
   2346         msb = mask AND NOT (mask >> 1);
   2347         carry_in = ((*addr AND LSB) != 0);
   2348         addr += size-1;
   2349         *addr &= mask;
   2350         carry_out = ((*addr AND LSB) != 0);
   2351         *addr >>= 1;
   2352         if (carry_in) *addr |= msb;
   2353         carry_in = carry_out;
   2354         addr--;
   2355         size--;
   2356         while (size-- > 0)
   2357         {
   2358             carry_out = ((*addr AND LSB) != 0);
   2359             *addr >>= 1;
   2360             if (carry_in) *addr |= MSB;
   2361             carry_in = carry_out;
   2362             addr--;
   2363         }
   2364     }
   2365     return(carry_out);
   2366 }
   2367 
   2368 boolean BitVector_shift_left(wordptr addr, boolean carry_in)
   2369 {
   2370     N_word  size = size_(addr);
   2371     N_word  mask = mask_(addr);
   2372     N_word  msb;
   2373     boolean carry_out = carry_in;
   2374 
   2375     if (size > 0)
   2376     {
   2377         msb = mask AND NOT (mask >> 1);
   2378         while (size-- > 1)
   2379         {
   2380             carry_out = ((*addr AND MSB) != 0);
   2381             *addr <<= 1;
   2382             if (carry_in) *addr |= LSB;
   2383             carry_in = carry_out;
   2384             addr++;
   2385         }
   2386         carry_out = ((*addr AND msb) != 0);
   2387         *addr <<= 1;
   2388         if (carry_in) *addr |= LSB;
   2389         *addr &= mask;
   2390     }
   2391     return(carry_out);
   2392 }
   2393 
   2394 boolean BitVector_shift_right(wordptr addr, boolean carry_in)
   2395 {
   2396     N_word  size = size_(addr);
   2397     N_word  mask = mask_(addr);
   2398     N_word  msb;
   2399     boolean carry_out = carry_in;
   2400 
   2401     if (size > 0)
   2402     {
   2403         msb = mask AND NOT (mask >> 1);
   2404         addr += size-1;
   2405         *addr &= mask;
   2406         carry_out = ((*addr AND LSB) != 0);
   2407         *addr >>= 1;
   2408         if (carry_in) *addr |= msb;
   2409         carry_in = carry_out;
   2410         addr--;
   2411         size--;
   2412         while (size-- > 0)
   2413         {
   2414             carry_out = ((*addr AND LSB) != 0);
   2415             *addr >>= 1;
   2416             if (carry_in) *addr |= MSB;
   2417             carry_in = carry_out;
   2418             addr--;
   2419         }
   2420     }
   2421     return(carry_out);
   2422 }
   2423 
   2424 void BitVector_Move_Left(wordptr addr, N_int bits)
   2425 {
   2426     N_word count;
   2427     N_word words;
   2428 
   2429     if (bits > 0)
   2430     {
   2431         count = bits AND MODMASK;
   2432         words = bits >> LOGBITS;
   2433         if (bits >= bits_(addr)) BitVector_Empty(addr);
   2434         else
   2435         {
   2436             while (count-- > 0) BitVector_shift_left(addr,0);
   2437             BitVector_Word_Insert(addr,0,words,TRUE);
   2438         }
   2439     }
   2440 }
   2441 
   2442 void BitVector_Move_Right(wordptr addr, N_int bits)
   2443 {
   2444     N_word count;
   2445     N_word words;
   2446 
   2447     if (bits > 0)
   2448     {
   2449         count = bits AND MODMASK;
   2450         words = bits >> LOGBITS;
   2451         if (bits >= bits_(addr)) BitVector_Empty(addr);
   2452         else
   2453         {
   2454             while (count-- > 0) BitVector_shift_right(addr,0);
   2455             BitVector_Word_Delete(addr,0,words,TRUE);
   2456         }
   2457     }
   2458 }
   2459 
   2460 void BitVector_Insert(wordptr addr, N_int offset, N_int count, boolean clear)
   2461 {
   2462     N_word bits = bits_(addr);
   2463     N_word last;
   2464 
   2465     if ((count > 0) and (offset < bits))
   2466     {
   2467         last = offset + count;
   2468         if (last < bits)
   2469         {
   2470             BitVector_Interval_Copy(addr,addr,last,offset,(bits-last));
   2471         }
   2472         else last = bits;
   2473         if (clear) BitVector_Interval_Empty(addr,offset,(last-1));
   2474     }
   2475 }
   2476 
   2477 void BitVector_Delete(wordptr addr, N_int offset, N_int count, boolean clear)
   2478 {
   2479     N_word bits = bits_(addr);
   2480     N_word last;
   2481 
   2482     if ((count > 0) and (offset < bits))
   2483     {
   2484         last = offset + count;
   2485         if (last < bits)
   2486         {
   2487             BitVector_Interval_Copy(addr,addr,offset,last,(bits-last));
   2488         }
   2489         else count = bits - offset;
   2490         if (clear) BitVector_Interval_Empty(addr,(bits-count),(bits-1));
   2491     }
   2492 }
   2493 
   2494 boolean BitVector_increment(wordptr addr)                   /* X++           */
   2495 {
   2496     N_word  size  = size_(addr);
   2497     N_word  mask  = mask_(addr);
   2498     wordptr last  = addr + size - 1;
   2499     boolean carry = TRUE;
   2500 
   2501     if (size > 0)
   2502     {
   2503         *last |= NOT mask;
   2504         while (carry and (size-- > 0))
   2505         {
   2506             carry = (++(*addr++) == 0);
   2507         }
   2508         *last &= mask;
   2509     }
   2510     return(carry);
   2511 }
   2512 
   2513 boolean BitVector_decrement(wordptr addr)                   /* X--           */
   2514 {
   2515     N_word  size  = size_(addr);
   2516     N_word  mask  = mask_(addr);
   2517     wordptr last  = addr + size - 1;
   2518     boolean carry = TRUE;
   2519 
   2520     if (size > 0)
   2521     {
   2522         *last &= mask;
   2523         while (carry and (size-- > 0))
   2524         {
   2525             carry = (*addr == 0);
   2526             --(*addr++);
   2527         }
   2528         *last &= mask;
   2529     }
   2530     return(carry);
   2531 }
   2532 
   2533 boolean BitVector_compute(wordptr X, wordptr Y, wordptr Z, boolean minus, boolean *carry)
   2534 {
   2535     N_word size = size_(X);
   2536     N_word mask = mask_(X);
   2537     N_word vv = 0;
   2538     N_word cc;
   2539     N_word mm;
   2540     N_word yy;
   2541     N_word zz;
   2542     N_word lo;
   2543     N_word hi;
   2544 
   2545     if (size > 0)
   2546     {
   2547         if (minus) cc = (*carry == 0);
   2548         else       cc = (*carry != 0);
   2549         /* deal with (size-1) least significant full words first: */
   2550         while (--size > 0)
   2551         {
   2552             yy = *Y++;
   2553             if (minus) zz = (N_word) NOT ( Z ? *Z++ : 0 );
   2554             else       zz = (N_word)     ( Z ? *Z++ : 0 );
   2555             lo = (yy AND LSB) + (zz AND LSB) + cc;
   2556             hi = (yy >> 1) + (zz >> 1) + (lo >> 1);
   2557             cc = ((hi AND MSB) != 0);
   2558             *X++ = (hi << 1) OR (lo AND LSB);
   2559         }
   2560         /* deal with most significant word (may be used only partially): */
   2561         yy = *Y AND mask;
   2562         if (minus) zz = (N_word) NOT ( Z ? *Z : 0 );
   2563         else       zz = (N_word)     ( Z ? *Z : 0 );
   2564         zz &= mask;
   2565         if (mask == LSB) /* special case, only one bit used */
   2566         {
   2567             vv = cc;
   2568             lo = yy + zz + cc;
   2569             cc = (lo >> 1);
   2570             vv ^= cc;
   2571             *X = lo AND LSB;
   2572         }
   2573         else
   2574         {
   2575             if (NOT mask) /* not all bits are used, but more than one */
   2576             {
   2577                 mm = (mask >> 1);
   2578                 vv = (yy AND mm) + (zz AND mm) + cc;
   2579                 mm = mask AND NOT mm;
   2580                 lo = yy + zz + cc;
   2581                 cc = (lo >> 1);
   2582                 vv ^= cc;
   2583                 vv &= mm;
   2584                 cc &= mm;
   2585                 *X = lo AND mask;
   2586             }
   2587             else /* other special case, all bits are used */
   2588             {
   2589                 mm = NOT MSB;
   2590                 lo = (yy AND mm) + (zz AND mm) + cc;
   2591                 vv = lo AND MSB;
   2592                 hi = ((yy AND MSB) >> 1) + ((zz AND MSB) >> 1) + (vv >> 1);
   2593                 cc = hi AND MSB;
   2594                 vv ^= cc;
   2595                 *X = (hi << 1) OR (lo AND mm);
   2596             }
   2597         }
   2598         if (minus) *carry = (cc == 0);
   2599         else       *carry = (cc != 0);
   2600     }
   2601     return(vv != 0);
   2602 }
   2603 
   2604 boolean BitVector_add(wordptr X, wordptr Y, wordptr Z, boolean *carry)
   2605 {
   2606     return(BitVector_compute(X,Y,Z,FALSE,carry));
   2607 }
   2608 
   2609 boolean BitVector_sub(wordptr X, wordptr Y, wordptr Z, boolean *carry)
   2610 {
   2611     return(BitVector_compute(X,Y,Z,TRUE,carry));
   2612 }
   2613 
   2614 boolean BitVector_inc(wordptr X, wordptr Y)
   2615 {
   2616     boolean carry = TRUE;
   2617 
   2618     return(BitVector_compute(X,Y,NULL,FALSE,&carry));
   2619 }
   2620 
   2621 boolean BitVector_dec(wordptr X, wordptr Y)
   2622 {
   2623     boolean carry = TRUE;
   2624 
   2625     return(BitVector_compute(X,Y,NULL,TRUE,&carry));
   2626 }
   2627 
   2628 void BitVector_Negate(wordptr X, wordptr Y)
   2629 {
   2630     N_word  size  = size_(X);
   2631     N_word  mask  = mask_(X);
   2632     boolean carry = TRUE;
   2633 
   2634     if (size > 0)
   2635     {
   2636         while (size-- > 0)
   2637         {
   2638             *X = NOT *Y++;
   2639             if (carry)
   2640             {
   2641                 carry = (++(*X) == 0);
   2642             }
   2643             X++;
   2644         }
   2645         *(--X) &= mask;
   2646     }
   2647 }
   2648 
   2649 void BitVector_Absolute(wordptr X, wordptr Y)
   2650 {
   2651     N_word size = size_(Y);
   2652     N_word mask = mask_(Y);
   2653 
   2654     if (size > 0)
   2655     {
   2656         if (*(Y+size-1) AND (mask AND NOT (mask >> 1))) BitVector_Negate(X,Y);
   2657         else                                             BitVector_Copy(X,Y);
   2658     }
   2659 }
   2660 
   2661 Z_int BitVector_Sign(wordptr addr)
   2662 {
   2663     N_word  size = size_(addr);
   2664     N_word  mask = mask_(addr);
   2665     wordptr last = addr + size - 1;
   2666     boolean r    = TRUE;
   2667 
   2668     if (size > 0)
   2669     {
   2670         *last &= mask;
   2671         while (r and (size-- > 0)) r = ( *addr++ == 0 );
   2672     }
   2673     if (r) return((Z_int) 0);
   2674     else
   2675     {
   2676         if (*last AND (mask AND NOT (mask >> 1))) return((Z_int) -1);
   2677         else                                      return((Z_int)  1);
   2678     }
   2679 }
   2680 
   2681 ErrCode BitVector_Mul_Pos(wordptr X, wordptr Y, wordptr Z, boolean strict)
   2682 {
   2683     N_word  mask;
   2684     N_word  limit;
   2685     N_word  count;
   2686     Z_long  last;
   2687     wordptr sign;
   2688     boolean carry;
   2689     boolean overflow;
   2690     boolean ok = TRUE;
   2691 
   2692     /*
   2693        Requirements:
   2694          -  X, Y and Z must be distinct
   2695          -  X and Y must have equal sizes (whereas Z may be any size!)
   2696          -  Z should always contain the SMALLER of the two factors Y and Z
   2697        Constraints:
   2698          -  The contents of Y (and of X, of course) are destroyed
   2699             (only Z is preserved!)
   2700     */
   2701 
   2702     if ((X == Y) or (X == Z) or (Y == Z)) return(ErrCode_Same);
   2703     if (bits_(X) != bits_(Y)) return(ErrCode_Size);
   2704     BitVector_Empty(X);
   2705     if (BitVector_is_empty(Y)) return(ErrCode_Ok); /* exit also taken if bits_(Y)==0 */
   2706     if ((last = Set_Max(Z)) < 0L) return(ErrCode_Ok);
   2707     limit = (N_word) last;
   2708     sign = Y + size_(Y) - 1;
   2709     mask = mask_(Y);
   2710     *sign &= mask;
   2711     mask &= NOT (mask >> 1);
   2712     for ( count = 0; (ok and (count <= limit)); count++ )
   2713     {
   2714         if ( BIT_VECTOR_TST_BIT(Z,count) )
   2715         {
   2716             carry = false;
   2717             overflow = BitVector_compute(X,X,Y,false,&carry);
   2718             if (strict) ok = not (carry or overflow);
   2719             else        ok = not  carry;
   2720         }
   2721         if (ok and (count < limit))
   2722         {
   2723             carry = BitVector_shift_left(Y,0);
   2724             if (strict)
   2725             {
   2726                 overflow = ((*sign AND mask) != 0);
   2727                 ok = not (carry or overflow);
   2728             }
   2729             else ok = not carry;
   2730         }
   2731     }
   2732     if (ok) return(ErrCode_Ok); else return(ErrCode_Ovfl);
   2733 }
   2734 
   2735 ErrCode BitVector_Multiply(wordptr X, wordptr Y, wordptr Z)
   2736 {
   2737     ErrCode error = ErrCode_Ok;
   2738     N_word  bit_x = bits_(X);
   2739     N_word  bit_y = bits_(Y);
   2740     N_word  bit_z = bits_(Z);
   2741     N_word  size;
   2742     N_word  mask;
   2743     N_word  msb;
   2744     wordptr ptr_y;
   2745     wordptr ptr_z;
   2746     boolean sgn_x;
   2747     boolean sgn_y;
   2748     boolean sgn_z;
   2749     boolean zero;
   2750     wordptr A;
   2751     wordptr B;
   2752 
   2753     /*
   2754        Requirements:
   2755          -  Y and Z must have equal sizes
   2756          -  X must have at least the same size as Y and Z but may be larger (!)
   2757        Features:
   2758          -  The contents of Y and Z are preserved
   2759          -  X may be identical with Y or Z (or both!)
   2760             (in-place multiplication is possible!)
   2761     */
   2762 
   2763     if ((bit_y != bit_z) or (bit_x < bit_y)) return(ErrCode_Size);
   2764     if (BitVector_is_empty(Y) or BitVector_is_empty(Z))
   2765     {
   2766         BitVector_Empty(X);
   2767     }
   2768     else
   2769     {
   2770         A = BitVector_Create(bit_y,FALSE);
   2771         if (A == NULL) return(ErrCode_Null);
   2772         B = BitVector_Create(bit_z,FALSE);
   2773         if (B == NULL) { BitVector_Destroy(A); return(ErrCode_Null); }
   2774         size  = size_(Y);
   2775         mask  = mask_(Y);
   2776         msb   = (mask AND NOT (mask >> 1));
   2777         sgn_y = (((*(Y+size-1) &= mask) AND msb) != 0);
   2778         sgn_z = (((*(Z+size-1) &= mask) AND msb) != 0);
   2779         sgn_x = sgn_y XOR sgn_z;
   2780         if (sgn_y) BitVector_Negate(A,Y); else BitVector_Copy(A,Y);
   2781         if (sgn_z) BitVector_Negate(B,Z); else BitVector_Copy(B,Z);
   2782         ptr_y = A + size;
   2783         ptr_z = B + size;
   2784         zero = TRUE;
   2785         while (zero and (size-- > 0))
   2786         {
   2787             zero &= (*(--ptr_y) == 0);
   2788             zero &= (*(--ptr_z) == 0);
   2789         }
   2790         if (*ptr_y > *ptr_z)
   2791         {
   2792             if (bit_x > bit_y)
   2793             {
   2794                 A = BitVector_Resize(A,bit_x);
   2795                 if (A == NULL) { BitVector_Destroy(B); return(ErrCode_Null); }
   2796             }
   2797             error = BitVector_Mul_Pos(X,A,B,TRUE);
   2798         }
   2799         else
   2800         {
   2801             if (bit_x > bit_z)
   2802             {
   2803                 B = BitVector_Resize(B,bit_x);
   2804                 if (B == NULL) { BitVector_Destroy(A); return(ErrCode_Null); }
   2805             }
   2806             error = BitVector_Mul_Pos(X,B,A,TRUE);
   2807         }
   2808         if ((not error) and sgn_x) BitVector_Negate(X,X);
   2809         BitVector_Destroy(A);
   2810         BitVector_Destroy(B);
   2811     }
   2812     return(error);
   2813 }
   2814 
   2815 ErrCode BitVector_Div_Pos(wordptr Q, wordptr X, wordptr Y, wordptr R)
   2816 {
   2817     N_word  bits = bits_(Q);
   2818     N_word  mask;
   2819     wordptr addr;
   2820     Z_long  last;
   2821     boolean flag;
   2822     boolean copy = FALSE; /* flags whether valid rest is in R (0) or X (1) */
   2823 
   2824     /*
   2825        Requirements:
   2826          -  All bit vectors must have equal sizes
   2827          -  Q, X, Y and R must all be distinct bit vectors
   2828          -  Y must be non-zero (of course!)
   2829        Constraints:
   2830          -  The contents of X (and Q and R, of course) are destroyed
   2831             (only Y is preserved!)
   2832     */
   2833 
   2834     if ((bits != bits_(X)) or (bits != bits_(Y)) or (bits != bits_(R)))
   2835         return(ErrCode_Size);
   2836     if ((Q == X) or (Q == Y) or (Q == R) or (X == Y) or (X == R) or (Y == R))
   2837         return(ErrCode_Same);
   2838     if (BitVector_is_empty(Y))
   2839         return(ErrCode_Zero);
   2840 
   2841     BitVector_Empty(R);
   2842     BitVector_Copy(Q,X);
   2843     if ((last = Set_Max(Q)) < 0L) return(ErrCode_Ok);
   2844     bits = (N_word) ++last;
   2845     while (bits-- > 0)
   2846     {
   2847         addr = Q + (bits >> LOGBITS);
   2848         mask = BITMASKTAB[bits AND MODMASK];
   2849         flag = ((*addr AND mask) != 0);
   2850         if (copy)
   2851         {
   2852             BitVector_shift_left(X,flag);
   2853             flag = FALSE;
   2854             BitVector_compute(R,X,Y,TRUE,&flag);
   2855         }
   2856         else
   2857         {
   2858             BitVector_shift_left(R,flag);
   2859             flag = FALSE;
   2860             BitVector_compute(X,R,Y,TRUE,&flag);
   2861         }
   2862         if (flag) *addr &= NOT mask;
   2863         else
   2864         {
   2865             *addr |= mask;
   2866             copy = not copy;
   2867         }
   2868     }
   2869     if (copy) BitVector_Copy(R,X);
   2870     return(ErrCode_Ok);
   2871 }
   2872 
   2873 ErrCode BitVector_Divide(wordptr Q, wordptr X, wordptr Y, wordptr R)
   2874 {
   2875     ErrCode error = ErrCode_Ok;
   2876     N_word  bits = bits_(Q);
   2877     N_word  size = size_(Q);
   2878     N_word  mask = mask_(Q);
   2879     N_word  msb = (mask AND NOT (mask >> 1));
   2880     boolean sgn_q;
   2881     boolean sgn_x;
   2882     boolean sgn_y;
   2883     wordptr A;
   2884     wordptr B;
   2885 
   2886     /*
   2887        Requirements:
   2888          -  All bit vectors must have equal sizes
   2889          -  Q and R must be two distinct bit vectors
   2890          -  Y must be non-zero (of course!)
   2891        Features:
   2892          -  The contents of X and Y are preserved
   2893          -  Q may be identical with X or Y (or both)
   2894             (in-place division is possible!)
   2895          -  R may be identical with X or Y (or both)
   2896             (but not identical with Q!)
   2897     */
   2898 
   2899     if ((bits != bits_(X)) or (bits != bits_(Y)) or (bits != bits_(R)))
   2900         return(ErrCode_Size);
   2901     if (Q == R)
   2902         return(ErrCode_Same);
   2903     if (BitVector_is_empty(Y))
   2904         return(ErrCode_Zero);
   2905 
   2906     if (BitVector_is_empty(X))
   2907     {
   2908         BitVector_Empty(Q);
   2909         BitVector_Empty(R);
   2910     }
   2911     else
   2912     {
   2913         A = BitVector_Create(bits,FALSE);
   2914         if (A == NULL) return(ErrCode_Null);
   2915         B = BitVector_Create(bits,FALSE);
   2916         if (B == NULL) { BitVector_Destroy(A); return(ErrCode_Null); }
   2917         size--;
   2918         sgn_x = (((*(X+size) &= mask) AND msb) != 0);
   2919         sgn_y = (((*(Y+size) &= mask) AND msb) != 0);
   2920         sgn_q = sgn_x XOR sgn_y;
   2921         if (sgn_x) BitVector_Negate(A,X); else BitVector_Copy(A,X);
   2922         if (sgn_y) BitVector_Negate(B,Y); else BitVector_Copy(B,Y);
   2923         if (not (error = BitVector_Div_Pos(Q,A,B,R)))
   2924         {
   2925             if (sgn_q) BitVector_Negate(Q,Q);
   2926             if (sgn_x) BitVector_Negate(R,R);
   2927         }
   2928         BitVector_Destroy(A);
   2929         BitVector_Destroy(B);
   2930     }
   2931     return(error);
   2932 }
   2933 
   2934 ErrCode BitVector_GCD(wordptr X, wordptr Y, wordptr Z)
   2935 {
   2936     ErrCode error = ErrCode_Ok;
   2937     N_word  bits = bits_(X);
   2938     N_word  size = size_(X);
   2939     N_word  mask = mask_(X);
   2940     N_word  msb = (mask AND NOT (mask >> 1));
   2941     boolean sgn_a;
   2942     boolean sgn_b;
   2943     boolean sgn_r;
   2944     wordptr Q;
   2945     wordptr R;
   2946     wordptr A;
   2947     wordptr B;
   2948     wordptr T;
   2949 
   2950     /*
   2951        Requirements:
   2952          -  All bit vectors must have equal sizes
   2953        Features:
   2954          -  The contents of Y and Z are preserved
   2955          -  X may be identical with Y or Z (or both)
   2956             (in-place is possible!)
   2957          -  GCD(0,z) == GCD(z,0) == z
   2958          -  negative values are handled correctly
   2959     */
   2960 
   2961     if ((bits != bits_(Y)) or (bits != bits_(Z))) return(ErrCode_Size);
   2962     if (BitVector_is_empty(Y))
   2963     {
   2964         if (X != Z) BitVector_Copy(X,Z);
   2965         return(ErrCode_Ok);
   2966     }
   2967     if (BitVector_is_empty(Z))
   2968     {
   2969         if (X != Y) BitVector_Copy(X,Y);
   2970         return(ErrCode_Ok);
   2971     }
   2972     Q = BitVector_Create(bits,false);
   2973     if (Q == NULL)
   2974     {
   2975         return(ErrCode_Null);
   2976     }
   2977     R = BitVector_Create(bits,FALSE);
   2978     if (R == NULL)
   2979     {
   2980         BitVector_Destroy(Q);
   2981         return(ErrCode_Null);
   2982     }
   2983     A = BitVector_Create(bits,FALSE);
   2984     if (A == NULL)
   2985     {
   2986         BitVector_Destroy(Q);
   2987         BitVector_Destroy(R);
   2988         return(ErrCode_Null);
   2989     }
   2990     B = BitVector_Create(bits,FALSE);
   2991     if (B == NULL)
   2992     {
   2993         BitVector_Destroy(Q);
   2994         BitVector_Destroy(R);
   2995         BitVector_Destroy(A);
   2996         return(ErrCode_Null);
   2997     }
   2998     size--;
   2999     sgn_a = (((*(Y+size) &= mask) AND msb) != 0);
   3000     sgn_b = (((*(Z+size) &= mask) AND msb) != 0);
   3001     if (sgn_a) BitVector_Negate(A,Y); else BitVector_Copy(A,Y);
   3002     if (sgn_b) BitVector_Negate(B,Z); else BitVector_Copy(B,Z);
   3003     while (not error)
   3004     {
   3005         if (not (error = BitVector_Div_Pos(Q,A,B,R)))
   3006         {
   3007             if (BitVector_is_empty(R)) break;
   3008             T = A; sgn_r = sgn_a;
   3009             A = B; sgn_a = sgn_b;
   3010             B = R; sgn_b = sgn_r;
   3011             R = T;
   3012         }
   3013     }
   3014     if (not error)
   3015     {
   3016         if (sgn_b) BitVector_Negate(X,B); else BitVector_Copy(X,B);
   3017     }
   3018     BitVector_Destroy(Q);
   3019     BitVector_Destroy(R);
   3020     BitVector_Destroy(A);
   3021     BitVector_Destroy(B);
   3022     return(error);
   3023 }
   3024 
   3025 ErrCode BitVector_GCD2(wordptr U, wordptr V, wordptr W, wordptr X, wordptr Y)
   3026 {
   3027     ErrCode error = ErrCode_Ok;
   3028     N_word  bits = bits_(U);
   3029     N_word  size = size_(U);
   3030     N_word  mask = mask_(U);
   3031     N_word  msb = (mask AND NOT (mask >> 1));
   3032     boolean minus;
   3033     boolean carry;
   3034     boolean sgn_q;
   3035     boolean sgn_r;
   3036     boolean sgn_a;
   3037     boolean sgn_b;
   3038     boolean sgn_x;
   3039     boolean sgn_y;
   3040     listptr L;
   3041     wordptr Q;
   3042     wordptr R;
   3043     wordptr A;
   3044     wordptr B;
   3045     wordptr T;
   3046     wordptr X1;
   3047     wordptr X2;
   3048     wordptr X3;
   3049     wordptr Y1;
   3050     wordptr Y2;
   3051     wordptr Y3;
   3052     wordptr Z;
   3053 
   3054     /*
   3055        Requirements:
   3056          -  All bit vectors must have equal sizes
   3057          -  U, V, and W must all be distinct bit vectors
   3058        Features:
   3059          -  The contents of X and Y are preserved
   3060          -  U, V and W may be identical with X or Y (or both,
   3061             provided that U, V and W are mutually distinct)
   3062             (i.e., in-place is possible!)
   3063          -  GCD(0,z) == GCD(z,0) == z
   3064          -  negative values are handled correctly
   3065     */
   3066 
   3067     if ((bits != bits_(V)) or
   3068         (bits != bits_(W)) or
   3069         (bits != bits_(X)) or
   3070         (bits != bits_(Y)))
   3071     {
   3072         return(ErrCode_Size);
   3073     }
   3074     if ((U == V) or (U == W) or (V == W))
   3075     {
   3076         return(ErrCode_Same);
   3077     }
   3078     if (BitVector_is_empty(X))
   3079     {
   3080         if (U != Y) BitVector_Copy(U,Y);
   3081         BitVector_Empty(V);
   3082         BitVector_Empty(W);
   3083         *W = 1;
   3084         return(ErrCode_Ok);
   3085     }
   3086     if (BitVector_is_empty(Y))
   3087     {
   3088         if (U != X) BitVector_Copy(U,X);
   3089         BitVector_Empty(V);
   3090         BitVector_Empty(W);
   3091         *V = 1;
   3092         return(ErrCode_Ok);
   3093     }
   3094     if ((L = BitVector_Create_List(bits,false,11)) == NULL)
   3095     {
   3096         return(ErrCode_Null);
   3097     }
   3098     Q  = L[0];
   3099     R  = L[1];
   3100     A  = L[2];
   3101     B  = L[3];
   3102     X1 = L[4];
   3103     X2 = L[5];
   3104     X3 = L[6];
   3105     Y1 = L[7];
   3106     Y2 = L[8];
   3107     Y3 = L[9];
   3108     Z  = L[10];
   3109     size--;
   3110     sgn_a = (((*(X+size) &= mask) AND msb) != 0);
   3111     sgn_b = (((*(Y+size) &= mask) AND msb) != 0);
   3112     if (sgn_a) BitVector_Negate(A,X); else BitVector_Copy(A,X);
   3113     if (sgn_b) BitVector_Negate(B,Y); else BitVector_Copy(B,Y);
   3114     BitVector_Empty(X1);
   3115     BitVector_Empty(X2);
   3116     *X1 = 1;
   3117     BitVector_Empty(Y1);
   3118     BitVector_Empty(Y2);
   3119     *Y2 = 1;
   3120     sgn_x = false;
   3121     sgn_y = false;
   3122     while (not error)
   3123     {
   3124         if ((error = BitVector_Div_Pos(Q,A,B,R)))
   3125         {
   3126             break;
   3127         }
   3128         if (BitVector_is_empty(R))
   3129         {
   3130             break;
   3131         }
   3132         sgn_q = sgn_a XOR sgn_b;
   3133 
   3134         if (sgn_x) BitVector_Negate(Z,X2); else BitVector_Copy(Z,X2);
   3135         if ((error = BitVector_Mul_Pos(X3,Z,Q,true)))
   3136         {
   3137             break;
   3138         }
   3139         minus = not (sgn_x XOR sgn_q);
   3140         carry = 0;
   3141         if (BitVector_compute(X3,X1,X3,minus,&carry))
   3142         {
   3143             error = ErrCode_Ovfl;
   3144             break;
   3145         }
   3146         sgn_x = (((*(X3+size) &= mask) AND msb) != 0);
   3147 
   3148         if (sgn_y) BitVector_Negate(Z,Y2); else BitVector_Copy(Z,Y2);
   3149         if ((error = BitVector_Mul_Pos(Y3,Z,Q,true)))
   3150         {
   3151             break;
   3152         }
   3153         minus = not (sgn_y XOR sgn_q);
   3154         carry = 0;
   3155         if (BitVector_compute(Y3,Y1,Y3,minus,&carry))
   3156         {
   3157             error = ErrCode_Ovfl;
   3158             break;
   3159         }
   3160         sgn_y = (((*(Y3+size) &= mask) AND msb) != 0);
   3161 
   3162         T = A; sgn_r = sgn_a;
   3163         A = B; sgn_a = sgn_b;
   3164         B = R; sgn_b = sgn_r;
   3165         R = T;
   3166 
   3167         T = X1;
   3168         X1 = X2;
   3169         X2 = X3;
   3170         X3 = T;
   3171 
   3172         T = Y1;
   3173         Y1 = Y2;
   3174         Y2 = Y3;
   3175         Y3 = T;
   3176     }
   3177     if (not error)
   3178     {
   3179         if (sgn_b) BitVector_Negate(U,B); else BitVector_Copy(U,B);
   3180         BitVector_Copy(V,X2);
   3181         BitVector_Copy(W,Y2);
   3182     }
   3183     BitVector_Destroy_List(L,11);
   3184     return(error);
   3185 }
   3186 
   3187 ErrCode BitVector_Power(wordptr X, wordptr Y, wordptr Z)
   3188 {
   3189     ErrCode error = ErrCode_Ok;
   3190     N_word  bits  = bits_(X);
   3191     boolean first = TRUE;
   3192     Z_long  last;
   3193     N_word  limit;
   3194     N_word  count;
   3195     wordptr T;
   3196 
   3197     /*
   3198        Requirements:
   3199          -  X must have at least the same size as Y but may be larger (!)
   3200          -  X may not be identical with Z
   3201          -  Z must be positive
   3202        Features:
   3203          -  The contents of Y and Z are preserved
   3204     */
   3205 
   3206     if (X == Z) return(ErrCode_Same);
   3207     if (bits < bits_(Y)) return(ErrCode_Size);
   3208     if (BitVector_msb_(Z)) return(ErrCode_Expo);
   3209     if ((last = Set_Max(Z)) < 0L)
   3210     {
   3211         if (bits < 2) return(ErrCode_Ovfl);
   3212         BitVector_Empty(X);
   3213         *X |= LSB;
   3214         return(ErrCode_Ok);                             /* anything ^ 0 == 1 */
   3215     }
   3216     if (BitVector_is_empty(Y))
   3217     {
   3218         if (X != Y) BitVector_Empty(X);
   3219         return(ErrCode_Ok);                    /* 0 ^ anything not zero == 0 */
   3220     }
   3221     T = BitVector_Create(bits,FALSE);
   3222     if (T == NULL) return(ErrCode_Null);
   3223     limit = (N_word) last;
   3224     for ( count = 0; ((!error) and (count <= limit)); count++ )
   3225     {
   3226         if ( BIT_VECTOR_TST_BIT(Z,count) )
   3227         {
   3228             if (first)
   3229             {
   3230                 first = FALSE;
   3231                 if (count) {             BitVector_Copy(X,T); }
   3232                 else       { if (X != Y) BitVector_Copy(X,Y); }
   3233             }
   3234             else error = BitVector_Multiply(X,T,X); /* order important because T > X */
   3235         }
   3236         if ((!error) and (count < limit))
   3237         {
   3238             if (count) error = BitVector_Multiply(T,T,T);
   3239             else       error = BitVector_Multiply(T,Y,Y);
   3240         }
   3241     }
   3242     BitVector_Destroy(T);
   3243     return(error);
   3244 }
   3245 
   3246 void BitVector_Block_Store(wordptr addr, charptr buffer, N_int length)
   3247 {
   3248     N_word  size = size_(addr);
   3249     N_word  mask = mask_(addr);
   3250     N_word  value;
   3251     N_word  count;
   3252 
   3253     /* provide translation for independence of endian-ness: */
   3254     if (size > 0)
   3255     {
   3256         while (size-- > 0)
   3257         {
   3258             value = 0;
   3259             for ( count = 0; (length > 0) and (count < BITS); count += 8 )
   3260             {
   3261                 value |= (((N_word) *buffer++) << count); length--;
   3262             }
   3263             *addr++ = value;
   3264         }
   3265         *(--addr) &= mask;
   3266     }
   3267 }
   3268 
   3269 charptr BitVector_Block_Read(wordptr addr, N_intptr length)
   3270 {
   3271     N_word  size = size_(addr);
   3272     N_word  value;
   3273     N_word  count;
   3274     charptr buffer;
   3275     charptr target;
   3276 
   3277     /* provide translation for independence of endian-ness: */
   3278     *length = size << FACTOR;
   3279     buffer = (charptr) yasm_xmalloc((size_t) ((*length)+1));
   3280     if (buffer == NULL) return(NULL);
   3281     target = buffer;
   3282     if (size > 0)
   3283     {
   3284         *(addr+size-1) &= mask_(addr);
   3285         while (size-- > 0)
   3286         {
   3287             value = *addr++;
   3288             count = BITS >> 3;
   3289             while (count-- > 0)
   3290             {
   3291                 *target++ = (N_char) (value AND 0x00FF);
   3292                 if (count > 0) value >>= 8;
   3293             }
   3294         }
   3295     }
   3296     *target = (N_char) '\0';
   3297     return(buffer);
   3298 }
   3299 
   3300 void BitVector_Word_Store(wordptr addr, N_int offset, N_int value)
   3301 {
   3302     N_word size = size_(addr);
   3303 
   3304     if (size > 0)
   3305     {
   3306         if (offset < size) *(addr+offset) = value;
   3307         *(addr+size-1) &= mask_(addr);
   3308     }
   3309 }
   3310 
   3311 N_int BitVector_Word_Read(wordptr addr, N_int offset)
   3312 {
   3313     N_word size = size_(addr);
   3314 
   3315     if (size > 0)
   3316     {
   3317         *(addr+size-1) &= mask_(addr);
   3318         if (offset < size) return( *(addr+offset) );
   3319     }
   3320     return( (N_int) 0 );
   3321 }
   3322 
   3323 void BitVector_Word_Insert(wordptr addr, N_int offset, N_int count,
   3324                            boolean clear)
   3325 {
   3326     N_word  size = size_(addr);
   3327     N_word  mask = mask_(addr);
   3328     wordptr last = addr+size-1;
   3329 
   3330     if (size > 0)
   3331     {
   3332         *last &= mask;
   3333         if (offset > size) offset = size;
   3334         BIT_VECTOR_ins_words(addr+offset,size-offset,count,clear);
   3335         *last &= mask;
   3336     }
   3337 }
   3338 
   3339 void BitVector_Word_Delete(wordptr addr, N_int offset, N_int count,
   3340                            boolean clear)
   3341 {
   3342     N_word  size = size_(addr);
   3343     N_word  mask = mask_(addr);
   3344     wordptr last = addr+size-1;
   3345 
   3346     if (size > 0)
   3347     {
   3348         *last &= mask;
   3349         if (offset > size) offset = size;
   3350         BIT_VECTOR_del_words(addr+offset,size-offset,count,clear);
   3351         *last &= mask;
   3352     }
   3353 }
   3354 
   3355 void BitVector_Chunk_Store(wordptr addr, N_int chunksize, N_int offset,
   3356                            N_long value)
   3357 {
   3358     N_word bits = bits_(addr);
   3359     N_word mask;
   3360     N_word temp;
   3361 
   3362     if ((chunksize > 0) and (offset < bits))
   3363     {
   3364         if (chunksize > LONGBITS) chunksize = LONGBITS;
   3365         if ((offset + chunksize) > bits) chunksize = bits - offset;
   3366         addr += offset >> LOGBITS;
   3367         offset &= MODMASK;
   3368         while (chunksize > 0)
   3369         {
   3370             mask = (N_word) (~0L << offset);
   3371             bits = offset + chunksize;
   3372             if (bits < BITS)
   3373             {
   3374                 mask &= (N_word) ~(~0L << bits);
   3375                 bits = chunksize;
   3376             }
   3377             else bits = BITS - offset;
   3378             temp = (N_word) (value << offset);
   3379             temp &= mask;
   3380             *addr &= NOT mask;
   3381             *addr++ |= temp;
   3382             value >>= bits;
   3383             chunksize -= bits;
   3384             offset = 0;
   3385         }
   3386     }
   3387 }
   3388 
   3389 N_long BitVector_Chunk_Read(wordptr addr, N_int chunksize, N_int offset)
   3390 {
   3391     N_word bits = bits_(addr);
   3392     N_word chunkbits = 0;
   3393     N_long value = 0L;
   3394     N_long temp;
   3395     N_word mask;
   3396 
   3397     if ((chunksize > 0) and (offset < bits))
   3398     {
   3399         if (chunksize > LONGBITS) chunksize = LONGBITS;
   3400         if ((offset + chunksize) > bits) chunksize = bits - offset;
   3401         addr += offset >> LOGBITS;
   3402         offset &= MODMASK;
   3403         while (chunksize > 0)
   3404         {
   3405             bits = offset + chunksize;
   3406             if (bits < BITS)
   3407             {
   3408                 mask = (N_word) ~(~0L << bits);
   3409                 bits = chunksize;
   3410             }
   3411             else
   3412             {
   3413                 mask = (N_word) ~0L;
   3414                 bits = BITS - offset;
   3415             }
   3416             temp = (N_long) ((*addr++ AND mask) >> offset);
   3417             value |= temp << chunkbits;
   3418             chunkbits += bits;
   3419             chunksize -= bits;
   3420             offset = 0;
   3421         }
   3422     }
   3423     return(value);
   3424 }
   3425 
   3426     /*******************/
   3427     /* set operations: */
   3428     /*******************/
   3429 
   3430 void Set_Union(wordptr X, wordptr Y, wordptr Z)             /* X = Y + Z     */
   3431 {
   3432     N_word bits = bits_(X);
   3433     N_word size = size_(X);
   3434     N_word mask = mask_(X);
   3435 
   3436     if ((size > 0) and (bits == bits_(Y)) and (bits == bits_(Z)))
   3437     {
   3438         while (size-- > 0) *X++ = *Y++ OR *Z++;
   3439         *(--X) &= mask;
   3440     }
   3441 }
   3442 
   3443 void Set_Intersection(wordptr X, wordptr Y, wordptr Z)      /* X = Y * Z     */
   3444 {
   3445     N_word bits = bits_(X);
   3446     N_word size = size_(X);
   3447     N_word mask = mask_(X);
   3448 
   3449     if ((size > 0) and (bits == bits_(Y)) and (bits == bits_(Z)))
   3450     {
   3451         while (size-- > 0) *X++ = *Y++ AND *Z++;
   3452         *(--X) &= mask;
   3453     }
   3454 }
   3455 
   3456 void Set_Difference(wordptr X, wordptr Y, wordptr Z)        /* X = Y \ Z     */
   3457 {
   3458     N_word bits = bits_(X);
   3459     N_word size = size_(X);
   3460     N_word mask = mask_(X);
   3461 
   3462     if ((size > 0) and (bits == bits_(Y)) and (bits == bits_(Z)))
   3463     {
   3464         while (size-- > 0) *X++ = *Y++ AND NOT *Z++;
   3465         *(--X) &= mask;
   3466     }
   3467 }
   3468 
   3469 void Set_ExclusiveOr(wordptr X, wordptr Y, wordptr Z)       /* X=(Y+Z)\(Y*Z) */
   3470 {
   3471     N_word bits = bits_(X);
   3472     N_word size = size_(X);
   3473     N_word mask = mask_(X);
   3474 
   3475     if ((size > 0) and (bits == bits_(Y)) and (bits == bits_(Z)))
   3476     {
   3477         while (size-- > 0) *X++ = *Y++ XOR *Z++;
   3478         *(--X) &= mask;
   3479     }
   3480 }
   3481 
   3482 void Set_Complement(wordptr X, wordptr Y)                   /* X = ~Y        */
   3483 {
   3484     N_word size = size_(X);
   3485     N_word mask = mask_(X);
   3486 
   3487     if ((size > 0) and (bits_(X) == bits_(Y)))
   3488     {
   3489         while (size-- > 0) *X++ = NOT *Y++;
   3490         *(--X) &= mask;
   3491     }
   3492 }
   3493 
   3494     /******************/
   3495     /* set functions: */
   3496     /******************/
   3497 
   3498 boolean Set_subset(wordptr X, wordptr Y)                    /* X subset Y ?  */
   3499 {
   3500     N_word size = size_(X);
   3501     boolean r = FALSE;
   3502 
   3503     if ((size > 0) and (bits_(X) == bits_(Y)))
   3504     {
   3505         r = TRUE;
   3506         while (r and (size-- > 0)) r = ((*X++ AND NOT *Y++) == 0);
   3507     }
   3508     return(r);
   3509 }
   3510 
   3511 N_int Set_Norm(wordptr addr)                                /* = | X |       */
   3512 {
   3513     byteptr byte;
   3514     N_word  bytes;
   3515     N_int   n;
   3516 
   3517     byte = (byteptr) addr;
   3518     bytes = size_(addr) << FACTOR;
   3519     n = 0;
   3520     while (bytes-- > 0)
   3521     {
   3522         n += BitVector_BYTENORM[*byte++];
   3523     }
   3524     return(n);
   3525 }
   3526 
   3527 N_int Set_Norm2(wordptr addr)                               /* = | X |       */
   3528 {
   3529     N_word  size = size_(addr);
   3530     N_word  w0,w1;
   3531     N_int   n,k;
   3532 
   3533     n = 0;
   3534     while (size-- > 0)
   3535     {
   3536         k = 0;
   3537         w1 = NOT (w0 = *addr++);
   3538         while (w0 and w1)
   3539         {
   3540             w0 &= w0 - 1;
   3541             w1 &= w1 - 1;
   3542             k++;
   3543         }
   3544         if (w0 == 0) n += k;
   3545         else         n += BITS - k;
   3546     }
   3547     return(n);
   3548 }
   3549 
   3550 N_int Set_Norm3(wordptr addr)                               /* = | X |       */
   3551 {
   3552     N_word  size  = size_(addr);
   3553     N_int   count = 0;
   3554     N_word  c;
   3555 
   3556     while (size-- > 0)
   3557     {
   3558         c = *addr++;
   3559         while (c)
   3560         {
   3561             c &= c - 1;
   3562             count++;
   3563         }
   3564     }
   3565     return(count);
   3566 }
   3567 
   3568 Z_long Set_Min(wordptr addr)                                /* = min(X)      */
   3569 {
   3570     boolean empty = TRUE;
   3571     N_word  size  = size_(addr);
   3572     N_word  i     = 0;
   3573     N_word  c     = 0;         /* silence compiler warning */
   3574 
   3575     while (empty and (size-- > 0))
   3576     {
   3577         if ((c = *addr++)) empty = false; else i++;
   3578     }
   3579     if (empty) return((Z_long) LONG_MAX);                  /* plus infinity  */
   3580     i <<= LOGBITS;
   3581     while (not (c AND LSB))
   3582     {
   3583         c >>= 1;
   3584         i++;
   3585     }
   3586     return((Z_long) i);
   3587 }
   3588 
   3589 Z_long Set_Max(wordptr addr)                                /* = max(X)      */
   3590 {
   3591     boolean empty = TRUE;
   3592     N_word  size  = size_(addr);
   3593     N_word  i     = size;
   3594     N_word  c     = 0;         /* silence compiler warning */
   3595 
   3596     addr += size-1;
   3597     while (empty and (size-- > 0))
   3598     {
   3599         if ((c = *addr--)) empty = false; else i--;
   3600     }
   3601     if (empty) return((Z_long) LONG_MIN);                  /* minus infinity */
   3602     i <<= LOGBITS;
   3603     while (not (c AND MSB))
   3604     {
   3605         c <<= 1;
   3606         i--;
   3607     }
   3608     return((Z_long) --i);
   3609 }
   3610 
   3611     /**********************************/
   3612     /* matrix-of-booleans operations: */
   3613     /**********************************/
   3614 
   3615 void Matrix_Multiplication(wordptr X, N_int rowsX, N_int colsX,
   3616                            wordptr Y, N_int rowsY, N_int colsY,
   3617                            wordptr Z, N_int rowsZ, N_int colsZ)
   3618 {
   3619     N_word i;
   3620     N_word j;
   3621     N_word k;
   3622     N_word indxX;
   3623     N_word indxY;
   3624     N_word indxZ;
   3625     N_word termX;
   3626     N_word termY;
   3627     N_word sum;
   3628 
   3629   if ((colsY == rowsZ) and (rowsX == rowsY) and (colsX == colsZ) and
   3630       (bits_(X) == rowsX*colsX) and
   3631       (bits_(Y) == rowsY*colsY) and
   3632       (bits_(Z) == rowsZ*colsZ))
   3633   {
   3634     for ( i = 0; i < rowsY; i++ )
   3635     {
   3636         termX = i * colsX;
   3637         termY = i * colsY;
   3638         for ( j = 0; j < colsZ; j++ )
   3639         {
   3640             indxX = termX + j;
   3641             sum = 0;
   3642             for ( k = 0; k < colsY; k++ )
   3643             {
   3644                 indxY = termY + k;
   3645                 indxZ = k * colsZ + j;
   3646                 if ( BIT_VECTOR_TST_BIT(Y,indxY) &&
   3647                      BIT_VECTOR_TST_BIT(Z,indxZ) ) sum ^= 1;
   3648             }
   3649             if (sum) BIT_VECTOR_SET_BIT(X,indxX)
   3650             else     BIT_VECTOR_CLR_BIT(X,indxX)
   3651         }
   3652     }
   3653   }
   3654 }
   3655 
   3656 void Matrix_Product(wordptr X, N_int rowsX, N_int colsX,
   3657                     wordptr Y, N_int rowsY, N_int colsY,
   3658                     wordptr Z, N_int rowsZ, N_int colsZ)
   3659 {
   3660     N_word i;
   3661     N_word j;
   3662     N_word k;
   3663     N_word indxX;
   3664     N_word indxY;
   3665     N_word indxZ;
   3666     N_word termX;
   3667     N_word termY;
   3668     N_word sum;
   3669 
   3670   if ((colsY == rowsZ) and (rowsX == rowsY) and (colsX == colsZ) and
   3671       (bits_(X) == rowsX*colsX) and
   3672       (bits_(Y) == rowsY*colsY) and
   3673       (bits_(Z) == rowsZ*colsZ))
   3674   {
   3675     for ( i = 0; i < rowsY; i++ )
   3676     {
   3677         termX = i * colsX;
   3678         termY = i * colsY;
   3679         for ( j = 0; j < colsZ; j++ )
   3680         {
   3681             indxX = termX + j;
   3682             sum = 0;
   3683             for ( k = 0; k < colsY; k++ )
   3684             {
   3685                 indxY = termY + k;
   3686                 indxZ = k * colsZ + j;
   3687                 if ( BIT_VECTOR_TST_BIT(Y,indxY) &&
   3688                      BIT_VECTOR_TST_BIT(Z,indxZ) ) sum |= 1;
   3689             }
   3690             if (sum) BIT_VECTOR_SET_BIT(X,indxX)
   3691             else     BIT_VECTOR_CLR_BIT(X,indxX)
   3692         }
   3693     }
   3694   }
   3695 }
   3696 
   3697 void Matrix_Closure(wordptr addr, N_int rows, N_int cols)
   3698 {
   3699     N_word i;
   3700     N_word j;
   3701     N_word k;
   3702     N_word ii;
   3703     N_word ij;
   3704     N_word ik;
   3705     N_word kj;
   3706     N_word termi;
   3707     N_word termk;
   3708 
   3709   if ((rows == cols) and (bits_(addr) == rows*cols))
   3710   {
   3711     for ( i = 0; i < rows; i++ )
   3712     {
   3713         ii = i * cols + i;
   3714         BIT_VECTOR_SET_BIT(addr,ii)
   3715     }
   3716     for ( k = 0; k < rows; k++ )
   3717     {
   3718         termk = k * cols;
   3719         for ( i = 0; i < rows; i++ )
   3720         {
   3721             termi = i * cols;
   3722             ik = termi + k;
   3723             for ( j = 0; j < rows; j++ )
   3724             {
   3725                 ij = termi + j;
   3726                 kj = termk + j;
   3727                 if ( BIT_VECTOR_TST_BIT(addr,ik) &&
   3728                      BIT_VECTOR_TST_BIT(addr,kj) )
   3729                      BIT_VECTOR_SET_BIT(addr,ij)
   3730             }
   3731         }
   3732     }
   3733   }
   3734 }
   3735 
   3736 void Matrix_Transpose(wordptr X, N_int rowsX, N_int colsX,
   3737                       wordptr Y, N_int rowsY, N_int colsY)
   3738 {
   3739     N_word  i;
   3740     N_word  j;
   3741     N_word  ii;
   3742     N_word  ij;
   3743     N_word  ji;
   3744     N_word  addii;
   3745     N_word  addij;
   3746     N_word  addji;
   3747     N_word  bitii;
   3748     N_word  bitij;
   3749     N_word  bitji;
   3750     N_word  termi;
   3751     N_word  termj;
   3752     boolean swap;
   3753 
   3754   /* BEWARE that "in-place" is ONLY possible if the matrix is quadratic!! */
   3755 
   3756   if ((rowsX == colsY) and (colsX == rowsY) and
   3757       (bits_(X) == rowsX*colsX) and
   3758       (bits_(Y) == rowsY*colsY))
   3759   {
   3760     if (rowsY == colsY) /* in-place is possible! */
   3761     {
   3762         for ( i = 0; i < rowsY; i++ )
   3763         {
   3764             termi = i * colsY;
   3765             for ( j = 0; j < i; j++ )
   3766             {
   3767                 termj = j * colsX;
   3768                 ij = termi + j;
   3769                 ji = termj + i;
   3770                 addij = ij >> LOGBITS;
   3771                 addji = ji >> LOGBITS;
   3772                 bitij = BITMASKTAB[ij AND MODMASK];
   3773                 bitji = BITMASKTAB[ji AND MODMASK];
   3774                 swap = ((*(Y+addij) AND bitij) != 0);
   3775                 if ((*(Y+addji) AND bitji) != 0)
   3776                      *(X+addij) |=     bitij;
   3777                 else
   3778                      *(X+addij) &= NOT bitij;
   3779                 if (swap)
   3780                      *(X+addji) |=     bitji;
   3781                 else
   3782                      *(X+addji) &= NOT bitji;
   3783             }
   3784             ii = termi + i;
   3785             addii = ii >> LOGBITS;
   3786             bitii = BITMASKTAB[ii AND MODMASK];
   3787             if ((*(Y+addii) AND bitii) != 0)
   3788                  *(X+addii) |=     bitii;
   3789             else
   3790                  *(X+addii) &= NOT bitii;
   3791         }
   3792     }
   3793     else /* rowsX != colsX, in-place is NOT possible! */
   3794     {
   3795         for ( i = 0; i < rowsY; i++ )
   3796         {
   3797             termi = i * colsY;
   3798             for ( j = 0; j < colsY; j++ )
   3799             {
   3800                 termj = j * colsX;
   3801                 ij = termi + j;
   3802                 ji = termj + i;
   3803                 addij = ij >> LOGBITS;
   3804                 addji = ji >> LOGBITS;
   3805                 bitij = BITMASKTAB[ij AND MODMASK];
   3806                 bitji = BITMASKTAB[ji AND MODMASK];
   3807                 if ((*(Y+addij) AND bitij) != 0)
   3808                      *(X+addji) |=     bitji;
   3809                 else
   3810                      *(X+addji) &= NOT bitji;
   3811             }
   3812         }
   3813     }
   3814   }
   3815 }
   3816 
   3817 /*****************************************************************************/
   3818 /*  VERSION:  6.4                                                            */
   3819 /*****************************************************************************/
   3820 /*  VERSION HISTORY:                                                         */
   3821 /*****************************************************************************/
   3822 /*                                                                           */
   3823 /*    Version 6.4  03.10.04  Added C++ comp. directives. Improved "Norm()".  */
   3824 /*    Version 6.3  28.09.02  Added "Create_List()" and "GCD2()".             */
   3825 /*    Version 6.2  15.09.02  Overhauled error handling. Fixed "GCD()".       */
   3826 /*    Version 6.1  08.10.01  Make VMS linker happy: _lsb,_msb => _lsb_,_msb_ */
   3827 /*    Version 6.0  08.10.00  Corrected overflow handling.                    */
   3828 /*    Version 5.8  14.07.00  Added "Power()". Changed "Copy()".              */
   3829 /*    Version 5.7  19.05.99  Quickened "Div_Pos()". Added "Product()".       */
   3830 /*    Version 5.6  02.11.98  Leading zeros eliminated in "to_Hex()".         */
   3831 /*    Version 5.5  21.09.98  Fixed bug of uninitialized "error" in Multiply. */
   3832 /*    Version 5.4  07.09.98  Fixed bug of uninitialized "error" in Divide.   */
   3833 /*    Version 5.3  12.05.98  Improved Norm. Completed history.               */
   3834 /*    Version 5.2  31.03.98  Improved Norm.                                  */
   3835 /*    Version 5.1  09.03.98  No changes.                                     */
   3836 /*    Version 5.0  01.03.98  Major additions and rewrite.                    */
   3837 /*    Version 4.2  16.07.97  Added is_empty, is_full.                        */
   3838 /*    Version 4.1  30.06.97  Added word-ins/del, move-left/right, inc/dec.   */
   3839 /*    Version 4.0  23.04.97  Rewrite. Added bit shift and bool. matrix ops.  */
   3840 /*    Version 3.2  04.02.97  Added interval methods.                         */
   3841 /*    Version 3.1  21.01.97  Fixed bug on 64 bit machines.                   */
   3842 /*    Version 3.0  12.01.97  Added flip.                                     */
   3843 /*    Version 2.0  14.12.96  Efficiency and consistency improvements.        */
   3844 /*    Version 1.1  08.01.96  Added Resize and ExclusiveOr.                   */
   3845 /*    Version 1.0  14.12.95  First version under UNIX (with Perl module).    */
   3846 /*    Version 0.9  01.11.93  First version of C library under MS-DOS.        */
   3847 /*    Version 0.1  ??.??.89  First version in Turbo Pascal under CP/M.       */
   3848 /*                                                                           */
   3849 /*****************************************************************************/
   3850 /*  AUTHOR:                                                                  */
   3851 /*****************************************************************************/
   3852 /*                                                                           */
   3853 /*    Steffen Beyer                                                          */
   3854 /*    mailto:sb (at) engelschall.com                                              */
   3855 /*    http://www.engelschall.com/u/sb/download/                              */
   3856 /*                                                                           */
   3857 /*****************************************************************************/
   3858 /*  COPYRIGHT:                                                               */
   3859 /*****************************************************************************/
   3860 /*                                                                           */
   3861 /*    Copyright (c) 1995 - 2004 by Steffen Beyer.                            */
   3862 /*    All rights reserved.                                                   */
   3863 /*                                                                           */
   3864 /*****************************************************************************/
   3865 /*  LICENSE:                                                                 */
   3866 /*****************************************************************************/
   3867 /* This package is free software; you can use, modify and redistribute       */
   3868 /* it under the same terms as Perl itself, i.e., under the terms of          */
   3869 /* the "Artistic License" or the "GNU General Public License".               */
   3870 /*                                                                           */
   3871 /* The C library at the core of this Perl module can additionally            */
   3872 /* be used, modified and redistributed under the terms of the                */
   3873 /* "GNU Library General Public License".                                     */
   3874 /*                                                                           */
   3875 /*****************************************************************************/
   3876 /*  ARTISTIC LICENSE:                                                        */
   3877 /*****************************************************************************/
   3878 /*
   3879                          The "Artistic License"
   3880 
   3881                                 Preamble
   3882 
   3883 The intent of this document is to state the conditions under which a
   3884 Package may be copied, such that the Copyright Holder maintains some
   3885 semblance of artistic control over the development of the package,
   3886 while giving the users of the package the right to use and distribute
   3887 the Package in a more-or-less customary fashion, plus the right to make
   3888 reasonable modifications.
   3889 
   3890 Definitions:
   3891 
   3892         "Package" refers to the collection of files distributed by the
   3893         Copyright Holder, and derivatives of that collection of files
   3894         created through textual modification.
   3895 
   3896         "Standard Version" refers to such a Package if it has not been
   3897         modified, or has been modified in accordance with the wishes
   3898         of the Copyright Holder as specified below.
   3899 
   3900         "Copyright Holder" is whoever is named in the copyright or
   3901         copyrights for the package.
   3902 
   3903         "You" is you, if you're thinking about copying or distributing
   3904         this Package.
   3905 
   3906         "Reasonable copying fee" is whatever you can justify on the
   3907         basis of media cost, duplication charges, time of people involved,
   3908         and so on.  (You will not be required to justify it to the
   3909         Copyright Holder, but only to the computing community at large
   3910         as a market that must bear the fee.)
   3911 
   3912         "Freely Available" means that no fee is charged for the item
   3913         itself, though there may be fees involved in handling the item.
   3914         It also means that recipients of the item may redistribute it
   3915         under the same conditions they received it.
   3916 
   3917 1. You may make and give away verbatim copies of the source form of the
   3918 Standard Version of this Package without restriction, provided that you
   3919 duplicate all of the original copyright notices and associated disclaimers.
   3920 
   3921 2. You may apply bug fixes, portability fixes and other modifications
   3922 derived from the Public Domain or from the Copyright Holder.  A Package
   3923 modified in such a way shall still be considered the Standard Version.
   3924 
   3925 3. You may otherwise modify your copy of this Package in any way, provided
   3926 that you insert a prominent notice in each changed file stating how and
   3927 when you changed that file, and provided that you do at least ONE of the
   3928 following:
   3929 
   3930     a) place your modifications in the Public Domain or otherwise make them
   3931     Freely Available, such as by posting said modifications to Usenet or
   3932     an equivalent medium, or placing the modifications on a major archive
   3933     site such as uunet.uu.net, or by allowing the Copyright Holder to include
   3934     your modifications in the Standard Version of the Package.
   3935 
   3936     b) use the modified Package only within your corporation or organization.
   3937 
   3938     c) rename any non-standard executables so the names do not conflict
   3939     with standard executables, which must also be provided, and provide
   3940     a separate manual page for each non-standard executable that clearly
   3941     documents how it differs from the Standard Version.
   3942 
   3943     d) make other distribution arrangements with the Copyright Holder.
   3944 
   3945 4. You may distribute the programs of this Package in object code or
   3946 executable form, provided that you do at least ONE of the following:
   3947 
   3948     a) distribute a Standard Version of the executables and library files,
   3949     together with instructions (in the manual page or equivalent) on where
   3950     to get the Standard Version.
   3951 
   3952     b) accompany the distribution with the machine-readable source of
   3953     the Package with your modifications.
   3954 
   3955     c) give non-standard executables non-standard names, and clearly
   3956     document the differences in manual pages (or equivalent), together
   3957     with instructions on where to get the Standard Version.
   3958 
   3959     d) make other distribution arrangements with the Copyright Holder.
   3960 
   3961 5. You may charge a reasonable copying fee for any distribution of this
   3962 Package.  You may charge any fee you choose for support of this
   3963 Package.  You may not charge a fee for this Package itself.  However,
   3964 you may distribute this Package in aggregate with other (possibly
   3965 commercial) programs as part of a larger (possibly commercial) software
   3966 distribution provided that you do not advertise this Package as a
   3967 product of your own.  You may embed this Package's interpreter within
   3968 an executable of yours (by linking); this shall be construed as a mere
   3969 form of aggregation, provided that the complete Standard Version of the
   3970 interpreter is so embedded.
   3971 
   3972 6. The scripts and library files supplied as input to or produced as
   3973 output from the programs of this Package do not automatically fall
   3974 under the copyright of this Package, but belong to whoever generated
   3975 them, and may be sold commercially, and may be aggregated with this
   3976 Package.  If such scripts or library files are aggregated with this
   3977 Package via the so-called "undump" or "unexec" methods of producing a
   3978 binary executable image, then distribution of such an image shall
   3979 neither be construed as a distribution of this Package nor shall it
   3980 fall under the restrictions of Paragraphs 3 and 4, provided that you do
   3981 not represent such an executable image as a Standard Version of this
   3982 Package.
   3983 
   3984 7. C subroutines (or comparably compiled subroutines in other
   3985 languages) supplied by you and linked into this Package in order to
   3986 emulate subroutines and variables of the language defined by this
   3987 Package shall not be considered part of this Package, but are the
   3988 equivalent of input as in Paragraph 6, provided these subroutines do
   3989 not change the language in any way that would cause it to fail the
   3990 regression tests for the language.
   3991 
   3992 8. Aggregation of this Package with a commercial distribution is always
   3993 permitted provided that the use of this Package is embedded; that is,
   3994 when no overt attempt is made to make this Package's interfaces visible
   3995 to the end user of the commercial distribution.  Such use shall not be
   3996 construed as a distribution of this Package.
   3997 
   3998 9. The name of the Copyright Holder may not be used to endorse or promote
   3999 products derived from this software without specific prior written permission.
   4000 
   4001 10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
   4002 IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
   4003 WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
   4004 
   4005                                 The End
   4006 */
   4007 /*****************************************************************************/
   4008 /*  GNU GENERAL PUBLIC LICENSE:                                              */
   4009 /*****************************************************************************/
   4010 /* This program is free software; you can redistribute it and/or             */
   4011 /* modify it under the terms of the GNU General Public License               */
   4012 /* as published by the Free Software Foundation; either version 2            */
   4013 /* of the License, or (at your option) any later version.                    */
   4014 /*                                                                           */
   4015 /* This program is distributed in the hope that it will be useful,           */
   4016 /* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
   4017 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
   4018 /* GNU General Public License for more details.                              */
   4019 /*                                                                           */
   4020 /* You should have received a copy of the GNU General Public License         */
   4021 /* along with this program; if not, write to the                             */
   4022 /* Free Software Foundation, Inc.,                                           */
   4023 /* 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.                 */
   4024 /*                                                                           */
   4025 /*****************************************************************************/
   4026 /*  GNU LIBRARY GENERAL PUBLIC LICENSE:                                      */
   4027 /*****************************************************************************/
   4028 /*    This library is free software; you can redistribute it and/or          */
   4029 /*    modify it under the terms of the GNU Library General Public            */
   4030 /*    License as published by the Free Software Foundation; either           */
   4031 /*    version 2 of the License, or (at your option) any later version.       */
   4032 /*                                                                           */
   4033 /*    This library is distributed in the hope that it will be useful,        */
   4034 /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
   4035 /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU       */
   4036 /*    Library General Public License for more details.                       */
   4037 /*                                                                           */
   4038 /*    You should have received a copy of the GNU Library General Public      */
   4039 /*    License along with this library; if not, write to the                  */
   4040 /*    Free Software Foundation, Inc.,                                        */
   4041 /*    59 Temple Place, Suite 330, Boston, MA 02111-1307 USA                  */
   4042 /*                                                                           */
   4043 /*    or download a copy from ftp://ftp.gnu.org/pub/gnu/COPYING.LIB-2.0      */
   4044 /*                                                                           */
   4045 /*****************************************************************************/
   4046