Subversion Repositories Kolibri OS

Rev

Rev 6082 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3391 Serge 1
/*
2
 * lib/bitmap.c
3
 * Helper functions for bitmap.h.
4
 *
5056 serge 5
 * This source code is licensed under the GNU General Public License,
3391 Serge 6
 * Version 2.  See the file COPYING for more details.
7
 */
8
#include 
9
#include 
7143 serge 10
#include 
3391 Serge 11
#include 
12
#include 
13
#include 
14
#include 
15
#include 
7143 serge 16
#include 
17
#include 
18
 
19
#include 
3391 Serge 20
//#include 
21
 
22
/*
23
 * bitmaps provide an array of bits, implemented using an an
24
 * array of unsigned longs.  The number of valid bits in a
25
 * given bitmap does _not_ need to be an exact multiple of
26
 * BITS_PER_LONG.
27
 *
28
 * The possible unused bits in the last, partially used word
29
 * of a bitmap are 'don't care'.  The implementation makes
30
 * no particular effort to keep them zero.  It ensures that
31
 * their value will not affect the results of any operation.
32
 * The bitmap operations that return Boolean (bitmap_empty,
33
 * for example) or scalar (bitmap_weight, for example) results
34
 * carefully filter out these unused bits from impacting their
35
 * results.
36
 *
37
 * These operations actually hold to a slightly stronger rule:
38
 * if you don't input any bitmaps to these ops that have some
39
 * unused bits set, then they won't output any set unused bits
40
 * in output bitmaps.
41
 *
42
 * The byte ordering of bitmaps is more natural on little
43
 * endian architectures.  See the big-endian headers
44
 * include/asm-ppc64/bitops.h and include/asm-s390/bitops.h
45
 * for the best explanations of this ordering.
46
 */
47
 
48
int __bitmap_equal(const unsigned long *bitmap1,
5056 serge 49
		const unsigned long *bitmap2, unsigned int bits)
3391 Serge 50
{
5056 serge 51
	unsigned int k, lim = bits/BITS_PER_LONG;
3391 Serge 52
	for (k = 0; k < lim; ++k)
53
		if (bitmap1[k] != bitmap2[k])
54
			return 0;
55
 
56
	if (bits % BITS_PER_LONG)
57
		if ((bitmap1[k] ^ bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits))
58
			return 0;
59
 
60
	return 1;
61
}
62
EXPORT_SYMBOL(__bitmap_equal);
63
 
5056 serge 64
void __bitmap_complement(unsigned long *dst, const unsigned long *src, unsigned int bits)
3391 Serge 65
{
5056 serge 66
	unsigned int k, lim = bits/BITS_PER_LONG;
3391 Serge 67
	for (k = 0; k < lim; ++k)
68
		dst[k] = ~src[k];
69
 
70
	if (bits % BITS_PER_LONG)
5056 serge 71
		dst[k] = ~src[k];
3391 Serge 72
}
73
EXPORT_SYMBOL(__bitmap_complement);
74
 
75
/**
76
 * __bitmap_shift_right - logical right shift of the bits in a bitmap
77
 *   @dst : destination bitmap
78
 *   @src : source bitmap
79
 *   @shift : shift by this many bits
6082 serge 80
 *   @nbits : bitmap size, in bits
3391 Serge 81
 *
82
 * Shifting right (dividing) means moving bits in the MS -> LS bit
83
 * direction.  Zeros are fed into the vacated MS positions and the
84
 * LS bits shifted off the bottom are lost.
85
 */
6082 serge 86
void __bitmap_shift_right(unsigned long *dst, const unsigned long *src,
87
			unsigned shift, unsigned nbits)
3391 Serge 88
{
6082 serge 89
	unsigned k, lim = BITS_TO_LONGS(nbits);
90
	unsigned off = shift/BITS_PER_LONG, rem = shift % BITS_PER_LONG;
91
	unsigned long mask = BITMAP_LAST_WORD_MASK(nbits);
3391 Serge 92
	for (k = 0; off + k < lim; ++k) {
93
		unsigned long upper, lower;
94
 
95
		/*
96
		 * If shift is not word aligned, take lower rem bits of
97
		 * word above and make them the top rem bits of result.
98
		 */
99
		if (!rem || off + k + 1 >= lim)
100
			upper = 0;
101
		else {
102
			upper = src[off + k + 1];
6082 serge 103
			if (off + k + 1 == lim - 1)
3391 Serge 104
				upper &= mask;
6082 serge 105
			upper <<= (BITS_PER_LONG - rem);
3391 Serge 106
		}
107
		lower = src[off + k];
6082 serge 108
		if (off + k == lim - 1)
3391 Serge 109
			lower &= mask;
6082 serge 110
		lower >>= rem;
111
		dst[k] = lower | upper;
3391 Serge 112
	}
113
	if (off)
114
		memset(&dst[lim - off], 0, off*sizeof(unsigned long));
115
}
116
EXPORT_SYMBOL(__bitmap_shift_right);
117
 
