Subversion Repositories delphiutils

Rev

Rev 9 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
9 daniel-mar 1
unit BitOps;
2
 
3
(*************************************************************
4
 
5
    BitOps.pas
6
    Bit- Byte- and Nibbleoperations
7
    64 Bit Edition; Rev 21 March 2010
8
 
9
    (C) 2010 ViaThinkSoft [www.viathinksoft.com]
10
    Developed by Daniel Marschall [www.daniel-marschall.de]
11
 
12
*************************************************************)
13
 
14
interface
15
 
16
uses
17
  SysUtils;
18
 
19
// * TYPES *
20
 
21
type
22
  Nibble = 0..127;
23
  THexNibble = $0..$F;
24
  T4BitPos = 0..3;
25
  T8BitPos = 0..7;
26
  T16BitPos = 0..15;
27
  T32BitPos = 0..31;
28
  T64BitPos = 0..63;
29
 
30
  // Maximum amount of bytes in the biggest data type (int64)
31
  TBytePos = 0..7;
32
  // Maximum amount of nibbles in the biggest data type (int64)
33
  THexNibblePos = 0..15;
34
 
35
  TBit = Boolean;
36
  THexNibbleBitArray = array[Low(T4BitPos)..High(T4BitPos)] of TBit;
37
  TByteBitArray = array[Low(T8BitPos)..High(T8BitPos)] of TBit;
38
  TBitString = type string;
39
  TByteBitString = type TBitString;
40
  THexNibbleBitString = type TBitString;
41
 
42
// ******************
43
// * BYTE FUNCTIONS *
44
// ******************
45
 
46
// Build a byte.
47
// Either you combine two nibbles...
48
function BuildByte(AUpperNibble, ALowerNibble: THexNibble): Byte; overload;
49
// ...or you define an array of 8 bits.
50
function BuildByte(ABitArray: TByteBitArray): Byte; overload;
51
// ...or you define a bitstring (e.g. '00011100')
52
function BuildByte(ABits: TByteBitString): Byte; overload;
53
// ...or you define the bits as parameters
54
function BuildByte(ABit1, ABit2, ABit3, ABit4, ABit5, ABit6, ABit7,
55
  ABit8: TBit): Byte; overload;
56
 
57
// Converts a byte into a array of 8 bits
58
function GetByteBitArray(AByte: Byte): TByteBitArray;
59
 
60
// Getting and setting the lower nibble of a byte.
61
function GetLowerNibble(AByte: Byte): THexNibble;
62
function SetLowerNibble(AByte: Byte; ANewNibble: THexNibble): Byte;
63
 
64
// Getting and setting the upper nibble of a byte.
65
function GetUpperNibble(AByte: Byte): THexNibble;
66
function SetUpperNibble(AByte: Byte; ANewNibble: THexNibble): Byte;
67
 
68
// Interchanges upper and lower Nibble in a byte
69
function InterchangeNibbles(AByte: Byte): Byte;
70
 
71
// Creates an 8-bit-array from a 8-bit-string
72
// Throws EBitStringTooLong and EBitStringInvalidCharacter
73
function ByteBitArrayFromBitString(const ABits: TByteBitString):
74
  TByteBitArray;
75
 
76
// Getting and setting of a bit in a byte
77
function GetByteBit(AByte: Byte; ABitPos: T8BitPos): TBit;
78
function SetByteBit(AByte: Byte; ABitPos: T8BitPos; ANewBit: TBit): Byte;
79
 
80
// Logical operations for the 8 bit arrays.
81
function ByteBitArrayShr(ABitArray: TByteBitArray;
82
  AVal: Longword): TByteBitArray;
83
function ByteBitArrayShl(ABitArray: TByteBitArray;
84
  AVal: Longword): TByteBitArray;
85
function ByteBitArrayAnd(ABitArray, ABitArray2: TByteBitArray): TByteBitArray;
86
function ByteBitArrayOr(ABitArray, ABitArray2: TByteBitArray): TByteBitArray;
87
function ByteBitArrayXor(ABitArray, ABitArray2: TByteBitArray): TByteBitArray;
88
function ByteBitArrayNot(ABitArray: TByteBitArray): TByteBitArray;
89
 
