Rotate a bool array in C++ - c++

EDIT
I found the memcpy definition has told us about its undefined behavior when target and src has overlap:
The memcpy() function copies n bytes from memory area src to memory area dst. If dst and src overlap, behavior is undefined.Applications in which dst and src might overlap should use memmove(3) instead.
Original Question
I have a simple program that looks like this:
static void RotateLeft(bool *In, int len, int loop) {
for(int i = 0;i< 28;i++) {
LOGI("%d -> %d", i, In[i]);
}
bool Tmp[256] = {0};
memcpy(Tmp, In, loop);
memcpy(In, In + loop, len - loop);
LOGI("len = %d, loop = %d", len, loop); // <--- always 28 and 1
for(int i = 0;i< 28;i++) {
LOGI("%d -> %d", i, In[i]); <----- broken
}
memcpy(In + len - loop, Tmp, loop);
}
RotateLeft(`bool array`, 28, 1)
It is weird that this program doesn't work right on the arm64-v8a platform (but works well on other platforms):
The input array is something like this:
0 0 0 1 1 1 1 0 1 0 0 1 0 1 ...
The rotated array should be:
0 0 1 1 1 1 0 1 0 0 1 0 1 0...
But it actually outputs:
0 0 1 1 1 1 0 1 0 0 1 1 0 0 ...
UPDATE
Here's how this program allocate array:
bool K[64], *KL=&K[0], *KR=&K[28];
// do something fill `K`
RotateLeft(KR, 28, 1);

The underlying assumption for this code is that sizeof(bool) is 1. Unfortunately, this is not guaranteed by the C++ standard as explained in this answer. So your code is completely compiler dependent.
Therefore use std::copy() whenever you can instead of memcpy(). Or use std::rotate() as suggested by NathanOlivier in the comments.
By the way, it's unrelated, but you'd better make sure that loop>=0 && loop<256 && len>=loop if you want to avoid undefined behavior.

Related

Shifting elements of a container and filling shifted place with default constructed elements

For example:
c = {"aaa", "aaa"} -> c >> 1 -> c = {"", "aaa"}
I thought I can use std::shift_right but it uses std::move internally and moved from object are left unspecified state:
std::vector<bool> bv(5, true);
std::shift_left(begin(bv), end(bv), 4); // prints 1 1 1 1 1
After some search come up with this but wonder is there a better solution:
std::rotate(begin(bv), begin(bv) + 4, end(bv));
std::fill_n(begin(bv), 4, false); // 0 0 0 0 1
While it is true that std::move() leaves objects in an unspecified state, you can still assign a new value to the element. So the following is perfectly fine.
constexpr size_t N = 4;
std::vector<bool> bv(5, true);
std::shift_right(bv.begin(), bv.end(), N); // prints 1 1 1 1 1 (but the first 4 elements are in an unspecified state).
std::fill_n(bv.begin(), 4, false); // 0 0 0 0 1

gltf, are matrices ever to be transposed?

