I've been wondering what the most efficient way to reverse the order of a BitArray in C#. To be clear, I don't want to inverse the Bitarray by calling .Not(), I want to reverse the order of the bits in the array.
Cheers,
Chris
public void Reverse(BitArray array)
{
int length = array.Length;
int mid = (length / 2);
for (int i = 0; i < mid; i++)
{
bool bit = array[i];
array[i] = array[length - i - 1];
array[length - i - 1] = bit;
}
}
For a long array and relative few uses, just wrap it:
class BitArrayReverse
{
private BitArray _ba;
public BitArrayReverse(BitArray ba) { _ba = ba; }
public bool this[int index]
{
get { return _ba[_ba.Length - 1 - index]; }
set { _ba[_ba.Length - 1 - index] = value; }
}
}
This will be the best way
to reverse MSB <-> LSB of any length using XOR in the for loop
public static BitArray BitsReverse(BitArray bits)
{
int len = bits.Count;
BitArray a = new BitArray(bits);
BitArray b = new BitArray(bits);
for (int i = 0, j = len-1; i < len; ++i, --j)
{
a[i] = a[i] ^ b[j];
b[j] = a[i] ^ b[j];
a[i] = a[i] ^ b[j];
}
return a;
}
// in 010000011010000011100b
// out 001110000010110000010b
Dim myBA As New BitArray(4)
myBA(0) = True
myBA(1) = False
myBA(2) = True
myBA(3) = True
Dim myBoolArray1(3) As Boolean
myBA.CopyTo(myBoolArray1, 0)
Array.Reverse(myBoolArray1)
myBA = New BitArray(myBoolArray1)
For a short but inefficient answer:
using System.Linq;
var reversedBa = new BitArray(myBa.Cast<bool>().Reverse().ToArray())
Because the size if fixed at 8-bits just the "table" lookup from below is sufficient -- when dealing with a plain byte a look-up is likely the quickest way. The extra overhead of BitSet to get/set the data may, however, nullify the look-up benefit. Also the initial build cost and persistent overhead need to be considered (but the values could be coded into an array literal ... ick!)
On the other hand, if the data is only 8 bit (ever), and "performance is important", why use a BitArray at all? A BitArray could always be used for the nice features, such as "exploding" to an Enumerable while C# already has decent byte bit manipulation built-in.
Assuming a more general case that the data is 8-bit aligned... but of some undetermined length
Is this actually better (faster, more efficient, etc) than just doing it "per item" in the BitArray? I have no idea but suspect not. I would definitely start with the "simple" methods -- this is here as just a proof-of-concept and may (or may not be) interesting to compare in a benchmark. Anyway, write for clarity first ... and the below is not it! (There is at least one bug in it -- I blame the extra complexity ;-)
byte reverse (byte b) {
byte o = 0;
for (var i = 0; i < 8; i++) {
o <<= 1;
o |= (byte)(b & 1);
b >>= 1;
}
return o;
}
byte[] table;
BitArray reverse8 (BitArray ar) {
if (ar.Count % 8 != 0) {
throw new Exception("no!");
}
byte[] d = new byte[ar.Count / 8];
ar.CopyTo(d, 0);
// this only works if the bit array is
// a multiple of 8. we swap bytes and
// then reverse bits in each byte
int mid = d.Length / 2;
for (int i = 0, j = d.Length - 1; i < mid; i++, j--) {
byte t = d[i];
d[i] = table[d[j]];
d[j] = table[t];
}
return new BitArray(d);
}
string tostr (BitArray x) {
return string.Join("",
x.OfType<bool>().Select(i => i ? "1" : "0").ToArray());
}
void Main()
{
table = Enumerable.Range(0,256).Select(v => reverse((byte)v)).ToArray();
{
byte[] s = new byte[] { 1, 0xff };
BitArray ar = new BitArray(s);
// linqpad :)
tostr(ar).Dump();
tostr(reverse8(ar)).Dump();
}
"--".Dump();
{
byte[] s = new byte[] { 3, 42, 19 };
BitArray ar = new BitArray(s);
// linqpad :)
tostr(ar).Dump();
tostr(reverse8(ar)).Dump();
}
}
Output:
1000000011111111
1111111100000001
--
110000000101010011001000
000100110101010000000011
The expr.Dump() is a LINQPad feature.
Adapted the answer from #TimLoyd and turned it into an extension for easier use.
public static BitArray Reverse(this BitArray array)
{
int length = array.Length;
int mid = (length / 2);
for (int i = 0; i < mid; i++)
{
bool bit = array[i];
array[i] = array[length - i - 1];
array[length - i - 1] = bit;
}
return new BitArray(array);
}
Usage:
var bits = new BitArray(some_bytes).Reverse();
Related
What are alternatives to this method
tmp = c[0];
c[0] = c[1];
c[1] = c[2];
c[2] = c[3];
c[3] = tmp;
to left rotate a char array with 4 elements
Using generics and rotating in place (thanks Jon Skeet for the suggestion):
static void Rotate<T>(T[] source)
{
var temp = source[0];
Array.Copy(source, 1, source, 0, source.Length - 1);
source[source.Length - 1] = temp;
}
These should work for any array of at least 2 length, and on any array.
If performance is critical and the arrays are always small, use this:
static void Rotate<T>(T[] source)
{
var temp = source[0];
for (int i = 0; i < source.Length - 1; i++)
source[i] = source[i + 1];
source[source.Length - 1] = temp;
}
The first method is the fastest with large arrays, but for 4 items, this one's almost as fast as your example method.
An alterantive to rotating the array, is to rotate the index when accessing the array, i.e you are creating a virtual ring
int origin = someValue;
int x = c[(i + origin) % c.Length];
I'm not sure if you're asking for a more efficient method or for an easier way to type that, but i'm going to try answering you assuming you want an easier way
so try:
int temp = c[0]
for(int i = 0; i < c.count; i++)
{
if (i == (c.count - 1))
{
c[i] = temp;
break;
}
c[i] = c[i + 1];
}
Do the job in single step.
Using System.Linq;
int[] ar = { 1,2,3,4,5};
int k = 1; //
int[] ar1= ar.Skip(k) // Start with the last elements
.Concat(ar.Take(k)) // Then the first elements
.ToArray();
Output-- 2,3,4,5,1
In ruby rotating array can be done in one line.
def array_rotate(arr)
i, j = arr.length - 1, 0
arr[j],arr[i], i, j = arr[i], arr[j], i - 1, j + 1 while(j<arr.length/2)
puts "#{arr}"
end
How can I convert BitArray to a single int?
private int getIntFromBitArray(BitArray bitArray)
{
if (bitArray.Length > 32)
throw new ArgumentException("Argument length shall be at most 32 bits.");
int[] array = new int[1];
bitArray.CopyTo(array, 0);
return array[0];
}
private int getIntFromBitArray(BitArray bitArray)
{
int value = 0;
for (int i = 0; i < bitArray.Count; i++)
{
if (bitArray[i])
value += Convert.ToInt16(Math.Pow(2, i));
}
return value;
}
This version:
works for up to 64 bits
doesn't rely on knowledge of BitArray implementation details
doesn't needlessly allocate memory
doesn't throw any exceptions (feel free to add a check if you expect more bits)
should be more than reasonably performant
Implementation:
public static ulong BitArrayToU64(BitArray ba)
{
var len = Math.Min(64, ba.Count);
ulong n = 0;
for (int i = 0; i < len; i++) {
if (ba.Get(i))
n |= 1UL << i;
}
return n;
}
Reffering to this post (#43935747). A value X is short tpe whic I set two bits (6 and 10) like below:
short X=1;
var result = X;
var bitsToSet = new [ ] { 5,9 };
foreach ( var bitToSet in bitsToSet )
{
result+=( short ) Math.Pow ( 2,bitToSet );
}
string binary = Convert.ToString ( result,2 );
Now I would like to read the specific all bits from Value X and put it in to an array or a bit type like bool Val1= bit1, bool Val2=bit2....
I am a newbie and I think it is pretty simple for you guyes..
So Say I have an array of bytes that is 16 long, with each 8 bits representing my data and an array that is 8 long with each 4 bits (so 2 per byte) representing my data.
If I wanted to loop over these and get the values, what would be the easiest way of doing so?
My poor attempt would be something like this, but this doesn't appear to be working as I expect.
for(int i = 0; i < bigByteArray.Length; i++)
{
byte BigByteInfo = bigByteArray[i];
byte SmallByteInfo;
if(i % 2 == 0)
{
SmallByteInfo = smallByteArray[i / 2] % 16;
}
else
{
SmallByteInfo = smallByteArray[i / 2] / 16;
}
//Use of data Here.
}
you can use this class as helper class
public class FoutBitsArrayEnumerator : IEnumeable<byte>
{
FoutBitsArrayEnumerator(byte[] array)
{
this.array = array;
}
public IEnumerator<byte> GetEnumerator
{
foreach (byte i in array)
{
yield return i & 15;
yield return (i >> 4) & 15;
}
}
byte[] array;
}
If I understand right (bigByteArray is 16 long, smallByteArray is 8 long, packed):
for(int i = 0; i < bigByteArray.Length; i++)
{
bigByteArray[i] = (byte)((smallByteArray[i / 2] >> (i % 2 == 0 ? 4 : 0)) & 0xF);
}
I have a datastructure with a field of the float-type. A collection of these structures needs to be sorted by the value of the float. Is there a radix-sort implementation for this.
If there isn't, is there a fast way to access the exponent, the sign and the mantissa.
Because if you sort the floats first on mantissa, exponent, and on exponent the last time. You sort floats in O(n).
Update:
I was quite interested in this topic, so I sat down and implemented it (using this very fast and memory conservative implementation). I also read this one (thanks celion) and found out that you even dont have to split the floats into mantissa and exponent to sort it. You just have to take the bits one-to-one and perform an int sort. You just have to care about the negative values, that have to be inversely put in front of the positive ones at the end of the algorithm (I made that in one step with the last iteration of the algorithm to save some cpu time).
So heres my float radixsort:
public static float[] RadixSort(this float[] array)
{
// temporary array and the array of converted floats to ints
int[] t = new int[array.Length];
int[] a = new int[array.Length];
for (int i = 0; i < array.Length; i++)
a[i] = BitConverter.ToInt32(BitConverter.GetBytes(array[i]), 0);
// set the group length to 1, 2, 4, 8 or 16
// and see which one is quicker
int groupLength = 4;
int bitLength = 32;
// counting and prefix arrays
// (dimension is 2^r, the number of possible values of a r-bit number)
int[] count = new int[1 << groupLength];
int[] pref = new int[1 << groupLength];
int groups = bitLength / groupLength;
int mask = (1 << groupLength) - 1;
int negatives = 0, positives = 0;
for (int c = 0, shift = 0; c < groups; c++, shift += groupLength)
{
// reset count array
for (int j = 0; j < count.Length; j++)
count[j] = 0;
// counting elements of the c-th group
for (int i = 0; i < a.Length; i++)
{
count[(a[i] >> shift) & mask]++;
// additionally count all negative
// values in first round
if (c == 0 && a[i] < 0)
negatives++;
}
if (c == 0) positives = a.Length - negatives;
// calculating prefixes
pref[0] = 0;
for (int i = 1; i < count.Length; i++)
pref[i] = pref[i - 1] + count[i - 1];
// from a[] to t[] elements ordered by c-th group
for (int i = 0; i < a.Length; i++){
// Get the right index to sort the number in
int index = pref[(a[i] >> shift) & mask]++;
if (c == groups - 1)
{
// We're in the last (most significant) group, if the
// number is negative, order them inversely in front
// of the array, pushing positive ones back.
if (a[i] < 0)
index = positives - (index - negatives) - 1;
else
index += negatives;
}
t[index] = a[i];
}
// a[]=t[] and start again until the last group
t.CopyTo(a, 0);
}
// Convert back the ints to the float array
float[] ret = new float[a.Length];
for (int i = 0; i < a.Length; i++)
ret[i] = BitConverter.ToSingle(BitConverter.GetBytes(a[i]), 0);
return ret;
}
It is slightly slower than an int radix sort, because of the array copying at the beginning and end of the function, where the floats are bitwise copied to ints and back. The whole function nevertheless is again O(n). In any case much faster than sorting 3 times in a row like you proposed. I dont see much room for optimizations anymore, but if anyone does: feel free to tell me.
To sort descending change this line at the very end:
ret[i] = BitConverter.ToSingle(BitConverter.GetBytes(a[i]), 0);
to this:
ret[a.Length - i - 1] = BitConverter.ToSingle(BitConverter.GetBytes(a[i]), 0);
Measuring:
I set up some short test, containing all special cases of floats (NaN, +/-Inf, Min/Max value, 0) and random numbers. It sorts exactly the same order as Linq or Array.Sort sorts floats:
NaN -> -Inf -> Min -> Negative Nums -> 0 -> Positive Nums -> Max -> +Inf
So i ran a test with a huge array of 10M numbers:
float[] test = new float[10000000];
Random rnd = new Random();
for (int i = 0; i < test.Length; i++)
{
byte[] buffer = new byte[4];
rnd.NextBytes(buffer);
float rndfloat = BitConverter.ToSingle(buffer, 0);
switch(i){
case 0: { test[i] = float.MaxValue; break; }
case 1: { test[i] = float.MinValue; break; }
case 2: { test[i] = float.NaN; break; }
case 3: { test[i] = float.NegativeInfinity; break; }
case 4: { test[i] = float.PositiveInfinity; break; }
case 5: { test[i] = 0f; break; }
default: { test[i] = test[i] = rndfloat; break; }
}
}
And stopped the time of the different sorting algorithms:
Stopwatch sw = new Stopwatch();
sw.Start();
float[] sorted1 = test.RadixSort();
sw.Stop();
Console.WriteLine(string.Format("RadixSort: {0}", sw.Elapsed));
sw.Reset();
sw.Start();
float[] sorted2 = test.OrderBy(x => x).ToArray();
sw.Stop();
Console.WriteLine(string.Format("Linq OrderBy: {0}", sw.Elapsed));
sw.Reset();
sw.Start();
Array.Sort(test);
float[] sorted3 = test;
sw.Stop();
Console.WriteLine(string.Format("Array.Sort: {0}", sw.Elapsed));
And the output was (update: now ran with release build, not debug):
RadixSort: 00:00:03.9902332
Linq OrderBy: 00:00:17.4983272
Array.Sort: 00:00:03.1536785
roughly more than four times as fast as Linq. That is not bad. But still not yet that fast as Array.Sort, but also not that much worse. But i was really surprised by this one: I expected it to be slightly slower than Linq on very small arrays. But then I ran a test with just 20 elements:
RadixSort: 00:00:00.0012944
Linq OrderBy: 00:00:00.0072271
Array.Sort: 00:00:00.0002979
and even this time my Radixsort is quicker than Linq, but way slower than array sort. :)
Update 2:
I made some more measurements and found out some interesting things: longer group length constants mean less iterations and more memory usage. If you use a group length of 16 bits (only 2 iterations), you have a huge memory overhead when sorting small arrays, but you can beat Array.Sort if it comes to arrays larger than about 100k elements, even if not very much. The charts axes are both logarithmized:
(source: daubmeier.de)
There's a nice explanation of how to perform radix sort on floats here:
http://www.codercorner.com/RadixSortRevisited.htm
If all your values are positive, you can get away with using the binary representation; the link explains how to handle negative values.
By doing some fancy casting and swapping arrays instead of copying this version is 2x faster for 10M numbers as Philip Daubmeiers original with grouplength set to 8. It is 3x faster as Array.Sort for that arraysize.
static public void RadixSortFloat(this float[] array, int arrayLen = -1)
{
// Some use cases have an array that is longer as the filled part which we want to sort
if (arrayLen < 0) arrayLen = array.Length;
// Cast our original array as long
Span<float> asFloat = array;
Span<int> a = MemoryMarshal.Cast<float, int>(asFloat);
// Create a temp array
Span<int> t = new Span<int>(new int[arrayLen]);
// set the group length to 1, 2, 4, 8 or 16 and see which one is quicker
int groupLength = 8;
int bitLength = 32;
// counting and prefix arrays
// (dimension is 2^r, the number of possible values of a r-bit number)
var dim = 1 << groupLength;
int groups = bitLength / groupLength;
if (groups % 2 != 0) throw new Exception("groups must be even so data is in original array at end");
var count = new int[dim];
var pref = new int[dim];
int mask = (dim) - 1;
int negatives = 0, positives = 0;
// counting elements of the 1st group incuding negative/positive
for (int i = 0; i < arrayLen; i++)
{
if (a[i] < 0) negatives++;
count[(a[i] >> 0) & mask]++;
}
positives = arrayLen - negatives;
int c;
int shift;
for (c = 0, shift = 0; c < groups - 1; c++, shift += groupLength)
{
CalcPrefixes();
var nextShift = shift + groupLength;
//
for (var i = 0; i < arrayLen; i++)
{
var ai = a[i];
// Get the right index to sort the number in
int index = pref[( ai >> shift) & mask]++;
count[( ai>> nextShift) & mask]++;
t[index] = ai;
}
// swap the arrays and start again until the last group
var temp = a;
a = t;
t = temp;
}
// Last round
CalcPrefixes();
for (var i = 0; i < arrayLen; i++)
{
var ai = a[i];
// Get the right index to sort the number in
int index = pref[( ai >> shift) & mask]++;
// We're in the last (most significant) group, if the
// number is negative, order them inversely in front
// of the array, pushing positive ones back.
if ( ai < 0) index = positives - (index - negatives) - 1; else index += negatives;
//
t[index] = ai;
}
void CalcPrefixes()
{
pref[0] = 0;
for (int i = 1; i < dim; i++)
{
pref[i] = pref[i - 1] + count[i - 1];
count[i - 1] = 0;
}
}
}
You can use an unsafe block to memcpy or alias a float * to a uint * to extract the bits.
I think your best bet if the values aren't too close and there's a reasonable precision requirement, you can just use the actual float digits before and after the decimal point to do the sorting.
For example, you can just use the first 4 decimals (be they 0 or not) to do the sorting.
I have a byte[] testKey = new byte[8];
This obviously starts with all bytes as 0. I want to go through all the bytes and increment by 1 on each iteration of the loop so eventually I go through all possibilities of the byte array. I also want to do this as FAST as possible. Yes I am trying to write a brute forcer.
Update I got the unsafe method working, and it is the quickest. However, by my calculations, it is going to take 76,000,000 years to loop through doing DES encryption on each key using the .Net DESCryptoServiceProvider. 10,000 encryptions takes 1.3 seconds. Thanks for all the awesome answers to the most useless question ever!
btw; it takes a lot of processing to check 2^64 options...
Well, the fastest way may be to just use an Int64 (aka long) or UInt64 (ulong), and use ++? Do you really need the byte[]?
As a hacky alternative, how about:
Array.Clear(data, 0, data.Length);
while (true)
{
// use data here
if (++data[7] == 0) if (++data[6] == 0)
if (++data[5] == 0) if (++data[4] == 0)
if (++data[3] == 0) if (++data[2] == 0)
if (++data[1] == 0) if (++data[0] == 0) break;
}
The only other approach I can think of would be to use unsafe code to talk to an array as though it is an int64... messy.
unsafe static void Test() {
byte[] data = new byte[8];
fixed (byte* first = data) {
ulong* value = (ulong*)first;
do {
// use data here
*value = *value + 1;
} while (*value != 0);
}
}
This is how you increase the value in the array:
int index = testKey.Length - 1;
while (index >= 0) {
if (testKey[index] < 255) {
testKey[index]++;
break;
} else {
testKey[index--] = 0;
}
}
When index is -1 after this code, you have iterated all combinations.
This will be slightly faster than using BitConverter, as it doesn't create a new array for each iteration.
Edit:
A small performance test showed that this is about 1400 times faster than using BitConverter...
What a great question! Here's a way to do it without unsafe code:
public struct LongAndBytes
{
[FieldOffset(0)]
public ulong UlongValue;
[FieldOffset(0)]
public byte Byte0;
[FieldOffset(1)]
public byte Byte1;
[FieldOffset(2)]
public byte Byte2;
[FieldOffset(3)]
public byte Byte3;
[FieldOffset(4)]
public byte Byte4;
[FieldOffset(5)]
public byte Byte5;
[FieldOffset(6)]
public byte Byte6;
[FieldOffset(7)]
public byte Byte7;
public byte[] ToArray()
{
return new byte[8] {Byte0, Byte1, Byte2, Byte3, Byte4, Byte5, Byte6, Byte7};
}
}
// ...
LongAndBytes lab = new LongAndBytes();
lab.UlongValue = 0;
do {
// stuff
lab.UlongValue++;
} while (lab.ULongValue != 0);
Each of the members Byte0...Byte7 overlap the ulong and share its members. It's not an array - I tried dinking around with that and had unsatisfactory results. I bet someone knows the magic declaration to make that happen. I can do that for a P/Invoke, but not for use in .NET as an array is an object.
byte[8] is essentially an ulong but if you really need it to be byte[8] you can use
byte[] bytes = new byte[8];
ulong i = 0;
bytes = BitConverter.GetBytes(i);
You can extract the bytes using bit operators:
byte[] bytes = new byte[8];
for (ulong u = 0; u < ulong.MaxValue; u++)
{
bytes[0] = (byte)(u & 0xff);
bytes[1] = (byte)((u >> 8) & 0xff);
bytes[2] = (byte)((u >> 16) & 0xff);
bytes[3] = (byte)((u >> 24) & 0xff);
bytes[4] = (byte)((u >> 32) & 0xff);
bytes[5] = (byte)((u >> 40) & 0xff);
bytes[6] = (byte)((u >> 48) & 0xff);
bytes[7] = (byte)((u >> 56) & 0xff);
// do your stuff...
}
This is less 'hackish', since it operates on an unsigned 64-bit integer first and then extract the bytes. However beware CPU endianess.
for (UInt64 i = 0; i < UInt64.MaxValue; i++)
{
byte[] data = BitConverter.GetBytes(i)
}
byte[] array = new byte[8];
int[] shifts = new int[] { 0, 8, 16, 24, 32, 40, 48, 56 };
for (long index = long.MinValue; index <= long.MaxValue; index++)
{
for (int i = 0; i < 8; i++)
{
array[i] = (byte)((index >> shifts[i]) & 0xff);
}
// test array
}
for (int i = 0; i < bytes.Length & 0 == ++bytes[i]; i++);
Should be as fast as the unsafe method and allows arrays of any size.
Simple iteration:
static IEnumerable<byte[]> Iterate(int arrayLength) {
var arr = new byte[arrayLength];
var i = 0;
yield return arr;
while (i < arrayLength)
{
if (++arr[i] != 0)
{
i = 0;
yield return arr;
}
else i++;
}
}
static void Main(string[] args)
{
foreach (var arr in Iterate(2))
{
Console.Write(String.Join(",", arr.Select(x => $"{x:D3}")));
Console.WriteLine();
}
}
Sorry for the late post, but I needed the described feature too and implemented it in a pretty easy way in my opinion. Maybe it's useful for somebody else too:
private byte[] IncrementBytes(byte[] bytes)
{
for (var i = bytes.Length - 1; i >= 0; i--)
{
if (bytes[i] < byte.MaxValue)
{
bytes[i]++;
break;
}
bytes[i] = 0;
}
return bytes;
}
BitConverter.ToInt64 / BitConverter.GetBytes - convert 8 byte to exactly long, and increment it.
When almost done convert back to bytes.
It is the fastest way in system