90
// Inverse the bits of a byte
91
function InverseByteBits(x: Byte): Byte;
92
 
93
// Reverses the bit sequence of a byte
94
function ReverseByteBitSequence(AByte: Byte): Byte;
95
 
96
// ********************
97
// * NIBBLE FUNCTIONS *
98
// ********************
99
 
100
// Build a Nibble.
101
// You can define an array of 4 bits.
102
function BuildNibble(ABitArray: THexNibbleBitArray): Nibble; overload;
103
// ...or you define a bitstring (e.g. '0001')
104
function BuildNibble(ABits: THexNibbleBitString): Nibble; overload;
105
// ...or you define the bits as parameters
106
function BuildNibble(ABit1, ABit2, ABit3, ABit4: TBit): Nibble; overload;
107
 
108
// Converts a nibble into a array of 4 bits
109
function GetNibbleBitArray(ANibble: Nibble): THexNibbleBitArray;
110
 
111
// Creates an 4-bit-array from a 4-bit-string
112
// Throws EBitStringTooLong and EBitStringInvalidCharacter
113
function NibbleBitArrayFromBitString(const ABits: THexNibbleBitString):
114
  THexNibbleBitArray;
115
 
116
// Getting and setting of a bit in a nibble
117
function GetNibbleBit(ANibble: Nibble; ABitPos: T4BitPos): TBit;
118
function SetNibbleBit(ANibble: Nibble; ABitPos: T4BitPos;
119
  ANewBit: TBit): Nibble;
120
 
121
// Logical operations for the 4 bit arrays.
122
function NibbleBitArrayShr(ABitArray: THexNibbleBitArray; AVal: Longword):
123
  THexNibbleBitArray;
124
function NibbleBitArrayShl(ABitArray: THexNibbleBitArray; AVal: Longword):
125
  THexNibbleBitArray;
126
function NibbleBitArrayAnd(ABitArray, ABitArray2: THexNibbleBitArray):
127
  THexNibbleBitArray;
128
function NibbleBitArrayOr(ABitArray, ABitArray2: THexNibbleBitArray):
129
  THexNibbleBitArray;
130
function NibbleBitArrayXor(ABitArray, ABitArray2: THexNibbleBitArray):
131
  THexNibbleBitArray;
132
function NibbleBitArrayNot(ABitArray: THexNibbleBitArray): THexNibbleBitArray;
133
 
134
// Inverse the bits of a nibble
135
function InverseNibbleBits(x: Nibble): Nibble;
136
 
137
// Reverses the bit sequence of a nibble
138
function ReverseNibbleBitSequence(ANibble: Nibble): Nibble;
139
 
140
// * EXCEPTIONS *
141
 
142
type
143
  EInvalidBitString = class(Exception);
144
  EBitStringTooLong = class(EInvalidBitString);
145
  EBitStringInvalidCharacter = class(EInvalidBitString);
146
 
147
// * CONSTANTS *
148
 
149
// Lookup tables to avoid calculation each time
150
const
151
  AllSetBitsBytes: array[TBytePos] of int64 =
152
   ($00000000000000FF,
153
    $000000000000FFFF,
154
    $0000000000FFFFFF,
155
    $00000000FFFFFFFF,
156
    $000000FFFFFFFFFF,
157
    $0000FFFFFFFFFFFF,
158
    $00FFFFFFFFFFFFFF,
159
    $FFFFFFFFFFFFFFFF);
160
 
161
  AllSetBitsNibbles: array[THexNibblePos] of int64 =
162
   ($000000000000000F,
163
    $00000000000000FF,
164
    $0000000000000FFF,
165
    $000000000000FFFF,
166
    $00000000000FFFFF,
167
    $0000000000FFFFFF,
168
    $000000000FFFFFFF,
169
    $00000000FFFFFFFF,
170
    $0000000FFFFFFFFF,
171
    $000000FFFFFFFFFF,
172
    $00000FFFFFFFFFFF,
173
    $0000FFFFFFFFFFFF,
174
    $000FFFFFFFFFFFFF,
175
    $00FFFFFFFFFFFFFF,
176
    $0FFFFFFFFFFFFFFF,
177
    $FFFFFFFFFFFFFFFF);
178
 
179
  AllSetBitsNibble: array[THexNibblePos] of int64 =
