145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "util.h"
245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "coretype.h"
445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*****************************************************************************/
645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*  MODULE NAME:  BitVector.c                           MODULE TYPE:  (adt)  */
745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*****************************************************************************/
845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*  MODULE IMPORTS:                                                          */
945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*****************************************************************************/
1045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include <ctype.h>                                  /*  MODULE TYPE:  (sys)  */
1145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include <limits.h>                                 /*  MODULE TYPE:  (sys)  */
1245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include <string.h>                                 /*  MODULE TYPE:  (sys)  */
1345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*****************************************************************************/
1445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*  MODULE INTERFACE:                                                        */
1545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*****************************************************************************/
1645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "bitvect.h"
1745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
1845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* ToolBox.h */
1945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define and         &&      /* logical (boolean) operators: lower case */
2045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define or          ||
2145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define not         !
2245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
2345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define AND         &       /* binary (bitwise) operators: UPPER CASE */
2445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define OR          |
2545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define XOR         ^
2645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define NOT         ~
2745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define SHL         <<
2845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define SHR         >>
2945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
3045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#ifdef ENABLE_MODULO
3145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define mod         %       /* arithmetic operators */
3245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#endif
3345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
3445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define blockdef(name,size)         unsigned char name[size]
3545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define blocktypedef(name,size)     typedef unsigned char name[size]
3645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
3745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*****************************************************************************/
3845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*  MODULE RESOURCES:                                                        */
3945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*****************************************************************************/
4045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
4145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define bits_(BitVector) *(BitVector-3)
4245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define size_(BitVector) *(BitVector-2)
4345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define mask_(BitVector) *(BitVector-1)
4445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
4545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define  ERRCODE_TYPE  "sizeof(word) > sizeof(size_t)"
4645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define  ERRCODE_BITS  "bits(word) != sizeof(word)*8"
4745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define  ERRCODE_WORD  "bits(word) < 16"
4845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define  ERRCODE_LONG  "bits(word) > bits(long)"
4945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define  ERRCODE_POWR  "bits(word) != 2^x"
5045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define  ERRCODE_LOGA  "bits(word) != 2^ld(bits(word))"
5145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define  ERRCODE_NULL  "unable to allocate memory"
5245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define  ERRCODE_INDX  "index out of range"
5345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define  ERRCODE_ORDR  "minimum > maximum index"
5445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define  ERRCODE_SIZE  "bit vector size mismatch"
5545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define  ERRCODE_PARS  "input string syntax error"
5645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define  ERRCODE_OVFL  "numeric overflow error"
5745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define  ERRCODE_SAME  "result vector(s) must be distinct"
5845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define  ERRCODE_EXPO  "exponent must be positive"
5945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define  ERRCODE_ZERO  "division by zero error"
6045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define  ERRCODE_OOPS  "unexpected internal error - please contact author"
6145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
6245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgconst N_int BitVector_BYTENORM[256] =
6345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
6445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    0x00, 0x01, 0x01, 0x02,  0x01, 0x02, 0x02, 0x03,
6545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    0x01, 0x02, 0x02, 0x03,  0x02, 0x03, 0x03, 0x04, /* 0x00 */
6645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    0x01, 0x02, 0x02, 0x03,  0x02, 0x03, 0x03, 0x04,
6745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05, /* 0x10 */
6845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    0x01, 0x02, 0x02, 0x03,  0x02, 0x03, 0x03, 0x04,
6945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05, /* 0x20 */
7045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05,
7145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06, /* 0x30 */
7245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    0x01, 0x02, 0x02, 0x03,  0x02, 0x03, 0x03, 0x04,
7345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05, /* 0x40 */
7445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05,
7545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06, /* 0x50 */
7645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05,
7745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06, /* 0x60 */
7845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06,
7945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    0x04, 0x05, 0x05, 0x06,  0x05, 0x06, 0x06, 0x07, /* 0x70 */
8045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    0x01, 0x02, 0x02, 0x03,  0x02, 0x03, 0x03, 0x04,
8145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05, /* 0x80 */
8245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05,
8345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06, /* 0x90 */
8445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05,
8545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06, /* 0xA0 */
8645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06,
8745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    0x04, 0x05, 0x05, 0x06,  0x05, 0x06, 0x06, 0x07, /* 0xB0 */
8845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05,
8945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06, /* 0xC0 */
9045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06,
9145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    0x04, 0x05, 0x05, 0x06,  0x05, 0x06, 0x06, 0x07, /* 0xD0 */
9245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06,
9345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    0x04, 0x05, 0x05, 0x06,  0x05, 0x06, 0x06, 0x07, /* 0xE0 */
9445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    0x04, 0x05, 0x05, 0x06,  0x05, 0x06, 0x06, 0x07,
9545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    0x05, 0x06, 0x06, 0x07,  0x06, 0x07, 0x07, 0x08  /* 0xF0 */
9645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
9745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
9845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*****************************************************************************/
9945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*  MODULE IMPLEMENTATION:                                                   */
10045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*****************************************************************************/
10145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
10245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /**********************************************/
10345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* global implementation-intrinsic constants: */
10445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /**********************************************/
10545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
10645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define BIT_VECTOR_HIDDEN_WORDS 3
10745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
10845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*****************************************************************/
10945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* global machine-dependent constants (set by "BitVector_Boot"): */
11045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*****************************************************************/
11145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
11245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic N_word BITS;     /* = # of bits in machine word (must be power of 2)  */
11345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic N_word MODMASK;  /* = BITS - 1 (mask for calculating modulo BITS)     */
11445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic N_word LOGBITS;  /* = ld(BITS) (logarithmus dualis)                   */
11545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic N_word FACTOR;   /* = ld(BITS / 8) (ld of # of bytes)                 */
11645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
11745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic N_word LSB = 1;  /* = mask for least significant bit                  */
11845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic N_word MSB;      /* = mask for most significant bit                   */
11945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
12045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic N_word LONGBITS; /* = # of bits in unsigned long                      */
12145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
12245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic N_word LOG10;    /* = logarithm to base 10 of BITS - 1                */
12345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic N_word EXP10;    /* = largest possible power of 10 in signed int      */
12445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
12545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /********************************************************************/
12645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* global bit mask table for fast access (set by "BitVector_Boot"): */
12745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /********************************************************************/
12845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
12945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic wordptr BITMASKTAB;
13045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
13145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*****************************/
13245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* global macro definitions: */
13345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*****************************/
13445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
13545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define BIT_VECTOR_ZERO_WORDS(target,count) \
13645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (count-- > 0) *target++ = 0;
13745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
13845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define BIT_VECTOR_FILL_WORDS(target,fill,count) \
13945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (count-- > 0) *target++ = fill;
14045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
14145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define BIT_VECTOR_FLIP_WORDS(target,flip,count) \
14245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (count-- > 0) *target++ ^= flip;
14345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
14445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define BIT_VECTOR_COPY_WORDS(target,source,count) \
14545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (count-- > 0) *target++ = *source++;
14645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
14745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define BIT_VECTOR_BACK_WORDS(target,source,count) \
14845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    { target += count; source += count; while (count-- > 0) *--target = *--source; }
14945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
15045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define BIT_VECTOR_CLR_BIT(address,index) \
15145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    *(address+(index>>LOGBITS)) &= NOT BITMASKTAB[index AND MODMASK];
15245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
15345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define BIT_VECTOR_SET_BIT(address,index) \
15445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    *(address+(index>>LOGBITS)) |= BITMASKTAB[index AND MODMASK];
15545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
15645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define BIT_VECTOR_TST_BIT(address,index) \
15745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    ((*(address+(index>>LOGBITS)) AND BITMASKTAB[index AND MODMASK]) != 0)
15845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
15945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define BIT_VECTOR_FLP_BIT(address,index,mask) \
16045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    (mask = BITMASKTAB[index AND MODMASK]), \
16145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    (((*(addr+(index>>LOGBITS)) ^= mask) AND mask) != 0)
16245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
16345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define BIT_VECTOR_DIGITIZE(type,value,digit) \
16445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    value = (type) ((digit = value) / 10); \
16545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    digit -= value * 10; \
16645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    digit += (type) '0';
16745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
16845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*********************************************************/
16945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* private low-level functions (potentially dangerous!): */
17045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*********************************************************/
17145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
17245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic N_word power10(N_word x)
17345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
17445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word y = 1;
17545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
17645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (x-- > 0) y *= 10;
17745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(y);
17845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
17945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
18045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void BIT_VECTOR_zro_words(wordptr addr, N_word count)
18145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
18245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    BIT_VECTOR_ZERO_WORDS(addr,count)
18345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
18445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
18545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void BIT_VECTOR_cpy_words(wordptr target, wordptr source, N_word count)
18645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
18745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    BIT_VECTOR_COPY_WORDS(target,source,count)
18845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
18945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
19045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void BIT_VECTOR_mov_words(wordptr target, wordptr source, N_word count)
19145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
19245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (target != source)
19345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
19445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (target < source) BIT_VECTOR_COPY_WORDS(target,source,count)
19545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else                 BIT_VECTOR_BACK_WORDS(target,source,count)
19645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
19745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
19845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
19945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void BIT_VECTOR_ins_words(wordptr addr, N_word total, N_word count,
20045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                 boolean clear)
20145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
20245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word length;
20345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
20445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((total > 0) and (count > 0))
20545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
20645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (count > total) count = total;
20745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        length = total - count;
20845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (length > 0) BIT_VECTOR_mov_words(addr+count,addr,length);
20945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (clear)      BIT_VECTOR_zro_words(addr,count);
21045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
21145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
21245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
21345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void BIT_VECTOR_del_words(wordptr addr, N_word total, N_word count,
21445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                 boolean clear)
21545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
21645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word length;
21745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
21845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((total > 0) and (count > 0))
21945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
22045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (count > total) count = total;
22145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        length = total - count;
22245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (length > 0) BIT_VECTOR_mov_words(addr,addr+count,length);
22345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (clear)      BIT_VECTOR_zro_words(addr+length,count);
22445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
22545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
22645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
22745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic void BIT_VECTOR_reverse(charptr string, N_word length)
22845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
22945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    charptr last;
23045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_char  temp;
23145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
23245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (length > 1)
23345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
23445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        last = string + length - 1;
23545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (string < last)
23645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
23745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            temp = *string;
23845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *string = *last;
23945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *last = temp;
24045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            string++;
24145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            last--;
24245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
24345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
24445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
24545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
24645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic N_word BIT_VECTOR_int2str(charptr string, N_word value)
24745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
24845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  length;
24945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  digit;
25045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    charptr work;
25145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
25245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    work = string;
25345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (value > 0)
25445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
25545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        length = 0;
25645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (value > 0)
25745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
25845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            BIT_VECTOR_DIGITIZE(N_word,value,digit)
25945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *work++ = (N_char) digit;
26045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            length++;
26145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
26245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BIT_VECTOR_reverse(string,length);
26345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
26445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    else
26545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
26645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        length = 1;
26745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *work++ = (N_char) '0';
26845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
26945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(length);
27045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
27145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
27245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic N_word BIT_VECTOR_str2int(charptr string, N_word *value)
27345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
27445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  length;
27545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  digit;
27645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
27745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    *value = 0;
27845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    length = 0;
27945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    digit = (N_word) *string++;
28045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* separate because isdigit() is likely a macro! */
28145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (isdigit((int)digit) != 0)
28245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
28345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        length++;
28445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        digit -= (N_word) '0';
28545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (*value) *value *= 10;
28645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *value += digit;
28745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        digit = (N_word) *string++;
28845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
28945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(length);
29045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
29145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
29245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /********************************************/
29345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* routine to convert error code to string: */
29445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /********************************************/
29545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
29645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgconst char * BitVector_Error(ErrCode error)
29745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
29845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    switch (error)
29945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
30045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case ErrCode_Ok:   return(     NULL     ); break;
30145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case ErrCode_Type: return( ERRCODE_TYPE ); break;
30245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case ErrCode_Bits: return( ERRCODE_BITS ); break;
30345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case ErrCode_Word: return( ERRCODE_WORD ); break;
30445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case ErrCode_Long: return( ERRCODE_LONG ); break;
30545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case ErrCode_Powr: return( ERRCODE_POWR ); break;
30645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case ErrCode_Loga: return( ERRCODE_LOGA ); break;
30745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case ErrCode_Null: return( ERRCODE_NULL ); break;
30845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case ErrCode_Indx: return( ERRCODE_INDX ); break;
30945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case ErrCode_Ordr: return( ERRCODE_ORDR ); break;
31045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case ErrCode_Size: return( ERRCODE_SIZE ); break;
31145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case ErrCode_Pars: return( ERRCODE_PARS ); break;
31245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case ErrCode_Ovfl: return( ERRCODE_OVFL ); break;
31345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case ErrCode_Same: return( ERRCODE_SAME ); break;
31445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case ErrCode_Expo: return( ERRCODE_EXPO ); break;
31545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        case ErrCode_Zero: return( ERRCODE_ZERO ); break;
31645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        default:           return( ERRCODE_OOPS ); break;
31745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
31845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
31945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
32045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*****************************************/
32145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* automatic self-configuration routine: */
32245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*****************************************/
32345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
32445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*******************************************************/
32545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*                                                     */
32645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*   MUST be called once prior to any other function   */
32745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*   to initialize the machine dependent constants     */
32845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*   of this package! (But call only ONCE, or you      */
32945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*   will suffer memory leaks!)                        */
33045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*                                                     */
33145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*******************************************************/
33245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
33345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgErrCode BitVector_Boot(void)
33445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
33545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_long longsample = 1L;
33645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word sample = LSB;
33745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word lsb;
33845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
33945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (sizeof(N_word) > sizeof(size_t)) return(ErrCode_Type);
34045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
34145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    BITS = 1;
34245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (sample <<= 1) BITS++;    /* determine # of bits in a machine word */
34345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
34445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (BITS != (sizeof(N_word) << 3)) return(ErrCode_Bits);
34545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
34645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (BITS < 16) return(ErrCode_Word);
34745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
34845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    LONGBITS = 1;
34945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (longsample <<= 1) LONGBITS++;  /* = # of bits in an unsigned long */
35045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
35145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (BITS > LONGBITS) return(ErrCode_Long);
35245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
35345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    LOGBITS = 0;
35445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    sample = BITS;
35545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    lsb = (sample AND LSB);
35645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while ((sample >>= 1) and (not lsb))
35745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
35845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        LOGBITS++;
35945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        lsb = (sample AND LSB);
36045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
36145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
36245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (sample) return(ErrCode_Powr);      /* # of bits is not a power of 2! */
36345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
36445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (BITS != (LSB << LOGBITS)) return(ErrCode_Loga);
36545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
36645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    MODMASK = BITS - 1;
36745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    FACTOR = LOGBITS - 3;  /* ld(BITS / 8) = ld(BITS) - ld(8) = ld(BITS) - 3 */
36845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    MSB = (LSB << MODMASK);
36945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
37045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    BITMASKTAB = (wordptr) yasm_xmalloc((size_t) (BITS << FACTOR));
37145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
37245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (BITMASKTAB == NULL) return(ErrCode_Null);
37345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
37445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for ( sample = 0; sample < BITS; sample++ )
37545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
37645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BITMASKTAB[sample] = (LSB << sample);
37745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
37845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
37945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    LOG10 = (N_word) (MODMASK * 0.30103); /* = (BITS - 1) * ( ln 2 / ln 10 ) */
38045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    EXP10 = power10(LOG10);
38145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
38245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(ErrCode_Ok);
38345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
38445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
38545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid BitVector_Shutdown(void)
38645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
38745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (BITMASKTAB) yasm_xfree(BITMASKTAB);
38845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
38945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
39045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgN_word BitVector_Size(N_int bits)           /* bit vector size (# of words)  */
39145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
39245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word size;
39345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
39445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    size = bits >> LOGBITS;
39545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bits AND MODMASK) size++;
39645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(size);
39745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
39845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
39945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgN_word BitVector_Mask(N_int bits)           /* bit vector mask (unused bits) */
40045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
40145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word mask;
40245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
40345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    mask = bits AND MODMASK;
40445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (mask) mask = (N_word) ~(~0L << mask); else mask = (N_word) ~0L;
40545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(mask);
40645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
40745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
40845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgconst char * BitVector_Version(void)
40945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
41045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return("6.4");
41145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
41245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
41345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgN_int BitVector_Word_Bits(void)
41445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
41545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(BITS);
41645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
41745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
41845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgN_int BitVector_Long_Bits(void)
41945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
42045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(LONGBITS);
42145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
42245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
42345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/********************************************************************/
42445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*                                                                  */
42545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*  WARNING: Do not "free()" constant character strings, i.e.,      */
42645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*           don't call "BitVector_Dispose()" for strings returned  */
42745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*           by "BitVector_Error()" or "BitVector_Version()"!       */
42845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*                                                                  */
42945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*  ONLY call this function for strings allocated with "malloc()",  */
43045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*  i.e., the strings returned by the functions "BitVector_to_*()"  */
43145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*  and "BitVector_Block_Read()"!                                   */
43245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*                                                                  */
43345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/********************************************************************/
43445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
43545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid BitVector_Dispose(charptr string)                      /* free string   */
43645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
43745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (string != NULL) yasm_xfree((voidptr) string);
43845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
43945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
44045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid BitVector_Destroy(wordptr addr)                        /* free bitvec   */
44145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
44245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (addr != NULL)
44345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
44445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        addr -= BIT_VECTOR_HIDDEN_WORDS;
44545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_xfree((voidptr) addr);
44645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
44745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
44845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
44945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid BitVector_Destroy_List(listptr list, N_int count)      /* free list     */
45045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
45145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    listptr slot;
45245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
45345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (list != NULL)
45445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
45545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        slot = list;
45645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (count-- > 0)
45745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
45845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            BitVector_Destroy(*slot++);
45945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
46045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        free((voidptr) list);
46145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
46245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
46345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
46445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgwordptr BitVector_Create(N_int bits, boolean clear)         /* malloc        */
46545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
46645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  size;
46745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  mask;
46845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  bytes;
46945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr addr;
47045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr zero;
47145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
47245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    size = BitVector_Size(bits);
47345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    mask = BitVector_Mask(bits);
47445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bytes = (size + BIT_VECTOR_HIDDEN_WORDS) << FACTOR;
47545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    addr = (wordptr) yasm_xmalloc((size_t) bytes);
47645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (addr != NULL)
47745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
47845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *addr++ = bits;
47945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *addr++ = size;
48045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *addr++ = mask;
48145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (clear)
48245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
48345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            zero = addr;
48445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            BIT_VECTOR_ZERO_WORDS(zero,size)
48545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
48645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
48745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(addr);
48845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
48945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
49045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orglistptr BitVector_Create_List(N_int bits, boolean clear, N_int count)
49145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
49245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    listptr list = NULL;
49345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    listptr slot;
49445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr addr;
49545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_int   i;
49645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
49745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (count > 0)
49845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
49945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        list = (listptr) malloc(sizeof(wordptr) * count);
50045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (list != NULL)
50145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
50245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            slot = list;
50345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            for ( i = 0; i < count; i++ )
50445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
50545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                addr = BitVector_Create(bits,clear);
50645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (addr == NULL)
50745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
50845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    BitVector_Destroy_List(list,i);
50945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    return(NULL);
51045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
51145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                *slot++ = addr;
51245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
51345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
51445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
51545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(list);
51645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
51745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
51845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgwordptr BitVector_Resize(wordptr oldaddr, N_int bits)       /* realloc       */
51945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
52045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  bytes;
52145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  oldsize;
52245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  oldmask;
52345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  newsize;
52445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  newmask;
52545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr newaddr;
52645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr source;
52745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr target;
52845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
52945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    oldsize = size_(oldaddr);
53045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    oldmask = mask_(oldaddr);
53145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    newsize = BitVector_Size(bits);
53245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    newmask = BitVector_Mask(bits);
53345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (oldsize > 0) *(oldaddr+oldsize-1) &= oldmask;
53445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (newsize <= oldsize)
53545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
53645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        newaddr = oldaddr;
53745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        bits_(newaddr) = bits;
53845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        size_(newaddr) = newsize;
53945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        mask_(newaddr) = newmask;
54045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (newsize > 0) *(newaddr+newsize-1) &= newmask;
54145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
54245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    else
54345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
54445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        bytes = (newsize + BIT_VECTOR_HIDDEN_WORDS) << FACTOR;
54545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        newaddr = (wordptr) yasm_xmalloc((size_t) bytes);
54645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (newaddr != NULL)
54745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
54845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *newaddr++ = bits;
54945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *newaddr++ = newsize;
55045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *newaddr++ = newmask;
55145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            target = newaddr;
55245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            source = oldaddr;
55345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            newsize -= oldsize;
55445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            BIT_VECTOR_COPY_WORDS(target,source,oldsize)
55545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            BIT_VECTOR_ZERO_WORDS(target,newsize)
55645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
55745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BitVector_Destroy(oldaddr);
55845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
55945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(newaddr);
56045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
56145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
56245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgwordptr BitVector_Shadow(wordptr addr)     /* makes new, same size but empty */
56345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
56445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return( BitVector_Create(bits_(addr),true) );
56545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
56645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
56745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgwordptr BitVector_Clone(wordptr addr)               /* makes exact duplicate */
56845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
56945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  bits;
57045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr twin;
57145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
57245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bits = bits_(addr);
57345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    twin = BitVector_Create(bits,false);
57445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((twin != NULL) and (bits > 0))
57545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BIT_VECTOR_cpy_words(twin,addr,size_(addr));
57645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(twin);
57745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
57845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
57945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgwordptr BitVector_Concat(wordptr X, wordptr Y)      /* returns concatenation */
58045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
58145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* BEWARE that X = most significant part, Y = least significant part! */
58245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
58345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  bitsX;
58445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  bitsY;
58545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  bitsZ;
58645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr Z;
58745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
58845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bitsX = bits_(X);
58945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bitsY = bits_(Y);
59045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bitsZ = bitsX + bitsY;
59145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Z = BitVector_Create(bitsZ,false);
59245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((Z != NULL) and (bitsZ > 0))
59345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
59445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BIT_VECTOR_cpy_words(Z,Y,size_(Y));
59545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BitVector_Interval_Copy(Z,X,bitsY,0,bitsX);
59645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *(Z+size_(Z)-1) &= mask_(Z);
59745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
59845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(Z);
59945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
60045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
60145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid BitVector_Copy(wordptr X, wordptr Y)                           /* X = Y */
60245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
60345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  sizeX = size_(X);
60445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  sizeY = size_(Y);
60545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  maskX = mask_(X);
60645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  maskY = mask_(Y);
60745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  fill  = 0;
60845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr lastX;
60945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr lastY;
61045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
61145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((X != Y) and (sizeX > 0))
61245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
61345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        lastX = X + sizeX - 1;
61445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (sizeY > 0)
61545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
61645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            lastY = Y + sizeY - 1;
61745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if ( (*lastY AND (maskY AND NOT (maskY >> 1))) == 0 ) *lastY &= maskY;
61845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
61945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
62045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                fill = (N_word) ~0L;
62145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                *lastY |= NOT maskY;
62245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
62345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while ((sizeX > 0) and (sizeY > 0))
62445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
62545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                *X++ = *Y++;
62645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                sizeX--;
62745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                sizeY--;
62845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
62945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *lastY &= maskY;
63045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
63145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (sizeX-- > 0) *X++ = fill;
63245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *lastX &= maskX;
63345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
63445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
63545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
63645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid BitVector_Empty(wordptr addr)                        /* X = {}  clr all */
63745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
63845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word size = size_(addr);
63945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
64045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    BIT_VECTOR_ZERO_WORDS(addr,size)
64145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
64245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
64345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid BitVector_Fill(wordptr addr)                         /* X = ~{} set all */
64445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
64545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word size = size_(addr);
64645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word mask = mask_(addr);
64745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word fill = (N_word) ~0L;
64845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
64945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (size > 0)
65045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
65145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BIT_VECTOR_FILL_WORDS(addr,fill,size)
65245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *(--addr) &= mask;
65345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
65445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
65545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
65645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid BitVector_Flip(wordptr addr)                         /* X = ~X flip all */
65745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
65845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word size = size_(addr);
65945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word mask = mask_(addr);
66045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word flip = (N_word) ~0L;
66145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
66245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (size > 0)
66345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
66445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BIT_VECTOR_FLIP_WORDS(addr,flip,size)
66545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *(--addr) &= mask;
66645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
66745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
66845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
66945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid BitVector_Primes(wordptr addr)
67045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
67145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  bits = bits_(addr);
67245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  size = size_(addr);
67345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr work;
67445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  temp;
67545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  i,j;
67645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
67745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (size > 0)
67845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
67945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        temp = 0xAAAA;
68045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        i = BITS >> 4;
68145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (--i > 0)
68245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
68345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            temp <<= 16;
68445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            temp |= 0xAAAA;
68545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
68645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        i = size;
68745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        work = addr;
68845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *work++ = temp XOR 0x0006;
68945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (--i > 0) *work++ = temp;
69045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        for ( i = 3; (j = i * i) < bits; i += 2 )
69145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
69245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            for ( ; j < bits; j += i ) BIT_VECTOR_CLR_BIT(addr,j)
69345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
69445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *(addr+size-1) &= mask_(addr);
69545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
69645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
69745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
69845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid BitVector_Reverse(wordptr X, wordptr Y)
69945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
70045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word bits = bits_(X);
70145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word mask;
70245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word bit;
70345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word value;
70445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
70545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bits > 0)
70645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
70745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (X == Y) BitVector_Interval_Reverse(X,0,bits-1);
70845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else if (bits == bits_(Y))
70945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
71045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*          mask = mask_(Y);  */
71145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*          mask &= NOT (mask >> 1);  */
71245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            mask = BITMASKTAB[(bits-1) AND MODMASK];
71345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            Y += size_(Y) - 1;
71445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            value = 0;
71545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            bit = LSB;
71645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while (bits-- > 0)
71745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
71845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if ((*Y AND mask) != 0)
71945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
72045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    value |= bit;
72145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
72245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (not (mask >>= 1))
72345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
72445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    Y--;
72545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    mask = MSB;
72645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
72745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (not (bit <<= 1))
72845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
72945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    *X++ = value;
73045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    value = 0;
73145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    bit = LSB;
73245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
73345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
73445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (bit > LSB) *X = value;
73545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
73645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
73745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
73845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
73945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid BitVector_Interval_Empty(wordptr addr, N_int lower, N_int upper)
74045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{                                                  /* X = X \ [lower..upper] */
74145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  bits = bits_(addr);
74245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  size = size_(addr);
74345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr loaddr;
74445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr hiaddr;
74545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  lobase;
74645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  hibase;
74745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  lomask;
74845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  himask;
74945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  diff;
75045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
75145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((size > 0) and (lower < bits) and (upper < bits) and (lower <= upper))
75245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
75345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        lobase = lower >> LOGBITS;
75445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        hibase = upper >> LOGBITS;
75545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        diff = hibase - lobase;
75645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        loaddr = addr + lobase;
75745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        hiaddr = addr + hibase;
75845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
75945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        lomask = (N_word)   (~0L << (lower AND MODMASK));
76045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        himask = (N_word) ~((~0L << (upper AND MODMASK)) << 1);
76145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
76245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (diff == 0)
76345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
76445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *loaddr &= NOT (lomask AND himask);
76545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
76645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else
76745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
76845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *loaddr++ &= NOT lomask;
76945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while (--diff > 0)
77045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
77145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                *loaddr++ = 0;
77245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
77345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *hiaddr &= NOT himask;
77445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
77545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
77645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
77745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
77845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid BitVector_Interval_Fill(wordptr addr, N_int lower, N_int upper)
77945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{                                                  /* X = X + [lower..upper] */
78045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  bits = bits_(addr);
78145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  size = size_(addr);
78245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  fill = (N_word) ~0L;
78345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr loaddr;
78445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr hiaddr;
78545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  lobase;
78645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  hibase;
78745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  lomask;
78845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  himask;
78945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  diff;
79045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
79145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((size > 0) and (lower < bits) and (upper < bits) and (lower <= upper))
79245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
79345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        lobase = lower >> LOGBITS;
79445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        hibase = upper >> LOGBITS;
79545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        diff = hibase - lobase;
79645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        loaddr = addr + lobase;
79745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        hiaddr = addr + hibase;
79845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
79945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        lomask = (N_word)   (~0L << (lower AND MODMASK));
80045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        himask = (N_word) ~((~0L << (upper AND MODMASK)) << 1);
80145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
80245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (diff == 0)
80345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
80445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *loaddr |= (lomask AND himask);
80545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
80645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else
80745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
80845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *loaddr++ |= lomask;
80945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while (--diff > 0)
81045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
81145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                *loaddr++ = fill;
81245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
81345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *hiaddr |= himask;
81445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
81545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *(addr+size-1) &= mask_(addr);
81645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
81745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
81845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
81945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid BitVector_Interval_Flip(wordptr addr, N_int lower, N_int upper)
82045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{                                                  /* X = X ^ [lower..upper] */
82145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  bits = bits_(addr);
82245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  size = size_(addr);
82345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  flip = (N_word) ~0L;
82445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr loaddr;
82545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr hiaddr;
82645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  lobase;
82745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  hibase;
82845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  lomask;
82945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  himask;
83045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  diff;
83145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
83245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((size > 0) and (lower < bits) and (upper < bits) and (lower <= upper))
83345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
83445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        lobase = lower >> LOGBITS;
83545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        hibase = upper >> LOGBITS;
83645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        diff = hibase - lobase;
83745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        loaddr = addr + lobase;
83845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        hiaddr = addr + hibase;
83945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
84045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        lomask = (N_word)   (~0L << (lower AND MODMASK));
84145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        himask = (N_word) ~((~0L << (upper AND MODMASK)) << 1);
84245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
84345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (diff == 0)
84445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
84545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *loaddr ^= (lomask AND himask);
84645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
84745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else
84845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
84945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *loaddr++ ^= lomask;
85045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while (--diff > 0)
85145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
85245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                *loaddr++ ^= flip;
85345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
85445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *hiaddr ^= himask;
85545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
85645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *(addr+size-1) &= mask_(addr);
85745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
85845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
85945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
86045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid BitVector_Interval_Reverse(wordptr addr, N_int lower, N_int upper)
86145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
86245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  bits = bits_(addr);
86345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr loaddr;
86445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr hiaddr;
86545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  lomask;
86645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  himask;
86745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
86845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((bits > 0) and (lower < bits) and (upper < bits) and (lower < upper))
86945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
87045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        loaddr = addr + (lower >> LOGBITS);
87145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        hiaddr = addr + (upper >> LOGBITS);
87245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        lomask = BITMASKTAB[lower AND MODMASK];
87345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        himask = BITMASKTAB[upper AND MODMASK];
87445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        for ( bits = upper - lower + 1; bits > 1; bits -= 2 )
87545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
87645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (((*loaddr AND lomask) != 0) XOR ((*hiaddr AND himask) != 0))
87745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
87845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                *loaddr ^= lomask;  /* swap bits only if they differ! */
87945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                *hiaddr ^= himask;
88045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
88145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (not (lomask <<= 1))
88245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
88345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                lomask = LSB;
88445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                loaddr++;
88545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
88645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (not (himask >>= 1))
88745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
88845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                himask = MSB;
88945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                hiaddr--;
89045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
89145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
89245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
89345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
89445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
89545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgboolean BitVector_interval_scan_inc(wordptr addr, N_int start,
89645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    N_intptr min, N_intptr max)
89745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
89845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  size = size_(addr);
89945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  mask = mask_(addr);
90045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  offset;
90145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  bitmask;
90245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  value;
90345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean empty;
90445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
90545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((size == 0) or (start >= bits_(addr))) return(FALSE);
90645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
90745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    *min = start;
90845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    *max = start;
90945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
91045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    offset = start >> LOGBITS;
91145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
91245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    *(addr+size-1) &= mask;
91345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
91445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    addr += offset;
91545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    size -= offset;
91645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
91745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bitmask = BITMASKTAB[start AND MODMASK];
91845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    mask = NOT (bitmask OR (bitmask - 1));
91945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
92045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    value = *addr++;
92145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((value AND bitmask) == 0)
92245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
92345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        value &= mask;
92445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (value == 0)
92545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
92645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            offset++;
92745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            empty = TRUE;
92845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while (empty and (--size > 0))
92945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
93045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if ((value = *addr++)) empty = false; else offset++;
93145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
93245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (empty) return(FALSE);
93345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
93445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        start = offset << LOGBITS;
93545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        bitmask = LSB;
93645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        mask = value;
93745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (not (mask AND LSB))
93845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
93945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            bitmask <<= 1;
94045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            mask >>= 1;
94145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            start++;
94245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
94345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        mask = NOT (bitmask OR (bitmask - 1));
94445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *min = start;
94545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *max = start;
94645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
94745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    value = NOT value;
94845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    value &= mask;
94945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (value == 0)
95045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
95145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        offset++;
95245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        empty = TRUE;
95345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (empty and (--size > 0))
95445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
95545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if ((value = NOT *addr++)) empty = false; else offset++;
95645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
95745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (empty) value = LSB;
95845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
95945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    start = offset << LOGBITS;
96045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (not (value AND LSB))
96145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
96245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        value >>= 1;
96345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        start++;
96445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
96545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    *max = --start;
96645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(TRUE);
96745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
96845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
96945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgboolean BitVector_interval_scan_dec(wordptr addr, N_int start,
97045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                    N_intptr min, N_intptr max)
97145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
97245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  size = size_(addr);
97345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  mask = mask_(addr);
97445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word offset;
97545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word bitmask;
97645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word value;
97745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean empty;
97845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
97945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((size == 0) or (start >= bits_(addr))) return(FALSE);
98045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
98145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    *min = start;
98245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    *max = start;
98345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
98445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    offset = start >> LOGBITS;
98545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
98645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (offset >= size) return(FALSE);
98745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
98845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    *(addr+size-1) &= mask;
98945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
99045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    addr += offset;
99145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    size = ++offset;
99245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
99345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bitmask = BITMASKTAB[start AND MODMASK];
99445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    mask = (bitmask - 1);
99545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
99645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    value = *addr--;
99745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((value AND bitmask) == 0)
99845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
99945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        value &= mask;
100045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (value == 0)
100145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
100245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            offset--;
100345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            empty = TRUE;
100445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while (empty and (--size > 0))
100545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
100645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if ((value = *addr--)) empty = false; else offset--;
100745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
100845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (empty) return(FALSE);
100945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
101045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        start = offset << LOGBITS;
101145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        bitmask = MSB;
101245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        mask = value;
101345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (not (mask AND MSB))
101445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
101545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            bitmask >>= 1;
101645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            mask <<= 1;
101745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            start--;
101845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
101945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        mask = (bitmask - 1);
102045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *max = --start;
102145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *min = start;
102245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
102345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    value = NOT value;
102445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    value &= mask;
102545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (value == 0)
102645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
102745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        offset--;
102845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        empty = TRUE;
102945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (empty and (--size > 0))
103045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
103145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if ((value = NOT *addr--)) empty = false; else offset--;
103245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
103345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (empty) value = MSB;
103445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
103545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    start = offset << LOGBITS;
103645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (not (value AND MSB))
103745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
103845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        value <<= 1;
103945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        start--;
104045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
104145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    *min = start;
104245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(TRUE);
104345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
104445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
104545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid BitVector_Interval_Copy(wordptr X, wordptr Y, N_int Xoffset,
104645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                             N_int Yoffset, N_int length)
104745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
104845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  bitsX = bits_(X);
104945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  bitsY = bits_(Y);
105045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  source = 0;        /* silence compiler warning */
105145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  target = 0;        /* silence compiler warning */
105245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  s_lo_base;
105345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  s_hi_base;
105445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  s_lo_bit;
105545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  s_hi_bit;
105645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  s_base;
105745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  s_lower = 0;       /* silence compiler warning */
105845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  s_upper = 0;       /* silence compiler warning */
105945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  s_bits;
106045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  s_min;
106145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  s_max;
106245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  t_lo_base;
106345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  t_hi_base;
106445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  t_lo_bit;
106545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  t_hi_bit;
106645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  t_base;
106745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  t_lower = 0;       /* silence compiler warning */
106845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  t_upper = 0;       /* silence compiler warning */
106945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  t_bits;
107045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  t_min;
107145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  mask;
107245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  bits;
107345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  sel;
107445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean ascending;
107545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean notfirst;
107645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr Z = X;
107745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
107845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((length > 0) and (Xoffset < bitsX) and (Yoffset < bitsY))
107945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
108045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if ((Xoffset + length) > bitsX) length = bitsX - Xoffset;
108145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if ((Yoffset + length) > bitsY) length = bitsY - Yoffset;
108245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
108345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        ascending = (Xoffset <= Yoffset);
108445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
108545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        s_lo_base = Yoffset >> LOGBITS;
108645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        s_lo_bit = Yoffset AND MODMASK;
108745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        Yoffset += --length;
108845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        s_hi_base = Yoffset >> LOGBITS;
108945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        s_hi_bit = Yoffset AND MODMASK;
109045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
109145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        t_lo_base = Xoffset >> LOGBITS;
109245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        t_lo_bit = Xoffset AND MODMASK;
109345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        Xoffset += length;
109445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        t_hi_base = Xoffset >> LOGBITS;
109545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        t_hi_bit = Xoffset AND MODMASK;
109645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
109745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (ascending)
109845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
109945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            s_base = s_lo_base;
110045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            t_base = t_lo_base;
110145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
110245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else
110345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
110445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            s_base = s_hi_base;
110545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            t_base = t_hi_base;
110645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
110745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        s_bits = 0;
110845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        t_bits = 0;
110945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        Y += s_base;
111045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        X += t_base;
111145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        notfirst = FALSE;
111245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (TRUE)
111345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
111445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (t_bits == 0)
111545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
111645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (notfirst)
111745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
111845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    *X = target;
111945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    if (ascending)
112045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    {
112145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        if (t_base == t_hi_base) break;
112245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        t_base++;
112345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        X++;
112445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    }
112545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    else
112645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    {
112745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        if (t_base == t_lo_base) break;
112845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        t_base--;
112945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        X--;
113045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    }
113145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
113245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                sel = ((t_base == t_hi_base) << 1) OR (t_base == t_lo_base);
113345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                switch (sel)
113445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
113545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    case 0:
113645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        t_lower = 0;
113745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        t_upper = BITS - 1;
113845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        t_bits = BITS;
113945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        target = 0;
114045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        break;
114145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    case 1:
114245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        t_lower = t_lo_bit;
114345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        t_upper = BITS - 1;
114445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        t_bits = BITS - t_lo_bit;
114545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        mask = (N_word) (~0L << t_lower);
114645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        target = *X AND NOT mask;
114745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        break;
114845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    case 2:
114945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        t_lower = 0;
115045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        t_upper = t_hi_bit;
115145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        t_bits = t_hi_bit + 1;
115245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        mask = (N_word) ((~0L << t_upper) << 1);
115345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        target = *X AND mask;
115445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        break;
115545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    case 3:
115645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        t_lower = t_lo_bit;
115745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        t_upper = t_hi_bit;
115845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        t_bits = t_hi_bit - t_lo_bit + 1;
115945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        mask = (N_word) (~0L << t_lower);
116045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        mask &= (N_word) ~((~0L << t_upper) << 1);
116145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        target = *X AND NOT mask;
116245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        break;
116345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
116445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
116545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (s_bits == 0)
116645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
116745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (notfirst)
116845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
116945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    if (ascending)
117045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    {
117145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        if (s_base == s_hi_base) break;
117245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        s_base++;
117345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        Y++;
117445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    }
117545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    else
117645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    {
117745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        if (s_base == s_lo_base) break;
117845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        s_base--;
117945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        Y--;
118045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    }
118145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
118245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                source = *Y;
118345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                sel = ((s_base == s_hi_base) << 1) OR (s_base == s_lo_base);
118445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                switch (sel)
118545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
118645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    case 0:
118745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        s_lower = 0;
118845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        s_upper = BITS - 1;
118945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        s_bits = BITS;
119045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        break;
119145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    case 1:
119245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        s_lower = s_lo_bit;
119345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        s_upper = BITS - 1;
119445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        s_bits = BITS - s_lo_bit;
119545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        break;
119645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    case 2:
119745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        s_lower = 0;
119845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        s_upper = s_hi_bit;
119945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        s_bits = s_hi_bit + 1;
120045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        break;
120145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    case 3:
120245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        s_lower = s_lo_bit;
120345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        s_upper = s_hi_bit;
120445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        s_bits = s_hi_bit - s_lo_bit + 1;
120545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        break;
120645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
120745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
120845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            notfirst = TRUE;
120945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (s_bits > t_bits)
121045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
121145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                bits = t_bits - 1;
121245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (ascending)
121345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
121445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    s_min = s_lower;
121545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    s_max = s_lower + bits;
121645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
121745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else
121845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
121945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    s_max = s_upper;
122045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    s_min = s_upper - bits;
122145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
122245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                t_min = t_lower;
122345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
122445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
122545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
122645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                bits = s_bits - 1;
122745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (ascending) t_min = t_lower;
122845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else           t_min = t_upper - bits;
122945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                s_min = s_lower;
123045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                s_max = s_upper;
123145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
123245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            bits++;
123345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            mask = (N_word) (~0L << s_min);
123445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            mask &= (N_word) ~((~0L << s_max) << 1);
123545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (s_min == t_min) target |= (source AND mask);
123645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
123745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
123845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (s_min < t_min) target |= (source AND mask) << (t_min-s_min);
123945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else               target |= (source AND mask) >> (s_min-t_min);
124045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
124145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (ascending)
124245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
124345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                s_lower += bits;
124445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                t_lower += bits;
124545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
124645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
124745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
124845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                s_upper -= bits;
124945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                t_upper -= bits;
125045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
125145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            s_bits -= bits;
125245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            t_bits -= bits;
125345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
125445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *(Z+size_(Z)-1) &= mask_(Z);
125545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
125645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
125745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
125845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
125945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgwordptr BitVector_Interval_Substitute(wordptr X, wordptr Y,
126045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                      N_int Xoffset, N_int Xlength,
126145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                      N_int Yoffset, N_int Ylength)
126245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
126345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word Xbits = bits_(X);
126445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word Ybits = bits_(Y);
126545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word limit;
126645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word diff;
126745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
126845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((Xoffset <= Xbits) and (Yoffset <= Ybits))
126945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
127045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        limit = Xoffset + Xlength;
127145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (limit > Xbits)
127245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
127345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            limit = Xbits;
127445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            Xlength = Xbits - Xoffset;
127545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
127645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if ((Yoffset + Ylength) > Ybits)
127745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
127845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            Ylength = Ybits - Yoffset;
127945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
128045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (Xlength == Ylength)
128145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
128245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if ((Ylength > 0) and ((X != Y) or (Xoffset != Yoffset)))
128345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
128445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
128545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
128645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
128745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else /* Xlength != Ylength */
128845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
128945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (Xlength > Ylength)
129045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
129145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                diff = Xlength - Ylength;
129245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (Ylength > 0) BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
129345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (limit < Xbits) BitVector_Delete(X,Xoffset+Ylength,diff,FALSE);
129445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if ((X = BitVector_Resize(X,Xbits-diff)) == NULL) return(NULL);
129545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
129645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else /* Ylength > Xlength  ==>  Ylength > 0 */
129745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
129845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                diff = Ylength - Xlength;
129945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (X != Y)
130045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
130145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    if ((X = BitVector_Resize(X,Xbits+diff)) == NULL) return(NULL);
130245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    if (limit < Xbits) BitVector_Insert(X,limit,diff,FALSE);
130345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
130445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
130545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else /* in-place */
130645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
130745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    if ((Y = X = BitVector_Resize(X,Xbits+diff)) == NULL) return(NULL);
130845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    if (limit >= Xbits)
130945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    {
131045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
131145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    }
131245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    else /* limit < Xbits */
131345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    {
131445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        BitVector_Insert(X,limit,diff,FALSE);
131545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        if ((Yoffset+Ylength) <= limit)
131645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        {
131745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
131845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        }
131945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        else /* overlaps or lies above critical area */
132045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        {
132145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            if (limit <= Yoffset)
132245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            {
132345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                Yoffset += diff;
132445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
132545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            }
132645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            else /* Yoffset < limit */
132745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            {
132845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                Xlength = limit - Yoffset;
132945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Xlength);
133045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                Yoffset = Xoffset + Ylength; /* = limit + diff */
133145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                Xoffset += Xlength;
133245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                Ylength -= Xlength;
133345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
133445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            }
133545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        }
133645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    }
133745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
133845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
133945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
134045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
134145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(X);
134245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
134345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
134445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgboolean BitVector_is_empty(wordptr addr)                    /* X == {} ?     */
134545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
134645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  size = size_(addr);
134745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean r = TRUE;
134845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
134945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (size > 0)
135045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
135145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *(addr+size-1) &= mask_(addr);
135245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (r and (size-- > 0)) r = ( *addr++ == 0 );
135345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
135445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(r);
135545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
135645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
135745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgboolean BitVector_is_full(wordptr addr)                     /* X == ~{} ?    */
135845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
135945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  size = size_(addr);
136045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  mask = mask_(addr);
136145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean r = FALSE;
136245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr last;
136345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
136445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (size > 0)
136545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
136645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        r = TRUE;
136745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        last = addr + size - 1;
136845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *last |= NOT mask;
136945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (r and (size-- > 0)) r = ( NOT *addr++ == 0 );
137045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *last &= mask;
137145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
137245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(r);
137345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
137445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
137545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgboolean BitVector_equal(wordptr X, wordptr Y)               /* X == Y ?      */
137645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
137745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  size = size_(X);
137845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  mask = mask_(X);
137945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean r = FALSE;
138045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
138145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bits_(X) == bits_(Y))
138245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
138345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        r = TRUE;
138445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (size > 0)
138545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
138645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *(X+size-1) &= mask;
138745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *(Y+size-1) &= mask;
138845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while (r and (size-- > 0)) r = (*X++ == *Y++);
138945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
139045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
139145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(r);
139245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
139345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
139445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgZ_int BitVector_Lexicompare(wordptr X, wordptr Y)           /* X <,=,> Y ?   */
139545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{                                                           /*  unsigned     */
139645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  bitsX = bits_(X);
139745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  bitsY = bits_(Y);
139845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  size  = size_(X);
139945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean r = TRUE;
140045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
140145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bitsX == bitsY)
140245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
140345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (size > 0)
140445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
140545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            X += size;
140645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            Y += size;
140745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while (r and (size-- > 0)) r = (*(--X) == *(--Y));
140845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
140945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (r) return((Z_int) 0);
141045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else
141145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
141245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (*X < *Y) return((Z_int) -1); else return((Z_int) 1);
141345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
141445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
141545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    else
141645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
141745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (bitsX < bitsY) return((Z_int) -1); else return((Z_int) 1);
141845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
141945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
142045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
142145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgZ_int BitVector_Compare(wordptr X, wordptr Y)               /* X <,=,> Y ?   */
142245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{                                                           /*   signed      */
142345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  bitsX = bits_(X);
142445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  bitsY = bits_(Y);
142545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  size  = size_(X);
142645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  mask  = mask_(X);
142745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  sign;
142845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean r = TRUE;
142945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
143045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bitsX == bitsY)
143145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
143245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (size > 0)
143345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
143445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            X += size;
143545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            Y += size;
143645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            mask &= NOT (mask >> 1);
143745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if ((sign = (*(X-1) AND mask)) != (*(Y-1) AND mask))
143845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
143945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (sign) return((Z_int) -1); else return((Z_int) 1);
144045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
144145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while (r and (size-- > 0)) r = (*(--X) == *(--Y));
144245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
144345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (r) return((Z_int) 0);
144445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else
144545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
144645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (*X < *Y) return((Z_int) -1); else return((Z_int) 1);
144745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
144845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
144945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    else
145045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
145145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (bitsX < bitsY) return((Z_int) -1); else return((Z_int) 1);
145245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
145345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
145445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
145545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgcharptr BitVector_to_Hex(wordptr addr)
145645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
145745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  bits = bits_(addr);
145845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  size = size_(addr);
145945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  value;
146045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  count;
146145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  digit;
146245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  length;
146345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    charptr string;
146445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
146545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    length = bits >> 2;
146645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bits AND 0x0003) length++;
146745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    string = (charptr) yasm_xmalloc((size_t) (length+1));
146845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (string == NULL) return(NULL);
146945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    string += length;
147045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    *string = (N_char) '\0';
147145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (size > 0)
147245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
147345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *(addr+size-1) &= mask_(addr);
147445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while ((size-- > 0) and (length > 0))
147545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
147645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            value = *addr++;
147745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            count = BITS >> 2;
147845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while ((count-- > 0) and (length > 0))
147945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
148045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                digit = value AND 0x000F;
148145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (digit > 9) digit += (N_word) 'A' - 10;
148245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else           digit += (N_word) '0';
148345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                *(--string) = (N_char) digit; length--;
148445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if ((count > 0) and (length > 0)) value >>= 4;
148545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
148645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
148745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
148845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(string);
148945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
149045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
149145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgErrCode BitVector_from_Hex(wordptr addr, charptr string)
149245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
149345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  size = size_(addr);
149445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  mask = mask_(addr);
149545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean ok = TRUE;
149645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    size_t  length;
149745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  value;
149845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  count;
149945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int     digit;
150045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
150145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (size > 0)
150245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
150345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        length = strlen((char *) string);
150445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        string += length;
150545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (size-- > 0)
150645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
150745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            value = 0;
150845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            for ( count = 0; (ok and (length > 0) and (count < BITS)); count += 4 )
150945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
151045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                digit = (int) *(--string); length--;
151145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /* separate because toupper() is likely a macro! */
151245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                digit = toupper(digit);
151345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (digit == '_')
151445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    count -= 4;
151545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else if ((ok = (isxdigit(digit) != 0)))
151645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
151745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    if (digit >= (int) 'A') digit -= (int) 'A' - 10;
151845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    else                    digit -= (int) '0';
151945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    value |= (((N_word) digit) << count);
152045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
152145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
152245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *addr++ = value;
152345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
152445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *(--addr) &= mask;
152545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
152645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (ok) return(ErrCode_Ok);
152745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    else    return(ErrCode_Pars);
152845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
152945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
153045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgErrCode BitVector_from_Oct(wordptr addr, charptr string)
153145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
153245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  size = size_(addr);
153345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  mask = mask_(addr);
153445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean ok = TRUE;
153545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    size_t  length;
153645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  value;
153745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  value_fill = 0;
153845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  count;
153945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Z_word  count_fill = 0;
154045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int     digit = 0;
154145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
154245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (size > 0)
154345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
154445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        length = strlen((char *) string);
154545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        string += length;
154645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (size-- > 0)
154745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
154845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            value = value_fill;
154945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            for ( count = count_fill; (ok and (length > 0) and (count < BITS)); count += 3 )
155045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
155145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                digit = (int) *(--string); length--;
155245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (digit == '_')
155345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    count -= 3;
155445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else if ((ok = (isdigit(digit) && digit != '8' && digit != '9')) != 0)
155545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
155645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    digit -= (int) '0';
155745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    value |= (((N_word) digit) << count);
155845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
155945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
156045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            count_fill = (Z_word)count-(Z_word)BITS;
156145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (count_fill > 0)
156245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                value_fill = (((N_word) digit) >> (3-count_fill));
156345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
156445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                value_fill = 0;
156545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *addr++ = value;
156645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
156745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *(--addr) &= mask;
156845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
156945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (ok) return(ErrCode_Ok);
157045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    else    return(ErrCode_Pars);
157145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
157245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
157345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgcharptr BitVector_to_Bin(wordptr addr)
157445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
157545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  size = size_(addr);
157645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  value;
157745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  count;
157845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  digit;
157945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  length;
158045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    charptr string;
158145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
158245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    length = bits_(addr);
158345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    string = (charptr) yasm_xmalloc((size_t) (length+1));
158445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (string == NULL) return(NULL);
158545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    string += length;
158645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    *string = (N_char) '\0';
158745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (size > 0)
158845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
158945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *(addr+size-1) &= mask_(addr);
159045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (size-- > 0)
159145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
159245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            value = *addr++;
159345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            count = BITS;
159445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (count > length) count = length;
159545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while (count-- > 0)
159645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
159745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                digit = value AND 0x0001;
159845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                digit += (N_word) '0';
159945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                *(--string) = (N_char) digit; length--;
160045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (count > 0) value >>= 1;
160145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
160245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
160345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
160445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(string);
160545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
160645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
160745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgErrCode BitVector_from_Bin(wordptr addr, charptr string)
160845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
160945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  size = size_(addr);
161045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  mask = mask_(addr);
161145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean ok = TRUE;
161245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    size_t  length;
161345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  value;
161445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  count;
161545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int     digit;
161645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
161745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (size > 0)
161845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
161945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        length = strlen((char *) string);
162045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        string += length;
162145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (size-- > 0)
162245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
162345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            value = 0;
162445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            for ( count = 0; (ok and (length > 0) and (count < BITS)); count++ )
162545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
162645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                digit = (int) *(--string); length--;
162745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                switch (digit)
162845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
162945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    case (int) '0':
163045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        break;
163145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    case (int) '1':
163245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        value |= BITMASKTAB[count];
163345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        break;
163445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    case (int) '_':
163545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        count--;
163645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        break;
163745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    default:
163845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        ok = FALSE;
163945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        break;
164045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
164145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
164245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *addr++ = value;
164345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
164445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *(--addr) &= mask;
164545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
164645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (ok) return(ErrCode_Ok);
164745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    else    return(ErrCode_Pars);
164845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
164945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
165045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgcharptr BitVector_to_Dec(wordptr addr)
165145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
165245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  bits = bits_(addr);
165345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  length;
165445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  digits;
165545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  count;
165645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  q;
165745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  r;
165845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean loop;
165945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    charptr result;
166045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    charptr string;
166145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr quot;
166245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr rest;
166345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr temp;
166445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr base;
166545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Z_int   sign;
166645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
166745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    length = (N_word) (bits / 3.3);        /* digits = bits * ln(2) / ln(10) */
166845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    length += 2; /* compensate for truncating & provide space for minus sign */
166945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    result = (charptr) yasm_xmalloc((size_t) (length+1));   /* remember the '\0'! */
167045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (result == NULL) return(NULL);
167145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    string = result;
167245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    sign = BitVector_Sign(addr);
167345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((bits < 4) or (sign == 0))
167445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
167545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (bits > 0) digits = *addr; else digits = (N_word) 0;
167645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (sign < 0) digits = ((N_word)(-((Z_word)digits))) AND mask_(addr);
167745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *string++ = (N_char) digits + (N_char) '0';
167845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        digits = 1;
167945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
168045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    else
168145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
168245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        quot = BitVector_Create(bits,FALSE);
168345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (quot == NULL)
168445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
168545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            BitVector_Dispose(result);
168645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return(NULL);
168745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
168845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        rest = BitVector_Create(bits,FALSE);
168945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (rest == NULL)
169045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
169145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            BitVector_Dispose(result);
169245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            BitVector_Destroy(quot);
169345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return(NULL);
169445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
169545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        temp = BitVector_Create(bits,FALSE);
169645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (temp == NULL)
169745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
169845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            BitVector_Dispose(result);
169945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            BitVector_Destroy(quot);
170045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            BitVector_Destroy(rest);
170145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return(NULL);
170245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
170345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        base = BitVector_Create(bits,TRUE);
170445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (base == NULL)
170545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
170645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            BitVector_Dispose(result);
170745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            BitVector_Destroy(quot);
170845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            BitVector_Destroy(rest);
170945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            BitVector_Destroy(temp);
171045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return(NULL);
171145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
171245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (sign < 0) BitVector_Negate(quot,addr);
171345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else           BitVector_Copy(quot,addr);
171445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        digits = 0;
171545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *base = EXP10;
171645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        loop = (bits >= BITS);
171745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        do
171845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
171945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (loop)
172045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
172145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                BitVector_Copy(temp,quot);
172245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (BitVector_Div_Pos(quot,temp,base,rest))
172345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
172445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    BitVector_Dispose(result); /* emergency exit */
172545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    BitVector_Destroy(quot);
172645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    BitVector_Destroy(rest);   /* should never occur */
172745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    BitVector_Destroy(temp);   /* under normal operation */
172845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    BitVector_Destroy(base);
172945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    return(NULL);
173045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
173145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                loop = not BitVector_is_empty(quot);
173245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                q = *rest;
173345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
173445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else q = *quot;
173545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            count = LOG10;
173645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while (((loop and (count-- > 0)) or ((not loop) and (q != 0))) and
173745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                (digits < length))
173845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
173945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (q != 0)
174045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
174145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    BIT_VECTOR_DIGITIZE(N_word,q,r)
174245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
174345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else r = (N_word) '0';
174445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                *string++ = (N_char) r;
174545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                digits++;
174645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
174745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
174845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (loop and (digits < length));
174945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BitVector_Destroy(quot);
175045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BitVector_Destroy(rest);
175145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BitVector_Destroy(temp);
175245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BitVector_Destroy(base);
175345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
175445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((sign < 0) and (digits < length))
175545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
175645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *string++ = (N_char) '-';
175745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        digits++;
175845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
175945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    *string = (N_char) '\0';
176045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    BIT_VECTOR_reverse(result,digits);
176145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(result);
176245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
176345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
176445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstruct BitVector_from_Dec_static_data {
176545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr term;
176645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr base;
176745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr prod;
176845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr rank;
176945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr temp;
177045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org};
177145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
177245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgBitVector_from_Dec_static_data *BitVector_from_Dec_static_Boot(N_word bits)
177345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
177445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    BitVector_from_Dec_static_data *data;
177545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
177645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    data = yasm_xmalloc(sizeof(BitVector_from_Dec_static_data));
177745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
177845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bits > 0)
177945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
178045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data->term = BitVector_Create(BITS,FALSE);
178145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data->base = BitVector_Create(BITS,FALSE);
178245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data->prod = BitVector_Create(bits,FALSE);
178345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data->rank = BitVector_Create(bits,FALSE);
178445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data->temp = BitVector_Create(bits,FALSE);
178545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    } else {
178645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data->term = NULL;
178745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data->base = NULL;
178845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data->prod = NULL;
178945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data->rank = NULL;
179045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        data->temp = NULL;
179145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
179245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return data;
179345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
179445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
179545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid BitVector_from_Dec_static_Shutdown(BitVector_from_Dec_static_data *data)
179645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
179745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (data) {
179845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BitVector_Destroy(data->term);
179945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BitVector_Destroy(data->base);
180045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BitVector_Destroy(data->prod);
180145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BitVector_Destroy(data->rank);
180245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BitVector_Destroy(data->temp);
180345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
180445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    yasm_xfree(data);
180545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
180645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
180745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgErrCode BitVector_from_Dec_static(BitVector_from_Dec_static_data *data,
180845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                  wordptr addr, charptr string)
180945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
181045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    ErrCode error = ErrCode_Ok;
181145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  bits = bits_(addr);
181245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  mask = mask_(addr);
181345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean init = (bits > BITS);
181445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean minus;
181545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean shift;
181645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean carry;
181745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr term;
181845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr base;
181945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr prod;
182045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr rank;
182145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr temp;
182245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  accu;
182345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  powr;
182445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  count;
182545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    size_t  length;
182645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int     digit;
182745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
182845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bits > 0)
182945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
183045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        term = data->term;
183145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        base = data->base;
183245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        prod = data->prod;
183345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        rank = data->rank;
183445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        temp = data->temp;
183545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
183645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        length = strlen((char *) string);
183745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (length == 0) return(ErrCode_Pars);
183845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        digit = (int) *string;
183945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if ((minus = (digit == (int) '-')) or
184045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     (digit == (int) '+'))
184145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
184245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            string++;
184345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (--length == 0) return(ErrCode_Pars);
184445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
184545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        string += length;
184645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (init)
184745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
184845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            BitVector_Empty(prod);
184945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            BitVector_Empty(rank);
185045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
185145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BitVector_Empty(addr);
185245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *base = EXP10;
185345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        shift = FALSE;
185445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while ((not error) and (length > 0))
185545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
185645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            accu = 0;
185745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            powr = 1;
185845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            count = LOG10;
185945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while ((not error) and (length > 0) and (count-- > 0))
186045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
186145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                digit = (int) *(--string); length--;
186245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /* separate because isdigit() is likely a macro! */
186345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (isdigit(digit) != 0)
186445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
186545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    accu += ((N_word) digit - (N_word) '0') * powr;
186645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    powr *= 10;
186745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
186845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else error = ErrCode_Pars;
186945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
187045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (not error)
187145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
187245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (shift)
187345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
187445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    *term = accu;
187545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    BitVector_Copy(temp,rank);
187645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    error = BitVector_Mul_Pos(prod,temp,term,FALSE);
187745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
187845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else
187945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
188045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    *prod = accu;
188145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    if ((not init) and ((accu AND NOT mask) != 0)) error = ErrCode_Ovfl;
188245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
188345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (not error)
188445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
188545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    carry = FALSE;
188645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    BitVector_compute(addr,addr,prod,FALSE,&carry);
188745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    /* ignores sign change (= overflow) but not */
188845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    /* numbers too large (= carry) for resulting bit vector */
188945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    if (carry) error = ErrCode_Ovfl;
189045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    else
189145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    {
189245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        if (length > 0)
189345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        {
189445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            if (shift)
189545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            {
189645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                BitVector_Copy(temp,rank);
189745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                error = BitVector_Mul_Pos(rank,temp,base,FALSE);
189845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            }
189945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            else
190045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            {
190145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                *rank = *base;
190245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                shift = TRUE;
190345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            }
190445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        }
190545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    }
190645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
190745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
190845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
190945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (not error and minus)
191045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
191145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            BitVector_Negate(addr,addr);
191245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if ((*(addr + size_(addr) - 1) AND mask AND NOT (mask >> 1)) == 0)
191345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error = ErrCode_Ovfl;
191445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
191545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
191645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(error);
191745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
191845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
191945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgErrCode BitVector_from_Dec(wordptr addr, charptr string)
192045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
192145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    ErrCode error = ErrCode_Ok;
192245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  bits = bits_(addr);
192345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  mask = mask_(addr);
192445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean init = (bits > BITS);
192545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean minus;
192645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean shift;
192745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean carry;
192845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr term;
192945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr base;
193045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr prod;
193145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr rank;
193245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr temp;
193345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  accu;
193445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  powr;
193545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  count;
193645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    size_t  length;
193745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    int     digit;
193845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
193945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bits > 0)
194045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
194145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        length = strlen((char *) string);
194245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (length == 0) return(ErrCode_Pars);
194345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        digit = (int) *string;
194445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if ((minus = (digit == (int) '-')) or
194545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     (digit == (int) '+'))
194645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
194745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            string++;
194845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (--length == 0) return(ErrCode_Pars);
194945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
195045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        string += length;
195145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        term = BitVector_Create(BITS,FALSE);
195245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (term == NULL)
195345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
195445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return(ErrCode_Null);
195545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
195645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        base = BitVector_Create(BITS,FALSE);
195745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (base == NULL)
195845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
195945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            BitVector_Destroy(term);
196045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return(ErrCode_Null);
196145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
196245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        prod = BitVector_Create(bits,init);
196345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (prod == NULL)
196445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
196545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            BitVector_Destroy(term);
196645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            BitVector_Destroy(base);
196745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return(ErrCode_Null);
196845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
196945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        rank = BitVector_Create(bits,init);
197045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (rank == NULL)
197145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
197245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            BitVector_Destroy(term);
197345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            BitVector_Destroy(base);
197445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            BitVector_Destroy(prod);
197545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return(ErrCode_Null);
197645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
197745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        temp = BitVector_Create(bits,FALSE);
197845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (temp == NULL)
197945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
198045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            BitVector_Destroy(term);
198145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            BitVector_Destroy(base);
198245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            BitVector_Destroy(prod);
198345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            BitVector_Destroy(rank);
198445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return(ErrCode_Null);
198545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
198645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BitVector_Empty(addr);
198745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *base = EXP10;
198845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        shift = FALSE;
198945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while ((not error) and (length > 0))
199045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
199145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            accu = 0;
199245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            powr = 1;
199345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            count = LOG10;
199445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while ((not error) and (length > 0) and (count-- > 0))
199545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
199645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                digit = (int) *(--string); length--;
199745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                /* separate because isdigit() is likely a macro! */
199845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (isdigit(digit) != 0)
199945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
200045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    accu += ((N_word) digit - (N_word) '0') * powr;
200145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    powr *= 10;
200245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
200345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else error = ErrCode_Pars;
200445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
200545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (not error)
200645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
200745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (shift)
200845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
200945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    *term = accu;
201045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    BitVector_Copy(temp,rank);
201145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    error = BitVector_Mul_Pos(prod,temp,term,FALSE);
201245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
201345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else
201445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
201545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    *prod = accu;
201645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    if ((not init) and ((accu AND NOT mask) != 0)) error = ErrCode_Ovfl;
201745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
201845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (not error)
201945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                {
202045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    carry = FALSE;
202145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    BitVector_compute(addr,addr,prod,FALSE,&carry);
202245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    /* ignores sign change (= overflow) but not */
202345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    /* numbers too large (= carry) for resulting bit vector */
202445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    if (carry) error = ErrCode_Ovfl;
202545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    else
202645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    {
202745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        if (length > 0)
202845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        {
202945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            if (shift)
203045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            {
203145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                BitVector_Copy(temp,rank);
203245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                error = BitVector_Mul_Pos(rank,temp,base,FALSE);
203345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            }
203445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            else
203545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            {
203645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                *rank = *base;
203745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                shift = TRUE;
203845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            }
203945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        }
204045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    }
204145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                }
204245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
204345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
204445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BitVector_Destroy(term);
204545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BitVector_Destroy(base);
204645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BitVector_Destroy(prod);
204745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BitVector_Destroy(rank);
204845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BitVector_Destroy(temp);
204945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (not error and minus)
205045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
205145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            BitVector_Negate(addr,addr);
205245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if ((*(addr + size_(addr) - 1) AND mask AND NOT (mask >> 1)) == 0)
205345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                error = ErrCode_Ovfl;
205445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
205545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
205645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(error);
205745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
205845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
205945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgcharptr BitVector_to_Enum(wordptr addr)
206045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
206145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  bits = bits_(addr);
206245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  sample;
206345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  length;
206445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  digits;
206545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  factor;
206645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  power;
206745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  start;
206845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  min;
206945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  max;
207045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    charptr string;
207145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    charptr target;
207245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean comma;
207345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
207445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bits > 0)
207545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
207645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        sample = bits - 1;  /* greatest possible index */
207745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        length = 2;         /* account for index 0 and terminating '\0' */
207845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        digits = 1;         /* account for intervening dashes and commas */
207945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        factor = 1;
208045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        power = 10;
208145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (sample >= (power-1))
208245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
208345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            length += ++digits * factor * 6;  /* 9,90,900,9000,... (9*2/3 = 6) */
208445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            factor = power;
208545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            power *= 10;
208645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
208745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (sample > --factor)
208845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
208945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            sample -= factor;
209045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            factor = (N_word) ( sample / 3 );
209145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            factor = (factor << 1) + (sample - (factor * 3));
209245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            length += ++digits * factor;
209345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
209445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
209545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    else length = 1;
209645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    string = (charptr) yasm_xmalloc((size_t) length);
209745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (string == NULL) return(NULL);
209845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    start = 0;
209945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    comma = FALSE;
210045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    target = string;
210145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while ((start < bits) and BitVector_interval_scan_inc(addr,start,&min,&max))
210245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
210345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        start = max + 2;
210445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (comma) *target++ = (N_char) ',';
210545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (min == max)
210645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
210745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            target += BIT_VECTOR_int2str(target,min);
210845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
210945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else
211045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
211145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (min+1 == max)
211245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
211345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                target += BIT_VECTOR_int2str(target,min);
211445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                *target++ = (N_char) ',';
211545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                target += BIT_VECTOR_int2str(target,max);
211645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
211745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
211845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
211945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                target += BIT_VECTOR_int2str(target,min);
212045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                *target++ = (N_char) '-';
212145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                target += BIT_VECTOR_int2str(target,max);
212245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
212345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
212445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        comma = TRUE;
212545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
212645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    *target = (N_char) '\0';
212745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(string);
212845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
212945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
213045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgErrCode BitVector_from_Enum(wordptr addr, charptr string)
213145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
213245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    ErrCode error = ErrCode_Ok;
213345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  bits = bits_(addr);
213445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  state = 1;
213545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  token;
213645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  indx = 0;          /* silence compiler warning */
213745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  start = 0;         /* silence compiler warning */
213845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
213945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bits > 0)
214045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
214145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BitVector_Empty(addr);
214245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while ((not error) and (state != 0))
214345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
214445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            token = (N_word) *string;
214545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            /* separate because isdigit() is likely a macro! */
214645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (isdigit((int)token) != 0)
214745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
214845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                string += BIT_VECTOR_str2int(string,&indx);
214945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (indx < bits) token = (N_word) '0';
215045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else error = ErrCode_Indx;
215145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
215245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else string++;
215345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (not error)
215445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            switch (state)
215545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
215645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                case 1:
215745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    switch (token)
215845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    {
215945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        case (N_word) '0':
216045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            state = 2;
216145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            break;
216245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        case (N_word) '\0':
216345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            state = 0;
216445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            break;
216545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        default:
216645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            error = ErrCode_Pars;
216745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            break;
216845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    }
216945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    break;
217045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                case 2:
217145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    switch (token)
217245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    {
217345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        case (N_word) '-':
217445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            start = indx;
217545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            state = 3;
217645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            break;
217745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        case (N_word) ',':
217845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            BIT_VECTOR_SET_BIT(addr,indx)
217945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            state = 5;
218045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            break;
218145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        case (N_word) '\0':
218245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            BIT_VECTOR_SET_BIT(addr,indx)
218345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            state = 0;
218445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            break;
218545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        default:
218645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            error = ErrCode_Pars;
218745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            break;
218845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    }
218945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    break;
219045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                case 3:
219145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    switch (token)
219245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    {
219345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        case (N_word) '0':
219445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            if (start < indx)
219545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                BitVector_Interval_Fill(addr,start,indx);
219645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            else if (start == indx)
219745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                BIT_VECTOR_SET_BIT(addr,indx)
219845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            else error = ErrCode_Ordr;
219945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            state = 4;
220045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            break;
220145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        default:
220245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            error = ErrCode_Pars;
220345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            break;
220445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    }
220545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    break;
220645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                case 4:
220745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    switch (token)
220845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    {
220945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        case (N_word) ',':
221045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            state = 5;
221145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            break;
221245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        case (N_word) '\0':
221345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            state = 0;
221445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            break;
221545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        default:
221645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            error = ErrCode_Pars;
221745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            break;
221845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    }
221945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    break;
222045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                case 5:
222145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    switch (token)
222245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    {
222345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        case (N_word) '0':
222445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            state = 2;
222545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            break;
222645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        default:
222745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            error = ErrCode_Pars;
222845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                            break;
222945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    }
223045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    break;
223145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
223245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
223345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
223445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(error);
223545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
223645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
223745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid BitVector_Bit_Off(wordptr addr, N_int indx)            /* X = X \ {x}   */
223845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
223945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (indx < bits_(addr)) BIT_VECTOR_CLR_BIT(addr,indx)
224045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
224145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
224245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid BitVector_Bit_On(wordptr addr, N_int indx)             /* X = X + {x}   */
224345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
224445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (indx < bits_(addr)) BIT_VECTOR_SET_BIT(addr,indx)
224545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
224645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
224745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgboolean BitVector_bit_flip(wordptr addr, N_int indx)    /* X=(X+{x})\(X*{x}) */
224845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
224945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word mask;
225045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
225145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (indx < bits_(addr)) return( BIT_VECTOR_FLP_BIT(addr,indx,mask) );
225245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    else                    return( FALSE );
225345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
225445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
225545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgboolean BitVector_bit_test(wordptr addr, N_int indx)        /* {x} in X ?    */
225645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
225745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (indx < bits_(addr)) return( BIT_VECTOR_TST_BIT(addr,indx) );
225845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    else                    return( FALSE );
225945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
226045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
226145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid BitVector_Bit_Copy(wordptr addr, N_int indx, boolean bit)
226245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
226345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (indx < bits_(addr))
226445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
226545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (bit) BIT_VECTOR_SET_BIT(addr,indx)
226645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else     BIT_VECTOR_CLR_BIT(addr,indx)
226745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
226845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
226945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
227045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid BitVector_LSB(wordptr addr, boolean bit)
227145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
227245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bits_(addr) > 0)
227345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
227445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (bit) *addr |= LSB;
227545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else     *addr &= NOT LSB;
227645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
227745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
227845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
227945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid BitVector_MSB(wordptr addr, boolean bit)
228045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
228145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word size = size_(addr);
228245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word mask = mask_(addr);
228345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
228445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (size-- > 0)
228545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
228645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (bit) *(addr+size) |= mask AND NOT (mask >> 1);
228745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else     *(addr+size) &= NOT mask OR (mask >> 1);
228845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
228945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
229045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
229145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgboolean BitVector_lsb_(wordptr addr)
229245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
229345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (size_(addr) > 0) return( (*addr AND LSB) != 0 );
229445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    else                 return( FALSE );
229545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
229645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
229745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgboolean BitVector_msb_(wordptr addr)
229845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
229945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word size = size_(addr);
230045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word mask = mask_(addr);
230145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
230245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (size-- > 0)
230345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return( (*(addr+size) AND (mask AND NOT (mask >> 1))) != 0 );
230445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    else
230545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return( FALSE );
230645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
230745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
230845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgboolean BitVector_rotate_left(wordptr addr)
230945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
231045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  size = size_(addr);
231145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  mask = mask_(addr);
231245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  msb;
231345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean carry_in;
231445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean carry_out = FALSE;
231545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
231645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (size > 0)
231745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
231845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        msb = mask AND NOT (mask >> 1);
231945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        carry_in = ((*(addr+size-1) AND msb) != 0);
232045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (size-- > 1)
232145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
232245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            carry_out = ((*addr AND MSB) != 0);
232345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *addr <<= 1;
232445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (carry_in) *addr |= LSB;
232545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            carry_in = carry_out;
232645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            addr++;
232745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
232845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        carry_out = ((*addr AND msb) != 0);
232945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *addr <<= 1;
233045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (carry_in) *addr |= LSB;
233145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *addr &= mask;
233245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
233345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(carry_out);
233445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
233545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
233645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgboolean BitVector_rotate_right(wordptr addr)
233745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
233845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  size = size_(addr);
233945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  mask = mask_(addr);
234045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  msb;
234145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean carry_in;
234245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean carry_out = FALSE;
234345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
234445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (size > 0)
234545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
234645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        msb = mask AND NOT (mask >> 1);
234745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        carry_in = ((*addr AND LSB) != 0);
234845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        addr += size-1;
234945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *addr &= mask;
235045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        carry_out = ((*addr AND LSB) != 0);
235145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *addr >>= 1;
235245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (carry_in) *addr |= msb;
235345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        carry_in = carry_out;
235445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        addr--;
235545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        size--;
235645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (size-- > 0)
235745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
235845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            carry_out = ((*addr AND LSB) != 0);
235945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *addr >>= 1;
236045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (carry_in) *addr |= MSB;
236145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            carry_in = carry_out;
236245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            addr--;
236345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
236445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
236545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(carry_out);
236645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
236745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
236845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgboolean BitVector_shift_left(wordptr addr, boolean carry_in)
236945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
237045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  size = size_(addr);
237145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  mask = mask_(addr);
237245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  msb;
237345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean carry_out = carry_in;
237445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
237545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (size > 0)
237645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
237745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        msb = mask AND NOT (mask >> 1);
237845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (size-- > 1)
237945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
238045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            carry_out = ((*addr AND MSB) != 0);
238145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *addr <<= 1;
238245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (carry_in) *addr |= LSB;
238345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            carry_in = carry_out;
238445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            addr++;
238545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
238645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        carry_out = ((*addr AND msb) != 0);
238745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *addr <<= 1;
238845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (carry_in) *addr |= LSB;
238945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *addr &= mask;
239045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
239145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(carry_out);
239245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
239345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
239445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgboolean BitVector_shift_right(wordptr addr, boolean carry_in)
239545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
239645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  size = size_(addr);
239745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  mask = mask_(addr);
239845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  msb;
239945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean carry_out = carry_in;
240045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
240145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (size > 0)
240245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
240345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        msb = mask AND NOT (mask >> 1);
240445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        addr += size-1;
240545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *addr &= mask;
240645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        carry_out = ((*addr AND LSB) != 0);
240745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *addr >>= 1;
240845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (carry_in) *addr |= msb;
240945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        carry_in = carry_out;
241045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        addr--;
241145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        size--;
241245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (size-- > 0)
241345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
241445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            carry_out = ((*addr AND LSB) != 0);
241545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *addr >>= 1;
241645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (carry_in) *addr |= MSB;
241745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            carry_in = carry_out;
241845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            addr--;
241945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
242045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
242145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(carry_out);
242245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
242345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
242445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid BitVector_Move_Left(wordptr addr, N_int bits)
242545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
242645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word count;
242745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word words;
242845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
242945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bits > 0)
243045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
243145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        count = bits AND MODMASK;
243245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        words = bits >> LOGBITS;
243345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (bits >= bits_(addr)) BitVector_Empty(addr);
243445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else
243545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
243645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while (count-- > 0) BitVector_shift_left(addr,0);
243745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            BitVector_Word_Insert(addr,0,words,TRUE);
243845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
243945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
244045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
244145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
244245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid BitVector_Move_Right(wordptr addr, N_int bits)
244345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
244445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word count;
244545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word words;
244645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
244745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bits > 0)
244845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
244945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        count = bits AND MODMASK;
245045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        words = bits >> LOGBITS;
245145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (bits >= bits_(addr)) BitVector_Empty(addr);
245245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else
245345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
245445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while (count-- > 0) BitVector_shift_right(addr,0);
245545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            BitVector_Word_Delete(addr,0,words,TRUE);
245645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
245745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
245845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
245945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
246045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid BitVector_Insert(wordptr addr, N_int offset, N_int count, boolean clear)
246145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
246245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word bits = bits_(addr);
246345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word last;
246445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
246545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((count > 0) and (offset < bits))
246645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
246745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        last = offset + count;
246845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (last < bits)
246945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
247045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            BitVector_Interval_Copy(addr,addr,last,offset,(bits-last));
247145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
247245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else last = bits;
247345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (clear) BitVector_Interval_Empty(addr,offset,(last-1));
247445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
247545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
247645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
247745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid BitVector_Delete(wordptr addr, N_int offset, N_int count, boolean clear)
247845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
247945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word bits = bits_(addr);
248045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word last;
248145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
248245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((count > 0) and (offset < bits))
248345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
248445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        last = offset + count;
248545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (last < bits)
248645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
248745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            BitVector_Interval_Copy(addr,addr,offset,last,(bits-last));
248845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
248945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else count = bits - offset;
249045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (clear) BitVector_Interval_Empty(addr,(bits-count),(bits-1));
249145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
249245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
249345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
249445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgboolean BitVector_increment(wordptr addr)                   /* X++           */
249545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
249645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  size  = size_(addr);
249745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  mask  = mask_(addr);
249845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr last  = addr + size - 1;
249945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean carry = TRUE;
250045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
250145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (size > 0)
250245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
250345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *last |= NOT mask;
250445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (carry and (size-- > 0))
250545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
250645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            carry = (++(*addr++) == 0);
250745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
250845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *last &= mask;
250945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
251045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(carry);
251145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
251245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
251345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgboolean BitVector_decrement(wordptr addr)                   /* X--           */
251445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
251545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  size  = size_(addr);
251645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  mask  = mask_(addr);
251745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr last  = addr + size - 1;
251845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean carry = TRUE;
251945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
252045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (size > 0)
252145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
252245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *last &= mask;
252345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (carry and (size-- > 0))
252445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
252545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            carry = (*addr == 0);
252645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            --(*addr++);
252745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
252845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *last &= mask;
252945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
253045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(carry);
253145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
253245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
253345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgboolean BitVector_compute(wordptr X, wordptr Y, wordptr Z, boolean minus, boolean *carry)
253445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
253545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word size = size_(X);
253645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word mask = mask_(X);
253745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word vv = 0;
253845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word cc;
253945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word mm;
254045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word yy;
254145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word zz;
254245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word lo;
254345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word hi;
254445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
254545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (size > 0)
254645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
254745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (minus) cc = (*carry == 0);
254845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else       cc = (*carry != 0);
254945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* deal with (size-1) least significant full words first: */
255045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (--size > 0)
255145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
255245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yy = *Y++;
255345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (minus) zz = (N_word) NOT ( Z ? *Z++ : 0 );
255445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else       zz = (N_word)     ( Z ? *Z++ : 0 );
255545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            lo = (yy AND LSB) + (zz AND LSB) + cc;
255645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            hi = (yy >> 1) + (zz >> 1) + (lo >> 1);
255745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            cc = ((hi AND MSB) != 0);
255845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *X++ = (hi << 1) OR (lo AND LSB);
255945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
256045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        /* deal with most significant word (may be used only partially): */
256145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yy = *Y AND mask;
256245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (minus) zz = (N_word) NOT ( Z ? *Z : 0 );
256345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else       zz = (N_word)     ( Z ? *Z : 0 );
256445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        zz &= mask;
256545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (mask == LSB) /* special case, only one bit used */
256645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
256745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            vv = cc;
256845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            lo = yy + zz + cc;
256945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            cc = (lo >> 1);
257045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            vv ^= cc;
257145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *X = lo AND LSB;
257245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
257345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else
257445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
257545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (NOT mask) /* not all bits are used, but more than one */
257645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
257745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                mm = (mask >> 1);
257845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                vv = (yy AND mm) + (zz AND mm) + cc;
257945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                mm = mask AND NOT mm;
258045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                lo = yy + zz + cc;
258145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                cc = (lo >> 1);
258245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                vv ^= cc;
258345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                vv &= mm;
258445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                cc &= mm;
258545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                *X = lo AND mask;
258645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
258745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else /* other special case, all bits are used */
258845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
258945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                mm = NOT MSB;
259045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                lo = (yy AND mm) + (zz AND mm) + cc;
259145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                vv = lo AND MSB;
259245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                hi = ((yy AND MSB) >> 1) + ((zz AND MSB) >> 1) + (vv >> 1);
259345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                cc = hi AND MSB;
259445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                vv ^= cc;
259545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                *X = (hi << 1) OR (lo AND mm);
259645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
259745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
259845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (minus) *carry = (cc == 0);
259945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else       *carry = (cc != 0);
260045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
260145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(vv != 0);
260245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
260345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
260445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgboolean BitVector_add(wordptr X, wordptr Y, wordptr Z, boolean *carry)
260545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
260645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(BitVector_compute(X,Y,Z,FALSE,carry));
260745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
260845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
260945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgboolean BitVector_sub(wordptr X, wordptr Y, wordptr Z, boolean *carry)
261045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
261145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(BitVector_compute(X,Y,Z,TRUE,carry));
261245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
261345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
261445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgboolean BitVector_inc(wordptr X, wordptr Y)
261545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
261645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean carry = TRUE;
261745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
261845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(BitVector_compute(X,Y,NULL,FALSE,&carry));
261945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
262045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
262145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgboolean BitVector_dec(wordptr X, wordptr Y)
262245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
262345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean carry = TRUE;
262445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
262545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(BitVector_compute(X,Y,NULL,TRUE,&carry));
262645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
262745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
262845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid BitVector_Negate(wordptr X, wordptr Y)
262945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
263045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  size  = size_(X);
263145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  mask  = mask_(X);
263245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean carry = TRUE;
263345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
263445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (size > 0)
263545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
263645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (size-- > 0)
263745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
263845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *X = NOT *Y++;
263945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (carry)
264045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
264145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                carry = (++(*X) == 0);
264245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
264345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            X++;
264445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
264545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *(--X) &= mask;
264645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
264745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
264845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
264945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid BitVector_Absolute(wordptr X, wordptr Y)
265045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
265145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word size = size_(Y);
265245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word mask = mask_(Y);
265345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
265445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (size > 0)
265545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
265645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (*(Y+size-1) AND (mask AND NOT (mask >> 1))) BitVector_Negate(X,Y);
265745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else                                             BitVector_Copy(X,Y);
265845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
265945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
266045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
266145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgZ_int BitVector_Sign(wordptr addr)
266245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
266345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  size = size_(addr);
266445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  mask = mask_(addr);
266545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr last = addr + size - 1;
266645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean r    = TRUE;
266745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
266845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (size > 0)
266945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
267045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *last &= mask;
267145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (r and (size-- > 0)) r = ( *addr++ == 0 );
267245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
267345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (r) return((Z_int) 0);
267445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    else
267545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
267645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (*last AND (mask AND NOT (mask >> 1))) return((Z_int) -1);
267745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else                                      return((Z_int)  1);
267845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
267945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
268045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
268145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgErrCode BitVector_Mul_Pos(wordptr X, wordptr Y, wordptr Z, boolean strict)
268245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
268345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  mask;
268445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  limit;
268545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  count;
268645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Z_long  last;
268745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr sign;
268845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean carry;
268945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean overflow;
269045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean ok = TRUE;
269145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
269245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*
269345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org       Requirements:
269445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         -  X, Y and Z must be distinct
269545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         -  X and Y must have equal sizes (whereas Z may be any size!)
269645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         -  Z should always contain the SMALLER of the two factors Y and Z
269745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org       Constraints:
269845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         -  The contents of Y (and of X, of course) are destroyed
269945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            (only Z is preserved!)
270045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    */
270145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
270245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((X == Y) or (X == Z) or (Y == Z)) return(ErrCode_Same);
270345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bits_(X) != bits_(Y)) return(ErrCode_Size);
270445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    BitVector_Empty(X);
270545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (BitVector_is_empty(Y)) return(ErrCode_Ok); /* exit also taken if bits_(Y)==0 */
270645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((last = Set_Max(Z)) < 0L) return(ErrCode_Ok);
270745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    limit = (N_word) last;
270845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    sign = Y + size_(Y) - 1;
270945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    mask = mask_(Y);
271045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    *sign &= mask;
271145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    mask &= NOT (mask >> 1);
271245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for ( count = 0; (ok and (count <= limit)); count++ )
271345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
271445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if ( BIT_VECTOR_TST_BIT(Z,count) )
271545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
271645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            carry = false;
271745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            overflow = BitVector_compute(X,X,Y,false,&carry);
271845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (strict) ok = not (carry or overflow);
271945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else        ok = not  carry;
272045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
272145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (ok and (count < limit))
272245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
272345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            carry = BitVector_shift_left(Y,0);
272445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (strict)
272545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
272645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                overflow = ((*sign AND mask) != 0);
272745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                ok = not (carry or overflow);
272845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
272945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else ok = not carry;
273045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
273145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
273245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (ok) return(ErrCode_Ok); else return(ErrCode_Ovfl);
273345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
273445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
273545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgErrCode BitVector_Multiply(wordptr X, wordptr Y, wordptr Z)
273645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
273745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    ErrCode error = ErrCode_Ok;
273845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  bit_x = bits_(X);
273945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  bit_y = bits_(Y);
274045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  bit_z = bits_(Z);
274145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  size;
274245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  mask;
274345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  msb;
274445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr ptr_y;
274545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr ptr_z;
274645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean sgn_x;
274745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean sgn_y;
274845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean sgn_z;
274945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean zero;
275045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr A;
275145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr B;
275245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
275345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*
275445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org       Requirements:
275545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         -  Y and Z must have equal sizes
275645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         -  X must have at least the same size as Y and Z but may be larger (!)
275745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org       Features:
275845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         -  The contents of Y and Z are preserved
275945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         -  X may be identical with Y or Z (or both!)
276045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            (in-place multiplication is possible!)
276145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    */
276245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
276345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((bit_y != bit_z) or (bit_x < bit_y)) return(ErrCode_Size);
276445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (BitVector_is_empty(Y) or BitVector_is_empty(Z))
276545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
276645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BitVector_Empty(X);
276745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
276845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    else
276945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
277045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        A = BitVector_Create(bit_y,FALSE);
277145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (A == NULL) return(ErrCode_Null);
277245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        B = BitVector_Create(bit_z,FALSE);
277345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (B == NULL) { BitVector_Destroy(A); return(ErrCode_Null); }
277445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        size  = size_(Y);
277545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        mask  = mask_(Y);
277645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        msb   = (mask AND NOT (mask >> 1));
277745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        sgn_y = (((*(Y+size-1) &= mask) AND msb) != 0);
277845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        sgn_z = (((*(Z+size-1) &= mask) AND msb) != 0);
277945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        sgn_x = sgn_y XOR sgn_z;
278045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (sgn_y) BitVector_Negate(A,Y); else BitVector_Copy(A,Y);
278145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (sgn_z) BitVector_Negate(B,Z); else BitVector_Copy(B,Z);
278245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        ptr_y = A + size;
278345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        ptr_z = B + size;
278445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        zero = TRUE;
278545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (zero and (size-- > 0))
278645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
278745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            zero &= (*(--ptr_y) == 0);
278845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            zero &= (*(--ptr_z) == 0);
278945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
279045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (*ptr_y > *ptr_z)
279145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
279245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (bit_x > bit_y)
279345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
279445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                A = BitVector_Resize(A,bit_x);
279545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (A == NULL) { BitVector_Destroy(B); return(ErrCode_Null); }
279645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
279745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            error = BitVector_Mul_Pos(X,A,B,TRUE);
279845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
279945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else
280045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
280145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (bit_x > bit_z)
280245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
280345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                B = BitVector_Resize(B,bit_x);
280445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (B == NULL) { BitVector_Destroy(A); return(ErrCode_Null); }
280545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
280645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            error = BitVector_Mul_Pos(X,B,A,TRUE);
280745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
280845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if ((not error) and sgn_x) BitVector_Negate(X,X);
280945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BitVector_Destroy(A);
281045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BitVector_Destroy(B);
281145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
281245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(error);
281345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
281445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
281545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgErrCode BitVector_Div_Pos(wordptr Q, wordptr X, wordptr Y, wordptr R)
281645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
281745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  bits = bits_(Q);
281845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  mask;
281945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr addr;
282045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Z_long  last;
282145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean flag;
282245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean copy = FALSE; /* flags whether valid rest is in R (0) or X (1) */
282345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
282445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*
282545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org       Requirements:
282645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         -  All bit vectors must have equal sizes
282745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         -  Q, X, Y and R must all be distinct bit vectors
282845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         -  Y must be non-zero (of course!)
282945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org       Constraints:
283045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         -  The contents of X (and Q and R, of course) are destroyed
283145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            (only Y is preserved!)
283245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    */
283345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
283445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((bits != bits_(X)) or (bits != bits_(Y)) or (bits != bits_(R)))
283545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return(ErrCode_Size);
283645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((Q == X) or (Q == Y) or (Q == R) or (X == Y) or (X == R) or (Y == R))
283745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return(ErrCode_Same);
283845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (BitVector_is_empty(Y))
283945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return(ErrCode_Zero);
284045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
284145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    BitVector_Empty(R);
284245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    BitVector_Copy(Q,X);
284345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((last = Set_Max(Q)) < 0L) return(ErrCode_Ok);
284445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bits = (N_word) ++last;
284545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (bits-- > 0)
284645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
284745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        addr = Q + (bits >> LOGBITS);
284845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        mask = BITMASKTAB[bits AND MODMASK];
284945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        flag = ((*addr AND mask) != 0);
285045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (copy)
285145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
285245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            BitVector_shift_left(X,flag);
285345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            flag = FALSE;
285445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            BitVector_compute(R,X,Y,TRUE,&flag);
285545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
285645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else
285745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
285845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            BitVector_shift_left(R,flag);
285945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            flag = FALSE;
286045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            BitVector_compute(X,R,Y,TRUE,&flag);
286145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
286245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (flag) *addr &= NOT mask;
286345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else
286445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
286545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *addr |= mask;
286645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            copy = not copy;
286745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
286845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
286945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (copy) BitVector_Copy(R,X);
287045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(ErrCode_Ok);
287145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
287245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
287345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgErrCode BitVector_Divide(wordptr Q, wordptr X, wordptr Y, wordptr R)
287445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
287545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    ErrCode error = ErrCode_Ok;
287645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  bits = bits_(Q);
287745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  size = size_(Q);
287845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  mask = mask_(Q);
287945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  msb = (mask AND NOT (mask >> 1));
288045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean sgn_q;
288145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean sgn_x;
288245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean sgn_y;
288345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr A;
288445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr B;
288545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
288645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*
288745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org       Requirements:
288845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         -  All bit vectors must have equal sizes
288945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         -  Q and R must be two distinct bit vectors
289045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         -  Y must be non-zero (of course!)
289145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org       Features:
289245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         -  The contents of X and Y are preserved
289345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         -  Q may be identical with X or Y (or both)
289445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            (in-place division is possible!)
289545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         -  R may be identical with X or Y (or both)
289645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            (but not identical with Q!)
289745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    */
289845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
289945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((bits != bits_(X)) or (bits != bits_(Y)) or (bits != bits_(R)))
290045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return(ErrCode_Size);
290145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (Q == R)
290245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return(ErrCode_Same);
290345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (BitVector_is_empty(Y))
290445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return(ErrCode_Zero);
290545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
290645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (BitVector_is_empty(X))
290745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
290845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BitVector_Empty(Q);
290945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BitVector_Empty(R);
291045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
291145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    else
291245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
291345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        A = BitVector_Create(bits,FALSE);
291445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (A == NULL) return(ErrCode_Null);
291545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        B = BitVector_Create(bits,FALSE);
291645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (B == NULL) { BitVector_Destroy(A); return(ErrCode_Null); }
291745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        size--;
291845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        sgn_x = (((*(X+size) &= mask) AND msb) != 0);
291945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        sgn_y = (((*(Y+size) &= mask) AND msb) != 0);
292045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        sgn_q = sgn_x XOR sgn_y;
292145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (sgn_x) BitVector_Negate(A,X); else BitVector_Copy(A,X);
292245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (sgn_y) BitVector_Negate(B,Y); else BitVector_Copy(B,Y);
292345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (not (error = BitVector_Div_Pos(Q,A,B,R)))
292445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
292545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (sgn_q) BitVector_Negate(Q,Q);
292645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (sgn_x) BitVector_Negate(R,R);
292745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
292845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BitVector_Destroy(A);
292945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BitVector_Destroy(B);
293045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
293145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(error);
293245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
293345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
293445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgErrCode BitVector_GCD(wordptr X, wordptr Y, wordptr Z)
293545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
293645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    ErrCode error = ErrCode_Ok;
293745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  bits = bits_(X);
293845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  size = size_(X);
293945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  mask = mask_(X);
294045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  msb = (mask AND NOT (mask >> 1));
294145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean sgn_a;
294245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean sgn_b;
294345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean sgn_r;
294445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr Q;
294545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr R;
294645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr A;
294745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr B;
294845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr T;
294945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
295045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*
295145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org       Requirements:
295245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         -  All bit vectors must have equal sizes
295345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org       Features:
295445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         -  The contents of Y and Z are preserved
295545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         -  X may be identical with Y or Z (or both)
295645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            (in-place is possible!)
295745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         -  GCD(0,z) == GCD(z,0) == z
295845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         -  negative values are handled correctly
295945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    */
296045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
296145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((bits != bits_(Y)) or (bits != bits_(Z))) return(ErrCode_Size);
296245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (BitVector_is_empty(Y))
296345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
296445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (X != Z) BitVector_Copy(X,Z);
296545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return(ErrCode_Ok);
296645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
296745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (BitVector_is_empty(Z))
296845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
296945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (X != Y) BitVector_Copy(X,Y);
297045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return(ErrCode_Ok);
297145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
297245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Q = BitVector_Create(bits,false);
297345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (Q == NULL)
297445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
297545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return(ErrCode_Null);
297645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
297745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    R = BitVector_Create(bits,FALSE);
297845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (R == NULL)
297945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
298045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BitVector_Destroy(Q);
298145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return(ErrCode_Null);
298245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
298345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    A = BitVector_Create(bits,FALSE);
298445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (A == NULL)
298545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
298645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BitVector_Destroy(Q);
298745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BitVector_Destroy(R);
298845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return(ErrCode_Null);
298945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
299045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    B = BitVector_Create(bits,FALSE);
299145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (B == NULL)
299245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
299345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BitVector_Destroy(Q);
299445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BitVector_Destroy(R);
299545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BitVector_Destroy(A);
299645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return(ErrCode_Null);
299745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
299845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    size--;
299945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    sgn_a = (((*(Y+size) &= mask) AND msb) != 0);
300045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    sgn_b = (((*(Z+size) &= mask) AND msb) != 0);
300145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (sgn_a) BitVector_Negate(A,Y); else BitVector_Copy(A,Y);
300245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (sgn_b) BitVector_Negate(B,Z); else BitVector_Copy(B,Z);
300345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (not error)
300445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
300545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (not (error = BitVector_Div_Pos(Q,A,B,R)))
300645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
300745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (BitVector_is_empty(R)) break;
300845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            T = A; sgn_r = sgn_a;
300945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            A = B; sgn_a = sgn_b;
301045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            B = R; sgn_b = sgn_r;
301145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            R = T;
301245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
301345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
301445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (not error)
301545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
301645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (sgn_b) BitVector_Negate(X,B); else BitVector_Copy(X,B);
301745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
301845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    BitVector_Destroy(Q);
301945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    BitVector_Destroy(R);
302045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    BitVector_Destroy(A);
302145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    BitVector_Destroy(B);
302245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(error);
302345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
302445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
302545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgErrCode BitVector_GCD2(wordptr U, wordptr V, wordptr W, wordptr X, wordptr Y)
302645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
302745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    ErrCode error = ErrCode_Ok;
302845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  bits = bits_(U);
302945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  size = size_(U);
303045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  mask = mask_(U);
303145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  msb = (mask AND NOT (mask >> 1));
303245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean minus;
303345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean carry;
303445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean sgn_q;
303545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean sgn_r;
303645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean sgn_a;
303745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean sgn_b;
303845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean sgn_x;
303945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean sgn_y;
304045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    listptr L;
304145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr Q;
304245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr R;
304345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr A;
304445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr B;
304545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr T;
304645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr X1;
304745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr X2;
304845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr X3;
304945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr Y1;
305045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr Y2;
305145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr Y3;
305245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr Z;
305345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
305445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*
305545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org       Requirements:
305645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         -  All bit vectors must have equal sizes
305745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         -  U, V, and W must all be distinct bit vectors
305845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org       Features:
305945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         -  The contents of X and Y are preserved
306045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         -  U, V and W may be identical with X or Y (or both,
306145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            provided that U, V and W are mutually distinct)
306245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            (i.e., in-place is possible!)
306345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         -  GCD(0,z) == GCD(z,0) == z
306445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         -  negative values are handled correctly
306545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    */
306645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
306745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((bits != bits_(V)) or
306845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        (bits != bits_(W)) or
306945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        (bits != bits_(X)) or
307045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        (bits != bits_(Y)))
307145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
307245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return(ErrCode_Size);
307345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
307445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((U == V) or (U == W) or (V == W))
307545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
307645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return(ErrCode_Same);
307745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
307845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (BitVector_is_empty(X))
307945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
308045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (U != Y) BitVector_Copy(U,Y);
308145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BitVector_Empty(V);
308245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BitVector_Empty(W);
308345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *W = 1;
308445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return(ErrCode_Ok);
308545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
308645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (BitVector_is_empty(Y))
308745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
308845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (U != X) BitVector_Copy(U,X);
308945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BitVector_Empty(V);
309045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BitVector_Empty(W);
309145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *V = 1;
309245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return(ErrCode_Ok);
309345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
309445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((L = BitVector_Create_List(bits,false,11)) == NULL)
309545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
309645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return(ErrCode_Null);
309745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
309845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Q  = L[0];
309945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    R  = L[1];
310045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    A  = L[2];
310145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    B  = L[3];
310245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    X1 = L[4];
310345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    X2 = L[5];
310445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    X3 = L[6];
310545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Y1 = L[7];
310645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Y2 = L[8];
310745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Y3 = L[9];
310845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Z  = L[10];
310945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    size--;
311045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    sgn_a = (((*(X+size) &= mask) AND msb) != 0);
311145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    sgn_b = (((*(Y+size) &= mask) AND msb) != 0);
311245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (sgn_a) BitVector_Negate(A,X); else BitVector_Copy(A,X);
311345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (sgn_b) BitVector_Negate(B,Y); else BitVector_Copy(B,Y);
311445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    BitVector_Empty(X1);
311545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    BitVector_Empty(X2);
311645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    *X1 = 1;
311745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    BitVector_Empty(Y1);
311845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    BitVector_Empty(Y2);
311945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    *Y2 = 1;
312045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    sgn_x = false;
312145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    sgn_y = false;
312245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (not error)
312345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
312445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if ((error = BitVector_Div_Pos(Q,A,B,R)))
312545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
312645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            break;
312745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
312845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (BitVector_is_empty(R))
312945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
313045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            break;
313145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
313245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        sgn_q = sgn_a XOR sgn_b;
313345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
313445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (sgn_x) BitVector_Negate(Z,X2); else BitVector_Copy(Z,X2);
313545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if ((error = BitVector_Mul_Pos(X3,Z,Q,true)))
313645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
313745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            break;
313845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
313945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        minus = not (sgn_x XOR sgn_q);
314045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        carry = 0;
314145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (BitVector_compute(X3,X1,X3,minus,&carry))
314245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
314345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            error = ErrCode_Ovfl;
314445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            break;
314545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
314645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        sgn_x = (((*(X3+size) &= mask) AND msb) != 0);
314745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
314845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (sgn_y) BitVector_Negate(Z,Y2); else BitVector_Copy(Z,Y2);
314945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if ((error = BitVector_Mul_Pos(Y3,Z,Q,true)))
315045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
315145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            break;
315245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
315345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        minus = not (sgn_y XOR sgn_q);
315445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        carry = 0;
315545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (BitVector_compute(Y3,Y1,Y3,minus,&carry))
315645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
315745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            error = ErrCode_Ovfl;
315845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            break;
315945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
316045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        sgn_y = (((*(Y3+size) &= mask) AND msb) != 0);
316145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
316245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        T = A; sgn_r = sgn_a;
316345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        A = B; sgn_a = sgn_b;
316445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        B = R; sgn_b = sgn_r;
316545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        R = T;
316645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
316745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        T = X1;
316845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        X1 = X2;
316945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        X2 = X3;
317045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        X3 = T;
317145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
317245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        T = Y1;
317345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        Y1 = Y2;
317445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        Y2 = Y3;
317545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        Y3 = T;
317645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
317745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (not error)
317845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
317945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (sgn_b) BitVector_Negate(U,B); else BitVector_Copy(U,B);
318045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BitVector_Copy(V,X2);
318145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BitVector_Copy(W,Y2);
318245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
318345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    BitVector_Destroy_List(L,11);
318445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(error);
318545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
318645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
318745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgErrCode BitVector_Power(wordptr X, wordptr Y, wordptr Z)
318845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
318945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    ErrCode error = ErrCode_Ok;
319045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  bits  = bits_(X);
319145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean first = TRUE;
319245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Z_long  last;
319345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  limit;
319445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  count;
319545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr T;
319645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
319745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*
319845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org       Requirements:
319945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         -  X must have at least the same size as Y but may be larger (!)
320045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         -  X may not be identical with Z
320145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         -  Z must be positive
320245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org       Features:
320345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org         -  The contents of Y and Z are preserved
320445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    */
320545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
320645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (X == Z) return(ErrCode_Same);
320745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (bits < bits_(Y)) return(ErrCode_Size);
320845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (BitVector_msb_(Z)) return(ErrCode_Expo);
320945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((last = Set_Max(Z)) < 0L)
321045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
321145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (bits < 2) return(ErrCode_Ovfl);
321245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BitVector_Empty(X);
321345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *X |= LSB;
321445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return(ErrCode_Ok);                             /* anything ^ 0 == 1 */
321545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
321645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (BitVector_is_empty(Y))
321745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
321845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (X != Y) BitVector_Empty(X);
321945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return(ErrCode_Ok);                    /* 0 ^ anything not zero == 0 */
322045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
322145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    T = BitVector_Create(bits,FALSE);
322245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (T == NULL) return(ErrCode_Null);
322345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    limit = (N_word) last;
322445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for ( count = 0; ((!error) and (count <= limit)); count++ )
322545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
322645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if ( BIT_VECTOR_TST_BIT(Z,count) )
322745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
322845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (first)
322945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
323045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                first = FALSE;
323145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (count) {             BitVector_Copy(X,T); }
323245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else       { if (X != Y) BitVector_Copy(X,Y); }
323345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
323445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else error = BitVector_Multiply(X,T,X); /* order important because T > X */
323545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
323645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if ((!error) and (count < limit))
323745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
323845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (count) error = BitVector_Multiply(T,T,T);
323945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else       error = BitVector_Multiply(T,Y,Y);
324045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
324145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
324245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    BitVector_Destroy(T);
324345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(error);
324445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
324545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
324645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid BitVector_Block_Store(wordptr addr, charptr buffer, N_int length)
324745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
324845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  size = size_(addr);
324945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  mask = mask_(addr);
325045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  value;
325145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  count;
325245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
325345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* provide translation for independence of endian-ness: */
325445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (size > 0)
325545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
325645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (size-- > 0)
325745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
325845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            value = 0;
325945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            for ( count = 0; (length > 0) and (count < BITS); count += 8 )
326045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
326145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                value |= (((N_word) *buffer++) << count); length--;
326245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
326345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *addr++ = value;
326445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
326545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *(--addr) &= mask;
326645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
326745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
326845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
326945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgcharptr BitVector_Block_Read(wordptr addr, N_intptr length)
327045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
327145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  size = size_(addr);
327245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  value;
327345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  count;
327445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    charptr buffer;
327545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    charptr target;
327645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
327745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* provide translation for independence of endian-ness: */
327845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    *length = size << FACTOR;
327945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    buffer = (charptr) yasm_xmalloc((size_t) ((*length)+1));
328045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (buffer == NULL) return(NULL);
328145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    target = buffer;
328245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (size > 0)
328345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
328445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *(addr+size-1) &= mask_(addr);
328545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (size-- > 0)
328645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
328745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            value = *addr++;
328845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            count = BITS >> 3;
328945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            while (count-- > 0)
329045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
329145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                *target++ = (N_char) (value AND 0x00FF);
329245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (count > 0) value >>= 8;
329345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
329445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
329545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
329645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    *target = (N_char) '\0';
329745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(buffer);
329845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
329945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
330045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid BitVector_Word_Store(wordptr addr, N_int offset, N_int value)
330145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
330245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word size = size_(addr);
330345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
330445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (size > 0)
330545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
330645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (offset < size) *(addr+offset) = value;
330745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *(addr+size-1) &= mask_(addr);
330845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
330945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
331045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
331145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgN_int BitVector_Word_Read(wordptr addr, N_int offset)
331245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
331345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word size = size_(addr);
331445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
331545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (size > 0)
331645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
331745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *(addr+size-1) &= mask_(addr);
331845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (offset < size) return( *(addr+offset) );
331945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
332045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return( (N_int) 0 );
332145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
332245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
332345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid BitVector_Word_Insert(wordptr addr, N_int offset, N_int count,
332445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                           boolean clear)
332545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
332645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  size = size_(addr);
332745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  mask = mask_(addr);
332845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr last = addr+size-1;
332945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
333045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (size > 0)
333145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
333245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *last &= mask;
333345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (offset > size) offset = size;
333445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BIT_VECTOR_ins_words(addr+offset,size-offset,count,clear);
333545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *last &= mask;
333645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
333745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
333845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
333945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid BitVector_Word_Delete(wordptr addr, N_int offset, N_int count,
334045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                           boolean clear)
334145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
334245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  size = size_(addr);
334345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  mask = mask_(addr);
334445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    wordptr last = addr+size-1;
334545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
334645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (size > 0)
334745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
334845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *last &= mask;
334945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (offset > size) offset = size;
335045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BIT_VECTOR_del_words(addr+offset,size-offset,count,clear);
335145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *last &= mask;
335245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
335345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
335445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
335545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid BitVector_Chunk_Store(wordptr addr, N_int chunksize, N_int offset,
335645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                           N_long value)
335745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
335845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word bits = bits_(addr);
335945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word mask;
336045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word temp;
336145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
336245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((chunksize > 0) and (offset < bits))
336345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
336445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (chunksize > LONGBITS) chunksize = LONGBITS;
336545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if ((offset + chunksize) > bits) chunksize = bits - offset;
336645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        addr += offset >> LOGBITS;
336745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        offset &= MODMASK;
336845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (chunksize > 0)
336945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
337045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            mask = (N_word) (~0L << offset);
337145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            bits = offset + chunksize;
337245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (bits < BITS)
337345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
337445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                mask &= (N_word) ~(~0L << bits);
337545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                bits = chunksize;
337645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
337745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else bits = BITS - offset;
337845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            temp = (N_word) (value << offset);
337945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            temp &= mask;
338045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *addr &= NOT mask;
338145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            *addr++ |= temp;
338245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            value >>= bits;
338345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            chunksize -= bits;
338445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            offset = 0;
338545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
338645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
338745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
338845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
338945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgN_long BitVector_Chunk_Read(wordptr addr, N_int chunksize, N_int offset)
339045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
339145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word bits = bits_(addr);
339245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word chunkbits = 0;
339345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_long value = 0L;
339445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_long temp;
339545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word mask;
339645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
339745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((chunksize > 0) and (offset < bits))
339845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
339945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (chunksize > LONGBITS) chunksize = LONGBITS;
340045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if ((offset + chunksize) > bits) chunksize = bits - offset;
340145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        addr += offset >> LOGBITS;
340245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        offset &= MODMASK;
340345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (chunksize > 0)
340445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
340545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            bits = offset + chunksize;
340645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (bits < BITS)
340745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
340845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                mask = (N_word) ~(~0L << bits);
340945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                bits = chunksize;
341045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
341145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
341245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
341345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                mask = (N_word) ~0L;
341445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                bits = BITS - offset;
341545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
341645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            temp = (N_long) ((*addr++ AND mask) >> offset);
341745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            value |= temp << chunkbits;
341845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            chunkbits += bits;
341945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            chunksize -= bits;
342045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            offset = 0;
342145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
342245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
342345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(value);
342445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
342545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
342645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*******************/
342745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* set operations: */
342845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /*******************/
342945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
343045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid Set_Union(wordptr X, wordptr Y, wordptr Z)             /* X = Y + Z     */
343145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
343245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word bits = bits_(X);
343345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word size = size_(X);
343445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word mask = mask_(X);
343545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
343645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((size > 0) and (bits == bits_(Y)) and (bits == bits_(Z)))
343745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
343845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (size-- > 0) *X++ = *Y++ OR *Z++;
343945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *(--X) &= mask;
344045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
344145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
344245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
344345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid Set_Intersection(wordptr X, wordptr Y, wordptr Z)      /* X = Y * Z     */
344445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
344545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word bits = bits_(X);
344645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word size = size_(X);
344745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word mask = mask_(X);
344845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
344945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((size > 0) and (bits == bits_(Y)) and (bits == bits_(Z)))
345045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
345145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (size-- > 0) *X++ = *Y++ AND *Z++;
345245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *(--X) &= mask;
345345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
345445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
345545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
345645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid Set_Difference(wordptr X, wordptr Y, wordptr Z)        /* X = Y \ Z     */
345745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
345845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word bits = bits_(X);
345945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word size = size_(X);
346045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word mask = mask_(X);
346145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
346245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((size > 0) and (bits == bits_(Y)) and (bits == bits_(Z)))
346345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
346445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (size-- > 0) *X++ = *Y++ AND NOT *Z++;
346545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *(--X) &= mask;
346645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
346745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
346845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
346945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid Set_ExclusiveOr(wordptr X, wordptr Y, wordptr Z)       /* X=(Y+Z)\(Y*Z) */
347045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
347145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word bits = bits_(X);
347245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word size = size_(X);
347345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word mask = mask_(X);
347445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
347545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((size > 0) and (bits == bits_(Y)) and (bits == bits_(Z)))
347645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
347745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (size-- > 0) *X++ = *Y++ XOR *Z++;
347845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *(--X) &= mask;
347945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
348045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
348145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
348245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid Set_Complement(wordptr X, wordptr Y)                   /* X = ~Y        */
348345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
348445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word size = size_(X);
348545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word mask = mask_(X);
348645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
348745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((size > 0) and (bits_(X) == bits_(Y)))
348845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
348945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (size-- > 0) *X++ = NOT *Y++;
349045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        *(--X) &= mask;
349145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
349245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
349345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
349445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /******************/
349545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* set functions: */
349645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /******************/
349745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
349845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgboolean Set_subset(wordptr X, wordptr Y)                    /* X subset Y ?  */
349945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
350045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word size = size_(X);
350145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean r = FALSE;
350245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
350345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if ((size > 0) and (bits_(X) == bits_(Y)))
350445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
350545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        r = TRUE;
350645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (r and (size-- > 0)) r = ((*X++ AND NOT *Y++) == 0);
350745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
350845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(r);
350945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
351045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
351145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgN_int Set_Norm(wordptr addr)                                /* = | X |       */
351245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
351345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    byteptr byte;
351445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  bytes;
351545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_int   n;
351645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
351745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    byte = (byteptr) addr;
351845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    bytes = size_(addr) << FACTOR;
351945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    n = 0;
352045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (bytes-- > 0)
352145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
352245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        n += BitVector_BYTENORM[*byte++];
352345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
352445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(n);
352545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
352645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
352745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgN_int Set_Norm2(wordptr addr)                               /* = | X |       */
352845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
352945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  size = size_(addr);
353045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  w0,w1;
353145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_int   n,k;
353245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
353345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    n = 0;
353445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (size-- > 0)
353545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
353645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        k = 0;
353745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        w1 = NOT (w0 = *addr++);
353845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (w0 and w1)
353945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
354045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            w0 &= w0 - 1;
354145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            w1 &= w1 - 1;
354245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            k++;
354345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
354445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if (w0 == 0) n += k;
354545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else         n += BITS - k;
354645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
354745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(n);
354845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
354945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
355045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgN_int Set_Norm3(wordptr addr)                               /* = | X |       */
355145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
355245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  size  = size_(addr);
355345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_int   count = 0;
355445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  c;
355545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
355645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (size-- > 0)
355745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
355845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        c = *addr++;
355945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while (c)
356045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
356145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            c &= c - 1;
356245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            count++;
356345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
356445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
356545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return(count);
356645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
356745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
356845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgZ_long Set_Min(wordptr addr)                                /* = min(X)      */
356945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
357045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean empty = TRUE;
357145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  size  = size_(addr);
357245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  i     = 0;
357345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  c     = 0;         /* silence compiler warning */
357445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
357545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (empty and (size-- > 0))
357645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
357745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if ((c = *addr++)) empty = false; else i++;
357845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
357945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (empty) return((Z_long) LONG_MAX);                  /* plus infinity  */
358045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    i <<= LOGBITS;
358145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (not (c AND LSB))
358245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
358345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        c >>= 1;
358445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        i++;
358545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
358645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return((Z_long) i);
358745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
358845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
358945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgZ_long Set_Max(wordptr addr)                                /* = max(X)      */
359045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
359145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean empty = TRUE;
359245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  size  = size_(addr);
359345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  i     = size;
359445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  c     = 0;         /* silence compiler warning */
359545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
359645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    addr += size-1;
359745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (empty and (size-- > 0))
359845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
359945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if ((c = *addr--)) empty = false; else i--;
360045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
360145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (empty) return((Z_long) LONG_MIN);                  /* minus infinity */
360245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    i <<= LOGBITS;
360345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    while (not (c AND MSB))
360445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
360545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        c <<= 1;
360645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        i--;
360745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
360845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return((Z_long) --i);
360945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
361045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
361145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /**********************************/
361245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /* matrix-of-booleans operations: */
361345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    /**********************************/
361445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
361545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid Matrix_Multiplication(wordptr X, N_int rowsX, N_int colsX,
361645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                           wordptr Y, N_int rowsY, N_int colsY,
361745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                           wordptr Z, N_int rowsZ, N_int colsZ)
361845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
361945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word i;
362045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word j;
362145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word k;
362245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word indxX;
362345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word indxY;
362445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word indxZ;
362545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word termX;
362645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word termY;
362745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word sum;
362845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
362945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org  if ((colsY == rowsZ) and (rowsX == rowsY) and (colsX == colsZ) and
363045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org      (bits_(X) == rowsX*colsX) and
363145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org      (bits_(Y) == rowsY*colsY) and
363245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org      (bits_(Z) == rowsZ*colsZ))
363345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org  {
363445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for ( i = 0; i < rowsY; i++ )
363545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
363645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        termX = i * colsX;
363745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        termY = i * colsY;
363845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        for ( j = 0; j < colsZ; j++ )
363945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
364045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            indxX = termX + j;
364145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            sum = 0;
364245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            for ( k = 0; k < colsY; k++ )
364345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
364445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                indxY = termY + k;
364545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                indxZ = k * colsZ + j;
364645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if ( BIT_VECTOR_TST_BIT(Y,indxY) &&
364745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     BIT_VECTOR_TST_BIT(Z,indxZ) ) sum ^= 1;
364845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
364945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (sum) BIT_VECTOR_SET_BIT(X,indxX)
365045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else     BIT_VECTOR_CLR_BIT(X,indxX)
365145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
365245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
365345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org  }
365445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
365545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
365645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid Matrix_Product(wordptr X, N_int rowsX, N_int colsX,
365745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    wordptr Y, N_int rowsY, N_int colsY,
365845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    wordptr Z, N_int rowsZ, N_int colsZ)
365945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
366045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word i;
366145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word j;
366245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word k;
366345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word indxX;
366445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word indxY;
366545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word indxZ;
366645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word termX;
366745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word termY;
366845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word sum;
366945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
367045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org  if ((colsY == rowsZ) and (rowsX == rowsY) and (colsX == colsZ) and
367145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org      (bits_(X) == rowsX*colsX) and
367245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org      (bits_(Y) == rowsY*colsY) and
367345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org      (bits_(Z) == rowsZ*colsZ))
367445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org  {
367545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for ( i = 0; i < rowsY; i++ )
367645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
367745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        termX = i * colsX;
367845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        termY = i * colsY;
367945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        for ( j = 0; j < colsZ; j++ )
368045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
368145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            indxX = termX + j;
368245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            sum = 0;
368345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            for ( k = 0; k < colsY; k++ )
368445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
368545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                indxY = termY + k;
368645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                indxZ = k * colsZ + j;
368745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if ( BIT_VECTOR_TST_BIT(Y,indxY) &&
368845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     BIT_VECTOR_TST_BIT(Z,indxZ) ) sum |= 1;
368945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
369045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if (sum) BIT_VECTOR_SET_BIT(X,indxX)
369145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else     BIT_VECTOR_CLR_BIT(X,indxX)
369245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
369345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
369445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org  }
369545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
369645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
369745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid Matrix_Closure(wordptr addr, N_int rows, N_int cols)
369845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
369945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word i;
370045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word j;
370145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word k;
370245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word ii;
370345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word ij;
370445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word ik;
370545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word kj;
370645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word termi;
370745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word termk;
370845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
370945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org  if ((rows == cols) and (bits_(addr) == rows*cols))
371045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org  {
371145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for ( i = 0; i < rows; i++ )
371245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
371345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        ii = i * cols + i;
371445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        BIT_VECTOR_SET_BIT(addr,ii)
371545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
371645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    for ( k = 0; k < rows; k++ )
371745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
371845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        termk = k * cols;
371945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        for ( i = 0; i < rows; i++ )
372045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
372145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            termi = i * cols;
372245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            ik = termi + k;
372345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            for ( j = 0; j < rows; j++ )
372445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
372545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                ij = termi + j;
372645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                kj = termk + j;
372745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if ( BIT_VECTOR_TST_BIT(addr,ik) &&
372845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     BIT_VECTOR_TST_BIT(addr,kj) )
372945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     BIT_VECTOR_SET_BIT(addr,ij)
373045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
373145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
373245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
373345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org  }
373445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
373545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
373645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgvoid Matrix_Transpose(wordptr X, N_int rowsX, N_int colsX,
373745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                      wordptr Y, N_int rowsY, N_int colsY)
373845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org{
373945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  i;
374045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  j;
374145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  ii;
374245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  ij;
374345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  ji;
374445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  addii;
374545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  addij;
374645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  addji;
374745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  bitii;
374845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  bitij;
374945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  bitji;
375045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  termi;
375145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    N_word  termj;
375245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    boolean swap;
375345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
375445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org  /* BEWARE that "in-place" is ONLY possible if the matrix is quadratic!! */
375545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
375645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org  if ((rowsX == colsY) and (colsX == rowsY) and
375745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org      (bits_(X) == rowsX*colsX) and
375845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org      (bits_(Y) == rowsY*colsY))
375945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org  {
376045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if (rowsY == colsY) /* in-place is possible! */
376145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
376245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        for ( i = 0; i < rowsY; i++ )
376345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
376445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            termi = i * colsY;
376545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            for ( j = 0; j < i; j++ )
376645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
376745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                termj = j * colsX;
376845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                ij = termi + j;
376945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                ji = termj + i;
377045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                addij = ij >> LOGBITS;
377145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                addji = ji >> LOGBITS;
377245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                bitij = BITMASKTAB[ij AND MODMASK];
377345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                bitji = BITMASKTAB[ji AND MODMASK];
377445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                swap = ((*(Y+addij) AND bitij) != 0);
377545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if ((*(Y+addji) AND bitji) != 0)
377645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     *(X+addij) |=     bitij;
377745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else
377845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     *(X+addij) &= NOT bitij;
377945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if (swap)
378045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     *(X+addji) |=     bitji;
378145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else
378245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     *(X+addji) &= NOT bitji;
378345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
378445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            ii = termi + i;
378545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            addii = ii >> LOGBITS;
378645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            bitii = BITMASKTAB[ii AND MODMASK];
378745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if ((*(Y+addii) AND bitii) != 0)
378845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 *(X+addii) |=     bitii;
378945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else
379045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                 *(X+addii) &= NOT bitii;
379145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
379245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
379345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    else /* rowsX != colsX, in-place is NOT possible! */
379445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    {
379545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        for ( i = 0; i < rowsY; i++ )
379645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        {
379745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            termi = i * colsY;
379845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            for ( j = 0; j < colsY; j++ )
379945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            {
380045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                termj = j * colsX;
380145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                ij = termi + j;
380245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                ji = termj + i;
380345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                addij = ij >> LOGBITS;
380445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                addji = ji >> LOGBITS;
380545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                bitij = BITMASKTAB[ij AND MODMASK];
380645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                bitji = BITMASKTAB[ji AND MODMASK];
380745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if ((*(Y+addij) AND bitij) != 0)
380845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     *(X+addji) |=     bitji;
380945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                else
381045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                     *(X+addji) &= NOT bitji;
381145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            }
381245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        }
381345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    }
381445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org  }
381545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
381645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
381745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*****************************************************************************/
381845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*  VERSION:  6.4                                                            */
381945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*****************************************************************************/
382045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*  VERSION HISTORY:                                                         */
382145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*****************************************************************************/
382245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*                                                                           */
382345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    Version 6.4  03.10.04  Added C++ comp. directives. Improved "Norm()".  */
382445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    Version 6.3  28.09.02  Added "Create_List()" and "GCD2()".             */
382545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    Version 6.2  15.09.02  Overhauled error handling. Fixed "GCD()".       */
382645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    Version 6.1  08.10.01  Make VMS linker happy: _lsb,_msb => _lsb_,_msb_ */
382745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    Version 6.0  08.10.00  Corrected overflow handling.                    */
382845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    Version 5.8  14.07.00  Added "Power()". Changed "Copy()".              */
382945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    Version 5.7  19.05.99  Quickened "Div_Pos()". Added "Product()".       */
383045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    Version 5.6  02.11.98  Leading zeros eliminated in "to_Hex()".         */
383145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    Version 5.5  21.09.98  Fixed bug of uninitialized "error" in Multiply. */
383245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    Version 5.4  07.09.98  Fixed bug of uninitialized "error" in Divide.   */
383345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    Version 5.3  12.05.98  Improved Norm. Completed history.               */
383445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    Version 5.2  31.03.98  Improved Norm.                                  */
383545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    Version 5.1  09.03.98  No changes.                                     */
383645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    Version 5.0  01.03.98  Major additions and rewrite.                    */
383745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    Version 4.2  16.07.97  Added is_empty, is_full.                        */
383845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    Version 4.1  30.06.97  Added word-ins/del, move-left/right, inc/dec.   */
383945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    Version 4.0  23.04.97  Rewrite. Added bit shift and bool. matrix ops.  */
384045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    Version 3.2  04.02.97  Added interval methods.                         */
384145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    Version 3.1  21.01.97  Fixed bug on 64 bit machines.                   */
384245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    Version 3.0  12.01.97  Added flip.                                     */
384345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    Version 2.0  14.12.96  Efficiency and consistency improvements.        */
384445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    Version 1.1  08.01.96  Added Resize and ExclusiveOr.                   */
384545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    Version 1.0  14.12.95  First version under UNIX (with Perl module).    */
384645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    Version 0.9  01.11.93  First version of C library under MS-DOS.        */
384745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    Version 0.1  ??.??.89  First version in Turbo Pascal under CP/M.       */
384845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*                                                                           */
384945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*****************************************************************************/
385045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*  AUTHOR:                                                                  */
385145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*****************************************************************************/
385245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*                                                                           */
385345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    Steffen Beyer                                                          */
385445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    mailto:sb@engelschall.com                                              */
385545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    http://www.engelschall.com/u/sb/download/                              */
385645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*                                                                           */
385745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*****************************************************************************/
385845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*  COPYRIGHT:                                                               */
385945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*****************************************************************************/
386045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*                                                                           */
386145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    Copyright (c) 1995 - 2004 by Steffen Beyer.                            */
386245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    All rights reserved.                                                   */
386345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*                                                                           */
386445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*****************************************************************************/
386545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*  LICENSE:                                                                 */
386645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*****************************************************************************/
386745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* This package is free software; you can use, modify and redistribute       */
386845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* it under the same terms as Perl itself, i.e., under the terms of          */
386945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* the "Artistic License" or the "GNU General Public License".               */
387045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*                                                                           */
387145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* The C library at the core of this Perl module can additionally            */
387245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* be used, modified and redistributed under the terms of the                */
387345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* "GNU Library General Public License".                                     */
387445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*                                                                           */
387545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*****************************************************************************/
387645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*  ARTISTIC LICENSE:                                                        */
387745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*****************************************************************************/
387845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*
387945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                         The "Artistic License"
388045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
388145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                Preamble
388245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
388345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgThe intent of this document is to state the conditions under which a
388445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgPackage may be copied, such that the Copyright Holder maintains some
388545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgsemblance of artistic control over the development of the package,
388645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgwhile giving the users of the package the right to use and distribute
388745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgthe Package in a more-or-less customary fashion, plus the right to make
388845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgreasonable modifications.
388945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
389045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgDefinitions:
389145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
389245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        "Package" refers to the collection of files distributed by the
389345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        Copyright Holder, and derivatives of that collection of files
389445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        created through textual modification.
389545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
389645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        "Standard Version" refers to such a Package if it has not been
389745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        modified, or has been modified in accordance with the wishes
389845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        of the Copyright Holder as specified below.
389945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
390045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        "Copyright Holder" is whoever is named in the copyright or
390145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        copyrights for the package.
390245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
390345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        "You" is you, if you're thinking about copying or distributing
390445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        this Package.
390545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
390645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        "Reasonable copying fee" is whatever you can justify on the
390745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        basis of media cost, duplication charges, time of people involved,
390845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        and so on.  (You will not be required to justify it to the
390945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        Copyright Holder, but only to the computing community at large
391045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        as a market that must bear the fee.)
391145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
391245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        "Freely Available" means that no fee is charged for the item
391345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        itself, though there may be fees involved in handling the item.
391445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        It also means that recipients of the item may redistribute it
391545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        under the same conditions they received it.
391645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
391745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org1. You may make and give away verbatim copies of the source form of the
391845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgStandard Version of this Package without restriction, provided that you
391945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgduplicate all of the original copyright notices and associated disclaimers.
392045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
392145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org2. You may apply bug fixes, portability fixes and other modifications
392245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgderived from the Public Domain or from the Copyright Holder.  A Package
392345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgmodified in such a way shall still be considered the Standard Version.
392445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
392545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org3. You may otherwise modify your copy of this Package in any way, provided
392645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgthat you insert a prominent notice in each changed file stating how and
392745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgwhen you changed that file, and provided that you do at least ONE of the
392845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgfollowing:
392945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
393045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    a) place your modifications in the Public Domain or otherwise make them
393145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    Freely Available, such as by posting said modifications to Usenet or
393245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    an equivalent medium, or placing the modifications on a major archive
393345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    site such as uunet.uu.net, or by allowing the Copyright Holder to include
393445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    your modifications in the Standard Version of the Package.
393545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
393645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    b) use the modified Package only within your corporation or organization.
393745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
393845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    c) rename any non-standard executables so the names do not conflict
393945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    with standard executables, which must also be provided, and provide
394045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    a separate manual page for each non-standard executable that clearly
394145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    documents how it differs from the Standard Version.
394245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
394345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    d) make other distribution arrangements with the Copyright Holder.
394445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
394545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org4. You may distribute the programs of this Package in object code or
394645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgexecutable form, provided that you do at least ONE of the following:
394745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
394845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    a) distribute a Standard Version of the executables and library files,
394945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    together with instructions (in the manual page or equivalent) on where
395045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    to get the Standard Version.
395145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
395245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    b) accompany the distribution with the machine-readable source of
395345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    the Package with your modifications.
395445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
395545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    c) give non-standard executables non-standard names, and clearly
395645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    document the differences in manual pages (or equivalent), together
395745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    with instructions on where to get the Standard Version.
395845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
395945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    d) make other distribution arrangements with the Copyright Holder.
396045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
396145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org5. You may charge a reasonable copying fee for any distribution of this
396245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgPackage.  You may charge any fee you choose for support of this
396345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgPackage.  You may not charge a fee for this Package itself.  However,
396445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgyou may distribute this Package in aggregate with other (possibly
396545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgcommercial) programs as part of a larger (possibly commercial) software
396645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgdistribution provided that you do not advertise this Package as a
396745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgproduct of your own.  You may embed this Package's interpreter within
396845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.organ executable of yours (by linking); this shall be construed as a mere
396945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgform of aggregation, provided that the complete Standard Version of the
397045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orginterpreter is so embedded.
397145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
397245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org6. The scripts and library files supplied as input to or produced as
397345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgoutput from the programs of this Package do not automatically fall
397445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgunder the copyright of this Package, but belong to whoever generated
397545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgthem, and may be sold commercially, and may be aggregated with this
397645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgPackage.  If such scripts or library files are aggregated with this
397745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgPackage via the so-called "undump" or "unexec" methods of producing a
397845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgbinary executable image, then distribution of such an image shall
397945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgneither be construed as a distribution of this Package nor shall it
398045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgfall under the restrictions of Paragraphs 3 and 4, provided that you do
398145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgnot represent such an executable image as a Standard Version of this
398245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgPackage.
398345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
398445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org7. C subroutines (or comparably compiled subroutines in other
398545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orglanguages) supplied by you and linked into this Package in order to
398645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgemulate subroutines and variables of the language defined by this
398745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgPackage shall not be considered part of this Package, but are the
398845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgequivalent of input as in Paragraph 6, provided these subroutines do
398945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgnot change the language in any way that would cause it to fail the
399045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgregression tests for the language.
399145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
399245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org8. Aggregation of this Package with a commercial distribution is always
399345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgpermitted provided that the use of this Package is embedded; that is,
399445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgwhen no overt attempt is made to make this Package's interfaces visible
399545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgto the end user of the commercial distribution.  Such use shall not be
399645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgconstrued as a distribution of this Package.
399745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
399845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org9. The name of the Copyright Holder may not be used to endorse or promote
399945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgproducts derived from this software without specific prior written permission.
400045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
400145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
400245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgIMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
400345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgWARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
400445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
400545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                                The End
400645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org*/
400745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*****************************************************************************/
400845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*  GNU GENERAL PUBLIC LICENSE:                                              */
400945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*****************************************************************************/
401045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* This program is free software; you can redistribute it and/or             */
401145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* modify it under the terms of the GNU General Public License               */
401245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* as published by the Free Software Foundation; either version 2            */
401345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* of the License, or (at your option) any later version.                    */
401445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*                                                                           */
401545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* This program is distributed in the hope that it will be useful,           */
401645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
401745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
401845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* GNU General Public License for more details.                              */
401945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*                                                                           */
402045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* You should have received a copy of the GNU General Public License         */
402145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* along with this program; if not, write to the                             */
402245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* Free Software Foundation, Inc.,                                           */
402345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/* 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.                 */
402445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*                                                                           */
402545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*****************************************************************************/
402645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*  GNU LIBRARY GENERAL PUBLIC LICENSE:                                      */
402745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*****************************************************************************/
402845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    This library is free software; you can redistribute it and/or          */
402945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    modify it under the terms of the GNU Library General Public            */
403045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    License as published by the Free Software Foundation; either           */
403145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    version 2 of the License, or (at your option) any later version.       */
403245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*                                                                           */
403345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    This library is distributed in the hope that it will be useful,        */
403445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
403545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU       */
403645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    Library General Public License for more details.                       */
403745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*                                                                           */
403845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    You should have received a copy of the GNU Library General Public      */
403945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    License along with this library; if not, write to the                  */
404045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    Free Software Foundation, Inc.,                                        */
404145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    59 Temple Place, Suite 330, Boston, MA 02111-1307 USA                  */
404245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*                                                                           */
404345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*    or download a copy from ftp://ftp.gnu.org/pub/gnu/COPYING.LIB-2.0      */
404445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*                                                                           */
404545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org/*****************************************************************************/
4046