It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 12 years ago.
I am trying to adapt a digital electronics problem to a C++ STL based program.
Originally I have 4 inputs C1, C2, C3, C4. This means I have a total of 16 combinations:
0000
0001
.
.
.
1111
I have a multimap defined by
typedef std::pair<int, int> au_pair; //vertices
typedef std::pair<int, int> acq_pair; //ch qlty
typedef std::multimap<int, acq_pair> au_map;
typedef au_map::iterator It_au;
The no. of simulations depend on the size of the au_map.
For eg: if the au_map.size() = 5 I will have C1, C2, C3, C4, C5. and therefore 2^5 = 32 cases.
For example:
If theau_map.size()=4, I need to simulate my algorithm for 16 cases.
for(It_au it = a_map.begin(); it != a_map.end(); it++)
{
acq_pair it1 = it->second;
//case 0:
//C3 = 0, C2 = 0, C1 = 0, C0 = 0
//Update it1.second with corresponding C values
//simulate algorithm
//case 1:
//C3 = 0, C2 = 0, C1 = 0, C0 = 1
//simulate
.........
//case 15:
//C3 = 1, C2 = 1, C1 = 1, C0 = 1
//simulate
}
Not the best idea. Right now you're doing a lot of useless work by manually setting your C1-C4 and by writing some simulation routines right in your for loop.
Automate it.
Use some abstract State-Simulator mapper (where Simulator actually stands for some concrete functional object).
typedef char State;
struct basic_simulator {
// You could also pass some other parameters to your
// simulator
virtual void operator()(...) = 0
};
struct concrete_simulator : public basic_simulator {
virtual void operator()(...) {
// Do something concrete
// Trolololo
}
};
typedef basic_simulator Simulator;
And in this case your actual wrapper would look like std::map<State, Simulator*> map;
What you need to do next do means getting C1-C4 values from your state which is defined as char. Use bitwise operators.
All your states could be defined as 0-15 numbers converted to binary (2 -> 0010). So to get C1-C4 values you would simply have to make appropriate shifts:
// C1 C2 C3 C4
// -----------
// 1 1 1 1
State state = 15;
for (int i = 3; i >= 0; i--) {
// State of some of the inputs, defined by one bit
InputState C_xx = ((state >> i) & 1);
}
Now simply map all those 0-15 states to appropriate simulating functor:
std::map<State, Simulator*> mapper;
// Generally speaking, you should use some sort of
// smart pointer here
mapper[0] = new concrete_simulator(...);
mapper[1] = ...
What is really cool that you could have only, let's say, 3 or four concrete simulators which would be mapped to some states accordingly.
In this case invoking actual simulation would mean something like:
// Fire appropriate simulation object
(*(mapper[actual_state]))(...);
and making every possible simulation means iterating over every map element.
Update: the same technique could be used for states where you have more than 4 inputs / single input state can have more than two possible values.
Just write an appropriate mapping function and state generator.
Hum... why not letting a for loop enumerate the various combinations for you ?
for (size_t i = 0; i != 16; ++i)
{
bool const c1 = i & 1;
bool const c2 = i & 2;
bool const c3 = i & 4;
bool const c4 = i & 8;
// your algorithm
}
A bit easier than setting them by hand.
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 days ago.
Improve this question
While studying enums, I have seen some people use them in combination with bit shifting. Being a beginner and unsure of correct usage, I would appreciate advice.
So here are 2 examples.
#define BIT(x) (1<<x)
enum WithBits{`
first = BIT(0), //first = 1
second = BIT(1), // second = 2
third = BIT(2) //third = 4 }
BIT(x) is defined where each of enum members has value of 1 shifted x times to the left. For example x of member third is 2. 1 is shifted 2 times so third is connected with value 4. In the end, values of first , second and third are 1, 2 and 4 respectively.
Now we could also do this.
enum WithoutBits{`
first = 1, // first = 1
second = 2, // second = 2
third = 4 // third = 4 }
In this case, first, second and third are also 1, 2 and 4.
Both examples work fine.
What exactly is the difference? Why and when should I use first enum example (WithBits) instead of second example (WithoutBits)?
Thanks you for your time, any help is welcome!
There is no reason to use macros like that. You can either directly write the bit shifts:
enum MyEnum : uint16_t {
first = 1 << 0,
second = 1 << 1,
...
Or as hex, which is clearer than decimal when the values get larger:
enum MyEnum : uint16_t {
first = 0x1,
second = 0x2,
...
You probably should specify the size of the enum explicitly when you're making bitmasks, so I've added that above.
The two pieces of code create exactly the same structure, which can be used in exactly the same way. The BIT macro, or spelling out 1 << 2 instead of 4, is just an aid to humans reading the code, to signal the intention of the code. Whether it does a good job of signalling that intention is a matter of opinion.
The actual ability to use it in a "bitmask" (what you probably meant by "bitfield") doesn't come from how you write the values, but quite simply from choosing values that each have one bit set, so that you can use boolean logic to create and test different combinations.
Another approach is to use a metafunction to generate these masks.
template<typename T, unsigned int BIT>
struct bit_mask
{
static_assert(std::is_integral<T>());
static constexpr T value = T{1} << BIT;
}
You could then use this metafunction:
static_assert(bit_mask<uint8_t, 2>::value == 4); // 0b00000100
static_assert(bit_mask<uint16_t, 8>::value == 256); // 0b00000001 00000000
auto floatBitmask = bit_mask<float, 3>::value; // Won't compile
This approach could also be extended to allow you to set multiple bits in the integer, by providing a parameter pack of unsigned ints and recursively ORing the bit shift produced by each parameter provided in the pack:
template<typename T, unsigned int... BIT>
struct bit_mask
{
static_assert(std::is_integral<T>());
static constexpr T value = 0;
};
template<typename T, unsigned int BIT, unsigned int... BITS>
struct bit_mask<T, BIT, BITS...>
{
static_assert(std::is_integral<T>());
static constexpr T value = (T{1} << BIT) | bit_mask<T, BITS...>::value;
};
template<typename T, unsigned int BIT_A, unsigned int BIT_B>
struct bit_mask<T, BIT_A, BIT_B>
{
static_assert(std::is_integral<T>());
static constexpr T value = (T{1} << BIT_A) | (T{1} << BIT_B);
};
This can then be used:
static_assert(bit_mask<uint16_t, 2>::value == 4); // 0b00000000 00000100
static_assert(bit_mask<uint16_t, 8>::value == 256); // 0b00000001 00000000
static_assert(bit_mask<uint16_t, 2, 8>::value == 260); // 0b00000001 00000100
static_assert(bit_mask<uint8_t, 0, 1, 2, 3, 4, 5, 6, 7>::value == 255); // 0b11111111
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 months ago.
Improve this question
I have tried to come up with a solution to the n-queen problem, through backtracking. I have created a board, and I think I have created functions which checks whether a piece can be placed at position column2 or not, in comparison to a piece at position column1. And I guess I somehow want to loop through the columns, to check if the current piece is in a forbidden position to any of the power pieces already placed at the first row through the current minus one. I haven't done this yet, but I'm just confused at the moment, so I can't really see how I should do it.
Let me share the code I have written so far
// Method for creating chessboard
vector<vector<vector<int>>> create_chessboard(int size_of_board)
{
vector<int> v1;
vector<vector<int>> v2;
vector<vector<vector<int>>> v3;
for (int i = 0; i < size_of_board; i++)
{
for (int j = 0; j < size_of_board; j++)
{
v1.clear();
v1.push_back(i);
v1.push_back(j);
v2.push_back(v1);
}
v3.push_back(v2);
v2.clear();
}
return v3;
}
// Method for visualizing chessboard
void visualize_board(vector<vector<vector<int>>> chess, int dimension_of_board)
{
int i = 1;
for (vector<vector<int>> rows : chess)
{
for (int j = 0; j < dimension_of_board; j++)
{
cout << "(" << rows[j][0] << "," << rows[j][1] << ")" << " ";
}
cout << endl;
}
}
// Method for checking if two coordinates are on the same diagonal
bool check_diagonal(vector<int> coordinate1, vector<int> coordinate2)
{
if(abs(coordinate1[1] - coordinate2[1]) == abs(coordinate1[0] - coordinate2[0]))
{
return true;
}
return false;
}
bool check_column(vector<int> coordinate1, vector<int> coordinate2)
{
if(coordinate1[1] == coordinate2[1])
{
return true;
}
return false;
}
bool check_row(vector<int> coordinate1, vector<int> coordinate2)
{
if (coordinate1[0] == coordinate2[0])
{
return true;
}
return false;
}
bool check_allowed_positions(vector<int> coordinate1, vector<int> coordinate2, int column)
{
if (check_diagonal(coordinate1, coordinate2))
{
return false;
}
if (check_column(coordinate1, coordinate2))
{
return false;
}
if (check_row(coordinate1, coordinate2))
{
return false;
}
return true;
}
vector<vector<int>> solve_nqueen(vector<vector<vector<int>>> board, int dimension_of_board, int row)
{
vector<int> first_element = board[0][0];
vector<vector<int>> solution_space;
if (dimension_of_board == row)
{
cout << "we found a solution!";
}
/*
if (dimension_of_board == row)
{
}
for (int j = 0; j < dimension_of_board; j++)
{
if (check_allowed_positions(board, row, j))
{
do something here
solve_nqueen(board, dimension_of_board, row+1);
}
else
{
do something here;
}
}
return;
*/
return solution_space;
}
I would be really happy if someone could just lay up a few steps I have to take in order to build the solve_nqueen function, and maybe some remarks on how I could do that. If I should complement with some further information, just let me know! I'm happy to elaborate.
I hope this isn't a stupid question, but I have been trying to search the internet for a solution. But I didn't manage to use what I found.
Best wishes,
Joel
There is not always a solution, like e.g. not for 2 queens on 2x2 board, or for 3 queens on a 3x3 board.
This is a well-known problem (which can also be found in the internet). According to this, there is not a simple rule or structure, how you can find a solution. In fact, you could reduce the problem by symmetries, but that is not that simple, too.
Well according to this, you have to loop through all (n out of n x n) solutions, and do all tests for every queen. (In fact, reduce it to half again, by only checking a certain pair of queens, once only - but again that is not much, and such reduction takes some time, too).
Note: Your check routines are correct.
For 8 queens on a 8x8 board, write 8 nested loops from i(x)=0 to 63
(row is i(x)%8 and column is i(x)/8). You also need to check then, if a queen does not sit on queen, but your check routines will already find that. Within second nested loop, you can already check if the first two queens are okay, or otherwise, you do not have to go any deeper, but can already increment the value of first nested loop (move the second queen on a new position).
Also it would be nice, I propose not to write the search for a n-problem, but for a n=8 problem or n=7 problem. (That is easier for the beginning.).
Speed-Ups:
While going deeper into the nested loops, you might hold a quick
record (array) of positions which already did not work for upper
loops (still 64 records to check, but could be written to be faster than doing your check routines again).
Or even better, do the inner loops only through a list from remaining candidates, much less than (n x n) positions.
There should be some more options for speed-ups, which you might find.
Final proposal: do not only wait for the full result to come, but also track, when e.g. you find a valid position of 5 queens, then of 6 queens and so on - which will be more fun then (instead of waiting ages with nothing happening).
A further idea is not to loop, e.g. from 0 to 63 for each queen, but "randomly". Which also might lead to more surprising. For this, mix an array 0 .. 63 to a random order. Then, still do the loop from 0 to 63 but this is just the index to the random vector. Al right? Anyway, it would even be more interesting to create 8 random vectors, for each queen one random vector. If you run this program then, anything could happen ... the first few trials could (theoretically) already deliver a successful result.
If you would like to become super efficient, please note that the queen state on the 8x8 board can be stored in one 64-bit-integer variable (64 times '0' or '1' where '1' means here is queen. Keyword: bitboards). But I didn't mention this in the beginning, because the approach which you started is quite different.
And from that on, you could create 64 bit masks for each queen position, to each position to which a queen can go. Then you only need to do 1 "bitwise AND" operation of two (properly defined) 64-bit variables, like a & b, which replaces your (diagonal-, column-, row-) check routines by only one operation and thus is much faster.
Avoid too many function calls, or use inline.
... an endless list of possible dramatic speed-ups: compiler options, parallelization, better algorithms, avoid cache misses (work on a possibly low amount of memory or access memory in a regular way), ... as usual ...
My best answer, e.g. for 8-queen problem:
queen is between 0 .. 7
queen is between 8 .. 15
queen is between 16 .. 23
queen is between 24 .. 31
queen is between 32 .. 39
queen is between 40 .. 47
queen is between 48 .. 55
queen is between 56 .. 63
because all 8 queens have to be on different rows!
These are the limits of the nested loops then, which gives "only"
8 * 8 * 8 * 8 * 8 * 8 * 8 * 8 = 16777216
possibilities to be checked. This can be quick on modern machines.
Then probably you don't need anything more sophisticated (to which my first answer refers - for the 8x8 queens problem.) Anyway, you could still also keep a record of which column is still free, while diving into the nested loops, which yields a further dramatic cut down of checks.
I wrote some C code (similar to C++) to verify my answer. In fact, it is very fast, much less than a second (real 0m0,004s; user 0m0,003s; sys 0m0,001s). The code finds the correct number of 92 solutions for the 8x8 queens problem.
#include <stdio.h>
int f(int a, int b)
{
int r1, c1, r2, c2, d1, d2;
int flag = 1;
r1 = a / 8;
r2 = b / 8;
c1 = a % 8;
c2 = b % 8;
d1 = r1 - r2;
d2 = c1 - c2;
if( d1 == d2 || d1 == -d2 || c1 == c2 ) flag=0;
return flag;
}
int main()
{
int p0,p1, p2, p3, p4, p5, p6, p7;
int solutions=0;
for(p0=0; p0<8; p0++)
{
for(p1=8; p1<16; p1++)
{
if( f(p0,p1) )
for(p2=16; p2<24; p2++)
{
if( f(p0,p2) && f(p1,p2) )
for(p3=24; p3<32; p3++)
{
if( f(p0,p3) && f(p1,p3) && f(p2,p3) )
for(p4=32; p4<40; p4++)
{
if( f(p0,p4) && f(p1,p4) && f(p2,p4) && f(p3,p4))
for(p5=40; p5<48; p5++)
{
if( f(p0,p5) && f(p1,p5) && f(p2,p5) && f(p3,p5) && f(p4,p5) )
for(p6=48; p6<56; p6++)
{
if( f(p0,p6) && f(p1,p6) && f(p2,p6) && f(p3,p6) && f(p4,p6) && f(p5,p6))
for(p7=56; p7<64; p7++)
{
if( f(p0,p7) && f(p1,p7) && f(p2,p7) && f(p3,p7) && f(p4,p7) && f(p5,p7) && f(p6,p7))
{
solutions++;
// 0 .. 63 integer print
printf("%2i %2i %2i %2i %2i %2i %2i %2i\n",
p0,p1,p2,p3,p4,p5,p6,p7);
// a1 .. h8 chess notation print
//printf("%c%d %c%d %c%d %c%d %c%d %c%d %c%d %c%d\n",
//p0%8+'a', p0/8+1, p1%8+'a', p1/8+1, p2%8+'a', p2/8+1, p3%8+'a', p3/8+1,
//p4%8+'a', p4/8+1, p5%8+'a', p5/8+1, p6%8+'a', p6/8+1, p7%8+'a', p7/8+1);
}
}
}
}
}
}
}
}
}
printf("%i solutions have been found\n",solutions);
return 1;
}
Notes: Subroutine f checks if two queen positions are "ok" with each other (1 means true, 0 means false, in C). An inner loop is only entered, if all already selected positions (in outer loops) are "ok" with each other.
I got the js code below from an archive of hackers delight (view the source)
The code takes in a value (such as 7) and spits out a magic number to multiply with. Then you bitshift to get the results. I don't remember assembly or any math so I'm sure I'm wrong but I can't find the reason why I'm wrong
From my understanding you could get a magic number by writing ceil(1/divide * 1<<32) (or <<64 for 64bit values, but you'd need bigger ints). If you multiple an integer with imul you'd get the result in one register and the remainder in another. The result register is magically the correct result of a division with this magic number from my formula
I wrote some C++ code to show what I mean. However I only tested with the values below. It seems correct. The JS code has a loop and more and I was wondering, why? Am I missing something? What values can I use to get an incorrect result that the JS code would get correctly? I'm not very good at math so I didn't understand any of the comments
#include <cstdio>
#include <cassert>
int main(int argc, char *argv[])
{
auto test_divisor = 7;
auto test_value = 43;
auto a = test_value*test_divisor;
auto b = a-1; //One less test
auto magic = (1ULL<<32)/test_divisor;
if (((1ULL<<32)%test_divisor) != 0) {
magic++; //Round up
}
auto answer1 = (a*magic) >> 32;
auto answer2 = (b*magic) >> 32;
assert(answer1 == test_value);
assert(answer2 == test_value-1);
printf("%lld %lld\n", answer1, answer2);
}
JS code from hackers delight
var two31 = 0x80000000
var two32 = 0x100000000
function magic_signed(d) { with(Math) {
if (d >= two31) d = d - two32// Treat large positive as short for negative.
var ad = abs(d)
var t = two31 + (d >>> 31)
var anc = t - 1 - t%ad // Absolute value of nc.
var p = 31 // Init p.
var q1 = floor(two31/anc) // Init q1 = 2**p/|nc|.
var r1 = two31 - q1*anc // Init r1 = rem(2**p, |nc|).
var q2 = floor(two31/ad) // Init q2 = 2**p/|d|.
var r2 = two31 - q2*ad // Init r2 = rem(2**p, |d|).
do {
p = p + 1;
q1 = 2*q1; // Update q1 = 2**p/|nc|.
r1 = 2*r1; // Update r1 = rem(2**p, |nc|.
if (r1 >= anc) { // (Must be an unsigned
q1 = q1 + 1; // comparison here).
r1 = r1 - anc;}
q2 = 2*q2; // Update q2 = 2**p/|d|.
r2 = 2*r2; // Update r2 = rem(2**p, |d|.
if (r2 >= ad) { // (Must be an unsigned
q2 = q2 + 1; // comparison here).
r2 = r2 - ad;}
var delta = ad - r2;
} while (q1 < delta || (q1 == delta && r1 == 0))
var mag = q2 + 1
if (d < 0) mag = two32 - mag // Magic number and
shift = p - 32 // shift amount to return.
return mag
}}
In the C CODE:
auto magic = (1ULL<<32)/test_divisor;
We get Integer Value in magic because both (1ULL<<32) & test_divisor are Integers.
The Algorithms requires incrementing magic on certain conditions, which is the next conditional statement.
Now, multiplication also gives Integers:
auto answer1 = (a*magic) >> 32;
auto answer2 = (b*magic) >> 32;
C CODE is DONE !
In the JS CODE:
All Variables are var ; no Data types !
No Integer Division ; No Integer Multiplication !
Bitwise Operations are not easy and not suitable to use in this Algorithm.
Numeric Data is via Number & BigInt which are not like "C Int" or "C Unsigned Long Long".
Hence the Algorithm is using loops to Iteratively add and compare whether "Division & Multiplication" has occurred to within the nearest Integer.
Both versions try to Implement the same Algorithm ; Both "should" give same answer, but JS Version is "buggy" & non-standard.
While there are many Issues with the JS version, I will highlight only 3:
(1) In the loop, while trying to get the best Power of 2, we have these two statements :
p = p + 1;
q1 = 2*q1; // Update q1 = 2**p/|nc|.
It is basically incrementing a counter & multiplying a number by 2, which is a left shift in C++.
The C++ version will not require this rigmarole.
(2) The while Condition has 2 Equality comparisons on RHS of || :
while (q1 < delta || (q1 == delta && r1 == 0))
But both these will be false in floating Point Calculations [[ eg check "Math.sqrt(2)*Math.sqrt(0.5) == 1" : even though this must be true, it will almost always be false ]] hence the while Condition is basically the LHS of || , because RHS will always be false.
(3) The JS version returns only one variable mag but user is supposed to get (& use) even variable shift which is given by global variable access. Inconsistent & BAD !
Comparing , we see that the C Version is more Standard, but Point is to not use auto but use int64_t with known number of bits.
First I think ceil(1/divide * 1<<32) can, depending on the divide, have cases where the result is off by one. So you don't need a loop but sometimes you need a corrective factor.
Secondly the JS code seems to allow for other shifts than 32: shift = p - 32 // shift amount to return. But then it never returns that. So not sure what is going on there.
Why not implement the JS code in C++ as well and then run a loop over all int32_t and see if they give the same result? That shouldn't take too long.
And when you find a d where they differ you can then test a / d for all int32_t a using both magic numbers and compare a / d, a * m_ceil and a * m_js.
I am currently working on a program that will take a English description of a language and then use the description to create a DFA for those specs. I allow certain operations, example {w | w has the sub string 01 in the beginning} and other options such as even odd sub string, more less or exactly than k sub string, etc. The user also chooses the alphabet.
My question is how would i know how many states I will need? since the user gives me my alphabet and rules I don't know anything until run time. I have created DFA's/transition tables before, but in those cases I knew what my DFA was and could declare it in a class or have it static. Should I be using the 5 tupil (Q, ∑, δ, q0, F)? or taking a different approach? Any help wrapping my head around the problem is appreciated.
My question is how would i know how many states I will need?
You won't.
You can represent the transition function as std::unordered_map of pairs of (q, σ) ∈ (Q, Σ) to q ∈ Q
using state = int;
using symbol = char;
using tranFn = std::unordered_map<std::pair<state, symbol>, state>;
// sets up transition function, the values can be read at runtime
tranFn fn;
fn[{0, 'a'}] = 1;
fn[{0, 'b'}] = 2;
fn[{1, 'a'}] = 1;
fn[{1, 'b'}] = 0;
fn[{2, 'a'}] = 2;
fn[{2, 'b'}] = 2;
// run the dfa
state s = 0;
symbol sym;
while(std::cin >> sym)
s = fn[{s, sym}];
std::cout << s;
btw, if 1 is the accepting state in the dfa above, it accepts exactly a(a + ba)*
We have this example:
struct X {
int e0 : 6;
int e1 : 6;
int e2 : 6;
...
int e10 : 6;
};
struct X c;
How can I access the members "automatically", something like that:
c.e{0-10} ?
Say if I want to read c.e0, then c.e1 ...
If my struct would have 1000 elements, I do not think that I should write so much code, right ?
Can you help me with a workaround, an idea ?
I mention that I already read other posts related somehow to this problem, but I did not find a solution.
Thank you very much !
As others have said, you cannot do exactly what you want with bit fields. It looks like you want to store a large number of 6 bit integers with maximum space efficiency. I will not argue whether this is a good idea or not. Instead I will present an old-school C like way of doing exactly that, using C++ features for encapsulation (untested). The idea is that 4 6 bit integers require 24 bits, or 3 characters.
// In each group of 3 chars store 4 6 bit ints
const int nbr_elements = 1000;
struct X
{
// 1,2,3 or 4 elements require 3 chars, 5,6,7,8 require 6 chars etc.
char[ 3*((nbr_elements-1)/4) + 3 ] storage;
int get( int idx );
};
int X::get( int idx )
{
int dat;
int offset = 3*(idx/4); // eg idx=0,1,2,3 -> 0 idx=4,5,6,7 -> 3 etc.
char a = storage[offset++];
char b = storage[offset++];
char c = storage[offset];
switch( idx%4) // bits lie like this; 00000011:11112222:22333333
{
case 0: dat = (a>>2)&0x3f; break;
case 1: dat = ((a<<4)&0x30) + ((b>>4)&0x0f); break;
case 2: dat = ((b<<2)&0x3c) + ((c>>6)&0x03); break;
case 3: dat = c&0x3f; break;
}
return dat;
}
I will leave the companion put() function as an exercise.
It sounds like a struct isn't the right tool for what you're trying to do. You need either an array or a vector. Arrays are used for storing a number of the same type of data. Vectors are array wrappers that manage the addition and removal of items automatically.
If you need a list of the same data, and some other data (say a string) you can make an array or a vector part of your struct.
struct X {
int[10] numbs;
string name;
};
X c;
You can't. To do this would require some form of reflection, which is not supported in either C or C++.
Since your bitfields are of the same size, you could encapsulate std::bitset (or vector<bool>, gulp...) and provide your own iterators (each increment moving the bookmark six bits) and operator[] (etc) to allow your code to be more simple to write.
I am sure performance would suck compared to the bitfields though.
How about something like this:
char getByte(char *startPos, int index) {
int i = (index*6) / 8;
if (index % 4 == 0)
return 0b11111100 & startPos[i] >> 2;
else if (index % 4 == 3)
return 0b00111111 & startPos[i];
else if (index % 4 == 2)
return (0b00001111 & startPos[i] << 2) | (0b11000000 & startPos[i+1] >> 6);
else
return (0b00000011 & startPos[i] << 4) | (0b11110000 & startPos[i+1] >> 4);
}