As I am learning gltf, I already have 2 working skin models, and now I am trying the RiggedFigure.
The 2 other models worked just fine and I am using the same code. I am using the vscode gltf extension to verify my output.
The documentation states:
Accessors of matrix type have data stored in column-major order; start of each column must be aligned to 4-byte boundaries.
Eigen matrices are also column major, thus copying the raw bytes into an stl vector of type Eigen::Matrix4f should result in the correct data, and indeed, this is the case for 2 of the 3 models I have tried so far.
However for the rigged figure, vs code says the matrices should be (excuse the screenshot but I cannot copy paste the matrices for some reason):
My code prints:
0.999983 0.000442018 0.00581419 -0.00398856
0 0.997123 -0.0758045 0.0520021
-0.005831 0.0758032 0.997106 -0.684015
0 0 0 1
1 0 0 0
0 -0.01376 0.999905 -0.85674
0 -0.999905 -0.0137601 0.024791
0 0 0 1
1 0 0 0
0 0.979842 0.199774 -0.224555
0 -0.199774 0.979842 -1.05133
0 0 0 1
1 0 0 0
0 -0.00751853 0.999972 -1.12647
0 -0.999972 -0.00751847 0.00796944
0 0 0 1
-1 -1.50995e-07 0 0
0 0.00364935 0.999993 -1.19299
-1.51869e-07 0.999993 -0.00364941 0.00535393
0 0 0 1
-0.0623881 0.998036 -0.00569177 0.00162297
0.891518 0.0531644 -0.449853 0.404156
-0.448667 -0.0331397 -0.893084 0.998987
0 0 0 1
0.109672 0.988876 -0.100484 0.107683
-0.891521 0.0531632 -0.449849 0.404152
-0.439503 0.13892 0.887434 -0.993169
0 0 0 1
0.530194 0.847874 0.001751 -0.183428
0.760039 -0.474352 -0.444218 0.206564
-0.375811 0.236853 -0.895917 0.973213
0 0 0 1
-0.0705104 -0.619322 0.781965 -0.761146
-0.760038 -0.474352 -0.444223 0.206569
0.646043 -0.625645 -0.437261 0.633599
0 0 0 1
0.631434 0.775418 -0.00419003 -0.228155
0.649284 -0.53166 -0.543845 0.154659
-0.423935 0.340682 -0.839175 0.951451
0 0 0 1
0.111378 -0.773831 0.623523 -0.550204
-0.649284 -0.531661 -0.543845 0.15466
0.752347 -0.344271 -0.561651 0.809067
0 0 0 1
-0.830471 -0.549474 0.091635 -0.00030848
0.0339727 -0.214148 -0.97621 0.596867
0.556025 -0.807601 0.196511 -0.159297
0 0 0 1
-0.994689 0.102198 0.0121981 -0.0750653
-0.0339737 -0.214147 -0.97621 0.596867
-0.0971548 -0.97144 0.216482 -0.140501
0 0 0 1
-0.99973 0.0232223 -7.82996e-05 0.0784336
0.0051282 0.217484 -0.97605 0.357951
-0.0226493 -0.975788 -0.217544 0.0222206
0 0 0 1
-0.998171 -0.0599068 -0.00810355 -0.0775425
-0.00512856 0.217484 -0.97605 0.357951
0.0602345 -0.974224 -0.217393 0.0251548
0 0 0 1
-0.999327 0.0366897 0 0.0783684
0.0287104 0.781987 0.622632 -0.0567413
0.0228442 0.622213 -0.782514 0.0634761
0 0 0 1
-0.999326 0.00828946 0.0357652 -0.0814984
0.0287402 0.782804 0.621604 -0.0521458
-0.0228444 0.622213 -0.782514 0.0634761
0 0 0 1
0.994013 0.109264 0.000418345 -0.0755577
0.109252 -0.993835 -0.0188101 -0.0405796
-0.00164008 0.0187438 -0.999822 0.0227357
0 0 0 1
0.994011 -0.109281 0.000483894 0.0755372
-0.109253 -0.993836 -0.018811 -0.0405797
0.00253636 0.0186453 -0.999823 0.0228038
0 0 0 1
Which are the transposed versions of what vs code says.
My loading code is this (instantiated with typoe Eigen::Matrix4f):
void CopySparseBuffer(
void* dest,
const void* src,
const size_t element_count,
const size_t stride,
const size_t type_size)
{
assert(stride >= type_size);
// Typecast src and dest addresses to (char *)
unsigned char* csrc = (unsigned char*)src;
unsigned char* cdest = (unsigned char*)dest;
// Iterate over the total number of elements to copy
for(int i = 0; i < element_count; i++)
// Copy each byte of the element. Since the stride could be different from the
// type size (in the case of padding bytes for example) the right access
// should skip over any interleaved data, that's why we use the stride.
for(int j = 0; j < type_size; j++)
*(cdest + i * type_size + j) = *(csrc + i * stride + j);
}
template<typename T>
std::vector<T> ExtractDataFromAccessor(
const tinygltf::Model& model, const int accessor_index, bool print = false)
{
const int buffer_view_index = model.accessors[accessor_index].bufferView;
const int array_type = model.accessors[accessor_index].type;
const int component_type = model.accessors[accessor_index].componentType;
const int accessor_offset = model.accessors[accessor_index].byteOffset;
const int element_num = model.accessors[accessor_index].count;
const int buffer_index = model.bufferViews[buffer_view_index].buffer;
const int buffer_length = model.bufferViews[buffer_view_index].byteLength;
const int buffer_offset = model.bufferViews[buffer_view_index].byteOffset;
const int buffer_stride = model.bufferViews[buffer_view_index].byteStride;
const std::vector<unsigned char> data = model.buffers[buffer_index].data;
assert(
component_type == ComponentCode<T>() &&
"The component type found here should match that of the type (e.g. float and "
"float).");
assert(array_type == TypeCode<T>());
// Size in bytes of a single element (e.g. 12 for a vec3 of floats)
const int type_size = sizeof(T);
assert(
buffer_stride == 0 || buffer_stride >= sizeof(T) &&
"It doesn't make sense for a positive buffer "
"stride to be less than the type size");
assert(element_num * type_size <= buffer_length);
const size_t stride = std::max(buffer_stride, type_size);
std::vector<T> holder(element_num);
CopySparseBuffer(
holder.data(),
data.data() + buffer_offset + accessor_offset,
element_num,
stride,
type_size);
return holder;
}
I just figured it out so i will leave this here in case someone is in the same situation in the future.
The VS code vectors are the columns, not the rows, so my code and vs code actually agree, it's just the vs code output is confusing.
In short, evrything works, the output is just confusing.

