mirror of https://github.com/postgres/postgres
Adriaan JoubertREL7_0_PATCHES
parent
47e51683e6
commit
1f747c6722
@ -0,0 +1,10 @@ |
||||
CFLAGS = -g
|
||||
|
||||
varbit: vartest.o varbit.o |
||||
$(CC) $(CFLAGS) -o $@ $^
|
||||
|
||||
varbit.o: varbit.c varbit.h |
||||
vartest.o: vartest.c varbit.h |
||||
|
||||
clean: |
||||
rm -f *.o varbit
|
@ -0,0 +1,77 @@ |
||||
A set of C routines to implement an SQL-compliant bitstring type. |
||||
|
||||
The file varbit.c contains the c-functions to implement both BIT and |
||||
BIT VARYING. Both types are implemented in essentially the same way, |
||||
except that BIT is zero padded to a specified length. I've tried to |
||||
make this code as independent as possible of the byte length, but it |
||||
is quite possible that there may be problems on machines that don't |
||||
have 8 bits/byte (are there still any around?). |
||||
|
||||
In the input routines I have assumed that the parser eats the quotes |
||||
in B'...' or X'...'. |
||||
|
||||
The SQL standard only defines comparison, SUBSTR and concatenation |
||||
operators, and these have been implemented. In addition all logical |
||||
operators have been implemented, i.e. ~,|,&,^,<< and >>. This is |
||||
useful if one wants to build bit masks. If the two strings are not of |
||||
the same length the longer string is truncated (truncation was the |
||||
only real option, as padding with zeros could give unintuitive results |
||||
for ^) and the result has the length of the shorter string. If there |
||||
is a requirement for any other functions, let me know, and I will have |
||||
a look. |
||||
|
||||
My knowledge of postgres is not up to integrating a type, so I'm hoping |
||||
that somebody can integrate this type for me, or give me some hints as |
||||
to what needs to be done. These routines were developed outside the |
||||
postgres source tree, with a hacked version of postgres.h. The header |
||||
files probably need some ammending. |
||||
|
||||
The included files are |
||||
|
||||
varbit.h -- bit string header type |
||||
varbit.c -- the routines |
||||
vartest.c -- a few calls to the routines to |
||||
|
||||
The following routines are available. |
||||
|
||||
char * zpbitin(char *s, int dummy, int32 atttypmod); |
||||
Read in a zero padded bit string of the form X'...' or B'...' |
||||
|
||||
char * zpbitout(char *s); |
||||
Print a zero padded bit string in hex X'...' |
||||
|
||||
char * zpbitsout(char *s); |
||||
Print a zero padded bit string in binary B'...' |
||||
|
||||
char * varbitin(char *s, int dummy, int32 atttypmod); |
||||
Read in a varying length bit string of the form X'...' or B'...' |
||||
|
||||
[There is no need for separate output functions for varying bit, as |
||||
zpbitout will print them out correctly] |
||||
|
||||
char * bitcat (char *arg1, char *arg2); |
||||
Bit concatenation. |
||||
|
||||
char * bitsubstr (char *arg, int32 s, int32 l); |
||||
Substring of a bit string. |
||||
|
||||
bool biteq (char *arg1, char *arg2); |
||||
bool bitne (char *arg1, char *arg2); |
||||
bool bitge (char *arg1, char *arg2); |
||||
bool bitgt (char *arg1, char *arg2); |
||||
bool bitle (char *arg1, char *arg2); |
||||
bool bitlt (char *arg1, char *arg2); |
||||
int bitcmp (char *arg1, char *arg2); |
||||
Comparison operators |
||||
|
||||
char * bitand (char * arg1, char * arg2); |
||||
char * bitor (char * arg1, char * arg2); |
||||
char * bitxor (char * arg1, char * arg2); |
||||
char * bitnot (char * arg); |
||||
char * bitshiftright (char * arg, int shft); |
||||
char * bitshiftleft (char * arg, int shft); |
||||
Bit operations. |
||||
|
||||
If anything else needs to be done, please let me know. |
||||
|
||||
Adriaan (adriaan@albourne.com) |
@ -0,0 +1,74 @@ |
||||
#ifndef POSTGRES_H |
||||
#define POSTGRES_H |
||||
|
||||
#include <stdio.h> |
||||
|
||||
typedef char bool; |
||||
typedef signed char int8; |
||||
typedef signed short int16; |
||||
typedef signed int int32; |
||||
|
||||
/*#define NULL ((void *) 0)*/ |
||||
#define Min(x, y) ((x) < (y) ? (x) : (y)) |
||||
#define Max(x, y) ((x) > (y) ? (x) : (y)) |
||||
#define PointerIsValid(pointer) (bool)((void*)(pointer) != NULL) |
||||
|
||||
|
||||
typedef unsigned int Oid; |
||||
typedef int16 int2; |
||||
typedef int32 int4; |
||||
typedef float float4; |
||||
typedef double float8; |
||||
typedef unsigned char uint8; /* == 8 bits */ |
||||
typedef unsigned short uint16; /* == 16 bits */ |
||||
typedef unsigned int uint32; /* == 32 bits */ |
||||
typedef uint8 bits8; /* >= 8 bits */ |
||||
typedef uint16 bits16; /* >= 16 bits */ |
||||
typedef uint32 bits32; /* >= 32 bits */ |
||||
|
||||
|
||||
typedef int4 aclitem; |
||||
|
||||
#define InvalidOid 0 |
||||
#define OidIsValid(objectId) ((bool) (objectId != InvalidOid)) |
||||
|
||||
/* unfortunately, both regproc and RegProcedure are used */ |
||||
typedef Oid regproc; |
||||
typedef Oid RegProcedure; |
||||
|
||||
typedef char *((*func_ptr) ()); |
||||
|
||||
|
||||
#define RegProcedureIsValid(p) OidIsValid(p) |
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* Section 2: variable length and array types |
||||
* ---------------------------------------------------------------- |
||||
*/ |
||||
/* ----------------
|
||||
* struct varlena |
||||
* ---------------- |
||||
*/ |
||||
struct varlena |
||||
{ |
||||
int32 vl_len; |
||||
char vl_dat[1]; |
||||
}; |
||||
|
||||
#define VARSIZE(PTR) (((struct varlena *)(PTR))->vl_len) |
||||
#define VARDATA(PTR) (((struct varlena *)(PTR))->vl_dat) |
||||
#define VARHDRSZ sizeof(int32) |
||||
|
||||
typedef struct varlena bytea; |
||||
typedef struct varlena text; |
||||
|
||||
typedef int2 int28[8]; |
||||
typedef Oid oid8[8]; |
||||
|
||||
#define ERROR stderr |
||||
#define elog fprintf |
||||
|
||||
#define MaxAttrSize 10000 |
||||
|
||||
#define palloc malloc |
||||
#endif |
@ -0,0 +1,832 @@ |
||||
/*-------------------------------------------------------------------------
|
||||
* |
||||
* varbit.c |
||||
* Functions for the built-in type bit() and varying bit(). |
||||
* |
||||
* IDENTIFICATION |
||||
* $Header: /cvsroot/pgsql/contrib/bit/Attic/varbit.c,v 1.1 1999/11/29 22:34:36 momjian Exp $ |
||||
* |
||||
*------------------------------------------------------------------------- |
||||
*/ |
||||
#include "postgres.h" |
||||
#include "varbit.h" |
||||
/*
|
||||
#include "access/htup.h" |
||||
#include "catalog/pg_type.h" |
||||
#include "utils/builtins.h" |
||||
*/ |
||||
|
||||
|
||||
|
||||
/*
|
||||
Prefixes: |
||||
zp -- zero-padded fixed length bit string |
||||
var -- varying bit string |
||||
|
||||
attypmod -- contains the length of the bit string in bits, or for |
||||
varying bits the maximum length.
|
||||
|
||||
The data structure contains the following elements: |
||||
header -- length of the whole data structure (incl header) |
||||
in bytes. (as with all varying length datatypes) |
||||
data section -- private data section for the bits data structures |
||||
bitlength -- lenght of the bit string in bits |
||||
bitdata -- least significant byte first string |
||||
*/ |
||||
|
||||
/*
|
||||
* zpbitin - |
||||
|
||||
* converts a string to the internal representation of a bitstring. |
||||
* The length is determined by the number of bits required plus |
||||
* VARHDRSZ bytes or from atttypmod.
|
||||
* (XXX dummy is here because we pass typelem as the second argument
|
||||
* for array_in. copied this, no idea what it means??) |
||||
*/ |
||||
char * |
||||
zpbitin(char *s, int dummy, int32 atttypmod) |
||||
{ |
||||
char *result,
|
||||
*sp; /* pointer into the character string */ |
||||
bits8 *r; |
||||
int len, /* Length of the whole data structure */ |
||||
bitlen, /* Number of bits in the bit string */ |
||||
slen; /* Length of the input string */ |
||||
int bit_not_hex; /* 0 = hex string 1=bit string */ |
||||
int i, bc, ipad; |
||||
bits8 x, y; |
||||
|
||||
|
||||
if (s == NULL) |
||||
return NULL; |
||||
|
||||
/* Check that the first character is a b or an x */ |
||||
if (s[0]=='b' || s[0]=='B')
|
||||
bit_not_hex = 1; |
||||
else if (s[0]=='x' || s[0]=='X')
|
||||
bit_not_hex = 0; |
||||
else
|
||||
elog(ERROR, "zpbitin: %s is not a valid bitstring",s); |
||||
|
||||
slen = strlen(s) - 1; |
||||
/* Determine bitlength from input string */ |
||||
bitlen = slen; |
||||
if (!bit_not_hex) |
||||
bitlen *= 4; |
||||
|
||||
/* Sometimes atttypmod is not supplied. If it is supplied we need to make
|
||||
sure that the bitstring fits. Note that the number of infered bits can |
||||
be larger than the number of actual bits needed, but only if we are
|
||||
reading a hex string and not by more than 3 bits, as a hex string gives
|
||||
and accurate length upto 4 bits */ |
||||
if (atttypmod == -1) |
||||
atttypmod = bitlen; |
||||
else |
||||
if (bitlen>atttypmod && bit_not_hex || bitlen>atttypmod+3 && !bit_not_hex) |
||||
elog(ERROR, "zpbitin: bit string of size %d cannot be written into bits(%d)", |
||||
bitlen,atttypmod); |
||||
|
||||
|
||||
len = VARBITDATALEN(atttypmod); |
||||
|
||||
if (len > MaxAttrSize) |
||||
elog(ERROR, "zpbitin: length of bit() must be less than %d", |
||||
(MaxAttrSize-VARHDRSZ-VARBITHDRSZ)*BITSPERBYTE); |
||||
|
||||
result = (char *) palloc(len); |
||||
/* set to 0 so that *r is always initialised and strin is zero-padded */ |
||||
memset(result, 0, len); |
||||
VARSIZE(result) = len; |
||||
VARBITLEN(result) = atttypmod; |
||||
|
||||
/* We need to read the bitstring from the end, as we store it least
|
||||
significant byte first. s points to the byte before the beginning |
||||
of the bitstring */ |
||||
sp = s+1; |
||||
r = (bits8 *) VARBITS(result); |
||||
if (bit_not_hex)
|
||||
{ |
||||
/* Parse the bit representation of the string */ |
||||
/* We know it fits, as bitlen was compared to atttypmod */ |
||||
x = BITHIGH; |
||||
for (bc = 0; sp != s+slen+1; sp++, bc++) |
||||
{ |
||||
if (*sp=='1') |
||||
*r |= x; |
||||
if (bc==7) { |
||||
bc = 0; |
||||
x = BITHIGH; |
||||
r++; |
||||
} else
|
||||
x >>= 1; |
||||
} |
||||
} |
||||
else
|
||||
{ |
||||
/* Parse the hex representation of the string */ |
||||
for (bc = 0; sp != s+slen+1; sp++) |
||||
{ |
||||
if (*sp>='0' && *sp<='9')
|
||||
x = (bits8) (*sp - '0'); |
||||
else if (*sp>='A' && *sp<='F')
|
||||
x = (bits8) (*sp - 'A') + 10; |
||||
else if (*sp>='a' && *sp<='f')
|
||||
x = (bits8) (*sp - 'a') + 10; |
||||
else
|
||||
elog(ERROR,"Cannot parse %c as a hex digit",*sp); |
||||
if (bc) { |
||||
bc = 0; |
||||
*r++ |= x; |
||||
} else { |
||||
bc++; |
||||
*r = x<<4; |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (bitlen > atttypmod) { |
||||
/* Check that this fitted */ |
||||
r = (bits8 *) (result + len - 1); |
||||
ipad = VARBITPAD(result); |
||||
/* The bottom ipad bits of the byte pointed to by r need to be zero */ |
||||
/* printf("Byte %X shift %X %d\n",*r,(*r << (8-ipad)) & BITMASK,
|
||||
(*r << (8-ipad)) & BITMASK > 0); |
||||
*/ |
||||
if (((*r << (BITSPERBYTE-ipad)) & BITMASK) > 0) |
||||
elog(ERROR, "zpbitin: bit string too large for bit(%d) data type", |
||||
atttypmod); |
||||
} |
||||
|
||||
return result; |
||||
} |
||||
|
||||
/* zpbitout -
|
||||
* for the time being we print everything as hex strings, as this is likely
|
||||
* to be more compact than bit strings, and consequently much more efficient |
||||
* for long strings |
||||
*/ |
||||
char * |
||||
zpbitout(char *s) |
||||
{ |
||||
char *result, *r; |
||||
VarBit sp; |
||||
int i, len, bitlen; |
||||
|
||||
if (s == NULL) |
||||
{ |
||||
result = (char *) palloc(2); |
||||
result[0] = '-'; |
||||
result[1] = '\0'; |
||||
} |
||||
else |
||||
{ |
||||
bitlen = VARBITLEN(s); |
||||
len = bitlen/4 + (bitlen%4>0 ? 1 : 0); |
||||
result = (char *) palloc(len + 4); |
||||
sp = (bits8 *) VARBITS(s); |
||||
r = result; |
||||
*r++ = 'X'; |
||||
*r++ = '\''; |
||||
/* we cheat by knowing that we store full bytes zero padded */ |
||||
for (i=0; i<len; i+=2, sp++) { |
||||
*r++ = HEXDIG((*sp)>>4); |
||||
*r++ = HEXDIG((*sp) & 0xF); |
||||
} |
||||
/* Go back one step if we printed a hex number that was not part
|
||||
of the bitstring anymore */ |
||||
if (i==len+1) |
||||
r--; |
||||
*r++ = '\''; |
||||
*r = '\0'; |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
/* zpbitsout -
|
||||
* Prints the string a bits |
||||
*/ |
||||
char * |
||||
zpbitsout(char *s) |
||||
{ |
||||
char *result, *r; |
||||
VarBit sp; |
||||
bits8 x; |
||||
int i, k, len; |
||||
|
||||
if (s == NULL) |
||||
{ |
||||
result = (char *) palloc(2); |
||||
result[0] = '-'; |
||||
result[1] = '\0'; |
||||
} |
||||
else |
||||
{ |
||||
len = VARBITLEN(s); |
||||
result = (char *) palloc(len + 4); |
||||
sp = (bits8 *) VARBITS(s); |
||||
r = result; |
||||
*r++ = 'B'; |
||||
*r++ = '\''; |
||||
for (i=0; i<len-BITSPERBYTE; i+=BITSPERBYTE, sp++) { |
||||
x = *sp; |
||||
for (k=0; k<BITSPERBYTE; k++)
|
||||
{ |
||||
*r++ = (x & BITHIGH) ? '1' : '0'; |
||||
x <<= 1; |
||||
} |
||||
} |
||||
x = *sp; |
||||
for (k=i; k<len; k++) |
||||
{ |
||||
*r++ = (x & BITHIGH) ? '1' : '0'; |
||||
x <<= 1; |
||||
} |
||||
*r++ = '\''; |
||||
*r = '\0'; |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
|
||||
/*
|
||||
* varbitin - |
||||
* converts a string to the internal representation of a bitstring. |
||||
*/ |
||||
char * |
||||
varbitin(char *s, int dummy, int32 atttypmod) |
||||
{ |
||||
char *result,
|
||||
*sp; /* pointer into the character string */ |
||||
bits8 *r; |
||||
int len, /* Length of the whole data structure */ |
||||
bitlen, /* Number of bits in the bit string */ |
||||
slen; /* Length of the input string */ |
||||
int bit_not_hex; |
||||
int i, bc, ipad; |
||||
bits8 x, y; |
||||
|
||||
|
||||
if (s == NULL) |
||||
return NULL; |
||||
|
||||
/* Check that the first character is a b or an x */ |
||||
if (s[0]=='b' || s[0]=='B')
|
||||
bit_not_hex = 1; |
||||
else if (s[0]=='x' || s[0]=='X')
|
||||
bit_not_hex = 0; |
||||
else
|
||||
elog(ERROR, "zpbitin: %s is not a valid bitstring",s); |
||||
|
||||
slen = strlen(s) - 1; |
||||
/* Determine bitlength from input string */ |
||||
bitlen = slen; |
||||
if (!bit_not_hex) |
||||
bitlen *= 4; |
||||
|
||||
/* Sometimes atttypmod is not supplied. If it is supplied we need to make
|
||||
sure that the bitstring fits. Note that the number of infered bits can |
||||
be larger than the number of actual bits needed, but only if we are
|
||||
reading a hex string and not by more than 3 bits, as a hex string gives
|
||||
and accurate length upto 4 bits */ |
||||
if (atttypmod > -1) |
||||
if (bitlen>atttypmod && bit_not_hex || bitlen>atttypmod+3 && !bit_not_hex) |
||||
elog(ERROR, "varbitin: bit string of size %d cannot be written into varying bits(%d)", |
||||
bitlen,atttypmod); |
||||
|
||||
|
||||
len = VARBITDATALEN(bitlen); |
||||
|
||||
if (len > MaxAttrSize) |
||||
elog(ERROR, "varbitin: length of bit() must be less than %d", |
||||
(MaxAttrSize-VARHDRSZ-VARBITHDRSZ)*BITSPERBYTE); |
||||
|
||||
result = (char *) palloc(len); |
||||
/* set to 0 so that *r is always initialised and strin is zero-padded */ |
||||
memset(result, 0, len); |
||||
VARSIZE(result) = len; |
||||
VARBITLEN(result) = bitlen; |
||||
|
||||
/* We need to read the bitstring from the end, as we store it least
|
||||
significant byte first. s points to the byte before the beginning |
||||
of the bitstring */ |
||||
sp = s + 1; |
||||
r = (VarBit) VARBITS(result); |
||||
if (bit_not_hex)
|
||||
{ |
||||
/* Parse the bit representation of the string */ |
||||
x = BITHIGH; |
||||
for (bc = 0; sp != s+slen+1; sp++, bc++) |
||||
{ |
||||
if (*sp=='1') |
||||
*r |= x; |
||||
if (bc==7) { |
||||
bc = 0; |
||||
x = BITHIGH; |
||||
r++; |
||||
} else
|
||||
x >>= 1; |
||||
} |
||||
} |
||||
else
|
||||
{ |
||||
for (bc = 0; sp != s+slen+1; sp++) |
||||
{ |
||||
if (*sp>='0' && *sp<='9')
|
||||
x = (bits8) (*sp - '0'); |
||||
else if (*sp>='A' && *sp<='F')
|
||||
x = (bits8) (*sp - 'A') + 10; |
||||
else if (*sp>='a' && *sp<='f')
|
||||
x = (bits8) (*sp - 'a') + 10; |
||||
else
|
||||
elog(ERROR,"Cannot parse %c as a hex digit",*sp); |
||||
if (bc) { |
||||
bc = 0; |
||||
*r++ |= x; |
||||
} else { |
||||
bc++; |
||||
*r = x<<4; |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (bitlen > atttypmod) { |
||||
/* Check that this fitted */ |
||||
r = (bits8 *) (result + len - 1); |
||||
ipad = VARBITPAD(result); |
||||
/* The bottom ipad bits of the byte pointed to by r need to be zero */ |
||||
if (((*r << (BITSPERBYTE-ipad)) & BITMASK) > 0) |
||||
elog(ERROR, "varbitin: bit string too large for varying bit(%d) data type", |
||||
atttypmod); |
||||
} |
||||
|
||||
return result; |
||||
} |
||||
|
||||
/*
|
||||
the zpbitout routines are fine for varying bits as well
|
||||
*/ |
||||
|
||||
|
||||
/*
|
||||
* Comparison operators |
||||
* |
||||
* We only need one set of comparison operators for bitstrings, as the lengths |
||||
* are stored in the same way for zero-padded and varying bit strings.
|
||||
* |
||||
* Note that the standard is not unambiguous about the comparison between
|
||||
* zero-padded bit strings and varying bitstrings. If the same value is written |
||||
* into a zero padded bitstring as into a varying bitstring, but the zero
|
||||
* padded bitstring has greater length, it will be bigger.
|
||||
* |
||||
* Zeros from the beginning of a bitstring cannot simply be ignored, as they |
||||
* may be part of a bit string and may be significant. |
||||
*/ |
||||
|
||||
bool |
||||
biteq (char *arg1, char *arg2) |
||||
{ |
||||
int bitlen1, |
||||
bitlen2; |
||||
bits8 *p1, *p2; |
||||
|
||||
if (!PointerIsValid(arg1) || !PointerIsValid(arg2)) |
||||
return (bool) 0; |
||||
bitlen1 = VARBITLEN(arg1); |
||||
bitlen2 = VARBITLEN(arg2); |
||||
if (bitlen1 != bitlen2) |
||||
return (bool) 0; |
||||
|
||||
/* bit strings are always stored in a full number of bytes */ |
||||
return memcmp((void *)VARBITS(arg1),(void *)VARBITS(arg2), |
||||
VARBITBYTES(arg1)) == 0; |
||||
} |
||||
|
||||
bool |
||||
bitne (char *arg1, char *arg2) |
||||
{ |
||||
int bitlen1, |
||||
bitlen2; |
||||
bits8 *p1, *p2; |
||||
|
||||
if (!PointerIsValid(arg1) || !PointerIsValid(arg2)) |
||||
return (bool) 0; |
||||
bitlen1 = VARBITLEN(arg1); |
||||
bitlen2 = VARBITLEN(arg2); |
||||
if (bitlen1 != bitlen2) |
||||
return (bool) 1; |
||||
|
||||
/* bit strings are always stored in a full number of bytes */ |
||||
return memcmp((void *)VARBITS(arg1),(void *)VARBITS(arg2), |
||||
VARBITBYTES(arg1)) != 0; |
||||
} |
||||
|
||||
/* bitcmp
|
||||
*
|
||||
* Compares two bitstrings and returns -1, 0, 1 depending on whether the first |
||||
* string is smaller, equal, or bigger than the second. All bits are considered |
||||
* and additional zero bits may make one string smaller/larger than the other, |
||||
* even if their zero-padded values would be the same. |
||||
* Anything is equal to undefined. |
||||
*/ |
||||
int
|
||||
bitcmp (char *arg1, char *arg2) |
||||
{ |
||||
int bitlen1, bytelen1, |
||||
bitlen2, bytelen2; |
||||
bits8 *p1, *p2; |
||||
int cmp; |
||||
|
||||
if (!PointerIsValid(arg1) || !PointerIsValid(arg2)) |
||||
return (bool) 0; |
||||
bytelen1 = VARBITBYTES(arg1);
|
||||
bytelen2 = VARBITBYTES(arg2); |
||||
|
||||
cmp = memcmp(VARBITS(arg1),VARBITS(arg2),Min(bytelen1,bytelen2)); |
||||
if (cmp==0) { |
||||
bitlen1 = VARBITLEN(arg1); |
||||
bitlen2 = VARBITLEN(arg2); |
||||
if (bitlen1 != bitlen2)
|
||||
return bitlen1 < bitlen2 ? -1 : 1; |
||||
} |
||||
return cmp; |
||||
} |
||||
|
||||
bool |
||||
bitlt (char *arg1, char *arg2) |
||||
{ |
||||
return (bool) (bitcmp(arg1,arg2) == -1); |
||||
} |
||||
|
||||
bool |
||||
bitle (char *arg1, char *arg2) |
||||
{ |
||||
return (bool) (bitcmp(arg1,arg2) <= 0); |
||||
} |
||||
|
||||
bool |
||||
bitge (char *arg1, char *arg2) |
||||
{ |
||||
return (bool) (bitcmp(arg1,arg2) >= 0); |
||||
} |
||||
|
||||
bool |
||||
bitgt (char *arg1, char *arg2) |
||||
{ |
||||
return (bool) (bitcmp(arg1,arg2) == 1); |
||||
} |
||||
|
||||
/* bitcat
|
||||
* Concatenation of bit strings |
||||
*/ |
||||
char * |
||||
bitcat (char *arg1, char *arg2) |
||||
{ |
||||
int bitlen1, bitlen2, bytelen, bit1pad, bit2shift; |
||||
char *result; |
||||
bits8 *pr, *pa; |
||||
|
||||
if (!PointerIsValid(arg1) || !PointerIsValid(arg2)) |
||||
return NULL; |
||||
|
||||
bitlen1 = VARBITLEN(arg1); |
||||
bitlen2 = VARBITLEN(arg2); |
||||
|
||||
bytelen = VARBITDATALEN(bitlen1+bitlen2); |
||||
|
||||
result = (char *) palloc(bytelen*sizeof(bits8)); |
||||
VARSIZE(result) = bytelen; |
||||
VARBITLEN(result) = bitlen1+bitlen2; |
||||
printf("%d %d %d \n",VARBITBYTES(arg1),VARBITLEN(arg1),VARBITPAD(arg1)); |
||||
/* Copy the first bitstring in */ |
||||
memcpy(VARBITS(result),VARBITS(arg1),VARBITBYTES(arg1)); |
||||
/* Copy the second bit string */ |
||||
bit1pad = VARBITPAD(arg1); |
||||
if (bit1pad==0)
|
||||
{ |
||||
memcpy(VARBITS(result)+VARBITBYTES(arg1),VARBITS(arg2), |
||||
VARBITBYTES(arg2)); |
||||
} |
||||
else if (bitlen2>0) |
||||
{ |
||||
/* We need to shift all the results to fit */ |
||||
bit2shift = BITSPERBYTE - bit1pad; |
||||
pa = (VarBit) VARBITS(arg2); |
||||
pr = (VarBit) VARBITS(result)+VARBITBYTES(arg1)-1; |
||||
for ( ; pa < VARBITEND(arg2); pa++) { |
||||
*pr = *pr | ((*pa >> bit2shift) & BITMASK); |
||||
pr++; |
||||
if (pr < VARBITEND(result)) |
||||
*pr = (*pa << bit1pad) & BITMASK; |
||||
} |
||||
} |
||||
|
||||
return result; |
||||
} |
||||
|
||||
/* bitsubstr
|
||||
* retrieve a substring from the bit string.
|
||||
* Note, s is 1-based. |
||||
* SQL draft 6.10 9) |
||||
*/ |
||||
char *
|
||||
bitsubstr (char *arg, int32 s, int32 l) |
||||
{ |
||||
int bitlen, |
||||
rbitlen, |
||||
len, |
||||
ipad, |
||||
ishift, |
||||
i; |
||||
int e, s1, e1; |
||||
char * result; |
||||
bits8 mask, *r, *ps; |
||||
|
||||
if (!PointerIsValid(arg)) |
||||
return NULL; |
||||
|
||||
bitlen = VARBITLEN(arg); |
||||
e = s+l; |
||||
s1 = Max(s,1); |
||||
e1 = Min(e,bitlen+1); |
||||
if (s1>bitlen || e1<1)
|
||||
{ |
||||
/* Need to return a null string */ |
||||
len = VARBITDATALEN(0); |
||||
result = (char *) palloc(len); |
||||
VARBITLEN(result) = 0; |
||||
VARSIZE(result) = len; |
||||
}
|
||||
else
|
||||
{ |
||||
/* OK, we've got a true substring starting at position s1-1 and
|
||||
ending at position e1-1 */ |
||||
rbitlen = e1-s1; |
||||
len = VARBITDATALEN(rbitlen); |
||||
result = (char *) palloc(len); |
||||
VARBITLEN(result) = rbitlen; |
||||
VARSIZE(result) = len; |
||||
/* Are we copying from a byte boundary? */ |
||||
if ((s1-1)%BITSPERBYTE==0)
|
||||
{ |
||||
/* Yep, we are copying bytes */ |
||||
len -= VARHDRSZ + VARBITHDRSZ; |
||||
memcpy(VARBITS(result),VARBITS(arg)+(s1-1)/BITSPERBYTE,len); |
||||
}
|
||||
else
|
||||
{ |
||||
/* Figure out how much we need to shift the sequence by */ |
||||
ishift = (s1-1)%BITSPERBYTE; |
||||
r = (VarBit) VARBITS(result); |
||||
ps = (VarBit) VARBITS(arg) + (s1-1)/BITSPERBYTE; |
||||
for (i=0; i<len; i++)
|
||||
{ |
||||
*r = (*ps <<ishift) & BITMASK; |
||||
if ((++ps) < VARBITEND(arg)) |
||||
*r |= *ps >>(BITSPERBYTE-ishift); |
||||
r++; |
||||
} |
||||
} |
||||
/* Do we need to pad at the end? */ |
||||
ipad = VARBITPAD(result); |
||||
if (ipad > 0)
|
||||
{ |
||||
mask = BITMASK << ipad; |
||||
*(VARBITS(result) + len - 1) &= mask; |
||||
} |
||||
} |
||||
|
||||
return result; |
||||
} |
||||
|
||||
/* bitand
|
||||
* perform a logical AND on two bit strings. The result is automatically |
||||
* truncated to the shorter bit string |
||||
*/ |
||||
char * |
||||
bitand (char * arg1, char * arg2) |
||||
{ |
||||
int len, |
||||
i; |
||||
char *result; |
||||
bits8 *p1,
|
||||
*p2,
|
||||
*r; |
||||
|
||||
if (!PointerIsValid(arg1) || !PointerIsValid(arg2)) |
||||
return (bool) 0; |
||||
|
||||
len = Min(VARSIZE(arg1),VARSIZE(arg2)); |
||||
result = (char *) palloc(len); |
||||
VARSIZE(result) = len; |
||||
VARBITLEN(result) = Min(VARBITLEN(arg1),VARBITLEN(arg2)); |
||||
|
||||
p1 = (bits8 *) VARBITS(arg1); |
||||
p2 = (bits8 *) VARBITS(arg2); |
||||
r = (bits8 *) VARBITS(result); |
||||
for (i=0; i<Min(VARBITBYTES(arg1),VARBITBYTES(arg2)); i++) |
||||
*r++ = *p1++ & *p2++; |
||||
|
||||
/* Padding is not needed as & of 0 pad is 0 */ |
||||
|
||||
return result; |
||||
} |
||||
|
||||
/* bitor
|
||||
* perform a logical OR on two bit strings. The result is automatically |
||||
* truncated to the shorter bit string. |
||||
*/ |
||||
char * |
||||
bitor (char * arg1, char * arg2) |
||||
{ |
||||
int len, |
||||
i; |
||||
char *result; |
||||
bits8 *p1,
|
||||
*p2,
|
||||
*r; |
||||
bits8 mask; |
||||
|
||||
if (!PointerIsValid(arg1) || !PointerIsValid(arg2)) |
||||
return (bool) 0; |
||||
|
||||
len = Min(VARSIZE(arg1),VARSIZE(arg2)); |
||||
result = (char *) palloc(len); |
||||
VARSIZE(result) = len; |
||||
VARBITLEN(result) = Min(VARBITLEN(arg1),VARBITLEN(arg2)); |
||||
|
||||
p1 = (bits8 *) VARBITS(arg1); |
||||
p2 = (bits8 *) VARBITS(arg2); |
||||
r = (bits8 *) VARBITS(result); |
||||
for (i=0; i<Min(VARBITBYTES(arg1),VARBITBYTES(arg2)); i++) |
||||
*r++ = *p1++ | *p2++; |
||||
|
||||
/* Pad the result */ |
||||
mask = BITMASK << VARBITPAD(result); |
||||
*r &= mask; |
||||
|
||||
return result; |
||||
} |
||||
|
||||
/* bitxor
|
||||
* perform a logical XOR on two bit strings. The result is automatically |
||||
* truncated to the shorter bit string. |
||||
*/ |
||||
char * |
||||
bitxor (char * arg1, char * arg2) |
||||
{ |
||||
int len, |
||||
i; |
||||
char *result; |
||||
bits8 *p1,
|
||||
*p2,
|
||||
*r; |
||||
bits8 mask; |
||||
|
||||
if (!PointerIsValid(arg1) || !PointerIsValid(arg2)) |
||||
return (bool) 0; |
||||
|
||||
len = Min(VARSIZE(arg1),VARSIZE(arg2)); |
||||
result = (char *) palloc(len); |
||||
VARSIZE(result) = len; |
||||
VARBITLEN(result) = Min(VARBITLEN(arg1),VARBITLEN(arg2)); |
||||
|
||||
p1 = (bits8 *) VARBITS(arg1); |
||||
p2 = (bits8 *) VARBITS(arg2); |
||||
r = (bits8 *) VARBITS(result); |
||||
for (i=0; i<Min(VARBITBYTES(arg1),VARBITBYTES(arg2)); i++) |
||||
{ |
||||
*r++ = *p1++ ^ *p2++; |
||||
} |
||||
|
||||
/* Pad the result */ |
||||
mask = BITMASK << VARBITPAD(result); |
||||
*r &= mask; |
||||
|
||||
return result; |
||||
} |
||||
|
||||
/* bitnot
|
||||
* perform a logical NOT on a bit strings. |
||||
*/ |
||||
char * |
||||
bitnot (char * arg) |
||||
{ |
||||
int len; |
||||
char *result; |
||||
bits8 *p,
|
||||
*r; |
||||
bits8 mask; |
||||
|
||||
if (!PointerIsValid(arg)) |
||||
return (bool) 0; |
||||
|
||||
result = (char *) palloc(VARSIZE(arg)); |
||||
VARSIZE(result) = VARSIZE(arg); |
||||
VARBITLEN(result) = VARBITLEN(arg); |
||||
|
||||
p = (bits8 *) VARBITS(arg); |
||||
r = (bits8 *) VARBITS(result); |
||||
for ( ; p < VARBITEND(arg); p++, r++) |
||||
*r = ~*p; |
||||
|
||||
/* Pad the result */ |
||||
mask = BITMASK << VARBITPAD(result); |
||||
*r &= mask; |
||||
|
||||
return result; |
||||
} |
||||
|
||||
/* bitshiftleft
|
||||
* do a left shift (i.e. to the beginning of the string) of the bit string |
||||
*/ |
||||
char * |
||||
bitshiftleft (char * arg, int shft) |
||||
{ |
||||
int byte_shift, ishift, len; |
||||
char *result; |
||||
bits8 *p,
|
||||
*r; |
||||
|
||||
if (!PointerIsValid(arg)) |
||||
return (bool) 0; |
||||
|
||||
/* Negative shift is a shift to the right */ |
||||
if (shft < 0)
|
||||
return bitshiftright(arg, -shft); |
||||
|
||||
result = (char *) palloc(VARSIZE(arg)); |
||||
VARSIZE(result) = VARSIZE(arg); |
||||
VARBITLEN(result) = VARBITLEN(arg); |
||||
r = (bits8 *) VARBITS(result); |
||||
|
||||
byte_shift = shft/BITSPERBYTE; |
||||
ishift = shft % BITSPERBYTE; |
||||
p = ((bits8 *) VARBITS(arg)) + byte_shift; |
||||
|
||||
if (ishift == 0) { |
||||
/* Special case: we can do a memcpy */ |
||||
len = VARBITBYTES(arg) - byte_shift; |
||||
memcpy(r, p, len); |
||||
memset(r+len, 0, byte_shift); |
||||
} else { |
||||
for ( ; p < VARBITEND(arg); r++) { |
||||
*r = *p <<ishift; |
||||
if ((++p) < VARBITEND(arg)) |
||||
*r |= *p >>(BITSPERBYTE-ishift); |
||||
} |
||||
for ( ; r < VARBITEND(result) ; r++ )
|
||||
*r = (bits8) 0; |
||||
} |
||||
|
||||
return result; |
||||
} |
||||
|
||||
/* bitshiftright
|
||||
* do a right shift (i.e. to the beginning of the string) of the bit string |
||||
*/ |
||||
char * |
||||
bitshiftright (char * arg, int shft) |
||||
{ |
||||
int byte_shift, ishift, len; |
||||
char *result; |
||||
bits8 *p,
|
||||
*r; |
||||
|
||||
if (!PointerIsValid(arg)) |
||||
return (bool) 0; |
||||
|
||||
/* Negative shift is a shift to the left */ |
||||
if (shft < 0)
|
||||
return bitshiftleft(arg, -shft); |
||||
|
||||
result = (char *) palloc(VARSIZE(arg)); |
||||
VARSIZE(result) = VARSIZE(arg); |
||||
VARBITLEN(result) = VARBITLEN(arg); |
||||
r = (bits8 *) VARBITS(result); |
||||
|
||||
byte_shift = shft/BITSPERBYTE; |
||||
ishift = shft % BITSPERBYTE; |
||||
p = (bits8 *) VARBITS(arg); |
||||
|
||||
/* Set the first part of the result to 0 */ |
||||
memset(r, 0, byte_shift); |
||||
|
||||
if (ishift == 0)
|
||||
{ |
||||
/* Special case: we can do a memcpy */ |
||||
len = VARBITBYTES(arg) - byte_shift; |
||||
memcpy(r+byte_shift, p, len); |
||||
}
|
||||
else
|
||||
{ |
||||
r += byte_shift; |
||||
*r = 0; /* Initialise first byte */ |
||||
for ( ; r < VARBITEND(result); p++) { |
||||
*r |= *p >> ishift; |
||||
if ((++r) < VARBITEND(result)) |
||||
*r = (*p <<(BITSPERBYTE-ishift)) & BITMASK; |
||||
} |
||||
} |
||||
|
||||
return result; |
||||
} |
@ -0,0 +1,48 @@ |
||||
#include "postgres.h" |
||||
|
||||
typedef bits8 *VarBit; |
||||
typedef uint32 BitIndex; |
||||
|
||||
#define HEXDIG(z) (z)<10 ? ((z)+'0') : ((z)-10+'A') |
||||
|
||||
|
||||
#define BITSPERBYTE 8 |
||||
#define VARBITHDRSZ sizeof(int32) |
||||
/* Number of bits in this bit string */ |
||||
#define VARBITLEN(PTR) (((struct varlena *)VARDATA(PTR))->vl_len) |
||||
/* Pointer tp the first byte containing bit string data */ |
||||
#define VARBITS(PTR) (((struct varlena *)VARDATA(PTR))->vl_dat) |
||||
/* Number of bytes in the data section of a bit string */ |
||||
#define VARBITBYTES(PTR) (VARSIZE(PTR) - VARHDRSZ - VARBITHDRSZ) |
||||
/* Padding of the bit string at the end */ |
||||
#define VARBITPAD(PTR) (VARBITBYTES(PTR)*BITSPERBYTE - VARBITLEN(PTR)) |
||||
/* Number of bytes needed to store a bit string of a given length */ |
||||
#define VARBITDATALEN(BITLEN) (BITLEN/BITSPERBYTE + \ |
||||
(BITLEN%BITSPERBYTE > 0 ? 1 : 0) + \
|
||||
VARHDRSZ + VARBITHDRSZ) |
||||
/* pointer beyond the end of the bit string (like end() in STL containers) */ |
||||
#define VARBITEND(PTR) ((bits8 *) (PTR + VARSIZE(PTR))) |
||||
/* Mask that will cover exactly one byte, i.e. BITSPERBYTE bits */ |
||||
#define BITMASK 0xFF |
||||
#define BITHIGH 0x80 |
||||
|
||||
|
||||
char * zpbitin(char *s, int dummy, int32 atttypmod); |
||||
char * zpbitout(char *s); |
||||
char * zpbitsout(char *s); |
||||
char * varbitin(char *s, int dummy, int32 atttypmod); |
||||
bool biteq (char *arg1, char *arg2); |
||||
bool bitne (char *arg1, char *arg2); |
||||
bool bitge (char *arg1, char *arg2); |
||||
bool bitgt (char *arg1, char *arg2); |
||||
bool bitle (char *arg1, char *arg2); |
||||
bool bitlt (char *arg1, char *arg2); |
||||
int bitcmp (char *arg1, char *arg2); |
||||
char * bitand (char * arg1, char * arg2); |
||||
char * bitor (char * arg1, char * arg2); |
||||
char * bitxor (char * arg1, char * arg2); |
||||
char * bitnot (char * arg); |
||||
char * bitshiftright (char * arg, int shft); |
||||
char * bitshiftleft (char * arg, int shft); |
||||
char * bitcat (char *arg1, char *arg2); |
||||
char * bitsubstr (char *arg, int32 s, int32 l); |
@ -0,0 +1,172 @@ |
||||
#include "postgres.h" |
||||
#include "varbit.h" |
||||
#include <stdio.h> |
||||
|
||||
const int numb = 8; |
||||
/*
|
||||
const char *b[] = { "B0010", "B11011011", "B0001", "X3F12", "X27", "B", |
||||
"X11", "B100111"}; |
||||
int atttypmod[] = {-1, -1, -1,-1,-1,-1,-1,-1 }; |
||||
*/ |
||||
const char *b[] = { "B0010", "B11011011", "B10001", "X3D12", "X27", "B", |
||||
"X11", "B100111"}; |
||||
int atttypmod[] = { 7, 9, 6, 18, 11, 6, -1, -1 }; |
||||
|
||||
|
||||
void print_details (unsigned char *s)
|
||||
{ |
||||
int i; |
||||
printf ("Length in bytes : %d\n",VARSIZE(s)); |
||||
printf ("Length of bitstring: %d\n",VARBITLEN(s)); |
||||
for (i=8; i<VARSIZE(s); i++)
|
||||
printf ("%X%X ",s[i]>>4,s[i]&0xF); |
||||
printf("\n"); |
||||
} |
||||
|
||||
void |
||||
main ()
|
||||
{ |
||||
int i, j; |
||||
char *s[numb]; |
||||
|
||||
for (i=0; i<numb; i++) { |
||||
printf ("Input: %s\n",b[i]); |
||||
s[i] = zpbitin(b[i], 0, atttypmod[i]); |
||||
//print_details(s[i]);
|
||||
printf ("%s = %s\n",zpbitout(s[i]),zpbitsout(s[i])); |
||||
} |
||||
|
||||
printf ("\nCOMPARISONS:\n"); |
||||
for (i=0; i<numb; i++) |
||||
for (j=i+1; j<numb; j++) |
||||
printf("%s <=> %s = %d\n",zpbitsout(s[i]),zpbitsout(s[j]), |
||||
bitcmp(s[i],s[j])); |
||||
|
||||
printf ("\nCONCATENATION:\n"); |
||||
for (i=0; i<numb; i++) |
||||
for (j=i+1; j<numb; j++) |
||||
printf("%s || %s = %s\n",zpbitsout(s[i]),zpbitsout(s[j]), |
||||
zpbitsout(bitcat(s[i],s[j]))); |
||||
|
||||
printf("\nSUBSTR:\n"); |
||||
printf("%s (%d,%d) => %s\n",zpbitsout(s[3]),1,8, |
||||
zpbitsout(bitsubstr(s[3],1,8))); |
||||
printf("%s (%d,%d) => %s\n",zpbitsout(s[3]),9,8, |
||||
zpbitsout(bitsubstr(s[3],9,8))); |
||||
printf("%s (%d,%d) => %s\n",zpbitsout(s[3]),1,9, |
||||
zpbitsout(bitsubstr(s[3],1,9))); |
||||
printf("%s (%d,%d) => %s\n",zpbitsout(s[3]),3,5, |
||||
zpbitsout(bitsubstr(s[3],3,5))); |
||||
printf("%s (%d,%d) => %s\n",zpbitsout(s[3]),3,9, |
||||
zpbitsout(bitsubstr(s[3],3,9))); |
||||
printf("%s (%d,%d) => %s\n",zpbitsout(s[3]),3,17, |
||||
zpbitsout(bitsubstr(s[3],3,17))); |
||||
printf ("\nLOGICAL AND:\n"); |
||||
for (i=0; i<numb; i++) |
||||
for (j=i+1; j<numb; j++) |
||||
printf("%s & %s = %s\n",zpbitsout(s[i]),zpbitsout(s[j]), |
||||
zpbitsout(bitand(s[i],s[j]))); |
||||
|
||||
printf ("\nLOGICAL OR:\n"); |
||||
for (i=0; i<numb; i++) |
||||
for (j=i+1; j<numb; j++) |
||||
printf("%s | %s = %s\n",zpbitsout(s[i]),zpbitsout(s[j]), |
||||
zpbitsout(bitor(s[i],s[j]))); |
||||
|
||||
printf ("\nLOGICAL XOR:\n"); |
||||
for (i=0; i<numb; i++) |
||||
for (j=i+1; j<numb; j++) |
||||
printf("%s ^ %s = %s\n",zpbitsout(s[i]),zpbitsout(s[j]), |
||||
zpbitsout(bitxor(s[i],s[j]))); |
||||
|
||||
printf ("\nLOGICAL NOT:\n"); |
||||
for (i=0; i<numb; i++) |
||||
printf("~%s = %s\n",zpbitsout(s[i]),zpbitsout(bitnot(s[i]))); |
||||
|
||||
|
||||
printf ("\nSHIFT LEFT:\n"); |
||||
for (i=0; i<numb; i++) { |
||||
printf("%s\n",zpbitsout(s[i])); |
||||
for (j=0; j<=VARBITLEN(s[i]); j++) |
||||
printf("\t%3d\t%s\n",j,zpbitsout(bitshiftleft(s[i],j))); |
||||
} |
||||
|
||||
printf ("\nSHIFT RIGHT:\n"); |
||||
for (i=0; i<numb; i++) { |
||||
printf("%s\n",zpbitsout(s[i])); |
||||
for (j=0; j<=VARBITLEN(s[i]); j++) |
||||
printf("\t%3d\t%s\n",j,zpbitsout(bitshiftright(s[i],j))); |
||||
} |
||||
|
||||
printf ("\n\n ********** VARYING **********\n"); |
||||
for (i=0; i<numb; i++) { |
||||
printf ("Input: %s\n",b[i]); |
||||
s[i] = varbitin(b[i], 0, atttypmod[i]); |
||||
/*print_details(s);*/ |
||||
printf ("%s\n",zpbitout(s[i])); |
||||
printf ("%s\n",zpbitsout(s[i])); |
||||
} |
||||
|
||||
printf ("\nCOMPARISONS:\n"); |
||||
for (i=0; i<numb; i++) |
||||
for (j=i+1; j<numb; j++) |
||||
printf("%s <=> %s = %d\n",zpbitsout(s[i]),zpbitsout(s[j]), |
||||
bitcmp(s[i],s[j])); |
||||
|
||||
printf ("\nCONCATENATION:\n"); |
||||
for (i=0; i<numb; i++) |
||||
for (j=i+1; j<numb; j++) |
||||
printf("%s || %s = %s\n",zpbitsout(s[i]),zpbitsout(s[j]), |
||||
zpbitsout(bitcat(s[i],s[j]))); |
||||
|
||||
printf("\nSUBSTR:\n"); |
||||
printf("%s (%d,%d) => %s\n",zpbitsout(s[3]),1,8, |
||||
zpbitsout(bitsubstr(s[3],1,8))); |
||||
printf("%s (%d,%d) => %s\n",zpbitsout(s[3]),9,8, |
||||
zpbitsout(bitsubstr(s[3],9,8))); |
||||
printf("%s (%d,%d) => %s\n",zpbitsout(s[3]),1,9, |
||||
zpbitsout(bitsubstr(s[3],1,9))); |
||||
printf("%s (%d,%d) => %s\n",zpbitsout(s[3]),3,5, |
||||
zpbitsout(bitsubstr(s[3],3,5))); |
||||
printf("%s (%d,%d) => %s\n",zpbitsout(s[3]),3,9, |
||||
zpbitsout(bitsubstr(s[3],3,9))); |
||||
printf("%s (%d,%d) => %s\n",zpbitsout(s[3]),3,17, |
||||
zpbitsout(bitsubstr(s[3],3,17))); |
||||
printf ("\nLOGICAL AND:\n"); |
||||
for (i=0; i<numb; i++) |
||||
for (j=i+1; j<numb; j++) |
||||
printf("%s & %s = %s\n",zpbitsout(s[i]),zpbitsout(s[j]), |
||||
zpbitsout(bitand(s[i],s[j]))); |
||||
|
||||
printf ("\nLOGICAL OR:\n"); |
||||
for (i=0; i<numb; i++) |
||||
for (j=i+1; j<numb; j++) |
||||
printf("%s | %s = %s\n",zpbitsout(s[i]),zpbitsout(s[j]), |
||||
zpbitsout(bitor(s[i],s[j]))); |
||||
|
||||
printf ("\nLOGICAL XOR:\n"); |
||||
for (i=0; i<numb; i++) |
||||
for (j=i+1; j<numb; j++) |
||||
printf("%s ^ %s = %s\n",zpbitsout(s[i]),zpbitsout(s[j]), |
||||
zpbitsout(bitxor(s[i],s[j]))); |
||||
|
||||
printf ("\nLOGICAL NOT:\n"); |
||||
for (i=0; i<numb; i++) |
||||
printf("~%s = %s\n",zpbitsout(s[i]),zpbitsout(bitnot(s[i]))); |
||||
|
||||
|
||||
printf ("\nSHIFT LEFT:\n"); |
||||
for (i=0; i<numb; i++) { |
||||
printf("%s\n",zpbitsout(s[i])); |
||||
for (j=0; j<=VARBITLEN(s[i]); j++) |
||||
printf("\t%3d\t%s\n",j,zpbitsout(bitshiftleft(s[i],j))); |
||||
} |
||||
|
||||
printf ("\nSHIFT RIGHT:\n"); |
||||
for (i=0; i<numb; i++) { |
||||
printf("%s\n",zpbitsout(s[i])); |
||||
for (j=0; j<=VARBITLEN(s[i]); j++) |
||||
printf("\t%3d\t%s\n",j,zpbitsout(bitshiftright(s[i],j))); |
||||
} |
||||
|
||||
} |
Loading…
Reference in new issue