180
   ($000000000000000F,
181
    $00000000000000F0,
182
    $0000000000000F00,
183
    $000000000000F000,
184
    $00000000000F0000,
185
    $0000000000F00000,
186
    $000000000F000000,
187
    $00000000F0000000,
188
    $0000000F00000000,
189
    $000000F000000000,
190
    $00000F0000000000,
191
    $0000F00000000000,
192
    $000F000000000000,
193
    $00F0000000000000,
194
    $0F00000000000000,
195
    $F000000000000000);
196
 
197
  // Deprecated function:
198
  // function GetSingleBit(ABit: T64BitPos): Int64;
199
  //
200
  // Gives you a 64 bit datatype which is representing the binary coding
201
  //
202
  // 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001,
203
  // 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000010,
204
  // 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000100,
205
  // 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00001000,
206
  // 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00010000,
207
  // 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00100000,
208
  // 00000000 00000000 00000000 00000000 00000000 00000000 00000000 01000000,
209
  // 00000000 00000000 00000000 00000000 00000000 00000000 00000000 10000000,
210
  // 00000000 00000000 00000000 00000000 00000000 00000000 00000001 00000000,
211
  // ...
212
  // 10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000.
213
  //
214
  // Limitation because of the data type: 64 Bit
215
  //
216
  // For the GetByteBit() and SetByteBit functions we only need this array to
217
  // be max at $80 (128).
218
  // Manual calculation (not 64 bit useable) would be
219
  // result := Math.Floor(Math.Power(2, ABit));
220
  SingleBitArray: array[T64BitPos] of int64 =
221
   ($0000000000000001, $0000000000000002, $0000000000000004, $0000000000000008,
222
    $0000000000000010, $0000000000000020, $0000000000000040, $0000000000000080,
223
    $0000000000000100, $0000000000000200, $0000000000000400, $0000000000000800,
224
    $0000000000001000, $0000000000002000, $0000000000004000, $0000000000008000,
225
    $0000000000010000, $0000000000020000, $0000000000040000, $0000000000080000,
226
    $0000000000100000, $0000000000200000, $0000000000400000, $0000000000800000,
227
    $0000000001000000, $0000000002000000, $0000000004000000, $0000000008000000,
228
    $0000000010000000, $0000000020000000, $0000000040000000, $0000000080000000,
229
    $0000000100000000, $0000000200000000, $0000000400000000, $0000000800000000,
230
    $0000001000000000, $0000002000000000, $0000004000000000, $0000008000000000,
231
    $0000010000000000, $0000020000000000, $0000040000000000, $0000080000000000,
232
    $0000100000000000, $0000200000000000, $0000400000000000, $0000800000000000,
233
    $0001000000000000, $0002000000000000, $0004000000000000, $0008000000000000,
234
    $0010000000000000, $0020000000000000, $0040000000000000, $0080000000000000,
235
    $0100000000000000, $0200000000000000, $0400000000000000, $0800000000000000,
236
    $1000000000000000, $2000000000000000, $4000000000000000, $8000000000000000);
237
 
238
  // Deprecated function:
239
  // function GetSingleBitDynamicInversed(ABit: T64BitPos): Int64;
240
  //
241
  // Gives you a 64 bit datatype which is representing the dynamic inversed
242
  // binary encoding. (Dynamic inversed means, that only the used bytes get
243
  // inverted, so this is NOT the same as "NOT GetSingleBit(ABit)"!)
244
  //
245
  // 00000000 00000000 00000000 00000000 00000000 00000000 00000000 11111110,
246
  // 00000000 00000000 00000000 00000000 00000000 00000000 00000000 11111101,
247
  // 00000000 00000000 00000000 00000000 00000000 00000000 00000000 11111011,
248
  // 00000000 00000000 00000000 00000000 00000000 00000000 00000000 11110111,
249
  // 00000000 00000000 00000000 00000000 00000000 00000000 00000000 11101111,
250
  // 00000000 00000000 00000000 00000000 00000000 00000000 00000000 11011111,
251
  // 00000000 00000000 00000000 00000000 00000000 00000000 00000000 10111111,
252
  // 00000000 00000000 00000000 00000000 00000000 00000000 00000000 01111111,
