#ifndef MODULE_BIT_VECTOR
#define MODULE_BIT_VECTOR
#include <stdlib.h> /* MODULE TYPE: (sys) */
#include <limits.h> /* MODULE TYPE: (sys) */
#include <string.h> /* MODULE TYPE: (sys) */
#include <ctype.h> /* MODULE TYPE: (sys) */
#include "ToolBox.h" /* MODULE TYPE: (dat) */
typedef
enum
{
BV_ErrCode_Ok = 0,
BV_ErrCode_Type,
BV_ErrCode_Bits,
BV_ErrCode_Word,
BV_ErrCode_Powr,
BV_ErrCode_Loga,
BV_ErrCode_Lpwr,
BV_ErrCode_WgtL,
BV_ErrCode_Null,
BV_ErrCode_Indx,
BV_ErrCode_Ordr,
BV_ErrCode_Size,
BV_ErrCode_Pars,
BV_ErrCode_Ovfl,
BV_ErrCode_Same,
BV_ErrCode_Expo,
BV_ErrCode_Zero,
BV_ErrCode_Oops
}
BV_ErrCode;
typedef
wordptr *bv_listptr;
charptr BitVector_Error (BV_ErrCode error);
BV_ErrCode BitVector_Boot (
void
);
N_word BitVector_Size (N_int bits);
N_word BitVector_Mask (N_int bits);
charptr BitVector_Version (
void
);
N_int BitVector_Word_Bits (
void
);
N_int BitVector_Long_Bits (
void
);
wordptr BitVector_Create (N_int bits, boolean clear);
bv_listptr BitVector_Create_List(N_int bits, boolean clear, N_int count);
wordptr BitVector_Resize (wordptr oldaddr, N_int bits);
wordptr BitVector_Shadow (wordptr addr);
wordptr BitVector_Clone (wordptr addr);
wordptr BitVector_Concat (wordptr X, wordptr Y);
void
BitVector_Dispose (charptr string);
void
BitVector_Destroy (wordptr addr);
void
BitVector_Destroy_List (bv_listptr list, N_int count);
void
BitVector_Copy (wordptr X, wordptr Y);
void
BitVector_Empty (wordptr addr);
void
BitVector_Fill (wordptr addr);
void
BitVector_Flip (wordptr addr);
void
BitVector_Primes (wordptr addr);
void
BitVector_Reverse (wordptr X, wordptr Y);
void
BitVector_Interval_Empty (wordptr addr, N_int lower, N_int upper);
void
BitVector_Interval_Fill (wordptr addr, N_int lower, N_int upper);
void
BitVector_Interval_Flip (wordptr addr, N_int lower, N_int upper);
void
BitVector_Interval_Reverse (wordptr addr, N_int lower, N_int upper);
boolean BitVector_interval_scan_inc (wordptr addr, N_int start,
N_intptr min, N_intptr max);
boolean BitVector_interval_scan_dec (wordptr addr, N_int start,
N_intptr min, N_intptr max);
void
BitVector_Interval_Copy (wordptr X, wordptr Y, N_int Xoffset,
N_int Yoffset, N_int length);
wordptr BitVector_Interval_Substitute(wordptr X, wordptr Y,
N_int Xoffset, N_int Xlength,
N_int Yoffset, N_int Ylength);
boolean BitVector_is_empty (wordptr addr);
boolean BitVector_is_full (wordptr addr);
boolean BitVector_equal (wordptr X, wordptr Y);
Z_int BitVector_Lexicompare(wordptr X, wordptr Y);
Z_int BitVector_Compare (wordptr X, wordptr Y);
charptr BitVector_to_Hex (wordptr addr);
BV_ErrCode BitVector_from_Hex (wordptr addr, charptr string);
charptr BitVector_to_Bin (wordptr addr);
BV_ErrCode BitVector_from_Bin (wordptr addr, charptr string);
charptr BitVector_to_Dec (wordptr addr);
BV_ErrCode BitVector_from_Dec (wordptr addr, charptr string);
charptr BitVector_to_Enum (wordptr addr);
BV_ErrCode BitVector_from_Enum (wordptr addr, charptr string);
void
BitVector_Bit_Off (wordptr addr, N_int index);
void
BitVector_Bit_On (wordptr addr, N_int index);
boolean BitVector_bit_flip (wordptr addr, N_int index);
boolean BitVector_bit_test (wordptr addr, N_int index);
void
BitVector_Bit_Copy (wordptr addr, N_int index, boolean bit);
void
BitVector_LSB (wordptr addr, boolean bit);
void
BitVector_MSB (wordptr addr, boolean bit);
boolean BitVector_lsb_ (wordptr addr);
boolean BitVector_msb_ (wordptr addr);
boolean BitVector_rotate_left (wordptr addr);
boolean BitVector_rotate_right (wordptr addr);
boolean BitVector_shift_left (wordptr addr, boolean carry_in);
boolean BitVector_shift_right (wordptr addr, boolean carry_in);
void
BitVector_Move_Left (wordptr addr, N_int bits);
void
BitVector_Move_Right (wordptr addr, N_int bits);
void
BitVector_Insert (wordptr addr, N_int offset, N_int count,
boolean clear);
void
BitVector_Delete (wordptr addr, N_int offset, N_int count,
boolean clear);
boolean BitVector_increment (wordptr addr);
boolean BitVector_decrement (wordptr addr);
boolean BitVector_compute (wordptr X, wordptr Y, wordptr Z, boolean minus,
boolean *carry);
boolean BitVector_add (wordptr X, wordptr Y, wordptr Z, boolean *carry);
boolean BitVector_sub (wordptr X, wordptr Y, wordptr Z, boolean *carry);
boolean BitVector_inc (wordptr X, wordptr Y);
boolean BitVector_dec (wordptr X, wordptr Y);
void
BitVector_Negate (wordptr X, wordptr Y);
void
BitVector_Absolute (wordptr X, wordptr Y);
Z_int BitVector_Sign (wordptr addr);
BV_ErrCode BitVector_Mul_Pos (wordptr X, wordptr Y, wordptr Z, boolean strict);
BV_ErrCode BitVector_Multiply (wordptr X, wordptr Y, wordptr Z);
BV_ErrCode BitVector_Div_Pos (wordptr Q, wordptr X, wordptr Y, wordptr R);
BV_ErrCode BitVector_Divide (wordptr Q, wordptr X, wordptr Y, wordptr R);
BV_ErrCode BitVector_GCD (wordptr X, wordptr Y, wordptr Z);
BV_ErrCode BitVector_GCD2 (wordptr U, wordptr V, wordptr W,
wordptr X, wordptr Y);
BV_ErrCode BitVector_Power (wordptr X, wordptr Y, wordptr Z);
void
BitVector_Block_Store(wordptr addr, charptr buffer, N_int length);
charptr BitVector_Block_Read (wordptr addr, N_intptr length);
void
BitVector_Word_Store (wordptr addr, N_int offset, N_int value);
N_int BitVector_Word_Read (wordptr addr, N_int offset);
void
BitVector_Word_Insert(wordptr addr, N_int offset, N_int count,
boolean clear);
void
BitVector_Word_Delete(wordptr addr, N_int offset, N_int count,
boolean clear);
void
BitVector_Chunk_Store(wordptr addr, N_int chunksize,
N_int offset, N_long value);
N_long BitVector_Chunk_Read (wordptr addr, N_int chunksize,
N_int offset);
void
Set_Union (wordptr X, wordptr Y, wordptr Z);
void
Set_Intersection (wordptr X, wordptr Y, wordptr Z);
void
Set_Difference (wordptr X, wordptr Y, wordptr Z);
void
Set_ExclusiveOr (wordptr X, wordptr Y, wordptr Z);
void
Set_Complement (wordptr X, wordptr Y);
boolean Set_subset (wordptr X, wordptr Y);
N_int Set_Norm (wordptr addr);
N_int Set_Norm2 (wordptr addr);
N_int Set_Norm3 (wordptr addr);
Z_long Set_Min (wordptr addr);
Z_long Set_Max (wordptr addr);
void
Matrix_Multiplication(wordptr X, N_int rowsX, N_int colsX,
wordptr Y, N_int rowsY, N_int colsY,
wordptr Z, N_int rowsZ, N_int colsZ);
void
Matrix_Product (wordptr X, N_int rowsX, N_int colsX,
wordptr Y, N_int rowsY, N_int colsY,
wordptr Z, N_int rowsZ, N_int colsZ);
void
Matrix_Closure (wordptr addr, N_int rows, N_int cols);
void
Matrix_Transpose (wordptr X, N_int rowsX, N_int colsX,
wordptr Y, N_int rowsY, N_int colsY);
#define BV_BITS_(BitVector) *(BitVector-3)
#define BV_SIZE_(BitVector) *(BitVector-2)
#define BV_MASK_(BitVector) *(BitVector-1)
#define BV_ERRCODE_TYPE "sizeof(word) > sizeof(size_t)"
#define BV_ERRCODE_BITS "bits(word) != sizeof(word)*8"
#define BV_ERRCODE_WORD "bits(word) < 16"
#define BV_ERRCODE_POWR "bits(word) is not a power of two"
#define BV_ERRCODE_LOGA "bits(word) != 2^ld(bits(word))"
#define BV_ERRCODE_LPWR "bits(long) is not a power of two"
#define BV_ERRCODE_WGTL "bits(word) > bits(long)"
#define BV_ERRCODE_NULL "unable to allocate memory"
#define BV_ERRCODE_INDX "index out of range"
#define BV_ERRCODE_ORDR "minimum > maximum index"
#define BV_ERRCODE_SIZE "bit vector size mismatch"
#define BV_ERRCODE_PARS "input string syntax error"
#define BV_ERRCODE_OVFL "numeric overflow error"
#define BV_ERRCODE_SAME "result vector(s) must be distinct"
#define BV_ERRCODE_EXPO "exponent must be positive"
#define BV_ERRCODE_ZERO "division by zero error"
#define BV_ERRCODE_OOPS "unexpected internal error - please contact author"
const
N_int BV_ByteNorm[256] =
{
0x00, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x03,
0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04,
0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04,
0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04,
0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04,
0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07,
0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04,
0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07,
0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05,
0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07,
0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06,
0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07,
0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07,
0x05, 0x06, 0x06, 0x07, 0x06, 0x07, 0x07, 0x08
};
#define BV_HIDDENWORDS 3
static
N_word BV_WordBits;
static
N_word BV_ModMask;
static
N_word BV_LogBits;
static
N_word BV_Factor;
static
N_word BV_LSB = 1;
static
N_word BV_MSB;
static
N_word BV_LongBits;
static
N_word BV_Log10;
static
N_word BV_Exp10;
#define BV_MASKTABSIZE (sizeof(N_word) << 3)
static
N_word BV_BitMaskTab[BV_MASKTABSIZE];
#define BIT_VECTOR_ZERO_WORDS(target,count) \
while
(count-- > 0) *target++ = 0;
#define BIT_VECTOR_FILL_WORDS(target,fill,count) \
while
(count-- > 0) *target++ = fill;
#define BIT_VECTOR_FLIP_WORDS(target,flip,count) \
while
(count-- > 0) *target++ ^= flip;
#define BIT_VECTOR_COPY_WORDS(target,source,count) \
while
(count-- > 0) *target++ = *source++;
#define BIT_VECTOR_BACK_WORDS(target,source,count) \
{ target += count; source += count;
while
(count-- > 0) *--target = *--source; }
#define BIT_VECTOR_CLR_BIT(address,index) \
*(address+(index>>BV_LogBits)) &= NOT BV_BitMaskTab[index AND BV_ModMask];
#define BIT_VECTOR_SET_BIT(address,index) \
*(address+(index>>BV_LogBits)) |= BV_BitMaskTab[index AND BV_ModMask];
#define BIT_VECTOR_TST_BIT(address,index) \
((*(address+(index>>BV_LogBits)) AND BV_BitMaskTab[index AND BV_ModMask]) != 0)
#define BIT_VECTOR_FLP_BIT(address,index,mask) \
(mask = BV_BitMaskTab[index AND BV_ModMask]), \
(((*(addr+(index>>BV_LogBits)) ^= mask) AND mask) != 0)
#define BIT_VECTOR_DIGITIZE(type,value,digit) \
value = (type) ((digit = value) / 10); \
digit -= value * 10; \
digit += (type)
'0'
;
static
N_word BIT_VECTOR_power10(N_word x)
{
N_word y = 1;
while
(x-- > 0) y *= 10;
return
(y);
}
static
void
BIT_VECTOR_zro_words(wordptr addr, N_word count)
{
BIT_VECTOR_ZERO_WORDS(addr,count)
}
static
void
BIT_VECTOR_cpy_words(wordptr target, wordptr source, N_word count)
{
BIT_VECTOR_COPY_WORDS(target,source,count)
}
static
void
BIT_VECTOR_mov_words(wordptr target, wordptr source, N_word count)
{
if
(target != source)
{
if
(target < source) BIT_VECTOR_COPY_WORDS(target,source,count)
else
BIT_VECTOR_BACK_WORDS(target,source,count)
}
}
static
void
BIT_VECTOR_ins_words(wordptr addr, N_word total, N_word count,
boolean clear)
{
N_word length;
if
((total > 0) and (count > 0))
{
if
(count > total) count = total;
length = total - count;
if
(length > 0) BIT_VECTOR_mov_words(addr+count,addr,length);
if
(clear) BIT_VECTOR_zro_words(addr,count);
}
}
static
void
BIT_VECTOR_del_words(wordptr addr, N_word total, N_word count,
boolean clear)
{
N_word length;
if
((total > 0) and (count > 0))
{
if
(count > total) count = total;
length = total - count;
if
(length > 0) BIT_VECTOR_mov_words(addr,addr+count,length);
if
(clear) BIT_VECTOR_zro_words(addr+length,count);
}
}
static
void
BIT_VECTOR_reverse(charptr string, N_word length)
{
charptr last;
N_char temp;
if
(length > 1)
{
last = string + length - 1;
while
(string < last)
{
temp = *string;
*string = *last;
*last = temp;
string++;
last--;
}
}
}
static
N_word BIT_VECTOR_int2str(charptr string, N_word value)
{
N_word length;
N_word digit;
charptr work;
work = string;
if
(value > 0)
{
length = 0;
while
(value > 0)
{
BIT_VECTOR_DIGITIZE(N_word,value,digit)
*work++ = (N_char) digit;
length++;
}
BIT_VECTOR_reverse(string,length);
}
else
{
length = 1;
*work++ = (N_char)
'0'
;
}
return
(length);
}
static
N_word BIT_VECTOR_str2int(charptr string, N_word *value)
{
N_word length;
N_word digit;
*value = 0;
length = 0;
digit = (N_word) *string++;
while
(
isdigit
((
int
)digit) != 0)
{
length++;
digit -= (N_word)
'0'
;
if
(*value) *value *= 10;
*value += digit;
digit = (N_word) *string++;
}
return
(length);
}
charptr BitVector_Error(BV_ErrCode error)
{
switch
(error)
{
case
BV_ErrCode_Ok:
return
( (charptr) NULL );
break
;
case
BV_ErrCode_Type:
return
( (charptr) BV_ERRCODE_TYPE );
break
;
case
BV_ErrCode_Bits:
return
( (charptr) BV_ERRCODE_BITS );
break
;
case
BV_ErrCode_Word:
return
( (charptr) BV_ERRCODE_WORD );
break
;
case
BV_ErrCode_Powr:
return
( (charptr) BV_ERRCODE_POWR );
break
;
case
BV_ErrCode_Loga:
return
( (charptr) BV_ERRCODE_LOGA );
break
;
case
BV_ErrCode_Lpwr:
return
( (charptr) BV_ERRCODE_LPWR );
break
;
case
BV_ErrCode_WgtL:
return
( (charptr) BV_ERRCODE_WGTL );
break
;
case
BV_ErrCode_Null:
return
( (charptr) BV_ERRCODE_NULL );
break
;
case
BV_ErrCode_Indx:
return
( (charptr) BV_ERRCODE_INDX );
break
;
case
BV_ErrCode_Ordr:
return
( (charptr) BV_ERRCODE_ORDR );
break
;
case
BV_ErrCode_Size:
return
( (charptr) BV_ERRCODE_SIZE );
break
;
case
BV_ErrCode_Pars:
return
( (charptr) BV_ERRCODE_PARS );
break
;
case
BV_ErrCode_Ovfl:
return
( (charptr) BV_ERRCODE_OVFL );
break
;
case
BV_ErrCode_Same:
return
( (charptr) BV_ERRCODE_SAME );
break
;
case
BV_ErrCode_Expo:
return
( (charptr) BV_ERRCODE_EXPO );
break
;
case
BV_ErrCode_Zero:
return
( (charptr) BV_ERRCODE_ZERO );
break
;
default
:
return
( (charptr) BV_ERRCODE_OOPS );
break
;
}
}
BV_ErrCode BitVector_Boot(
void
)
{
N_word sample;
N_long longsample;
if
(
sizeof
(N_word) >
sizeof
(
size_t
))
return
(BV_ErrCode_Type);
BV_WordBits = 0;
sample = ~0;
while
(sample)
{
sample &= sample - 1;
BV_WordBits++;
}
if
(BV_WordBits != (
sizeof
(N_word) << 3))
return
(BV_ErrCode_Bits);
if
(BV_WordBits < 16)
return
(BV_ErrCode_Word);
BV_LongBits = 0;
longsample = ~0L;
while
(longsample)
{
longsample &= longsample - 1L;
BV_LongBits++;
}
BV_LogBits = 0;
sample = BV_ModMask = BV_WordBits - 1;
if
(sample AND BV_WordBits)
return
(BV_ErrCode_Powr);
while
(sample)
{
sample &= sample - 1;
BV_LogBits++;
}
if
(BV_WordBits != (BV_LSB << BV_LogBits))
return
(BV_ErrCode_Loga);
longsample = BV_LongBits - 1;
if
((longsample AND BV_LongBits) or (BV_LongBits != (
sizeof
(N_long) << 3)))
{
BV_LongBits = (
sizeof
(N_long) << 3);
longsample = BV_LongBits - 1;
if
(longsample AND BV_LongBits)
return
(BV_ErrCode_Lpwr);
}
if
(BV_WordBits > BV_LongBits)
return
(BV_ErrCode_WgtL);
if
(BV_WordBits > BV_MASKTABSIZE)
return
(BV_ErrCode_Oops);
for
( sample = 0; sample < BV_WordBits; sample++ )
{
BV_BitMaskTab[sample] = (BV_LSB << sample);
}
BV_Factor = BV_LogBits - 3;
BV_MSB = (BV_LSB << BV_ModMask);
BV_Log10 = (N_word) (BV_ModMask * 0.30103);
BV_Exp10 = BIT_VECTOR_power10(BV_Log10);
return
(BV_ErrCode_Ok);
}
N_word BitVector_Size(N_int bits)
{
N_word size;
size = bits >> BV_LogBits;
if
(bits AND BV_ModMask) size++;
return
(size);
}
N_word BitVector_Mask(N_int bits)
{
N_word mask;
mask = bits AND BV_ModMask;
if
(mask) mask = (N_word) ~(~0L << mask);
else
mask = (N_word) ~0L;
return
(mask);
}
charptr BitVector_Version(
void
)
{
return
((charptr)
"7.4"
);
}
N_int BitVector_Word_Bits(
void
)
{
return
(BV_WordBits);
}
N_int BitVector_Long_Bits(
void
)
{
return
(BV_LongBits);
}
void
BitVector_Dispose(charptr string)
{
if
(string != NULL)
free
((voidptr) string);
}
void
BitVector_Destroy(wordptr addr)
{
if
(addr != NULL)
{
addr -= BV_HIDDENWORDS;
free
((voidptr) addr);
}
}
void
BitVector_Destroy_List(bv_listptr list, N_int count)
{
bv_listptr slot;
if
(list != NULL)
{
slot = list;
while
(count-- > 0)
{
BitVector_Destroy(*slot++);
}
free
((voidptr) list);
}
}
wordptr BitVector_Create(N_int bits, boolean clear)
{
N_word size;
N_word mask;
N_word bytes;
wordptr addr;
wordptr zero;
size = BitVector_Size(bits);
mask = BitVector_Mask(bits);
bytes = (size + BV_HIDDENWORDS) << BV_Factor;
addr = (wordptr)
malloc
((
size_t
) bytes);
if
(addr != NULL)
{
*addr++ = bits;
*addr++ = size;
*addr++ = mask;
if
(clear)
{
zero = addr;
BIT_VECTOR_ZERO_WORDS(zero,size)
}
}
return
(addr);
}
bv_listptr BitVector_Create_List(N_int bits, boolean clear, N_int count)
{
bv_listptr list = NULL;
bv_listptr slot;
wordptr addr;
N_int i;
if
(count > 0)
{
list = (bv_listptr)
malloc
(
sizeof
(wordptr) * count);
if
(list != NULL)
{
slot = list;
for
( i = 0; i < count; i++ )
{
addr = BitVector_Create(bits,clear);
if
(addr == NULL)
{
BitVector_Destroy_List(list,i);
return
(NULL);
}
*slot++ = addr;
}
}
}
return
(list);
}
wordptr BitVector_Resize(wordptr oldaddr, N_int bits)
{
N_word bytes;
N_word oldsize;
N_word oldmask;
N_word newsize;
N_word newmask;
wordptr newaddr;
wordptr source;
wordptr target;
oldsize = BV_SIZE_(oldaddr);
oldmask = BV_MASK_(oldaddr);
newsize = BitVector_Size(bits);
newmask = BitVector_Mask(bits);
if
(oldsize > 0) *(oldaddr+oldsize-1) &= oldmask;
if
(newsize <= oldsize)
{
newaddr = oldaddr;
BV_BITS_(newaddr) = bits;
BV_SIZE_(newaddr) = newsize;
BV_MASK_(newaddr) = newmask;
if
(newsize > 0) *(newaddr+newsize-1) &= newmask;
}
else
{
bytes = (newsize + BV_HIDDENWORDS) << BV_Factor;
newaddr = (wordptr)
malloc
((
size_t
) bytes);
if
(newaddr != NULL)
{
*newaddr++ = bits;
*newaddr++ = newsize;
*newaddr++ = newmask;
target = newaddr;
source = oldaddr;
newsize -= oldsize;
BIT_VECTOR_COPY_WORDS(target,source,oldsize)
BIT_VECTOR_ZERO_WORDS(target,newsize)
}
BitVector_Destroy(oldaddr);
}
return
(newaddr);
}
wordptr BitVector_Shadow(wordptr addr)
{
return
( BitVector_Create(BV_BITS_(addr),
true
) );
}
wordptr BitVector_Clone(wordptr addr)
{
N_word bits;
wordptr twin;
bits = BV_BITS_(addr);
twin = BitVector_Create(bits,
false
);
if
((twin != NULL) and (bits > 0))
BIT_VECTOR_cpy_words(twin,addr,BV_SIZE_(addr));
return
(twin);
}
wordptr BitVector_Concat(wordptr X, wordptr Y)
{
N_word bitsX;
N_word bitsY;
N_word bitsZ;
wordptr Z;
bitsX = BV_BITS_(X);
bitsY = BV_BITS_(Y);
bitsZ = bitsX + bitsY;
Z = BitVector_Create(bitsZ,
false
);
if
((Z != NULL) and (bitsZ > 0))
{
BIT_VECTOR_cpy_words(Z,Y,BV_SIZE_(Y));
BitVector_Interval_Copy(Z,X,bitsY,0,bitsX);
*(Z+BV_SIZE_(Z)-1) &= BV_MASK_(Z);
}
return
(Z);
}
void
BitVector_Copy(wordptr X, wordptr Y)
{
N_word sizeX = BV_SIZE_(X);
N_word sizeY = BV_SIZE_(Y);
N_word maskX = BV_MASK_(X);
N_word maskY = BV_MASK_(Y);
N_word fill = 0;
wordptr lastX;
wordptr lastY;
if
((X != Y) and (sizeX > 0))
{
lastX = X + sizeX - 1;
if
(sizeY > 0)
{
lastY = Y + sizeY - 1;
if
( (*lastY AND (maskY AND NOT (maskY >> 1))) == 0 ) *lastY &= maskY;
else
{
fill = (N_word) ~0L;
*lastY |= NOT maskY;
}
while
((sizeX > 0) and (sizeY > 0))
{
*X++ = *Y++;
sizeX--;
sizeY--;
}
*lastY &= maskY;
}
while
(sizeX-- > 0) *X++ = fill;
*lastX &= maskX;
}
}
void
BitVector_Empty(wordptr addr)
{
N_word size = BV_SIZE_(addr);
BIT_VECTOR_ZERO_WORDS(addr,size)
}
void
BitVector_Fill(wordptr addr)
{
N_word size = BV_SIZE_(addr);
N_word mask = BV_MASK_(addr);
N_word fill = (N_word) ~0L;
if
(size > 0)
{
BIT_VECTOR_FILL_WORDS(addr,fill,size)
*(--addr) &= mask;
}
}
void
BitVector_Flip(wordptr addr)
{
N_word size = BV_SIZE_(addr);
N_word mask = BV_MASK_(addr);
N_word flip = (N_word) ~0L;
if
(size > 0)
{
BIT_VECTOR_FLIP_WORDS(addr,flip,size)
*(--addr) &= mask;
}
}
void
BitVector_Primes(wordptr addr)
{
N_word bits = BV_BITS_(addr);
N_word size = BV_SIZE_(addr);
wordptr work;
N_word temp;
N_word i,j;
if
(size > 0)
{
temp = 0xAAAA;
i = BV_WordBits >> 4;
while
(--i > 0)
{
temp <<= 16;
temp |= 0xAAAA;
}
i = size;
work = addr;
*work++ = temp XOR 0x0006;
while
(--i > 0) *work++ = temp;
for
( i = 3; (j = i * i) < bits; i += 2 )
{
for
( ; j < bits; j += i ) BIT_VECTOR_CLR_BIT(addr,j)
}
*(addr+size-1) &= BV_MASK_(addr);
}
}
void
BitVector_Reverse(wordptr X, wordptr Y)
{
N_word bits = BV_BITS_(X);
N_word mask;
N_word bit;
N_word value;
if
(bits > 0)
{
if
(X == Y) BitVector_Interval_Reverse(X,0,bits-1);
else
if
(bits == BV_BITS_(Y))
{
mask = BV_BitMaskTab[(bits-1) AND BV_ModMask];
Y += BV_SIZE_(Y) - 1;
value = 0;
bit = BV_LSB;
while
(bits-- > 0)
{
if
((*Y AND mask) != 0)
{
value |= bit;
}
if
(not (mask >>= 1))
{
Y--;
mask = BV_MSB;
}
if
(not (bit <<= 1))
{
*X++ = value;
value = 0;
bit = BV_LSB;
}
}
if
(bit > BV_LSB) *X = value;
}
}
}
void
BitVector_Interval_Empty(wordptr addr, N_int lower, N_int upper)
{
N_word bits = BV_BITS_(addr);
N_word size = BV_SIZE_(addr);
wordptr loaddr;
wordptr hiaddr;
N_word lobase;
N_word hibase;
N_word lomask;
N_word himask;
N_word diff;
if
((size > 0) and (lower < bits) and (upper < bits) and (lower <= upper))
{
lobase = lower >> BV_LogBits;
hibase = upper >> BV_LogBits;
diff = hibase - lobase;
loaddr = addr + lobase;
hiaddr = addr + hibase;
lomask = (N_word) (~0L << (lower AND BV_ModMask));
himask = (N_word) ~((~0L << (upper AND BV_ModMask)) << 1);
if
(diff == 0)
{
*loaddr &= NOT (lomask AND himask);
}
else
{
*loaddr++ &= NOT lomask;
while
(--diff > 0)
{
*loaddr++ = 0;
}
*hiaddr &= NOT himask;
}
}
}
void
BitVector_Interval_Fill(wordptr addr, N_int lower, N_int upper)
{
N_word bits = BV_BITS_(addr);
N_word size = BV_SIZE_(addr);
N_word fill = (N_word) ~0L;
wordptr loaddr;
wordptr hiaddr;
N_word lobase;
N_word hibase;
N_word lomask;
N_word himask;
N_word diff;
if
((size > 0) and (lower < bits) and (upper < bits) and (lower <= upper))
{
lobase = lower >> BV_LogBits;
hibase = upper >> BV_LogBits;
diff = hibase - lobase;
loaddr = addr + lobase;
hiaddr = addr + hibase;
lomask = (N_word) (~0L << (lower AND BV_ModMask));
himask = (N_word) ~((~0L << (upper AND BV_ModMask)) << 1);
if
(diff == 0)
{
*loaddr |= (lomask AND himask);
}
else
{
*loaddr++ |= lomask;
while
(--diff > 0)
{
*loaddr++ = fill;
}
*hiaddr |= himask;
}
*(addr+size-1) &= BV_MASK_(addr);
}
}
void
BitVector_Interval_Flip(wordptr addr, N_int lower, N_int upper)
{
N_word bits = BV_BITS_(addr);
N_word size = BV_SIZE_(addr);
N_word flip = (N_word) ~0L;
wordptr loaddr;
wordptr hiaddr;
N_word lobase;
N_word hibase;
N_word lomask;
N_word himask;
N_word diff;
if
((size > 0) and (lower < bits) and (upper < bits) and (lower <= upper))
{
lobase = lower >> BV_LogBits;
hibase = upper >> BV_LogBits;
diff = hibase - lobase;
loaddr = addr + lobase;
hiaddr = addr + hibase;
lomask = (N_word) (~0L << (lower AND BV_ModMask));
himask = (N_word) ~((~0L << (upper AND BV_ModMask)) << 1);
if
(diff == 0)
{
*loaddr ^= (lomask AND himask);
}
else
{
*loaddr++ ^= lomask;
while
(--diff > 0)
{
*loaddr++ ^= flip;
}
*hiaddr ^= himask;
}
*(addr+size-1) &= BV_MASK_(addr);
}
}
void
BitVector_Interval_Reverse(wordptr addr, N_int lower, N_int upper)
{
N_word bits = BV_BITS_(addr);
wordptr loaddr;
wordptr hiaddr;
N_word lomask;
N_word himask;
if
((bits > 0) and (lower < bits) and (upper < bits) and (lower < upper))
{
loaddr = addr + (lower >> BV_LogBits);
hiaddr = addr + (upper >> BV_LogBits);
lomask = BV_BitMaskTab[lower AND BV_ModMask];
himask = BV_BitMaskTab[upper AND BV_ModMask];
for
( bits = upper - lower + 1; bits > 1; bits -= 2 )
{
if
(((*loaddr AND lomask) != 0) XOR ((*hiaddr AND himask) != 0))
{
*loaddr ^= lomask;
*hiaddr ^= himask;
}
if
(not (lomask <<= 1))
{
lomask = BV_LSB;
loaddr++;
}
if
(not (himask >>= 1))
{
himask = BV_MSB;
hiaddr--;
}
}
}
}
boolean BitVector_interval_scan_inc(wordptr addr, N_int start,
N_intptr min, N_intptr max)
{
N_word size = BV_SIZE_(addr);
N_word mask = BV_MASK_(addr);
N_word offset;
N_word bitmask;
N_word value;
boolean empty;
if
((size == 0) or (start >= BV_BITS_(addr)))
return
(
false
);
*min = start;
*max = start;
offset = start >> BV_LogBits;
*(addr+size-1) &= mask;
addr += offset;
size -= offset;
bitmask = BV_BitMaskTab[start AND BV_ModMask];
mask = NOT (bitmask OR (bitmask - 1));
value = *addr++;
if
((value AND bitmask) == 0)
{
value &= mask;
if
(value == 0)
{
offset++;
empty =
true
;
while
(empty and (--size > 0))
{
if
((value = *addr++)) empty =
false
;
else
offset++;
}
if
(empty)
return
(
false
);
}
start = offset << BV_LogBits;
bitmask = BV_LSB;
mask = value;
while
(not (mask AND BV_LSB))
{
bitmask <<= 1;
mask >>= 1;
start++;
}
mask = NOT (bitmask OR (bitmask - 1));
*min = start;
*max = start;
}
value = NOT value;
value &= mask;
if
(value == 0)
{
offset++;
empty =
true
;
while
(empty and (--size > 0))
{
if
((value = NOT *addr++)) empty =
false
;
else
offset++;
}
if
(empty) value = BV_LSB;
}
start = offset << BV_LogBits;
while
(not (value AND BV_LSB))
{
value >>= 1;
start++;
}
*max = --start;
return
(
true
);
}
boolean BitVector_interval_scan_dec(wordptr addr, N_int start,
N_intptr min, N_intptr max)
{
N_word size = BV_SIZE_(addr);
N_word mask = BV_MASK_(addr);
N_word offset;
N_word bitmask;
N_word value;
boolean empty;
if
((size == 0) or (start >= BV_BITS_(addr)))
return
(
false
);
*min = start;
*max = start;
offset = start >> BV_LogBits;
if
(offset >= size)
return
(
false
);
*(addr+size-1) &= mask;
addr += offset;
size = ++offset;
bitmask = BV_BitMaskTab[start AND BV_ModMask];
mask = (bitmask - 1);
value = *addr--;
if
((value AND bitmask) == 0)
{
value &= mask;
if
(value == 0)
{
offset--;
empty =
true
;
while
(empty and (--size > 0))
{
if
((value = *addr--)) empty =
false
;
else
offset--;
}
if
(empty)
return
(
false
);
}
start = offset << BV_LogBits;
bitmask = BV_MSB;
mask = value;
while
(not (mask AND BV_MSB))
{
bitmask >>= 1;
mask <<= 1;
start--;
}
mask = (bitmask - 1);
*max = --start;
*min = start;
}
value = NOT value;
value &= mask;
if
(value == 0)
{
offset--;
empty =
true
;
while
(empty and (--size > 0))
{
if
((value = NOT *addr--)) empty =
false
;
else
offset--;
}
if
(empty) value = BV_MSB;
}
start = offset << BV_LogBits;
while
(not (value AND BV_MSB))
{
value <<= 1;
start--;
}
*min = start;
return
(
true
);
}
void
BitVector_Interval_Copy(wordptr X, wordptr Y, N_int Xoffset,
N_int Yoffset, N_int length)
{
N_word bitsX = BV_BITS_(X);
N_word bitsY = BV_BITS_(Y);
N_word source = 0;
N_word target = 0;
N_word s_lo_base;
N_word s_hi_base;
N_word s_lo_bit;
N_word s_hi_bit;
N_word s_base;
N_word s_lower = 0;
N_word s_upper = 0;
N_word s_bits;
N_word s_min;
N_word s_max;
N_word t_lo_base;
N_word t_hi_base;
N_word t_lo_bit;
N_word t_hi_bit;
N_word t_base;
N_word t_lower = 0;
N_word t_upper = 0;
N_word t_bits;
N_word t_min;
N_word mask;
N_word bits;
N_word select;
boolean ascending;
boolean notfirst;
wordptr Z = X;
if
((length > 0) and (Xoffset < bitsX) and (Yoffset < bitsY))
{
if
((Xoffset + length) > bitsX) length = bitsX - Xoffset;
if
((Yoffset + length) > bitsY) length = bitsY - Yoffset;
ascending = (Xoffset <= Yoffset);
s_lo_base = Yoffset >> BV_LogBits;
s_lo_bit = Yoffset AND BV_ModMask;
Yoffset += --length;
s_hi_base = Yoffset >> BV_LogBits;
s_hi_bit = Yoffset AND BV_ModMask;
t_lo_base = Xoffset >> BV_LogBits;
t_lo_bit = Xoffset AND BV_ModMask;
Xoffset += length;
t_hi_base = Xoffset >> BV_LogBits;
t_hi_bit = Xoffset AND BV_ModMask;
if
(ascending)
{
s_base = s_lo_base;
t_base = t_lo_base;
}
else
{
s_base = s_hi_base;
t_base = t_hi_base;
}
s_bits = 0;
t_bits = 0;
Y += s_base;
X += t_base;
notfirst =
false
;
while
(
true
)
{
if
(t_bits == 0)
{
if
(notfirst)
{
*X = target;
if
(ascending)
{
if
(t_base == t_hi_base)
break
;
t_base++;
X++;
}
else
{
if
(t_base == t_lo_base)
break
;
t_base--;
X--;
}
}
select = ((t_base == t_hi_base) << 1) OR (t_base == t_lo_base);
switch
(select)
{
case
0:
t_lower = 0;
t_upper = BV_WordBits - 1;
t_bits = BV_WordBits;
target = 0;
break
;
case
1:
t_lower = t_lo_bit;
t_upper = BV_WordBits - 1;
t_bits = BV_WordBits - t_lo_bit;
mask = (N_word) (~0L << t_lower);
target = *X AND NOT mask;
break
;
case
2:
t_lower = 0;
t_upper = t_hi_bit;
t_bits = t_hi_bit + 1;
mask = (N_word) ((~0L << t_upper) << 1);
target = *X AND mask;
break
;
case
3:
t_lower = t_lo_bit;
t_upper = t_hi_bit;
t_bits = t_hi_bit - t_lo_bit + 1;
mask = (N_word) (~0L << t_lower);
mask &= (N_word) ~((~0L << t_upper) << 1);
target = *X AND NOT mask;
break
;
}
}
if
(s_bits == 0)
{
if
(notfirst)
{
if
(ascending)
{
if
(s_base == s_hi_base)
break
;
s_base++;
Y++;
}
else
{
if
(s_base == s_lo_base)
break
;
s_base--;
Y--;
}
}
source = *Y;
select = ((s_base == s_hi_base) << 1) OR (s_base == s_lo_base);
switch
(select)
{
case
0:
s_lower = 0;
s_upper = BV_WordBits - 1;
s_bits = BV_WordBits;
break
;
case
1:
s_lower = s_lo_bit;
s_upper = BV_WordBits - 1;
s_bits = BV_WordBits - s_lo_bit;
break
;
case
2:
s_lower = 0;
s_upper = s_hi_bit;
s_bits = s_hi_bit + 1;
break
;
case
3:
s_lower = s_lo_bit;
s_upper = s_hi_bit;
s_bits = s_hi_bit - s_lo_bit + 1;
break
;
}
}
notfirst =
true
;
if
(s_bits > t_bits)
{
bits = t_bits - 1;
if
(ascending)
{
s_min = s_lower;
s_max = s_lower + bits;
}
else
{
s_max = s_upper;
s_min = s_upper - bits;
}
t_min = t_lower;
}
else
{
bits = s_bits - 1;
if
(ascending) t_min = t_lower;
else
t_min = t_upper - bits;
s_min = s_lower;
s_max = s_upper;
}
bits++;
mask = (N_word) (~0L << s_min);
mask &= (N_word) ~((~0L << s_max) << 1);
if
(s_min == t_min) target |= (source AND mask);
else
{
if
(s_min < t_min) target |= (source AND mask) << (t_min-s_min);
else
target |= (source AND mask) >> (s_min-t_min);
}
if
(ascending)
{
s_lower += bits;
t_lower += bits;
}
else
{
s_upper -= bits;
t_upper -= bits;
}
s_bits -= bits;
t_bits -= bits;
}
*(Z+BV_SIZE_(Z)-1) &= BV_MASK_(Z);
}
}
wordptr BitVector_Interval_Substitute(wordptr X, wordptr Y,
N_int Xoffset, N_int Xlength,
N_int Yoffset, N_int Ylength)
{
N_word Xbits = BV_BITS_(X);
N_word Ybits = BV_BITS_(Y);
N_word limit;
N_word diff;
if
((Xoffset <= Xbits) and (Yoffset <= Ybits))
{
limit = Xoffset + Xlength;
if
(limit > Xbits)
{
limit = Xbits;
Xlength = Xbits - Xoffset;
}
if
((Yoffset + Ylength) > Ybits)
{
Ylength = Ybits - Yoffset;
}
if
(Xlength == Ylength)
{
if
((Ylength > 0) and ((X != Y) or (Xoffset != Yoffset)))
{
BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
}
}
else
{
if
(Xlength > Ylength)
{
diff = Xlength - Ylength;
if
(Ylength > 0) BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
if
(limit < Xbits) BitVector_Delete(X,Xoffset+Ylength,diff,
false
);
if
((X = BitVector_Resize(X,Xbits-diff)) == NULL)
return
(NULL);
}
else
{
diff = Ylength - Xlength;
if
(X != Y)
{
if
((X = BitVector_Resize(X,Xbits+diff)) == NULL)
return
(NULL);
if
(limit < Xbits) BitVector_Insert(X,limit,diff,
false
);
BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
}
else
{
if
((Y = X = BitVector_Resize(X,Xbits+diff)) == NULL)
return
(NULL);
if
(limit >= Xbits)
{
BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
}
else
{
BitVector_Insert(X,limit,diff,
false
);
if
((Yoffset+Ylength) <= limit)
{
BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
}
else
{
if
(limit <= Yoffset)
{
Yoffset += diff;
BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
}
else
{
Xlength = limit - Yoffset;
BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Xlength);
Yoffset = Xoffset + Ylength;
Xoffset += Xlength;
Ylength -= Xlength;
BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
}
}
}
}
}
}
}
return
(X);
}
boolean BitVector_is_empty(wordptr addr)
{
N_word size = BV_SIZE_(addr);
boolean r =
true
;
if
(size > 0)
{
*(addr+size-1) &= BV_MASK_(addr);
while
(r and (size-- > 0)) r = ( *addr++ == 0 );
}
return
(r);
}
boolean BitVector_is_full(wordptr addr)
{
N_word size = BV_SIZE_(addr);
N_word mask = BV_MASK_(addr);
boolean r =
false
;
wordptr last;
if
(size > 0)
{
r =
true
;
last = addr + size - 1;
*last |= NOT mask;
while
(r and (size-- > 0)) r = ( NOT *addr++ == 0 );
*last &= mask;
}
return
(r);
}
boolean BitVector_equal(wordptr X, wordptr Y)
{
N_word size = BV_SIZE_(X);
N_word mask = BV_MASK_(X);
boolean r =
false
;
if
(BV_BITS_(X) == BV_BITS_(Y))
{
r =
true
;
if
(size > 0)
{
*(X+size-1) &= mask;
*(Y+size-1) &= mask;
while
(r and (size-- > 0)) r = (*X++ == *Y++);
}
}
return
(r);
}
Z_int BitVector_Lexicompare(wordptr X, wordptr Y)
{
N_word bitsX = BV_BITS_(X);
N_word bitsY = BV_BITS_(Y);
N_word size = BV_SIZE_(X);
boolean r =
true
;
if
(bitsX == bitsY)
{
if
(size > 0)
{
X += size;
Y += size;
while
(r and (size-- > 0)) r = (*(--X) == *(--Y));
}
if
(r)
return
((Z_int) 0);
else
{
if
(*X < *Y)
return
((Z_int) -1);
else
return
((Z_int) 1);
}
}
else
{
if
(bitsX < bitsY)
return
((Z_int) -1);
else
return
((Z_int) 1);
}
}
Z_int BitVector_Compare(wordptr X, wordptr Y)
{
N_word bitsX = BV_BITS_(X);
N_word bitsY = BV_BITS_(Y);
N_word size = BV_SIZE_(X);
N_word mask = BV_MASK_(X);
N_word sign;
boolean r =
true
;
if
(bitsX == bitsY)
{
if
(size > 0)
{
X += size;
Y += size;
mask &= NOT (mask >> 1);
if
((sign = (*(X-1) AND mask)) != (*(Y-1) AND mask))
{
if
(sign)
return
((Z_int) -1);
else
return
((Z_int) 1);
}
while
(r and (size-- > 0)) r = (*(--X) == *(--Y));
}
if
(r)
return
((Z_int) 0);
else
{
if
(*X < *Y)
return
((Z_int) -1);
else
return
((Z_int) 1);
}
}
else
{
if
(bitsX < bitsY)
return
((Z_int) -1);
else
return
((Z_int) 1);
}
}
charptr BitVector_to_Hex(wordptr addr)
{
N_word bits = BV_BITS_(addr);
N_word size = BV_SIZE_(addr);
N_word value;
N_word count;
N_word digit;
N_word length;
charptr string;
length = bits >> 2;
if
(bits AND 0x0003) length++;
string = (charptr)
malloc
((
size_t
) (length+1));
if
(string == NULL)
return
(NULL);
string += length;
*string = (N_char)
'\0'
;
if
(size > 0)
{
*(addr+size-1) &= BV_MASK_(addr);
while
((size-- > 0) and (length > 0))
{
value = *addr++;
count = BV_WordBits >> 2;
while
((count-- > 0) and (length > 0))
{
digit = value AND 0x000F;
if
(digit > 9) digit += (N_word)
'A'
- 10;
else
digit += (N_word)
'0'
;
*(--string) = (N_char) digit; length--;
if
((count > 0) and (length > 0)) value >>= 4;
}
}
}
return
(string);
}
BV_ErrCode BitVector_from_Hex(wordptr addr, charptr string)
{
N_word size = BV_SIZE_(addr);
N_word mask = BV_MASK_(addr);
boolean ok =
true
;
N_word length;
N_word value;
N_word count;
int
digit;
if
(size > 0)
{
length =
strlen
((
char
*) string);
string += length;
while
(size-- > 0)
{
value = 0;
for
( count = 0; (ok and (length > 0) and (count < BV_WordBits)); count += 4 )
{
digit = (
int
) *(--string); length--;
digit =
toupper
(digit);
if
((ok = (
isxdigit
(digit) != 0)))
{
if
(digit >= (
int
)
'A'
) digit -= (
int
)
'A'
- 10;
else
digit -= (
int
)
'0'
;
value |= (((N_word) digit) << count);
}
}
*addr++ = value;
}
*(--addr) &= mask;
}
if
(ok)
return
(BV_ErrCode_Ok);
else
return
(BV_ErrCode_Pars);
}
charptr BitVector_to_Bin(wordptr addr)
{
N_word size = BV_SIZE_(addr);
N_word value;
N_word count;
N_word digit;
N_word length;
charptr string;
length = BV_BITS_(addr);
string = (charptr)
malloc
((
size_t
) (length+1));
if
(string == NULL)
return
(NULL);
string += length;
*string = (N_char)
'\0'
;
if
(size > 0)
{
*(addr+size-1) &= BV_MASK_(addr);
while
(size-- > 0)
{
value = *addr++;
count = BV_WordBits;
if
(count > length) count = length;
while
(count-- > 0)
{
digit = value AND 0x0001;
digit += (N_word)
'0'
;
*(--string) = (N_char) digit; length--;
if
(count > 0) value >>= 1;
}
}
}
return
(string);
}
BV_ErrCode BitVector_from_Bin(wordptr addr, charptr string)
{
N_word size = BV_SIZE_(addr);
N_word mask = BV_MASK_(addr);
boolean ok =
true
;
N_word length;
N_word value;
N_word count;
int
digit;
if
(size > 0)
{
length =
strlen
((
char
*) string);
string += length;
while
(size-- > 0)
{
value = 0;
for
( count = 0; (ok and (length > 0) and (count < BV_WordBits)); count++ )
{
digit = (
int
) *(--string); length--;
switch
(digit)
{
case
(
int
)
'0'
:
break
;
case
(
int
)
'1'
:
value |= BV_BitMaskTab[count];
break
;
default
:
ok =
false
;
break
;
}
}
*addr++ = value;
}
*(--addr) &= mask;
}
if
(ok)
return
(BV_ErrCode_Ok);
else
return
(BV_ErrCode_Pars);
}
charptr BitVector_to_Dec(wordptr addr)
{
N_word bits = BV_BITS_(addr);
N_word length;
N_word digits;
N_word count;
N_word q;
N_word r;
boolean loop;
charptr result;
charptr string;
wordptr quot;
wordptr rest;
wordptr temp;
wordptr base;
Z_int sign;
length = (N_word) (bits / 3.3);
length += 2;
result = (charptr)
malloc
((
size_t
) (length+1));
if
(result == NULL)
return
(NULL);
string = result;
sign = BitVector_Sign(addr);
if
((bits < 4) or (sign == 0))
{
if
(bits > 0) digits = *addr;
else
digits = (N_word) 0;
if
(sign < 0) digits = ((N_word)(-((Z_word)digits))) AND BV_MASK_(addr);
*string++ = (N_char) digits + (N_char)
'0'
;
digits = 1;
}
else
{
quot = BitVector_Create(bits,
false
);
if
(quot == NULL)
{
BitVector_Dispose(result);
return
(NULL);
}
rest = BitVector_Create(bits,
false
);
if
(rest == NULL)
{
BitVector_Dispose(result);
BitVector_Destroy(quot);
return
(NULL);
}
temp = BitVector_Create(bits,
false
);
if
(temp == NULL)
{
BitVector_Dispose(result);
BitVector_Destroy(quot);
BitVector_Destroy(rest);
return
(NULL);
}
base = BitVector_Create(bits,
true
);
if
(base == NULL)
{
BitVector_Dispose(result);
BitVector_Destroy(quot);
BitVector_Destroy(rest);
BitVector_Destroy(temp);
return
(NULL);
}
if
(sign < 0) BitVector_Negate(quot,addr);
else
BitVector_Copy(quot,addr);
digits = 0;
*base = BV_Exp10;
loop = (bits >= BV_WordBits);
do
{
if
(loop)
{
BitVector_Copy(temp,quot);
if
(BitVector_Div_Pos(quot,temp,base,rest))
{
BitVector_Dispose(result);
BitVector_Destroy(quot);
BitVector_Destroy(rest);
BitVector_Destroy(temp);
BitVector_Destroy(base);
return
(NULL);
}
loop = not BitVector_is_empty(quot);
q = *rest;
}
else
q = *quot;
count = BV_Log10;
while
(((loop and (count-- > 0)) or ((not loop) and (q != 0))) and
(digits < length))
{
if
(q != 0)
{
BIT_VECTOR_DIGITIZE(N_word,q,r)
}
else
r = (N_word)
'0'
;
*string++ = (N_char) r;
digits++;
}
}
while
(loop and (digits < length));
BitVector_Destroy(quot);
BitVector_Destroy(rest);
BitVector_Destroy(temp);
BitVector_Destroy(base);
}
if
((sign < 0) and (digits < length))
{
*string++ = (N_char)
'-'
;
digits++;
}
*string = (N_char)
'\0'
;
BIT_VECTOR_reverse(result,digits);
return
(result);
}
BV_ErrCode BitVector_from_Dec(wordptr addr, charptr string)
{
BV_ErrCode error = BV_ErrCode_Ok;
N_word bits = BV_BITS_(addr);
N_word mask = BV_MASK_(addr);
boolean init = (bits > BV_WordBits);
boolean minus;
boolean shift;
boolean carry;
wordptr term;
wordptr base;
wordptr prod;
wordptr rank;
wordptr temp;
N_word accu;
N_word powr;
N_word count;
N_word length;
int
digit;
if
(bits > 0)
{
length =
strlen
((
char
*) string);
if
(length == 0)
return
(BV_ErrCode_Pars);
digit = (
int
) *string;
if
((minus = (digit == (
int
)
'-'
)) or
(digit == (
int
)
'+'
))
{
string++;
if
(--length == 0)
return
(BV_ErrCode_Pars);
}
string += length;
term = BitVector_Create(BV_WordBits,
false
);
if
(term == NULL)
{
return
(BV_ErrCode_Null);
}
base = BitVector_Create(BV_WordBits,
false
);
if
(base == NULL)
{
BitVector_Destroy(term);
return
(BV_ErrCode_Null);
}
prod = BitVector_Create(bits,init);
if
(prod == NULL)
{
BitVector_Destroy(term);
BitVector_Destroy(base);
return
(BV_ErrCode_Null);
}
rank = BitVector_Create(bits,init);
if
(rank == NULL)
{
BitVector_Destroy(term);
BitVector_Destroy(base);
BitVector_Destroy(prod);
return
(BV_ErrCode_Null);
}
temp = BitVector_Create(bits,
false
);
if
(temp == NULL)
{
BitVector_Destroy(term);
BitVector_Destroy(base);
BitVector_Destroy(prod);
BitVector_Destroy(rank);
return
(BV_ErrCode_Null);
}
BitVector_Empty(addr);
*base = BV_Exp10;
shift =
false
;
while
((not error) and (length > 0))
{
accu = 0;
powr = 1;
count = BV_Log10;
while
((not error) and (length > 0) and (count-- > 0))
{
digit = (
int
) *(--string); length--;
if
(
isdigit
(digit) != 0)
{
accu += ((N_word) digit - (N_word)
'0'
) * powr;
powr *= 10;
}
else
error = BV_ErrCode_Pars;
}
if
(not error)
{
if
(shift)
{
*term = accu;
BitVector_Copy(temp,rank);
error = BitVector_Mul_Pos(prod,temp,term,
false
);
}
else
{
*prod = accu;
if
((not init) and ((accu AND NOT mask) != 0)) error = BV_ErrCode_Ovfl;
}
if
(not error)
{
carry =
false
;
BitVector_compute(addr,addr,prod,
false
,&carry);
if
(carry) error = BV_ErrCode_Ovfl;
else
{
if
(length > 0)
{
if
(shift)
{
BitVector_Copy(temp,rank);
error = BitVector_Mul_Pos(rank,temp,base,
false
);
}
else
{
*rank = *base;
shift =
true
;
}
}
}
}
}
}
BitVector_Destroy(term);
BitVector_Destroy(base);
BitVector_Destroy(prod);
BitVector_Destroy(rank);
BitVector_Destroy(temp);
if
(not error and minus)
{
BitVector_Negate(addr,addr);
if
((*(addr + BV_SIZE_(addr) - 1) AND mask AND NOT (mask >> 1)) == 0)
error = BV_ErrCode_Ovfl;
}
}
return
(error);
}
charptr BitVector_to_Enum(wordptr addr)
{
N_word bits = BV_BITS_(addr);
N_word sample;
N_word length;
N_word digits;
N_word factor;
N_word power;
N_word start;
N_word min;
N_word max;
charptr string;
charptr target;
boolean comma;
if
(bits > 0)
{
sample = bits - 1;
length = 2;
digits = 1;
factor = 1;
power = 10;
while
(sample >= (power-1))
{
length += ++digits * factor * 6;
factor = power;
power *= 10;
}
if
(sample > --factor)
{
sample -= factor;
factor = (N_word) ( sample / 3 );
factor = (factor << 1) + (sample - (factor * 3));
length += ++digits * factor;
}
}
else
length = 1;
string = (charptr)
malloc
((
size_t
) length);
if
(string == NULL)
return
(NULL);
start = 0;
comma =
false
;
target = string;
while
((start < bits) and BitVector_interval_scan_inc(addr,start,&min,&max))
{
start = max + 2;
if
(comma) *target++ = (N_char)
','
;
if
(min == max)
{
target += BIT_VECTOR_int2str(target,min);
}
else
{
if
(min+1 == max)
{
target += BIT_VECTOR_int2str(target,min);
*target++ = (N_char)
','
;
target += BIT_VECTOR_int2str(target,max);
}
else
{
target += BIT_VECTOR_int2str(target,min);
*target++ = (N_char)
'-'
;
target += BIT_VECTOR_int2str(target,max);
}
}
comma =
true
;
}
*target = (N_char)
'\0'
;
return
(string);
}
BV_ErrCode BitVector_from_Enum(wordptr addr, charptr string)
{
BV_ErrCode error = BV_ErrCode_Ok;
N_word bits = BV_BITS_(addr);
N_word state = 1;
N_word start = 0;
N_word token;
N_word index;
if
(bits > 0)
{
BitVector_Empty(addr);
while
((not error) and (state != 0))
{
token = (N_word) *string;
if
(
isdigit
((
int
)token) != 0)
{
string += BIT_VECTOR_str2int(string,&index);
if
(index < bits) token = (N_word)
'0'
;
else
error = BV_ErrCode_Indx;
}
else
string++;
if
(not error)
switch
(state)
{
case
1:
switch
(token)
{
case
(N_word)
'0'
:
state = 2;
break
;
case
(N_word)
'\0'
:
state = 0;
break
;
default
:
error = BV_ErrCode_Pars;
break
;
}
break
;
case
2:
switch
(token)
{
case
(N_word)
'-'
:
start = index;
state = 3;
break
;
case
(N_word)
','
:
BIT_VECTOR_SET_BIT(addr,index)
state = 5;
break
;
case
(N_word)
'\0'
:
BIT_VECTOR_SET_BIT(addr,index)
state = 0;
break
;
default
:
error = BV_ErrCode_Pars;
break
;
}
break
;
case
3:
switch
(token)
{
case
(N_word)
'0'
:
if
(start < index)
BitVector_Interval_Fill(addr,start,index);
else
if
(start == index)
BIT_VECTOR_SET_BIT(addr,index)
else
error = BV_ErrCode_Ordr;
state = 4;
break
;
default
:
error = BV_ErrCode_Pars;
break
;
}
break
;
case
4:
switch
(token)
{
case
(N_word)
','
:
state = 5;
break
;
case
(N_word)
'\0'
:
state = 0;
break
;
default
:
error = BV_ErrCode_Pars;
break
;
}
break
;
case
5:
switch
(token)
{
case
(N_word)
'0'
:
state = 2;
break
;
default
:
error = BV_ErrCode_Pars;
break
;
}
break
;
}
}
}
return
(error);
}
void
BitVector_Bit_Off(wordptr addr, N_int index)
{
if
(index < BV_BITS_(addr)) BIT_VECTOR_CLR_BIT(addr,index)
}
void
BitVector_Bit_On(wordptr addr, N_int index)
{
if
(index < BV_BITS_(addr)) BIT_VECTOR_SET_BIT(addr,index)
}
boolean BitVector_bit_flip(wordptr addr, N_int index)
{
N_word mask;
if
(index < BV_BITS_(addr))
return
( BIT_VECTOR_FLP_BIT(addr,index,mask) );
else
return
(
false
);
}
boolean BitVector_bit_test(wordptr addr, N_int index)
{
if
(index < BV_BITS_(addr))
return
( BIT_VECTOR_TST_BIT(addr,index) );
else
return
(
false
);
}
void
BitVector_Bit_Copy(wordptr addr, N_int index, boolean bit)
{
if
(index < BV_BITS_(addr))
{
if
(bit) BIT_VECTOR_SET_BIT(addr,index)
else
BIT_VECTOR_CLR_BIT(addr,index)
}
}
void
BitVector_LSB(wordptr addr, boolean bit)
{
if
(BV_BITS_(addr) > 0)
{
if
(bit) *addr |= BV_LSB;
else
*addr &= NOT BV_LSB;
}
}
void
BitVector_MSB(wordptr addr, boolean bit)
{
N_word size = BV_SIZE_(addr);
N_word mask = BV_MASK_(addr);
if
(size-- > 0)
{
if
(bit) *(addr+size) |= mask AND NOT (mask >> 1);
else
*(addr+size) &= NOT mask OR (mask >> 1);
}
}
boolean BitVector_lsb_(wordptr addr)
{
if
(BV_SIZE_(addr) > 0)
return
( (*addr AND BV_LSB) != 0 );
else
return
(
false
);
}
boolean BitVector_msb_(wordptr addr)
{
N_word size = BV_SIZE_(addr);
N_word mask = BV_MASK_(addr);
if
(size-- > 0)
return
( (*(addr+size) AND (mask AND NOT (mask >> 1))) != 0 );
else
return
(
false
);
}
boolean BitVector_rotate_left(wordptr addr)
{
N_word size = BV_SIZE_(addr);
N_word mask = BV_MASK_(addr);
N_word msb;
boolean carry_in;
boolean carry_out =
false
;
if
(size > 0)
{
msb = mask AND NOT (mask >> 1);
carry_in = ((*(addr+size-1) AND msb) != 0);
while
(size-- > 1)
{
carry_out = ((*addr AND BV_MSB) != 0);
*addr <<= 1;
if
(carry_in) *addr |= BV_LSB;
carry_in = carry_out;
addr++;
}
carry_out = ((*addr AND msb) != 0);
*addr <<= 1;
if
(carry_in) *addr |= BV_LSB;
*addr &= mask;
}
return
(carry_out);
}
boolean BitVector_rotate_right(wordptr addr)
{
N_word size = BV_SIZE_(addr);
N_word mask = BV_MASK_(addr);
N_word msb;
boolean carry_in;
boolean carry_out =
false
;
if
(size > 0)
{
msb = mask AND NOT (mask >> 1);
carry_in = ((*addr AND BV_LSB) != 0);
addr += size-1;
*addr &= mask;
carry_out = ((*addr AND BV_LSB) != 0);
*addr >>= 1;
if
(carry_in) *addr |= msb;
carry_in = carry_out;
addr--;
size--;
while
(size-- > 0)
{
carry_out = ((*addr AND BV_LSB) != 0);
*addr >>= 1;
if
(carry_in) *addr |= BV_MSB;
carry_in = carry_out;
addr--;
}
}
return
(carry_out);
}
boolean BitVector_shift_left(wordptr addr, boolean carry_in)
{
N_word size = BV_SIZE_(addr);
N_word mask = BV_MASK_(addr);
N_word msb;
boolean carry_out = carry_in;
if
(size > 0)
{
msb = mask AND NOT (mask >> 1);
while
(size-- > 1)
{
carry_out = ((*addr AND BV_MSB) != 0);
*addr <<= 1;
if
(carry_in) *addr |= BV_LSB;
carry_in = carry_out;
addr++;
}
carry_out = ((*addr AND msb) != 0);
*addr <<= 1;
if
(carry_in) *addr |= BV_LSB;
*addr &= mask;
}
return
(carry_out);
}
boolean BitVector_shift_right(wordptr addr, boolean carry_in)
{
N_word size = BV_SIZE_(addr);
N_word mask = BV_MASK_(addr);
N_word msb;
boolean carry_out = carry_in;
if
(size > 0)
{
msb = mask AND NOT (mask >> 1);
addr += size-1;
*addr &= mask;
carry_out = ((*addr AND BV_LSB) != 0);
*addr >>= 1;
if
(carry_in) *addr |= msb;
carry_in = carry_out;
addr--;
size--;
while
(size-- > 0)
{
carry_out = ((*addr AND BV_LSB) != 0);
*addr >>= 1;
if
(carry_in) *addr |= BV_MSB;
carry_in = carry_out;
addr--;
}
}
return
(carry_out);
}
void
BitVector_Move_Left(wordptr addr, N_int bits)
{
N_word count;
N_word words;
if
(bits > 0)
{
count = bits AND BV_ModMask;
words = bits >> BV_LogBits;
if
(bits >= BV_BITS_(addr)) BitVector_Empty(addr);
else
{
while
(count-- > 0) BitVector_shift_left(addr,0);
BitVector_Word_Insert(addr,0,words,
true
);
}
}
}
void
BitVector_Move_Right(wordptr addr, N_int bits)
{
N_word count;
N_word words;
if
(bits > 0)
{
count = bits AND BV_ModMask;
words = bits >> BV_LogBits;
if
(bits >= BV_BITS_(addr)) BitVector_Empty(addr);
else
{
while
(count-- > 0) BitVector_shift_right(addr,0);
BitVector_Word_Delete(addr,0,words,
true
);
}
}
}
void
BitVector_Insert(wordptr addr, N_int offset, N_int count, boolean clear)
{
N_word bits = BV_BITS_(addr);
N_word last;
if
((count > 0) and (offset < bits))
{
last = offset + count;
if
(last < bits)
{
BitVector_Interval_Copy(addr,addr,last,offset,(bits-last));
}
else
last = bits;
if
(clear) BitVector_Interval_Empty(addr,offset,(last-1));
}
}
void
BitVector_Delete(wordptr addr, N_int offset, N_int count, boolean clear)
{
N_word bits = BV_BITS_(addr);
N_word last;
if
((count > 0) and (offset < bits))
{
last = offset + count;
if
(last < bits)
{
BitVector_Interval_Copy(addr,addr,offset,last,(bits-last));
}
else
count = bits - offset;
if
(clear) BitVector_Interval_Empty(addr,(bits-count),(bits-1));
}
}
boolean BitVector_increment(wordptr addr)
{
N_word size = BV_SIZE_(addr);
N_word mask = BV_MASK_(addr);
wordptr last = addr + size - 1;
boolean carry =
true
;
if
(size > 0)
{
*last |= NOT mask;
while
(carry and (size-- > 0))
{
carry = (++(*addr++) == 0);
}
*last &= mask;
}
return
(carry);
}
boolean BitVector_decrement(wordptr addr)
{
N_word size = BV_SIZE_(addr);
N_word mask = BV_MASK_(addr);
wordptr last = addr + size - 1;
boolean carry =
true
;
if
(size > 0)
{
*last &= mask;
while
(carry and (size-- > 0))
{
carry = (*addr == 0);
--(*addr++);
}
*last &= mask;
}
return
(carry);
}
boolean BitVector_compute(wordptr X, wordptr Y, wordptr Z, boolean minus, boolean *carry)
{
N_word size = BV_SIZE_(X);
N_word mask = BV_MASK_(X);
N_word vv = 0;
N_word cc;
N_word mm;
N_word yy;
N_word zz;
N_word lo;
N_word hi;
if
(size > 0)
{
if
(minus) cc = (*carry == 0);
else
cc = (*carry != 0);
while
(--size > 0)
{
yy = *Y++;
if
(minus) zz = (N_word) NOT ( Z ? *Z++ : 0 );
else
zz = (N_word) ( Z ? *Z++ : 0 );
lo = (yy AND BV_LSB) + (zz AND BV_LSB) + cc;
hi = (yy >> 1) + (zz >> 1) + (lo >> 1);
cc = ((hi AND BV_MSB) != 0);
*X++ = (hi << 1) OR (lo AND BV_LSB);
}
yy = *Y AND mask;
if
(minus) zz = (N_word) NOT ( Z ? *Z : 0 );
else
zz = (N_word) ( Z ? *Z : 0 );
zz &= mask;
if
(mask == BV_LSB)
{
vv = cc;
lo = yy + zz + cc;
cc = (lo >> 1);
vv ^= cc;
*X = lo AND BV_LSB;
}
else
{
if
(NOT mask)
{
mm = (mask >> 1);
vv = (yy AND mm) + (zz AND mm) + cc;
mm = mask AND NOT mm;
lo = yy + zz + cc;
cc = (lo >> 1);
vv ^= cc;
vv &= mm;
cc &= mm;
*X = lo AND mask;
}
else
{
mm = NOT BV_MSB;
lo = (yy AND mm) + (zz AND mm) + cc;
vv = lo AND BV_MSB;
hi = ((yy AND BV_MSB) >> 1) + ((zz AND BV_MSB) >> 1) + (vv >> 1);
cc = hi AND BV_MSB;
vv ^= cc;
*X = (hi << 1) OR (lo AND mm);
}
}
if
(minus) *carry = (cc == 0);
else
*carry = (cc != 0);
}
return
(vv != 0);
}
boolean BitVector_add(wordptr X, wordptr Y, wordptr Z, boolean *carry)
{
return
(BitVector_compute(X,Y,Z,
false
,carry));
}
boolean BitVector_sub(wordptr X, wordptr Y, wordptr Z, boolean *carry)
{
return
(BitVector_compute(X,Y,Z,
true
,carry));
}
boolean BitVector_inc(wordptr X, wordptr Y)
{
boolean carry =
true
;
return
(BitVector_compute(X,Y,NULL,
false
,&carry));
}
boolean BitVector_dec(wordptr X, wordptr Y)
{
boolean carry =
true
;
return
(BitVector_compute(X,Y,NULL,
true
,&carry));
}
void
BitVector_Negate(wordptr X, wordptr Y)
{
N_word size = BV_SIZE_(X);
N_word mask = BV_MASK_(X);
boolean carry =
true
;
if
(size > 0)
{
while
(size-- > 0)
{
*X = NOT *Y++;
if
(carry)
{
carry = (++(*X) == 0);
}
X++;
}
*(--X) &= mask;
}
}
void
BitVector_Absolute(wordptr X, wordptr Y)
{
N_word size = BV_SIZE_(Y);
N_word mask = BV_MASK_(Y);
if
(size > 0)
{
if
(*(Y+size-1) AND (mask AND NOT (mask >> 1))) BitVector_Negate(X,Y);
else
BitVector_Copy(X,Y);
}
}
Z_int BitVector_Sign(wordptr addr)
{
N_word size = BV_SIZE_(addr);
N_word mask = BV_MASK_(addr);
wordptr last = addr + size - 1;
boolean r =
true
;
if
(size > 0)
{
*last &= mask;
while
(r and (size-- > 0)) r = ( *addr++ == 0 );
}
if
(r)
return
((Z_int) 0);
else
{
if
(*last AND (mask AND NOT (mask >> 1)))
return
((Z_int) -1);
else
return
((Z_int) 1);
}
}
BV_ErrCode BitVector_Mul_Pos(wordptr X, wordptr Y, wordptr Z, boolean strict)
{
N_word mask;
N_word limit;
N_word count;
Z_long last;
wordptr sign;
boolean carry;
boolean overflow;
boolean ok =
true
;
if
((X == Y) or (X == Z) or (Y == Z))
return
(BV_ErrCode_Same);
if
(BV_BITS_(X) != BV_BITS_(Y))
return
(BV_ErrCode_Size);
BitVector_Empty(X);
if
(BitVector_is_empty(Y))
return
(BV_ErrCode_Ok);
if
((last = Set_Max(Z)) < 0L)
return
(BV_ErrCode_Ok);
limit = (N_word) last;
sign = Y + BV_SIZE_(Y) - 1;
mask = BV_MASK_(Y);
*sign &= mask;
mask &= NOT (mask >> 1);
for
( count = 0; (ok and (count <= limit)); count++ )
{
if
( BIT_VECTOR_TST_BIT(Z,count) )
{
carry =
false
;
overflow = BitVector_compute(X,X,Y,
false
,&carry);
if
(strict) ok = not (carry or overflow);
else
ok = not carry;
}
if
(ok and (count < limit))
{
carry = BitVector_shift_left(Y,0);
if
(strict)
{
overflow = ((*sign AND mask) != 0);
ok = not (carry or overflow);
}
else
ok = not carry;
}
}
if
(ok)
return
(BV_ErrCode_Ok);
else
return
(BV_ErrCode_Ovfl);
}
BV_ErrCode BitVector_Multiply(wordptr X, wordptr Y, wordptr Z)
{
BV_ErrCode error = BV_ErrCode_Ok;
N_word bit_x = BV_BITS_(X);
N_word bit_y = BV_BITS_(Y);
N_word bit_z = BV_BITS_(Z);
N_word size;
N_word mask;
N_word msb;
wordptr ptr_y;
wordptr ptr_z;
boolean sgn_x;
boolean sgn_y;
boolean sgn_z;
boolean zero;
wordptr A;
wordptr B;
if
((bit_y != bit_z) or (bit_x < bit_y))
return
(BV_ErrCode_Size);
if
(BitVector_is_empty(Y) or BitVector_is_empty(Z))
{
BitVector_Empty(X);
}
else
{
A = BitVector_Create(bit_y,
false
);
if
(A == NULL)
return
(BV_ErrCode_Null);
B = BitVector_Create(bit_z,
false
);
if
(B == NULL) { BitVector_Destroy(A);
return
(BV_ErrCode_Null); }
size = BV_SIZE_(Y);
mask = BV_MASK_(Y);
msb = (mask AND NOT (mask >> 1));
sgn_y = (((*(Y+size-1) &= mask) AND msb) != 0);
sgn_z = (((*(Z+size-1) &= mask) AND msb) != 0);
sgn_x = sgn_y XOR sgn_z;
if
(sgn_y) BitVector_Negate(A,Y);
else
BitVector_Copy(A,Y);
if
(sgn_z) BitVector_Negate(B,Z);
else
BitVector_Copy(B,Z);
ptr_y = A + size;
ptr_z = B + size;
zero =
true
;
while
(zero and (size-- > 0))
{
zero &= (*(--ptr_y) == 0);
zero &= (*(--ptr_z) == 0);
}
if
(*ptr_y > *ptr_z)
{
if
(bit_x > bit_y)
{
A = BitVector_Resize(A,bit_x);
if
(A == NULL) { BitVector_Destroy(B);
return
(BV_ErrCode_Null); }
}
error = BitVector_Mul_Pos(X,A,B,
true
);
}
else
{
if
(bit_x > bit_z)
{
B = BitVector_Resize(B,bit_x);
if
(B == NULL) { BitVector_Destroy(A);
return
(BV_ErrCode_Null); }
}
error = BitVector_Mul_Pos(X,B,A,
true
);
}
if
((not error) and sgn_x) BitVector_Negate(X,X);
BitVector_Destroy(A);
BitVector_Destroy(B);
}
return
(error);
}
BV_ErrCode BitVector_Div_Pos(wordptr Q, wordptr X, wordptr Y, wordptr R)
{
N_word bits = BV_BITS_(Q);
N_word mask;
wordptr addr;
Z_long last;
boolean flag;
boolean copy =
false
;
if
((bits != BV_BITS_(X)) or (bits != BV_BITS_(Y)) or (bits != BV_BITS_(R)))
return
(BV_ErrCode_Size);
if
((Q == X) or (Q == Y) or (Q == R) or (X == Y) or (X == R) or (Y == R))
return
(BV_ErrCode_Same);
if
(BitVector_is_empty(Y))
return
(BV_ErrCode_Zero);
BitVector_Empty(R);
BitVector_Copy(Q,X);
if
((last = Set_Max(Q)) < 0L)
return
(BV_ErrCode_Ok);
bits = (N_word) ++last;
while
(bits-- > 0)
{
addr = Q + (bits >> BV_LogBits);
mask = BV_BitMaskTab[bits AND BV_ModMask];
flag = ((*addr AND mask) != 0);
if
(copy)
{
BitVector_shift_left(X,flag);
flag =
false
;
BitVector_compute(R,X,Y,
true
,&flag);
}
else
{
BitVector_shift_left(R,flag);
flag =
false
;
BitVector_compute(X,R,Y,
true
,&flag);
}
if
(flag) *addr &= NOT mask;
else
{
*addr |= mask;
copy = not copy;
}
}
if
(copy) BitVector_Copy(R,X);
return
(BV_ErrCode_Ok);
}
BV_ErrCode BitVector_Divide(wordptr Q, wordptr X, wordptr Y, wordptr R)
{
BV_ErrCode error = BV_ErrCode_Ok;
N_word bits = BV_BITS_(Q);
N_word size = BV_SIZE_(Q);
N_word mask = BV_MASK_(Q);
N_word msb = (mask AND NOT (mask >> 1));
boolean sgn_q;
boolean sgn_x;
boolean sgn_y;
wordptr A;
wordptr B;
if
((bits != BV_BITS_(X)) or (bits != BV_BITS_(Y)) or (bits != BV_BITS_(R)))
return
(BV_ErrCode_Size);
if
(Q == R)
return
(BV_ErrCode_Same);
if
(BitVector_is_empty(Y))
return
(BV_ErrCode_Zero);
if
(BitVector_is_empty(X))
{
BitVector_Empty(Q);
BitVector_Empty(R);
}
else
{
A = BitVector_Create(bits,
false
);
if
(A == NULL)
return
(BV_ErrCode_Null);
B = BitVector_Create(bits,
false
);
if
(B == NULL) { BitVector_Destroy(A);
return
(BV_ErrCode_Null); }
size--;
sgn_x = (((*(X+size) &= mask) AND msb) != 0);
sgn_y = (((*(Y+size) &= mask) AND msb) != 0);
sgn_q = sgn_x XOR sgn_y;
if
(sgn_x) BitVector_Negate(A,X);
else
BitVector_Copy(A,X);
if
(sgn_y) BitVector_Negate(B,Y);
else
BitVector_Copy(B,Y);
if
(not (error = BitVector_Div_Pos(Q,A,B,R)))
{
if
(sgn_q) BitVector_Negate(Q,Q);
if
(sgn_x) BitVector_Negate(R,R);
}
BitVector_Destroy(A);
BitVector_Destroy(B);
}
return
(error);
}
BV_ErrCode BitVector_GCD(wordptr X, wordptr Y, wordptr Z)
{
BV_ErrCode error = BV_ErrCode_Ok;
N_word bits = BV_BITS_(X);
N_word size = BV_SIZE_(X);
N_word mask = BV_MASK_(X);
N_word msb = (mask AND NOT (mask >> 1));
boolean sgn_a;
boolean sgn_b;
boolean sgn_r;
wordptr Q;
wordptr R;
wordptr A;
wordptr B;
wordptr T;
if
((bits != BV_BITS_(Y)) or (bits != BV_BITS_(Z)))
return
(BV_ErrCode_Size);
if
(BitVector_is_empty(Y))
{
if
(X != Z) BitVector_Copy(X,Z);
return
(BV_ErrCode_Ok);
}
if
(BitVector_is_empty(Z))
{
if
(X != Y) BitVector_Copy(X,Y);
return
(BV_ErrCode_Ok);
}
Q = BitVector_Create(bits,
false
);
if
(Q == NULL)
{
return
(BV_ErrCode_Null);
}
R = BitVector_Create(bits,
false
);
if
(R == NULL)
{
BitVector_Destroy(Q);
return
(BV_ErrCode_Null);
}
A = BitVector_Create(bits,
false
);
if
(A == NULL)
{
BitVector_Destroy(Q);
BitVector_Destroy(R);
return
(BV_ErrCode_Null);
}
B = BitVector_Create(bits,
false
);
if
(B == NULL)
{
BitVector_Destroy(Q);
BitVector_Destroy(R);
BitVector_Destroy(A);
return
(BV_ErrCode_Null);
}
size--;
sgn_a = (((*(Y+size) &= mask) AND msb) != 0);
sgn_b = (((*(Z+size) &= mask) AND msb) != 0);
if
(sgn_a) BitVector_Negate(A,Y);
else
BitVector_Copy(A,Y);
if
(sgn_b) BitVector_Negate(B,Z);
else
BitVector_Copy(B,Z);
while
(not error)
{
if
(not (error = BitVector_Div_Pos(Q,A,B,R)))
{
if
(BitVector_is_empty(R))
break
;
T = A; sgn_r = sgn_a;
A = B; sgn_a = sgn_b;
B = R; sgn_b = sgn_r;
R = T;
}
}
if
(not error)
{
if
(sgn_b) BitVector_Negate(X,B);
else
BitVector_Copy(X,B);
}
BitVector_Destroy(Q);
BitVector_Destroy(R);
BitVector_Destroy(A);
BitVector_Destroy(B);
return
(error);
}
BV_ErrCode BitVector_GCD2(wordptr U, wordptr V, wordptr W, wordptr X, wordptr Y)
{
BV_ErrCode error = BV_ErrCode_Ok;
N_word bits = BV_BITS_(U);
N_word size = BV_SIZE_(U);
N_word mask = BV_MASK_(U);
N_word msb = (mask AND NOT (mask >> 1));
bv_listptr L;
boolean minus;
boolean carry;
boolean sgn_q;
boolean sgn_r;
boolean sgn_a;
boolean sgn_b;
boolean sgn_x;
boolean sgn_y;
wordptr Q;
wordptr R;
wordptr A;
wordptr B;
wordptr T;
wordptr X1;
wordptr X2;
wordptr X3;
wordptr Y1;
wordptr Y2;
wordptr Y3;
wordptr Z;
if
((bits != BV_BITS_(V)) or
(bits != BV_BITS_(W)) or
(bits != BV_BITS_(X)) or
(bits != BV_BITS_(Y)))
{
return
(BV_ErrCode_Size);
}
if
((U == V) or (U == W) or (V == W))
{
return
(BV_ErrCode_Same);
}
if
((bits == 0) or (size == 0))
{
return
(BV_ErrCode_Ok);
}
if
(BitVector_is_empty(X))
{
if
(U != Y) BitVector_Copy(U,Y);
BitVector_Empty(V);
BitVector_Empty(W);
if
(BV_SIZE_(W)) *W = 1;
return
(BV_ErrCode_Ok);
}
if
(BitVector_is_empty(Y))
{
if
(U != X) BitVector_Copy(U,X);
BitVector_Empty(V);
BitVector_Empty(W);
if
(BV_SIZE_(V)) *V = 1;
return
(BV_ErrCode_Ok);
}
if
((L = BitVector_Create_List(bits,
false
,11)) == NULL)
{
return
(BV_ErrCode_Null);
}
Q = L[0];
R = L[1];
A = L[2];
B = L[3];
X1 = L[4];
X2 = L[5];
X3 = L[6];
Y1 = L[7];
Y2 = L[8];
Y3 = L[9];
Z = L[10];
size--;
sgn_a = (((*(X+size) &= mask) AND msb) != 0);
sgn_b = (((*(Y+size) &= mask) AND msb) != 0);
if
(sgn_a) BitVector_Negate(A,X);
else
BitVector_Copy(A,X);
if
(sgn_b) BitVector_Negate(B,Y);
else
BitVector_Copy(B,Y);
BitVector_Empty(X1);
BitVector_Empty(X2);
*X1 = 1;
BitVector_Empty(Y1);
BitVector_Empty(Y2);
*Y2 = 1;
sgn_x =
false
;
sgn_y =
false
;
while
(not error)
{
if
((error = BitVector_Div_Pos(Q,A,B,R)))
{
break
;
}
if
(BitVector_is_empty(R))
{
break
;
}
sgn_q = sgn_a XOR sgn_b;
if
(sgn_x) BitVector_Negate(Z,X2);
else
BitVector_Copy(Z,X2);
if
((error = BitVector_Mul_Pos(X3,Z,Q,
true
)))
{
break
;
}
minus = not (sgn_x XOR sgn_q);
carry = 0;
if
(BitVector_compute(X3,X1,X3,minus,&carry))
{
error = BV_ErrCode_Ovfl;
break
;
}
sgn_x = (((*(X3+size) &= mask) AND msb) != 0);
if
(sgn_y) BitVector_Negate(Z,Y2);
else
BitVector_Copy(Z,Y2);
if
((error = BitVector_Mul_Pos(Y3,Z,Q,
true
)))
{
break
;
}
minus = not (sgn_y XOR sgn_q);
carry = 0;
if
(BitVector_compute(Y3,Y1,Y3,minus,&carry))
{
error = BV_ErrCode_Ovfl;
break
;
}
sgn_y = (((*(Y3+size) &= mask) AND msb) != 0);
T = A; sgn_r = sgn_a;
A = B; sgn_a = sgn_b;
B = R; sgn_b = sgn_r;
R = T;
T = X1;
X1 = X2;
X2 = X3;
X3 = T;
T = Y1;
Y1 = Y2;
Y2 = Y3;
Y3 = T;
}
if
(not error)
{
if
(sgn_b) BitVector_Negate(U,B);
else
BitVector_Copy(U,B);
BitVector_Copy(V,X2);
BitVector_Copy(W,Y2);
}
BitVector_Destroy_List(L,11);
return
(error);
}
BV_ErrCode BitVector_Power(wordptr X, wordptr Y, wordptr Z)
{
BV_ErrCode error = BV_ErrCode_Ok;
N_word bits = BV_BITS_(X);
boolean first =
true
;
Z_long last;
N_word limit;
N_word count;
wordptr T;
if
(X == Z)
return
(BV_ErrCode_Same);
if
(bits < BV_BITS_(Y))
return
(BV_ErrCode_Size);
if
(BitVector_msb_(Z))
return
(BV_ErrCode_Expo);
if
((last = Set_Max(Z)) < 0L)
{
if
(bits < 2)
return
(BV_ErrCode_Ovfl);
BitVector_Empty(X);
*X |= BV_LSB;
return
(BV_ErrCode_Ok);
}
if
(BitVector_is_empty(Y))
{
if
(X != Y) BitVector_Empty(X);
return
(BV_ErrCode_Ok);
}
T = BitVector_Create(bits,
false
);
if
(T == NULL)
return
(BV_ErrCode_Null);
limit = (N_word) last;
for
( count = 0; ((!error) and (count <= limit)); count++ )
{
if
( BIT_VECTOR_TST_BIT(Z,count) )
{
if
(first)
{
first =
false
;
if
(count) { BitVector_Copy(X,T); }
else
{
if
(X != Y) BitVector_Copy(X,Y); }
}
else
error = BitVector_Multiply(X,T,X);
}
if
((!error) and (count < limit))
{
if
(count) error = BitVector_Multiply(T,T,T);
else
error = BitVector_Multiply(T,Y,Y);
}
}
BitVector_Destroy(T);
return
(error);
}
void
BitVector_Block_Store(wordptr addr, charptr buffer, N_int length)
{
N_word size = BV_SIZE_(addr);
N_word mask = BV_MASK_(addr);
N_word value;
N_word count;
if
(size > 0)
{
while
(size-- > 0)
{
value = 0;
for
( count = 0; (length > 0) and (count < BV_WordBits); count += 8 )
{
value |= (((N_word) *buffer++) << count); length--;
}
*addr++ = value;
}
*(--addr) &= mask;
}
}
charptr BitVector_Block_Read(wordptr addr, N_intptr length)
{
N_word size = BV_SIZE_(addr);
N_word value;
N_word count;
charptr buffer;
charptr target;
*length = size << BV_Factor;
buffer = (charptr)
malloc
((
size_t
) ((*length)+1));
if
(buffer == NULL)
return
(NULL);
target = buffer;
if
(size > 0)
{
*(addr+size-1) &= BV_MASK_(addr);
while
(size-- > 0)
{
value = *addr++;
count = BV_WordBits >> 3;
while
(count-- > 0)
{
*target++ = (N_char) (value AND 0x00FF);
if
(count > 0) value >>= 8;
}
}
}
*target = (N_char)
'\0'
;
return
(buffer);
}
void
BitVector_Word_Store(wordptr addr, N_int offset, N_int value)
{
N_word size = BV_SIZE_(addr);
if
(size > 0)
{
if
(offset < size) *(addr+offset) = value;
*(addr+size-1) &= BV_MASK_(addr);
}
}
N_int BitVector_Word_Read(wordptr addr, N_int offset)
{
N_word size = BV_SIZE_(addr);
if
(size > 0)
{
*(addr+size-1) &= BV_MASK_(addr);
if
(offset < size)
return
( *(addr+offset) );
}
return
( (N_int) 0 );
}
void
BitVector_Word_Insert(wordptr addr, N_int offset, N_int count,
boolean clear)
{
N_word size = BV_SIZE_(addr);
N_word mask = BV_MASK_(addr);
wordptr last = addr+size-1;
if
(size > 0)
{
*last &= mask;
if
(offset > size) offset = size;
BIT_VECTOR_ins_words(addr+offset,size-offset,count,clear);
*last &= mask;
}
}
void
BitVector_Word_Delete(wordptr addr, N_int offset, N_int count,
boolean clear)
{
N_word size = BV_SIZE_(addr);
N_word mask = BV_MASK_(addr);
wordptr last = addr+size-1;
if
(size > 0)
{
*last &= mask;
if
(offset > size) offset = size;
BIT_VECTOR_del_words(addr+offset,size-offset,count,clear);
*last &= mask;
}
}
void
BitVector_Chunk_Store(wordptr addr, N_int chunksize, N_int offset,
N_long value)
{
N_word bits = BV_BITS_(addr);
N_word mask;
N_word temp;
if
((chunksize > 0) and (offset < bits))
{
if
(chunksize > BV_LongBits) chunksize = BV_LongBits;
if
((offset + chunksize) > bits) chunksize = bits - offset;
addr += offset >> BV_LogBits;
offset &= BV_ModMask;
while
(chunksize > 0)
{
mask = (N_word) (~0L << offset);
bits = offset + chunksize;
if
(bits < BV_WordBits)
{
mask &= (N_word) ~(~0L << bits);
bits = chunksize;
}
else
bits = BV_WordBits - offset;
temp = (N_word) (value << offset);
temp &= mask;
*addr &= NOT mask;
*addr++ |= temp;
value >>= bits;
chunksize -= bits;
offset = 0;
}
}
}
N_long BitVector_Chunk_Read(wordptr addr, N_int chunksize, N_int offset)
{
N_word bits = BV_BITS_(addr);
N_word chunkbits = 0;
N_long value = 0L;
N_long temp;
N_word mask;
if
((chunksize > 0) and (offset < bits))
{
if
(chunksize > BV_LongBits) chunksize = BV_LongBits;
if
((offset + chunksize) > bits) chunksize = bits - offset;
addr += offset >> BV_LogBits;
offset &= BV_ModMask;
while
(chunksize > 0)
{
bits = offset + chunksize;
if
(bits < BV_WordBits)
{
mask = (N_word) ~(~0L << bits);
bits = chunksize;
}
else
{
mask = (N_word) ~0L;
bits = BV_WordBits - offset;
}
temp = (N_long) ((*addr++ AND mask) >> offset);
value |= temp << chunkbits;
chunkbits += bits;
chunksize -= bits;
offset = 0;
}
}
return
(value);
}
void
Set_Union(wordptr X, wordptr Y, wordptr Z)
{
N_word bits = BV_BITS_(X);
N_word size = BV_SIZE_(X);
N_word mask = BV_MASK_(X);
if
((size > 0) and (bits == BV_BITS_(Y)) and (bits == BV_BITS_(Z)))
{
while
(size-- > 0) *X++ = *Y++ OR *Z++;
*(--X) &= mask;
}
}
void
Set_Intersection(wordptr X, wordptr Y, wordptr Z)
{
N_word bits = BV_BITS_(X);
N_word size = BV_SIZE_(X);
N_word mask = BV_MASK_(X);
if
((size > 0) and (bits == BV_BITS_(Y)) and (bits == BV_BITS_(Z)))
{
while
(size-- > 0) *X++ = *Y++ AND *Z++;
*(--X) &= mask;
}
}
void
Set_Difference(wordptr X, wordptr Y, wordptr Z)
{
N_word bits = BV_BITS_(X);
N_word size = BV_SIZE_(X);
N_word mask = BV_MASK_(X);
if
((size > 0) and (bits == BV_BITS_(Y)) and (bits == BV_BITS_(Z)))
{
while
(size-- > 0) *X++ = *Y++ AND NOT *Z++;
*(--X) &= mask;
}
}
void
Set_ExclusiveOr(wordptr X, wordptr Y, wordptr Z)
{
N_word bits = BV_BITS_(X);
N_word size = BV_SIZE_(X);
N_word mask = BV_MASK_(X);
if
((size > 0) and (bits == BV_BITS_(Y)) and (bits == BV_BITS_(Z)))
{
while
(size-- > 0) *X++ = *Y++ XOR *Z++;
*(--X) &= mask;
}
}
void
Set_Complement(wordptr X, wordptr Y)
{
N_word size = BV_SIZE_(X);
N_word mask = BV_MASK_(X);
if
((size > 0) and (BV_BITS_(X) == BV_BITS_(Y)))
{
while
(size-- > 0) *X++ = NOT *Y++;
*(--X) &= mask;
}
}
boolean Set_subset(wordptr X, wordptr Y)
{
N_word size = BV_SIZE_(X);
boolean r =
false
;
if
((size > 0) and (BV_BITS_(X) == BV_BITS_(Y)))
{
r =
true
;
while
(r and (size-- > 0)) r = ((*X++ AND NOT *Y++) == 0);
}
return
(r);
}
N_int Set_Norm(wordptr addr)
{
byteptr byte;
N_word bytes;
N_int n;
byte = (byteptr) addr;
bytes = BV_SIZE_(addr) << BV_Factor;
n = 0;
while
(bytes-- > 0)
{
n += BV_ByteNorm[*byte++];
}
return
(n);
}
N_int Set_Norm2(wordptr addr)
{
N_word size = BV_SIZE_(addr);
N_word w0,w1;
N_int n,k;
n = 0;
while
(size-- > 0)
{
k = 0;
w1 = NOT (w0 = *addr++);
while
(w0 and w1)
{
w0 &= w0 - 1;
w1 &= w1 - 1;
k++;
}
if
(w0 == 0) n += k;
else
n += BV_WordBits - k;
}
return
(n);
}
N_int Set_Norm3(wordptr addr)
{
N_word size = BV_SIZE_(addr);
N_int count = 0;
N_word c;
while
(size-- > 0)
{
c = *addr++;
while
(c)
{
c &= c - 1;
count++;
}
}
return
(count);
}
Z_long Set_Min(wordptr addr)
{
boolean empty =
true
;
N_word size = BV_SIZE_(addr);
N_word i = 0;
N_word c = 0;
while
(empty and (size-- > 0))
{
if
((c = *addr++)) empty =
false
;
else
i++;
}
if
(empty)
return
((Z_long) LONG_MAX);
i <<= BV_LogBits;
while
(not (c AND BV_LSB))
{
c >>= 1;
i++;
}
return
((Z_long) i);
}
Z_long Set_Max(wordptr addr)
{
boolean empty =
true
;
N_word size = BV_SIZE_(addr);
N_word i = size;
N_word c = 0;
addr += size-1;
while
(empty and (size-- > 0))
{
if
((c = *addr--)) empty =
false
;
else
i--;
}
if
(empty)
return
((Z_long) LONG_MIN);
i <<= BV_LogBits;
while
(not (c AND BV_MSB))
{
c <<= 1;
i--;
}
return
((Z_long) --i);
}
void
Matrix_Multiplication(wordptr X, N_int rowsX, N_int colsX,
wordptr Y, N_int rowsY, N_int colsY,
wordptr Z, N_int rowsZ, N_int colsZ)
{
N_word i;
N_word j;
N_word k;
N_word indxX;
N_word indxY;
N_word indxZ;
N_word termX;
N_word termY;
N_word sum;
if
((colsY == rowsZ) and (rowsX == rowsY) and (colsX == colsZ) and
(BV_BITS_(X) == rowsX*colsX) and
(BV_BITS_(Y) == rowsY*colsY) and
(BV_BITS_(Z) == rowsZ*colsZ))
{
for
( i = 0; i < rowsY; i++ )
{
termX = i * colsX;
termY = i * colsY;
for
( j = 0; j < colsZ; j++ )
{
indxX = termX + j;
sum = 0;
for
( k = 0; k < colsY; k++ )
{
indxY = termY + k;
indxZ = k * colsZ + j;
if
( BIT_VECTOR_TST_BIT(Y,indxY) &&
BIT_VECTOR_TST_BIT(Z,indxZ) ) sum ^= 1;
}
if
(sum) BIT_VECTOR_SET_BIT(X,indxX)
else
BIT_VECTOR_CLR_BIT(X,indxX)
}
}
}
}
void
Matrix_Product(wordptr X, N_int rowsX, N_int colsX,
wordptr Y, N_int rowsY, N_int colsY,
wordptr Z, N_int rowsZ, N_int colsZ)
{
N_word i;
N_word j;
N_word k;
N_word indxX;
N_word indxY;
N_word indxZ;
N_word termX;
N_word termY;
N_word sum;
if
((colsY == rowsZ) and (rowsX == rowsY) and (colsX == colsZ) and
(BV_BITS_(X) == rowsX*colsX) and
(BV_BITS_(Y) == rowsY*colsY) and
(BV_BITS_(Z) == rowsZ*colsZ))
{
for
( i = 0; i < rowsY; i++ )
{
termX = i * colsX;
termY = i * colsY;
for
( j = 0; j < colsZ; j++ )
{
indxX = termX + j;
sum = 0;
for
( k = 0; k < colsY; k++ )
{
indxY = termY + k;
indxZ = k * colsZ + j;
if
( BIT_VECTOR_TST_BIT(Y,indxY) &&
BIT_VECTOR_TST_BIT(Z,indxZ) ) sum |= 1;
}
if
(sum) BIT_VECTOR_SET_BIT(X,indxX)
else
BIT_VECTOR_CLR_BIT(X,indxX)
}
}
}
}
void
Matrix_Closure(wordptr addr, N_int rows, N_int cols)
{
N_word i;
N_word j;
N_word k;
N_word ii;
N_word ij;
N_word ik;
N_word kj;
N_word termi;
N_word termk;
if
((rows == cols) and (BV_BITS_(addr) == rows*cols))
{
for
( i = 0; i < rows; i++ )
{
ii = i * cols + i;
BIT_VECTOR_SET_BIT(addr,ii)
}
for
( k = 0; k < rows; k++ )
{
termk = k * cols;
for
( i = 0; i < rows; i++ )
{
termi = i * cols;
ik = termi + k;
for
( j = 0; j < rows; j++ )
{
ij = termi + j;
kj = termk + j;
if
( BIT_VECTOR_TST_BIT(addr,ik) &&
BIT_VECTOR_TST_BIT(addr,kj) )
BIT_VECTOR_SET_BIT(addr,ij)
}
}
}
}
}
void
Matrix_Transpose(wordptr X, N_int rowsX, N_int colsX,
wordptr Y, N_int rowsY, N_int colsY)
{
N_word i;
N_word j;
N_word ii;
N_word ij;
N_word ji;
N_word addii;
N_word addij;
N_word addji;
N_word bitii;
N_word bitij;
N_word bitji;
N_word termi;
N_word termj;
boolean swap;
if
((rowsX == colsY) and (colsX == rowsY) and
(BV_BITS_(X) == rowsX*colsX) and
(BV_BITS_(Y) == rowsY*colsY))
{
if
(rowsY == colsY)
{
for
( i = 0; i < rowsY; i++ )
{
termi = i * colsY;
for
( j = 0; j < i; j++ )
{
termj = j * colsX;
ij = termi + j;
ji = termj + i;
addij = ij >> BV_LogBits;
addji = ji >> BV_LogBits;
bitij = BV_BitMaskTab[ij AND BV_ModMask];
bitji = BV_BitMaskTab[ji AND BV_ModMask];
swap = ((*(Y+addij) AND bitij) != 0);
if
((*(Y+addji) AND bitji) != 0)
*(X+addij) |= bitij;
else
*(X+addij) &= NOT bitij;
if
(swap)
*(X+addji) |= bitji;
else
*(X+addji) &= NOT bitji;
}
ii = termi + i;
addii = ii >> BV_LogBits;
bitii = BV_BitMaskTab[ii AND BV_ModMask];
if
((*(Y+addii) AND bitii) != 0)
*(X+addii) |= bitii;
else
*(X+addii) &= NOT bitii;
}
}
else
{
for
( i = 0; i < rowsY; i++ )
{
termi = i * colsY;
for
( j = 0; j < colsY; j++ )
{
termj = j * colsX;
ij = termi + j;
ji = termj + i;
addij = ij >> BV_LogBits;
addji = ji >> BV_LogBits;
bitij = BV_BitMaskTab[ij AND BV_ModMask];
bitji = BV_BitMaskTab[ji AND BV_ModMask];
if
((*(Y+addij) AND bitij) != 0)
*(X+addji) |= bitji;
else
*(X+addji) &= NOT bitji;
}
}
}
}
}
#endif