Ordering an array based on 2D array of relations (higher, lower, doesn't matter)

I have been stuck with this problem for two days and I still can't get it right.
Basically, I have a 2D array with relations between certain numbers (in given range):
0 = the order doesn't matter
1 = the first number (number in left column) should be first
2 = the second number (number in upper row) should be first
So, I have some 2D array, for example this:
0 1 2 3 4 5 6
0 0 0 1 0 0 0 2
1 0 0 2 0 0 0 0
2 2 1 0 0 1 0 0
3 0 0 0 0 0 0 0
4 0 0 2 0 0 0 0
5 0 0 0 0 0 0 0
6 1 0 0 0 0 0 0
And my goal is to create a new array of given numbers (0 - 6) in such a way that it is following the rules from the 2D array (e.g. 0 is before 2 but it is after 6). I probably also have to check if such array exists and then create the array. And get something like this:
6 0 2 1 4 5
My Code
(It doesn't really matter, but I prefer c++)
So far I tried to start with ordered array 0123456 and then swap elements according to the table (but that obviously can't work). I also tried inserting the number in front of the other number according to the table, but it doesn't seem to work either.
// My code example
// I have:
// relArr[n][n] - array of relations
// resArr = {1, 2, ... , n} - result array
for (int i = 0; i < n; i++) {
for (int x = 0; x < n; x++) {
if (relArr[i][x] == 1) {
// Finding indexes of first (i) and second (x) number
int iI = 0;
int iX = 0;
while (resArr[iX] != x)
iX++;
while (resArr[iI] != i)
iI++;
// Placing the (i) before (x) and shifting array
int tmp, insert = iX+1;
if (iX < iI) {
tmp = resArr[iX];
resArr[iX] = resArr[iI];
while (insert < iI+1) {
int tt = resArr[insert];
resArr[insert] = tmp;
tmp = tt;
insert++;
}
}
} else if (relArr[i][x] == 2) {
int iI = 0;
int iX = 0;
while (resArr[iX] != x)
iX++;
while (resArr[iI] != i)
iI++;
int tmp, insert = iX-1;
if (iX > iI) {
tmp = resArr[iX];
resArr[iX] = resArr[iI];
while (insert > iI-1) {
int tt = resArr[insert];
resArr[insert] = tmp;
tmp = tt;
insert--;
}
}
}
}
}
I probably miss correct way how to check whether or not it is possible to create the array. Feel free to use vectors if you prefer them.
Thanks in advance for your help.
You seem to be re-ordering the output at the same time as you're reading the input. I think you should parse the input into a set of rules, process the rules a bit, then re-order the output at the end.
What are the constraints of the problem? If the input says that 0 goes before 1:
| 0 1
--+----
0 | 1
1 |
does it also guarantee that it will say that 1 comes after 0?
| 0 1
--+----
0 |
1 | 2
If so you can forget about the 2s and look only at the 1s:
| 0 1 2 3 4 5 6
--+--------------
0 | 1
1 |
2 | 1 1
3 |
4 |
5 |
6 | 1
From reading the input I would store a list of rules. I'd use std::vector<std::pair<int,int>> for this. It has the nice feature that yourPair.first comes before yourPair.second :)
0 before 2
2 before 1
2 before 4
6 before 0
You can discard any rules where the second value is never the first value of a different rule.
0 before 2
6 before 0
This list would then need to be sorted so that "... before x" and "x before ..." are guaranteed to be in that order.
6 before 0
0 before 2
Then move 6, 0, and 2 to the front of the list 0123456, giving you 6021345.
Does that help?
Thanks for the suggestion.
As suggested, only ones 1 are important in 2D array. I used them to create vector of directed edges and then I implemented Topological Sort. I decide to use this Topological Sorting Algorithm. It is basically Topological Sort, but it also checks for the cycle.
This successfully solved my problem.

The size of structure (sizeof) in C++ doesn't correspond the real size in case of arrays

I use dynamic arrays of the following structure:
struct TestStructure
{
unsigned int serial;
int channel;
int pedestal;
int noise;
int test;
};
The sizeof(TestStructure) returns 20, so I assume that there is no padding/alignment in the structure. It's logically because there are only 4-bytes types.
But I discovered that size of structure multiplied by element count is not equal the size of the array. There is an additional pad between elements of the array! So, in the following code:
TestStructure* test_struct = new TestStructure[element_count];
for (int i = 0; i < element_count; i++)
FillStructure(test_struct, i, i, i, i, i, i); // assigning 'i' for all elements
Long_t size_value = element_count * sizeof(TestStructure);
unsigned char* p_value = new unsigned char[size_value];
memcpy(p_value, test_struct, size_value);
The output array of chars contains the additional pads between elements:
sizeof(TestStructure) = 20. element_count = 10. size_value = 200. char array in the hex format:
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
6c 6c 2f 6c
1 0 0 0
1 0 0 0
1 0 0 0
1 0 0 0
1 0 0 0
6f 70 74 2f
2 0 0 0
...
Please, explain me.
Does dynamic array add pads between elements or
Does 'sizeof' operator show wrong size of the structure?
P.S. I use GCC 5.4.0 (Ubuntu 5.4.0-6ubuntu1~16.04.2).
EDIT: I use this code in a macro with ROOT CINT interpreter with GCC compiled library. Sorrry, It seems this bug concerned not with GCC but with ROOT CINT.
EDIT2: Yes, in my ROOT macro (executed by CINT interpreter) sizeof(TestStructure) returns 24 and after that when I call a function of the GCC compiled library (containing the code fragment listed above), the sizeof(TestStructure) returns 20 in the compiled function.
Although a compiler can add packing to the end of a struct, a compiler absolutely cannot add additional packing between the elements when manufacturing an array.
For an array TestStructure[n], the address of the i(th) element must be TestStructure + i * sizeof TestStructure. If this were not true then pointer arithmetic would break horribly.

conway game error with 2d array manipulation

So I'm working on the life game, and so far I have come up with this http://ideone.com/QG4tsS I'm not sure exactly if I am on the right track or not. Basically I have a function putting out random values to try and test my code. But nothing seems to happen. I suspect my problem lies with the following code
int sum = 0;
for (int k = (i - 1); k <= (i + 1); k++) {
for (int l = (j - 1); l <= (j + 1); l++) {
sum += currentGen[k][l];
}
}
return sum;
So my result gives me a 2d array with all 0's but shouldn't I start to see some changes and patterns starting to form? I get one 1 and the rest are 0.
Output
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 1
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
I provide this answer based on the code you posted at http://ideone.com/QG4tsS . You really should consider adding that code to your original question, so that future folks who find this on StackOverflow have the full context.
Your RandomCells function only sets cells to 1 if they meet the RANDOM threshold. It doesn't clear them to 0 otherwise. Once you fix that, you'll be all set. ie.
void RandomCells(int currentGen[][CELLY]) {
for (int i = 0; i < CELLX; i++) {
for (int j = 0; j < CELLY; j++) {
if (rand() % 100 + 1 < RANDOM) {
currentGen[i][j] = 1;
} else
{
currentGen[i][j] = 0;
}
}
}
}
Without that else clause, I was seeing initial generations that looked like this:
0 0 4196155 1
1813657216 1 4197653 0
-870503576 1 4197584 1
Clearly, most of those cells were non-zero, and so Conway's Life algorithm would map them to 0 in the next generation because of "crowding".
The reason currentGen was filled with such 'random' values is that it was allocated as an automatic variable to main. Automatic variables do not get initialized to any particular value. You need to initialize them yourself. You can do that by modifying your algorithm (as I did above), or by adding an explicit bit of code to initialize the structure.
This differs from file-scope variables, which C and C++ define as initialized-to-zero on program start if they don't have initializers or default constructors. (Pedants will point out that even that has caveats.)
Once you make the required fixes, to truly see Conway's Life, you'll need to set CELLX and CELLY to larger values...