118
 
119
/**
120
 * __bitmap_shift_left - logical left shift of the bits in a bitmap
121
 *   @dst : destination bitmap
122
 *   @src : source bitmap
123
 *   @shift : shift by this many bits
6082 serge 124
 *   @nbits : bitmap size, in bits
3391 Serge 125
 *
126
 * Shifting left (multiplying) means moving bits in the LS -> MS
127
 * direction.  Zeros are fed into the vacated LS bit positions
128
 * and those MS bits shifted off the top are lost.
129
 */
130
 
6082 serge 131
void __bitmap_shift_left(unsigned long *dst, const unsigned long *src,
132
			unsigned int shift, unsigned int nbits)
3391 Serge 133
{
6082 serge 134
	int k;
135
	unsigned int lim = BITS_TO_LONGS(nbits);
136
	unsigned int off = shift/BITS_PER_LONG, rem = shift % BITS_PER_LONG;
3391 Serge 137
	for (k = lim - off - 1; k >= 0; --k) {
138
		unsigned long upper, lower;
139
 
140
		/*
141
		 * If shift is not word aligned, take upper rem bits of
142
		 * word below and make them the bottom rem bits of result.
143
		 */
144
		if (rem && k > 0)
6082 serge 145
			lower = src[k - 1] >> (BITS_PER_LONG - rem);
3391 Serge 146
		else
147
			lower = 0;
6082 serge 148
		upper = src[k] << rem;
149
		dst[k + off] = lower | upper;
3391 Serge 150
	}
151
	if (off)
152
		memset(dst, 0, off*sizeof(unsigned long));
153
}
154
EXPORT_SYMBOL(__bitmap_shift_left);
155
 
156
int __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
5056 serge 157
				const unsigned long *bitmap2, unsigned int bits)
3391 Serge 158
{
5056 serge 159
	unsigned int k;
160
	unsigned int lim = bits/BITS_PER_LONG;
3391 Serge 161
	unsigned long result = 0;
162
 
5056 serge 163
	for (k = 0; k < lim; k++)
3391 Serge 164
		result |= (dst[k] = bitmap1[k] & bitmap2[k]);
5056 serge 165
	if (bits % BITS_PER_LONG)
166
		result |= (dst[k] = bitmap1[k] & bitmap2[k] &
167
			   BITMAP_LAST_WORD_MASK(bits));
3391 Serge 168
	return result != 0;
169
}
170
EXPORT_SYMBOL(__bitmap_and);
171
 
172
void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
5056 serge 173
				const unsigned long *bitmap2, unsigned int bits)
3391 Serge 174
{
5056 serge 175
	unsigned int k;
176
	unsigned int nr = BITS_TO_LONGS(bits);
3391 Serge 177
 
178
	for (k = 0; k < nr; k++)
179
		dst[k] = bitmap1[k] | bitmap2[k];
180
}
181
EXPORT_SYMBOL(__bitmap_or);
182
 
183
void __bitmap_xor(unsigned long *dst, const unsigned long *bitmap1,
5056 serge 184
				const unsigned long *bitmap2, unsigned int bits)
3391 Serge 185
{
5056 serge 186
	unsigned int k;
187
	unsigned int nr = BITS_TO_LONGS(bits);
3391 Serge 188
 
189
	for (k = 0; k < nr; k++)
190
		dst[k] = bitmap1[k] ^ bitmap2[k];
191
}
192
EXPORT_SYMBOL(__bitmap_xor);
193
 
194
int __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
5056 serge 195
				const unsigned long *bitmap2, unsigned int bits)
3391 Serge 196
{
5056 serge 197
	unsigned int k;
198
	unsigned int lim = bits/BITS_PER_LONG;
3391 Serge 199
	unsigned long result = 0;
200
 
5056 serge 201
	for (k = 0; k < lim; k++)
3391 Serge 202
		result |= (dst[k] = bitmap1[k] & ~bitmap2[k]);
5056 serge 203
	if (bits % BITS_PER_LONG)
204
		result |= (dst[k] = bitmap1[k] & ~bitmap2[k] &
205
			   BITMAP_LAST_WORD_MASK(bits));
3391 Serge 206
	return result != 0;
207
}
208
EXPORT_SYMBOL(__bitmap_andnot);
209
 
210
int __bitmap_intersects(const unsigned long *bitmap1,
5056 serge 211
			const unsigned long *bitmap2, unsigned int bits)
3391 Serge 212
{
5056 serge 213
	unsigned int k, lim = bits/BITS_PER_LONG;
3391 Serge 214
	for (k = 0; k < lim; ++k)
215
		if (bitmap1[k] & bitmap2[k])
216
			return 1;
217
 
218
	if (bits % BITS_PER_LONG)