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
62const 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
112static N_word BITS;     /* = # of bits in machine word (must be power of 2)  */
113static N_word MODMASK;  /* = BITS - 1 (mask for calculating modulo BITS)     */
114static N_word LOGBITS;  /* = ld(BITS) (logarithmus dualis)                   */
115static N_word FACTOR;   /* = ld(BITS / 8) (ld of # of bytes)                 */
116
117static N_word LSB = 1;  /* = mask for least significant bit                  */
118static N_word MSB;      /* = mask for most significant bit                   */
119
120static N_word LONGBITS; /* = # of bits in unsigned long                      */
121
122static N_word LOG10;    /* = logarithm to base 10 of BITS - 1                */
123static 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
129static 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
172static N_word power10(N_word x)
173{
174    N_word y = 1;
175
176    while (x-- > 0) y *= 10;
177    return(y);
178}
179
180static void BIT_VECTOR_zro_words(wordptr addr, N_word count)
181{
182    BIT_VECTOR_ZERO_WORDS(addr,count)
183}
184
185static void BIT_VECTOR_cpy_words(wordptr target, wordptr source, N_word count)
186{
187    BIT_VECTOR_COPY_WORDS(target,source,count)
188}
189
190static 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
199static 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
213static 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
227static 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
246static 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
272static 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
296const 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
333ErrCode 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
385void BitVector_Shutdown(void)
386{
387    if (BITMASKTAB) yasm_xfree(BITMASKTAB);
388}
389
390N_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
399N_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
408const char * BitVector_Version(void)
409{
410    return("6.4");
411}
412
413N_int BitVector_Word_Bits(void)
414{
415    return(BITS);
416}
417
418N_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
435void BitVector_Dispose(charptr string)                      /* free string   */
436{
437    if (string != NULL) yasm_xfree((voidptr) string);
438}
439
440void 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
449void 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
464wordptr 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
490listptr 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
518wordptr 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
562wordptr BitVector_Shadow(wordptr addr)     /* makes new, same size but empty */
563{
564    return( BitVector_Create(bits_(addr),true) );
565}
566
567wordptr 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
579wordptr 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
601void 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
636void BitVector_Empty(wordptr addr)                        /* X = {}  clr all */
637{
638    N_word size = size_(addr);
639
640    BIT_VECTOR_ZERO_WORDS(addr,size)
641}
642
643void 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
656void 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
669void 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
698void 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
739void 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
778void 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
819void 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
860void 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
895boolean 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
969boolean 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
1045void 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
1259wordptr 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
1344boolean 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
1357boolean 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
1375boolean 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
1394Z_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
1421Z_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
1455charptr 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
1491ErrCode 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
1530ErrCode 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
1573charptr 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
1607ErrCode 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
1650charptr 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
1764struct BitVector_from_Dec_static_data {
1765    wordptr term;
1766    wordptr base;
1767    wordptr prod;
1768    wordptr rank;
1769    wordptr temp;
1770};
1771
1772BitVector_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
1795void 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
1807ErrCode 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
1919ErrCode 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
2059charptr 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
2130ErrCode 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
2237void 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
2242void 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
2247boolean 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
2255boolean 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
2261void 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
2270void 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
2279void 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
2291boolean BitVector_lsb_(wordptr addr)
2292{
2293    if (size_(addr) > 0) return( (*addr AND LSB) != 0 );
2294    else                 return( FALSE );
2295}
2296
2297boolean 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
2308boolean 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
2336boolean 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
2368boolean 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
2394boolean 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
2424void 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
2442void 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
2460void 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
2477void 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
2494boolean 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
2513boolean 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
2533boolean 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
2604boolean BitVector_add(wordptr X, wordptr Y, wordptr Z, boolean *carry)
2605{
2606    return(BitVector_compute(X,Y,Z,FALSE,carry));
2607}
2608
2609boolean BitVector_sub(wordptr X, wordptr Y, wordptr Z, boolean *carry)
2610{
2611    return(BitVector_compute(X,Y,Z,TRUE,carry));
2612}
2613
2614boolean BitVector_inc(wordptr X, wordptr Y)
2615{
2616    boolean carry = TRUE;
2617
2618    return(BitVector_compute(X,Y,NULL,FALSE,&carry));
2619}
2620
2621boolean BitVector_dec(wordptr X, wordptr Y)
2622{
2623    boolean carry = TRUE;
2624
2625    return(BitVector_compute(X,Y,NULL,TRUE,&carry));
2626}
2627
2628void 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
2649void 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
2661Z_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
2681ErrCode 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
2735ErrCode 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
2815ErrCode 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
2873ErrCode 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
2934ErrCode 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
3025ErrCode 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
3187ErrCode 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
3246void 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
3269charptr 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
3300void 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
3311N_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
3323void 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
3339void 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
3355void 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
3389N_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
3430void 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
3443void 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
3456void 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
3469void 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
3482void 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
3498boolean 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
3511N_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
3527N_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
3550N_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
3568Z_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
3589Z_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
3615void 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
3656void 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
3697void 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
3736void 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@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
3883The intent of this document is to state the conditions under which a
3884Package may be copied, such that the Copyright Holder maintains some
3885semblance of artistic control over the development of the package,
3886while giving the users of the package the right to use and distribute
3887the Package in a more-or-less customary fashion, plus the right to make
3888reasonable modifications.
3889
3890Definitions:
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
39171. You may make and give away verbatim copies of the source form of the
3918Standard Version of this Package without restriction, provided that you
3919duplicate all of the original copyright notices and associated disclaimers.
3920
39212. You may apply bug fixes, portability fixes and other modifications
3922derived from the Public Domain or from the Copyright Holder.  A Package
3923modified in such a way shall still be considered the Standard Version.
3924
39253. You may otherwise modify your copy of this Package in any way, provided
3926that you insert a prominent notice in each changed file stating how and
3927when you changed that file, and provided that you do at least ONE of the
3928following:
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
39454. You may distribute the programs of this Package in object code or
3946executable 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
39615. You may charge a reasonable copying fee for any distribution of this
3962Package.  You may charge any fee you choose for support of this
3963Package.  You may not charge a fee for this Package itself.  However,
3964you may distribute this Package in aggregate with other (possibly
3965commercial) programs as part of a larger (possibly commercial) software
3966distribution provided that you do not advertise this Package as a
3967product of your own.  You may embed this Package's interpreter within
3968an executable of yours (by linking); this shall be construed as a mere
3969form of aggregation, provided that the complete Standard Version of the
3970interpreter is so embedded.
3971
39726. The scripts and library files supplied as input to or produced as
3973output from the programs of this Package do not automatically fall
3974under the copyright of this Package, but belong to whoever generated
3975them, and may be sold commercially, and may be aggregated with this
3976Package.  If such scripts or library files are aggregated with this
3977Package via the so-called "undump" or "unexec" methods of producing a
3978binary executable image, then distribution of such an image shall
3979neither be construed as a distribution of this Package nor shall it
3980fall under the restrictions of Paragraphs 3 and 4, provided that you do
3981not represent such an executable image as a Standard Version of this
3982Package.
3983
39847. C subroutines (or comparably compiled subroutines in other
3985languages) supplied by you and linked into this Package in order to
3986emulate subroutines and variables of the language defined by this
3987Package shall not be considered part of this Package, but are the
3988equivalent of input as in Paragraph 6, provided these subroutines do
3989not change the language in any way that would cause it to fail the
3990regression tests for the language.
3991
39928. Aggregation of this Package with a commercial distribution is always
3993permitted provided that the use of this Package is embedded; that is,
3994when no overt attempt is made to make this Package's interfaces visible
3995to the end user of the commercial distribution.  Such use shall not be
3996construed as a distribution of this Package.
3997
39989. The name of the Copyright Holder may not be used to endorse or promote
3999products derived from this software without specific prior written permission.
4000
400110. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
4002IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
4003WARRANTIES 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