core/indigo-core/common/base_c/bitarray.c (290 lines of code) (raw):
/****************************************************************************
* Copyright (C) from 2009 to Present EPAM Systems.
*
* This file is part of Indigo toolkit.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
***************************************************************************/
#include <stdlib.h>
#include <string.h>
#include "base_c/bitarray.h"
int bitGetBit(const void* bitarray, int bitno)
{
return ((((char*)bitarray)[bitno / 8] & (char)(1 << (bitno % 8))) == 0) ? 0 : 1;
}
void bitSetBit(void* bitarray, int bitno, int value)
{
if (value)
((char*)bitarray)[bitno / 8] |= (1 << (bitno % 8));
else
((char*)bitarray)[bitno / 8] &= ~(1 << (bitno % 8));
}
void bitFlipBit(void* bitarray, int bitno)
{
((char*)bitarray)[bitno / 8] ^= (1 << (bitno % 8));
}
int bitTestEquality(const void* bits1, const void* bits2, int nbits)
{
char* chars1 = (char*)bits1;
char* chars2 = (char*)bits2;
char mask = ~(0xFF << (nbits & 7));
int i;
for (i = 0; i < nbits / 8; i++)
if (chars1[i] != chars2[i])
return 0;
if ((chars1[nbits / 8] & mask) != (chars2[nbits / 8] & mask))
return 0;
return 1;
}
int bitTestEquality_Array(const void* bits, const void* bitarray, int array_start, int nbits)
{
int i;
for (i = 0; i < nbits; i++)
if (bitGetBit(bits, i) != bitGetBit(bitarray, array_start + i))
return 0;
return 1;
}
int bitTestEqualityByMask(const void* bits1, const void* bits2, const void* bitMaskVoid, int nbits)
{
const char* chars1 = (const char*)bits1;
const char* chars2 = (const char*)bits2;
const char* bitMask = (const char*)bitMaskVoid;
char mask = ~(0xFF << (nbits & 7));
int i;
for (i = 0; i < nbits / 8; i++)
if ((chars1[i] & bitMask[i]) != (chars2[i] & bitMask[i]))
return 0;
if (((chars1[nbits / 8] & bitMask[nbits / 8]) & mask) != ((chars2[nbits / 8] & bitMask[nbits / 8]) & mask))
return 0;
return 1;
}
// res = a & (b ^ ~c)
int bitGetAandBxorNotC(const void* a, const void* b, const void* c, void* res, int nbits)
{
const char* ac = (const char*)a;
const char* bc = (const char*)b;
const char* cc = (const char*)c;
char* rc = (char*)res;
int i;
for (i = 0; i < nbits / 8; i++)
rc[i] = ac[i] & (bc[i] ^ ~cc[i]);
if ((nbits & 7) != 0)
rc[i] = ac[i] & (bc[i] ^ ~cc[i]);
return 1;
}
int bitGetOnesCountByte(byte value)
{
static const int onesCount[] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2,
3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3,
3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5,
6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4,
3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4,
5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6,
6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8};
return onesCount[value];
}
int bitGetOnesCountDword(dword v)
{
// http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan
v = v - ((v >> 1) & 0x55555555); // reuse input as temporary
v = (v & 0x33333333) + ((v >> 2) & 0x33333333); // temp
return (((v + (v >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24; // count
}
int bitGetOnesCountQword(qword value)
{
return bitGetOnesCountDword((dword)value) + bitGetOnesCountDword((dword)(value >> 32));
}
int bitGetOnesCount(const byte* data, int size)
{
int count = 0;
while (size-- > 0)
count += bitGetOnesCountByte(*data++);
return count;
}
int bitGetOneHOIndex(byte value)
{
static const int oneHOIndex[] = {0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8};
return oneHOIndex[value];
}
int bitGetOneLOIndex(byte value)
{
static const int oneLOIndex[] = {8, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2,
0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0,
1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1,
0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0,
2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3,
0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0,
1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0};
return oneLOIndex[value];
}
int bitGetSize(int nbits)
{
return (nbits + 7) / 8;
}
int bitTestOnes(const byte* pattern, const byte* candidate, int n_bytes)
{
int qwords_count = n_bytes / sizeof(qword);
int bytes_left = n_bytes - qwords_count * sizeof(qword);
const qword* pattern_ptr = (const qword*)pattern;
const qword* candidate_ptr = (const qword*)candidate;
while (qwords_count-- > 0)
{
if ((*candidate_ptr & *pattern_ptr) != *pattern_ptr)
return 0;
pattern_ptr++;
candidate_ptr++;
}
if (bytes_left != 0)
{
qword mask = ~(qword)0 >> (64 - 8 * bytes_left);
if ((*candidate_ptr & *pattern_ptr & mask) != (*pattern_ptr & mask))
return 0;
}
return 1;
}
int bitIdecticalBits(const byte* bit1, const byte* bit2, int n_bytes)
{
int qwords_count = n_bytes / sizeof(qword);
int bytes_left = n_bytes - qwords_count * sizeof(qword);
int count = 0;
const qword* bit1_ptr = (const qword*)bit1;
const qword* bit2_ptr = (const qword*)bit2;
while (qwords_count-- > 0)
{
qword id = ~(*bit1_ptr ^ *bit2_ptr);
count += bitGetOnesCountQword(id);
bit1_ptr++;
bit2_ptr++;
}
if (bytes_left != 0)
{
qword mask = ~(qword)0 >> (64 - 8 * bytes_left);
qword id = (~(*bit1_ptr ^ *bit2_ptr)) & mask;
count += bitGetOnesCountQword(id);
}
return count;
}
int bitCommonOnes(const byte* bit1, const byte* bit2, int n_bytes)
{
int qwords_count = n_bytes / sizeof(qword);
int bytes_left = n_bytes - qwords_count * sizeof(qword);
int count = 0;
const qword* bit1_ptr = (const qword*)bit1;
const qword* bit2_ptr = (const qword*)bit2;
while (qwords_count-- > 0)
{
qword id = *bit1_ptr & *bit2_ptr;
count += bitGetOnesCountQword(id);
bit1_ptr++;
bit2_ptr++;
}
if (bytes_left != 0)
{
qword mask = ~(qword)0 >> (64 - 8 * bytes_left);
qword id = *bit1_ptr & *bit2_ptr & mask;
count += bitGetOnesCountQword(id);
}
return count;
}
int bitUniqueOnes(const byte* bit1, const byte* bit2, int n_bytes)
{
int qwords_count = n_bytes / sizeof(qword);
int bytes_left = n_bytes - qwords_count * sizeof(qword);
int count = 0;
const qword* bit1_ptr = (const qword*)bit1;
const qword* bit2_ptr = (const qword*)bit2;
while (qwords_count-- > 0)
{
qword id = *bit1_ptr & ~*bit2_ptr;
count += bitGetOnesCountQword(id);
bit1_ptr++;
bit2_ptr++;
}
if (bytes_left != 0)
{
qword mask = ~(qword)0 >> (64 - 8 * bytes_left);
qword id = *bit1_ptr & ~*bit2_ptr & mask;
count += bitGetOnesCountQword(id);
}
return count;
}
int bitDifferentOnes(const byte* bit1, const byte* bit2, int n_bytes)
{
int qwords_count = n_bytes / sizeof(qword);
int bytes_left = n_bytes - qwords_count * sizeof(qword);
int count = 0;
const qword* bit1_ptr = (const qword*)bit1;
const qword* bit2_ptr = (const qword*)bit2;
while (qwords_count-- > 0)
{
qword id = *bit1_ptr ^ *bit2_ptr;
count += bitGetOnesCount((byte*)&id, sizeof(qword));
bit1_ptr++;
bit2_ptr++;
}
if (bytes_left != 0)
{
qword mask = ~(qword)0 >> (64 - 8 * bytes_left);
qword id = (*bit1_ptr ^ *bit2_ptr) & mask;
count += bitGetOnesCountQword(id);
}
return count;
}
int bitUnionOnes(const byte* bit1, const byte* bit2, int n_bytes)
{
int qwords_count = n_bytes / sizeof(qword);
int bytes_left = n_bytes - qwords_count * sizeof(qword);
int count = 0;
const qword* bit1_ptr = (const qword*)bit1;
const qword* bit2_ptr = (const qword*)bit2;
while (qwords_count-- > 0)
{
qword id = *bit1_ptr | *bit2_ptr;
count += bitGetOnesCountQword(id);
bit1_ptr++;
bit2_ptr++;
}
if (bytes_left != 0)
{
qword mask = ~(qword)0 >> (64 - 8 * bytes_left);
qword id = (*bit1_ptr | *bit2_ptr) & mask;
count += bitGetOnesCountQword(id);
}
return count;
}
// a &= b
void bitAnd(byte* a, const byte* b, int nbytes)
{
while (nbytes-- > 0)
{
*a = *a & *b;
a++;
b++;
}
}
// a |= b
void bitOr(byte* a, const byte* b, int nbytes)
{
while (nbytes-- > 0)
{
*a = *a | *b;
a++;
b++;
}
}
int bitIsAllZero(const void* bits, int nbytes)
{
const byte* a = (const byte*)bits;
while (nbytes-- > 0)
{
if (*a != 0)
return 0;
a++;
}
return 1;
}
int bitLog2Dword(dword input)
{
int count = 0;
while (input > 0)
{
count++;
input >>= 1;
}
return count;
}