253
  // 00000000 00000000 00000000 00000000 00000000 00000000 11111110 11111111,
254
  // ...
255
  // 01111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111.
256
  //
257
  // Limitation because of the data type: 64 Bit
258
  //
259
  // Manual calculation (not 64 bit useable) would be
260
  // result := MathFloor(
261
  //   Math.Power(256, Math.Floor(ABit / 8)+1)-1 {***} -
262
  //   Math.Power(2, ABit));
263
  //
264
  // *** is the maximal value of the byte amount we were requesting.
265
  // Example:
266
  // If ABit in [ 0.. 7] => 1 Byte  used => (256^1-1) = $FF
267
  // If ABit in [ 8..15] => 2 Bytes used => (256^2-1) = $FF FF
268
  // If ABit in [16..23] => 3 Bytes used => (256^3-1) = $FF FF FF
269
  // If ABit in [24..31] => 4 Bytes used => (256^3-1) = $FF FF FF FF
270
  // ...
271
  SingleBitArrayDynamicInversed: array[T64BitPos] of int64 =
272
   ($00000000000000FE, $00000000000000FD, $00000000000000FB, $00000000000000F7,
273
    $00000000000000EF, $00000000000000DF, $00000000000000BF, $000000000000007F,
274
    $000000000000FEFF, $000000000000FDFF, $000000000000FBFF, $000000000000F7FF,
275
    $000000000000EFFF, $000000000000DFFF, $000000000000BFFF, $0000000000007FFF,
276
    $0000000000FEFFFF, $0000000000FDFFFF, $0000000000FBFFFF, $0000000000F7FFFF,
277
    $0000000000EFFFFF, $0000000000DFFFFF, $0000000000BFFFFF, $00000000007FFFFF,
278
    $00000000FEFFFFFF, $00000000FDFFFFFF, $00000000FBFFFFFF, $00000000F7FFFFFF,
279
    $00000000EFFFFFFF, $00000000DFFFFFFF, $00000000BFFFFFFF, $000000007FFFFFFF,
280
    $000000FEFFFFFFFF, $000000FDFFFFFFFF, $000000FBFFFFFFFF, $000000F7FFFFFFFF,
281
    $000000EFFFFFFFFF, $000000DFFFFFFFFF, $000000BFFFFFFFFF, $0000007FFFFFFFFF,
282
    $0000FEFFFFFFFFFF, $0000FDFFFFFFFFFF, $0000FBFFFFFFFFFF, $0000F7FFFFFFFFFF,
283
    $0000EFFFFFFFFFFF, $0000DFFFFFFFFFFF, $0000BFFFFFFFFFFF, $00007FFFFFFFFFFF,
284
    $00FEFFFFFFFFFFFF, $00FDFFFFFFFFFFFF, $00FBFFFFFFFFFFFF, $00F7FFFFFFFFFFFF,
285
    $00EFFFFFFFFFFFFF, $00DFFFFFFFFFFFFF, $00BFFFFFFFFFFFFF, $007FFFFFFFFFFFFF,
286
    $FEFFFFFFFFFFFFFF, $FDFFFFFFFFFFFFFF, $FBFFFFFFFFFFFFFF, $F7FFFFFFFFFFFFFF,
287
    $EFFFFFFFFFFFFFFF, $DFFFFFFFFFFFFFFF, $BFFFFFFFFFFFFFFF, $7FFFFFFFFFFFFFFF);
288
 
289
  // Gives you a 64 bit datatype which is representing the inversed
290
  // binary encoding.
291
  //
292
  // 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111110,
293
  // 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111101,
294
  // 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111011,
295
  // 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11110111,
296
  // 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11101111,
297
  // 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11011111,
298
  // 11111111 11111111 11111111 11111111 11111111 11111111 11111111 10111111,
299
  // 11111111 11111111 11111111 11111111 11111111 11111111 11111111 01111111,
300
  // 11111111 11111111 11111111 11111111 11111111 11111111 11111110 11111111,
301
  // ...
302
  // 01111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111.
303
  //
304
  // Limitation because of the data type: 64 Bit
305
  //
306
  // Manual calculation (not 64 bit useable) would be
307
  // result := NOT GetSingleBit(ABit)
308
  //
309
  SingleBitArrayInversed: array[T64BitPos] of int64 =
310
   ($FFFFFFFFFFFFFFFE, $FFFFFFFFFFFFFFFD, $FFFFFFFFFFFFFFFB, $FFFFFFFFFFFFFFF7,
311
    $FFFFFFFFFFFFFFEF, $FFFFFFFFFFFFFFDF, $FFFFFFFFFFFFFFBF, $FFFFFFFFFFFFFF7F,
312
    $FFFFFFFFFFFFFEFF, $FFFFFFFFFFFFFDFF, $FFFFFFFFFFFFFBFF, $FFFFFFFFFFFFF7FF,
313
    $FFFFFFFFFFFFEFFF, $FFFFFFFFFFFFDFFF, $FFFFFFFFFFFFBFFF, $FFFFFFFFFFFF7FFF,
314
    $FFFFFFFFFFFEFFFF, $FFFFFFFFFFFDFFFF, $FFFFFFFFFFFBFFFF, $FFFFFFFFFFF7FFFF,
315
    $FFFFFFFFFFEFFFFF, $FFFFFFFFFFDFFFFF, $FFFFFFFFFFBFFFFF, $FFFFFFFFFF7FFFFF,
316
    $FFFFFFFFFEFFFFFF, $FFFFFFFFFDFFFFFF, $FFFFFFFFFBFFFFFF, $FFFFFFFFF7FFFFFF,
317
    $FFFFFFFFEFFFFFFF, $FFFFFFFFDFFFFFFF, $FFFFFFFFBFFFFFFF, $FFFFFFFF7FFFFFFF,
318
    $FFFFFFFEFFFFFFFF, $FFFFFFFDFFFFFFFF, $FFFFFFFBFFFFFFFF, $FFFFFFF7FFFFFFFF,
319
    $FFFFFFEFFFFFFFFF, $FFFFFFDFFFFFFFFF, $FFFFFFBFFFFFFFFF, $FFFFFF7FFFFFFFFF,
320
    $FFFFFEFFFFFFFFFF, $FFFFFDFFFFFFFFFF, $FFFFFBFFFFFFFFFF, $FFFFF7FFFFFFFFFF,
321
    $FFFFEFFFFFFFFFFF, $FFFFDFFFFFFFFFFF, $FFFFBFFFFFFFFFFF, $FFFF7FFFFFFFFFFF,
322
    $FFFEFFFFFFFFFFFF, $FFFDFFFFFFFFFFFF, $FFFBFFFFFFFFFFFF, $FFF7FFFFFFFFFFFF,
323
    $FFEFFFFFFFFFFFFF, $FFDFFFFFFFFFFFFF, $FFBFFFFFFFFFFFFF, $FF7FFFFFFFFFFFFF,
324
    $FEFFFFFFFFFFFFFF, $FDFFFFFFFFFFFFFF, $FBFFFFFFFFFFFFFF, $F7FFFFFFFFFFFFFF,
325
    $EFFFFFFFFFFFFFFF, $DFFFFFFFFFFFFFFF, $BFFFFFFFFFFFFFFF, $7FFFFFFFFFFFFFFF);
326
 
327
implementation
328
 
329
resourcestring
330
  LngEBitStringInvalidCharacter = 'The bitstring "%s" contains a invalid ' +
331
    'character. Unexpected character "%s" at position "%d".';
332
  LngEBitStringTooLong = 'The bitstring "%s" is too long. Expected: %d byte.';
333
 
334
function GetByteBitArray(AByte: Byte): TByteBitArray;
335
var
336
  i: T8BitPos;
337
begin
338
  for i := Low(T8BitPos) to High(T8BitPos) do
339
  begin
340
    // result[i] := GetByteBit(AByte, i);
341
    result[i] := AByte and SingleBitArray[i] = SingleBitArray[i];
342
  end;
343
end;
344
 
345
function GetNibbleBitArray(ANibble: Nibble): THexNibbleBitArray;
346
var
347
  i: T4BitPos;
348
begin
349
  for i := Low(T4BitPos) to High(T4BitPos) do
350
  begin
351
    // result[i] := GetNibbleBit(ANibble, i);
352
    result[i] := ANibble and SingleBitArray[i] = SingleBitArray[i];
353
  end;
354
end;
355
 
356
function BuildByte(AUpperNibble, ALowerNibble: THexNibble): Byte;
357
begin
358
  // result := $10 * AUpperNibble + ALowerNibble;
359
  result := (AUpperNibble shl 4) + ALowerNibble;
360
end;
361
 
362
function BuildByte(ABitArray: TByteBitArray): Byte;
363
var
364
  i: T8BitPos;
365
begin
366
  result := 0;
367
  for i := Low(T8BitPos) to High(T8BitPos) do
368
  begin
369
    // SetByteBit(result, i, ABitArray[i]);
370
 
371
    if not ABitArray[i] then
372
      result := result and SingleBitArrayDynamicInversed[i]
373
    else
374
      result := result or SingleBitArray[i];
375
  end;
376
end;
377
 
378
function BuildByte(ABits: TByteBitString): Byte;
379
begin
380
  result := BuildByte(ByteBitArrayFromBitString(ABits));
381
end;
382
 
383
function BuildByte(ABit1, ABit2, ABit3, ABit4, ABit5, ABit6, ABit7,
384
  ABit8: TBit): Byte; overload;
385
var
386
  ba: TByteBitArray;
387
begin
388
  ba[0] := ABit1;
389
  ba[1] := ABit2;
390
  ba[2] := ABit3;
391
  ba[3] := ABit4;
392
  ba[4] := ABit5;
393
  ba[5] := ABit6;
394
  ba[6] := ABit7;
395
  ba[7] := ABit8;
396
  result := BuildByte(ba);
397
end;
398
 
399
function ByteBitArrayFromBitString(const ABits: TByteBitString): TByteBitArray;
400
var
401
  i: integer;
402
begin
403
  if Length(ABits) <> 8 then
404
  begin
405
    raise EBitStringTooLong.CreateFmt(LngEBitStringTooLong, [ABits, 8]);
406
    exit;
407
  end;
408
 
409
  for i := 1 to Length(ABits) do
410
  begin
411
    case ABits[i] of
412
      '0': result[i-1] := false;
413
      '1': result[i-1] := true;
414
    else
415
      raise EBitStringInvalidCharacter.CreateFmt(LngEBitStringInvalidCharacter,
416
        [ABits, ABits[i], i]);
417
    end;
418
  end;
419
end;
420
 
421
function NibbleBitArrayFromBitString(const ABits: THexNibbleBitString):
422
  THexNibbleBitArray;
423
var
424
  i: integer;
425
begin
426
  if Length(ABits) <> 4 then
427
  begin
428
    raise EBitStringTooLong.CreateFmt(LngEBitStringTooLong, [ABits, 4]);
429
    exit;
430
  end;
431
 
432
  for i := 1 to Length(ABits) do
433
  begin
434
    case ABits[i] of
435
      '0': result[i-1] := false;
436
      '1': result[i-1] := true;
437
    else
438
      raise EBitStringInvalidCharacter.CreateFmt(LngEBitStringInvalidCharacter,
439
        [ABits, ABits[i], i]);
440
    end;
441
  end;
442
end;
443
 
444
function BuildNibble(ABit1, ABit2, ABit3, ABit4: TBit): Nibble;
445
var
446
  ba: THexNibbleBitArray;
447
begin
448
  ba[0] := ABit1;
449
  ba[1] := ABit2;
450
  ba[2] := ABit3;
451
  ba[3] := ABit4;
452
  result := BuildNibble(ba);
453
end;
454
 
455
function BuildNibble(ABitArray: THexNibbleBitArray): Nibble;
456
var
457
  i: T4BitPos;
458
begin
459
  result := 0;
460
  for i := Low(T4BitPos) to High(T4BitPos) do
461
  begin
462
    // SetNibbleBit(result, i, ABitArray[i]);
463
 
464
    if not ABitArray[i] then
465
      result := result and SingleBitArrayDynamicInversed[i]
466
    else
467
      result := result or SingleBitArray[i];
468
  end;
469
end;
470
 
471
function BuildNibble(ABits: THexNibbleBitString): Nibble;
472
begin
473
  result := BuildNibble(NibbleBitArrayFromBitString(ABits));
474
end;
475
 
476
function GetLowerNibble(AByte: Byte): THexNibble;
477
begin
478
  result := AByte and AllSetBitsNibble[0];
479
end;
480
 
481
function SetLowerNibble(AByte: Byte; ANewNibble: THexNibble): Byte;
482
begin
483
  // result := BuildByte(GetUpperNibble(AByte), ANewNibble);
484
  // result := $10 * (AByte and AllSetBitsNibble[1] shr 4) + ANewNibble;
485
  // result := (AByte and AllSetBitsNibble[1] shr 4) shl 4 + ANewNibble;
486
 
487
  // Optimized: "shr 4 shl 4" removed
488
  result := (AByte and AllSetBitsNibble[1]) + ANewNibble;
489
end;
490
 
491
function GetUpperNibble(AByte: Byte): THexNibble;
492
begin
493
  result := AByte and AllSetBitsNibble[1] shr 4;
494
end;
495
 
496
function SetUpperNibble(AByte: Byte; ANewNibble: THexNibble): Byte;
497
begin
498
  // result := BuildByte(ANewNibble, GetLowerNibble(AByte));
499
  // result := ($10 * ANewNibble) + (AByte and AllSetBitsNibble[0]);
500
  result := (ANewNibble shl 4) + (AByte and AllSetBitsNibble[0]);
501
end;
502
 
503
function GetByteBit(AByte: Byte; ABitPos: T8BitPos): TBit;
504
begin
505
  // result := AByte and SingleBitArray[ABitPos] shr ABitPos = 1;
506
  // result := AByte and Math.Power(2, ABitPos) shr ABitPos = 1;
507
  // result := AByte and SingleBitArray[ABitPos] shr ABitPos = 1;
508
  result := AByte and SingleBitArray[ABitPos] = SingleBitArray[ABitPos];
509
end;
510
 
511
function SetByteBit(AByte: Byte; ABitPos: T8BitPos; ANewBit: TBit): Byte;
512
begin
513
  if not ANewBit then
514
  begin
515
    // Set a bit to 0.
516
    // Example: abcdefgh AND 11111011 = abcde0gh
517
 
518
    // result := AByte and (AllSetBitsBytes[0] - SingleBitArray[ABitPos]);
519
    // result := AByte and (AllSetBitsBytes[0] - Math.Power(2, ABitPos));
520
    result := AByte and SingleBitArrayDynamicInversed[ABitPos]
521
  end
522
  else
523
  begin
524
    // Set a bit to 1.
525
    // Example: abcdefgh OR 00000100 = abcde1gh
526
 
527
    // result := AByte or Math.Power(2, ABitPos);
528
    result := AByte or SingleBitArray[ABitPos];
529
  end;
530
end;
531
 
532
function GetNibbleBit(ANibble: Nibble; ABitPos: T4BitPos): TBit;
533
begin
534
  result := GetByteBit(ANibble, ABitPos);
535
end;
536
 
537
function SetNibbleBit(ANibble: Nibble; ABitPos: T4BitPos;
538
  ANewBit: TBit): Nibble;
539
begin
540
  result := SetByteBit(ANibble, ABitPos, ANewBit);
541
end;
542
 
543
function ByteBitArrayShr(ABitArray: TByteBitArray;
544
  AVal: Longword): TByteBitArray;
545
var
546
  b: Byte;
547
begin
548
  b := BuildByte(ABitArray);
549
  result := GetByteBitArray(b shr AVal);
550
end;
551
 
552
function ByteBitArrayShl(ABitArray: TByteBitArray;
553
  AVal: Longword): TByteBitArray;
554
var
555
  b: Byte;
556
begin
557
  b := BuildByte(ABitArray);
558
  result := GetByteBitArray(b shl AVal);
559
end;
560
 
561
function ByteBitArrayAnd(ABitArray, ABitArray2: TByteBitArray): TByteBitArray;
562
var
563
  b, b2: Byte;
564
begin
565
  b  := BuildByte(ABitArray);
566
  b2 := BuildByte(ABitArray2);
567
  result := GetByteBitArray(b and b2);
568
end;
569
 
570
function ByteBitArrayOr(ABitArray, ABitArray2: TByteBitArray): TByteBitArray;
571
var
572
  b, b2: Byte;
573
begin
574
  b  := BuildByte(ABitArray);
575
  b2 := BuildByte(ABitArray2);
576
  result := GetByteBitArray(b or b2);
577
end;
578
 
579
function ByteBitArrayXor(ABitArray, ABitArray2: TByteBitArray): TByteBitArray;
580
var
581
  b, b2: Byte;
582
begin
583
  b  := BuildByte(ABitArray);
584
  b2 := BuildByte(ABitArray2);
585
  result := GetByteBitArray(b xor b2);
586
end;
587
 
588
function ByteBitArrayNot(ABitArray: TByteBitArray): TByteBitArray;
589
var
590
  b: Byte;
591
begin
592
  b := BuildByte(ABitArray);
593
  result := GetByteBitArray(not b);
594
end;
595
 
596
function NibbleBitArrayShr(ABitArray: THexNibbleBitArray; AVal: Longword):
597
  THexNibbleBitArray;
598
var
599
  b: Nibble;
600
begin
601
  b := BuildNibble(ABitArray);
602
  result := GetNibbleBitArray(b shr AVal);
603
end;
604
 
605
function NibbleBitArrayShl(ABitArray: THexNibbleBitArray; AVal: Longword):
606
  THexNibbleBitArray;
607
var
608
  b: Nibble;
609
begin
610
  b := BuildNibble(ABitArray);
611
  result := GetNibbleBitArray(b shl AVal);
612
end;
613
 
614
function NibbleBitArrayAnd(ABitArray, ABitArray2: THexNibbleBitArray):
615
  THexNibbleBitArray;
616
var
617
  b, b2: Nibble;
618
begin
619
  b  := BuildNibble(ABitArray);
620
  b2 := BuildNibble(ABitArray2);
621
  result := GetNibbleBitArray(b and b2);
622
end;
623
 
624
function NibbleBitArrayOr(ABitArray, ABitArray2: THexNibbleBitArray):
625
  THexNibbleBitArray;
626
var
627
  b, b2: Nibble;
628
begin
629
  b  := BuildNibble(ABitArray);
630
  b2 := BuildNibble(ABitArray2);
631
  result := GetNibbleBitArray(b or b2);
632
end;
633
 
634
function NibbleBitArrayXor(ABitArray, ABitArray2: THexNibbleBitArray):
635
  THexNibbleBitArray;
636
var
637
  b, b2: Nibble;
638
begin
639
  b  := BuildNibble(ABitArray);
640
  b2 := BuildNibble(ABitArray2);
641
  result := GetNibbleBitArray(b xor b2);
642
end;
643
 
644
function NibbleBitArrayNot(ABitArray: THexNibbleBitArray): THexNibbleBitArray;
645
var
646
  b: Nibble;
647
begin
648
  b := BuildNibble(ABitArray);
649
  result := GetNibbleBitArray(not b);
650
end;
651
 
652
function InverseByteBits(x: Byte): Byte;
653
begin
654
  //     10110001
655
  // xor 11111111
656
  //   = 01001110
657
  result := x xor AllSetBitsBytes[0];
658
end;
659
 
660
function InverseNibbleBits(x: Nibble): Nibble;
661
begin
662
  //         0001
663
  // xor     1111
664
  //   =     1110
665
  result := x xor AllSetBitsNibbles[0];
666
end;
667
 
668
function InterchangeNibbles(AByte: Byte): Byte;
669
begin
670
  // result := BuildByte(GetLowerNibble(AByte), GetUpperNibble(AByte));
671
  result := (AByte and AllSetBitsNibble[0] shl 4) +
672
            (AByte and AllSetBitsNibble[1] shr 4)
673
end;
674
 
675
function ReverseByteBitSequence(AByte: Byte): Byte;
676
var
677
  ba: TByteBitArray;
678
begin
679
  ba := GetByteBitArray(AByte);
680
  result := BuildByte(ba[7], ba[6], ba[5], ba[4], ba[3], ba[2], ba[1], ba[0]);
681
end;
682
 
683
function ReverseNibbleBitSequence(ANibble: Nibble): Nibble;
684
var
685
  ba: THexNibbleBitArray;
686
begin
687
  ba := GetNibbleBitArray(ANibble);
688
  result := BuildNibble(ba[3], ba[2], ba[1], ba[0]);
689
end;
690
 
691
end.