Reverse channel values from 1D array - c++

I have a 1D array float64 arr[60] being used to store voltage values from a DAQ. The array is populated as such:
10 SAMPLES_PER_CHANNEL, 6 CHANNELS, grouped by channel
transducer_0 transducer_1 ... transducer_6
[0, 1 ..., 9, 10, 11 ..., 19 ... 50, 51 ..., 59]
I would like to store this data into a 1D array of pointers and to pass to a function whose definition is: bool func2(int samples, double* const* arr2)
I have asked a similar question in this post to which the accepted solution given by #Yakk was:
template<size_t stride, class T, size_t N, size_t count = N/stride>
std::array<T*, count> make_2d( T(&raw)[N] ) {
std::array<T*, count> retval;
for (size_t i = 0; i < count; ++i)
retval[i] = raw + i*stride;
return retval;
}
I am looking for help to generate the argument double* const* arr2 for func2() which is the reverse order of the values stored in the channels. E.g.
[channel 0] [channel 1] [channel 5]
{val 9, val 8 ...val 0}, {val 19, val 18 ...val 10}, ...
The input can either be the initial 1D array, or the 1D array of pointers as constructed through the templated make_2d() function. I'm wondering what the most efficient means to do this is as the array is being updated at a rate of 5000Hz. I'm hoping there is a way which I won't have to copy values from the input array, though I am more interested in time efficiency then space efficiency.
Currently I am creating a second array of pointers and copying the reverse channel values in.
// DOF == 6, SAMPLES_PER_CHANNEL = 10
double ch0[SAMPLES_PER_CHANNEL];
double ch1[SAMPLES_PER_CHANNEL];
double ch2[SAMPLES_PER_CHANNEL];
double ch3[SAMPLES_PER_CHANNEL];
double ch4[SAMPLES_PER_CHANNEL];
double ch5[SAMPLES_PER_CHANNEL];
double* data_rev[DOF] = {
ch0, ch1, ch2, ch3, ch4, ch5};
// generate reversed order array
for (int i = DOF - 1; i > 0; --i) {
for (int j = SAMPLES_PER_CHANNEL - 1; j > 0; --j) {
data_rev[DOF - 1 - i][SAMPLES_PER_CHANNEL - 1 - j] = static_cast<double>(data[(i*10)+j]);
}
}

If I understand you correctly, what you want is not possible:
You cannot pass an array of pointers to func2 that makes it appear as if the samples would be in reversed order (I assume, you can't modify func2), but as long as you are not working on a very low power machine, something like this is dirt cheap (both in time and space overhead):
double arr[60];
std::array<double,60> tmp;
int main() {
auto t = make_2d<10>(tmp);
std::reverse(t.begin(), t.end());
while (true) {
readData(arr, 60);
reverse_copy(begin(arr),end(arr), begin(tmp));
func2(60, t.data());
}
}

Related

Construct mirror vector around the centre element in c++

I have a for-loop that is constructing a vector with 101 elements, using (let's call it equation 1) for the first half of the vector, with the centre element using equation 2, and the latter half being a mirror of the first half.
Like so,
double fc = 0.25
const double PI = 3.1415926
// initialise vectors
int M = 50;
int N = 101;
std::vector<double> fltr;
fltr.resize(N);
std::vector<int> mArr;
mArr.resize(N);
// Creating vector mArr of 101 elements, going from -50 to +50
int count;
for(count = 0; count < N; count++)
mArr[count] = count - M;
// using these elements, enter in to equations to form vector 'fltr'
int n;
for(n = 0; n < M+1; n++)
// for elements 0 to 50 --> use equation 1
fltr[n] = (sin((fc*mArr[n])-M))/((mArr[n]-M)*PI);
// for element 51 --> use equation 2
fltr[M] = fc/PI;
This part of the code works fine and does what I expect, but for elements 52 to 101, I would like to mirror around element 51 (the output value using equation)
For a basic example;
1 2 3 4 5 6 0.2 6 5 4 3 2 1
This is what I have so far, but it just outputs 0's as the elements:
for(n = N; n > M; n--){
for(i = 0; n < M+1; i++)
fltr[n] = fltr[i];
}
I feel like there is an easier way to mirror part of a vector but I'm not sure how.
I would expect the values to plot like this:
After you have inserted the middle element, you can get a reverse iterator to the mid point and copy that range back into the vector through std::back_inserter. The vector is named vec in the example.
auto rbeg = vec.rbegin(), rend = vec.rend();
++rbeg;
copy(rbeg, rend, back_inserter(vec));
Lets look at your code:
for(n = N; n > M; n--)
for(i = 0; n < M+1; i++)
fltr[n] = fltr[i];
And lets make things shorter, N = 5, M = 3,
array is 1 2 3 0 0 and should become 1 2 3 2 1
We start your first outer loop with n = 3, pointing us to the first zero. Then, in the inner loop, we set i to 0 and call fltr[3] = fltr[0], leaving us with the array as
1 2 3 1 0
We could now continue, but it should be obvious that this first assignment was useless.
With this I want to give you a simple way how to go through your code and see what it actually does. You clearly had something different in mind. What should be clear is that we do need to assign every part of the second half once.
What your code does is for each value of n to change the value of fltr[n] M times, ending with setting it to fltr[M] in any case, regardless of what value n has. The result should be that all values in the second half of the array are now the same as the center, in my example it ends with
1 2 3 3 3
Note that there is also a direct error: starting with n = N and then accessing fltr[n]. N is out of bounds for an arry of size N.
To give you a very simple working solution:
for(int i=0; i<M; i++)
{
fltr[N-i-1] = fltr[i];
}
N-i-1 is the mirrored address of i (i = 0 -> N-i-1 = 101-0-1 = 100, last valid address in an array with 101 entries).
Now, I saw several guys answering with a more elaborate code, but I thought that as a beginner, it might be beneficial for you to do this in a very simple manner.
Other than that, as #Pzc already said in the comments, you could do this assignment in the loop where the data is generated.
Another thing, with your code
for(n = 0; n < M+1; n++)
// for elements 0 to 50 --> use equation 1
fltr[n] = (sin((fc*mArr[n])-M))/((mArr[n]-M)*PI);
// for element 51 --> use equation 2
fltr[M] = fc/PI;
I have two issues:
First, the indentation makes it look like fltr[M]=.. would be in the loop. Don't do that, not even if this should have been a mistake when you wrote the question and is not like this in the code. This will lead to errors in the future. Indentation is important. Using the auto-indentation of your IDE is an easy way to go. And try to use brackets, even if it is only one command.
Second, n < M+1 as a condition includes the center. The center is located at adress 50, and 50 < 50+1. You haven't seen any problem as after the loop you overwrite it, but in a different situation, this can easily produce errors.
There are other small things I'd change, and I recommend that, when your code works, you post it on CodeReview.
Let's use std::iota, std::transform, and std::copy instead of raw loops:
const double fc = 0.25;
constexpr double PI = 3.1415926;
const std::size_t M = 50;
const std::size_t N = 2 * M + 1;
std::vector<double> mArr(M);
std::iota(mArr.rbegin(), mArr.rend(), 1.); // = [M, M - 1, ..., 1]
const auto fn = [=](double m) { return std::sin((fc * m) + M) / ((m + M) * PI); };
std::vector<double> fltr(N);
std::transform(mArr.begin(), mArr.end(), fltr.begin(), fn);
fltr[M] = fc / PI;
std::copy(fltr.begin(), fltr.begin() + M, fltr.rbegin());

Compute series without being able to store values?

Problem statement[here]
Let be S a infinite secuence of integers:
S0 = a;
S1 = b;
Si = |Si-2 - Si-1| for all i >= 2.
You have two integers a and b. You must answer some queries about the n-th element in the sequence.(means print the nth number in the sequence i.e S(n) )
( 0 <= a,b <= 10^18),( 1 <= q <= 100000 )
What I Tried(This would give a runtime error) :
#include <bits/stdc++.h>
using namespace std;
long long int q,a,b,arr[100002];/*Can't declare an array of required size */
int main() {
// your code goes here
scanf("%lld%lld",&a,&b);
arr[0]=a,arr[1]=b;
scanf("%d",&q);
int p[100002];
long long int m = -1;//stores max index asked
for(int i=0;i<q;i++)
{
scanf("%lld",&p[i]);
m = (m>p[i])?m:p[i];
}
for(int i=2;i<=m;i++)//calculates series upto that index
{
arr[i]=abs(arr[i-1]-arr[i-2]);
}
for(int i=0;i<q;i++)
{
printf("%lld\n",arr[p[i]]);
}
return 0;
}
Given : qi fits in 64 bit integer. since index can be very large and i cant declare that bit an array, how should i approach this problem(since brute force would give TLE). Thanks!
HA! There is a solution that doesn't require (complete) iteration:
Considering some values Si and Sj, where i, j > 1. Then, looking at how the numbers of the sequence are built (using the absolute value), we can conclude that both numbers are positive.
Then the absolute value of their difference is guaranteed to be less (or equal) than the larger of the two.
Assuming it is strictly less than the larger of the two, within the next two steps, the larger value of the original values will go "out of scope". From that we can conclude that in this case, the numbers of the sequence are getting smaller and smaller.
(*) If the difference is equal to the larger one, then the other number must have been 0. In the next step, one of two things might happen:
a) The larger goes out of scope, then the next two numbers are the calculated difference (which is equal to the larger) and 0, which will yield again the larger value. Then we have the same situation as in ...
b) The zero goes out of scope. Then the next step will compute the difference between the larger and the calculated difference (which is equal to the larger), resulting in 0. In the next step, this leads back to the original (*) situation.
Result: A repeating pattern of L, L, 0, ...
Some examples:
3, 1, 2, 1, 1, 0, 1, 1, 0, ...
1, 3, 2, 1, 1, 0, 1, 1, 0, ...
3.5, 1, 2.5, 1.5, 1, .5, .5, 0, .5, .5, 0, ...
.1, 1, .9, .1, .8, .7, .1, .6, .5, .1, .4, .3, .1, .2, .1, .1, 0, ...
Applying that to the code: As soon as one value is 0, no more iteration is required, the next two numbers will be the same as the previous, then there will be again a 0 and so on:
// A and B could also be negative, that wouldn't change the algorithm,
// but this way the implementation is easier
uint64_t sequence(uint64_t A, uint64_t B, size_t n) {
if (n == 0) {
return A;
}
uint64_t prev[2] = {A, B};
for (size_t it = 1u; it < n; ++it) {
uint64_t next =
(prev[0] > prev[1]) ?
(prev[0] - prev[1]) :
(prev[1] - prev[0]);
if (next == 0) {
size_t remaining = n - it - 1;
if (remaining % 3 == 0) {
return 0;
}
return prev[0]; // same as prev[1]
}
prev[0] = prev[1];
prev[1] = next;
}
return prev[1];
}
Live demo here (play with the a and b values if you like).
If you have repeated queries for the same A and B, you could cache all values until next == 0 in a std::vector, giving you really constant time for the following queries.
I'm also pretty sure that there's a pattern before the sequence reaches 0, but I wasn't able to find it.
I just noticed that I missed that it should be the absolute value of the difference ...
If it's fast enough, here is an iterative version:
// deciding on a concrete type is hard ...
uint64_t sequence (uint64_t A, uint64_t B, uint64_t n) {
if (n == 0) {
return A;
}
uint64_t prev[2] = {A, B};
for (auto it = 1u; it < n; ++it) {
auto next =
(prev[0] > prev[1]) ?
(prev[0] - prev[1]) :
(prev[1] - prev[0]);
prev[0] = prev[1];
prev[1] = next;
}
return prev[1];
}
As you see you don't need to store all values, only the last two numbers are needed to compute the next one.
If this isn't fast enough you could add memorisation: Store the pairs of prev values in an ordered std::map (mapping n to those pairs). You can then start from the entry with the next, lower value of n instead of from the beginning. Of course you need to manage that map then, too: Keep it small and filled with "useful" values.
This is not a programming problem, it's an algorithmic one. Let's look at the first numbers of that sequence:
a
b
a-b
b-(a-b) = 2b-a
(a-b)-(b-(a-b)) = 2(a-b)-b = 2a-3b
2b-a-(2a-3b) = 5b-3a
2a-3b-(5b-3a) = 5a-8b
...
Looking only at the absolute value of the coefficients shows ...
b: 0 1 1 2 3 5 8 ...
a: (1) 0 1 1 2 3 5 ...
... that this is about the Fibonacci sequence. Then, there's also the sign, but this is pretty easy:
b: - + - + - ...
a: + - + - + ...
So the nth number in your sequence should be equal to
f(0) = a
f(n) = (-1)^n * fib(n-1) * a +
(-1)^(n-1) * fib(n) * b
Of course now we have to calculate the nth Fibonacci number, but fortunately there's already a solution for that:
fib(n) = (phi^n - chi^n) / (phi - chi)
with
phi = (1 + sqr(5)) / 2
chi = 1 - phi
So, bringing that to code:
unsigned long fib(unsigned n) {
double const phi = (1 + sqrt(5)) / 2.0;
double const chi = 1 - phi;
return (pow(phi, n) - pow(chi, n)) / (phi - chi);
}
long sequence (long A, long B, unsigned n) {
if(n ==0) {
return A;
}
auto part_a = fib(n-1) * A;
auto part_b = fib (n) * B;
return (n % 2 == 0) ? (part_a - part_b) : (part_b - part_a);
}
Some live demo is here, but this gets problematic when approaching larger numbers (I suspect the fib getting incorrect).
The demo contains also the iterative version of the sequence, as control. If that's fast enough for you, use that instead. No need to store anything more than the last two numbers.
To improve this further, you could use a lookup table with holes for the Fibonacci numbers, i.e. remembering every tenth (and their successor) number of the sequence.

Get 1D array index from a 2D array

Is there a way to get the array index of a 1D array from a 2D array?
For Eg: I have a 2D array, the array size is unknown and changes (I've used std::vector) to push_back as and when required. This works fine as long as its a 2D array but I need to get the 1D array index of this 2D array.
2D array:
Group 1 - 1, 2, 3
Group 2 - 4, 5, 6
Group 3 - 7, 8, 9, 10, 11, 12
and so on.
So, basically is there a quick way to know that when 6 is selected from Group 2 i.e. Array[1][2] = 6 => I need the array index as: 1D array=> Array[5] = 6 => i.e. I need 5 as my answer. I have tried several things but no luck so far. Any suggestions?
If your data is static, you can make another array in which you will store the offset for each 1D array. For your example, you will have the following array offset = {0, 3, 6}. Then you can find the index by offset[row] + col.
If you can change the row sizes, then you can store the size of each row in a Binary indexed tree and find the offset in O(log n) with a single query, where n is the amount of rows (1D vectors). However, each time you change the row size, you would have to update the structure again in O(log n).
If you are creating a vector of vectors (or a list of vectors), the memory locations are not guaranteed to be related. So to make it behave like a 1-dimensional array, you would need to wrap the container in your own class and overload operator[]. That operator would then need to check the index to determine the proper vector element to return. A simplified version might look like:
T& operator[](std::size_t index)
{
std::size_t temp = index;
if (index < myVectors[0].size())
{
return myVectors[0][index];
}
temp = index - myVectors[0].size()
if (temp < myVectors[1].size())
{
return myVectors[1][temp];
}
// etc ...
}
You can simplify it to a loop:
T& operator[](std::size_t index)
{
std::size_t temp = index;
for (std::size_t i = 0; i < myVectors.size(); ++i)
{
if (temp < myVectors[i].size())
{
return myVectors[i][temp];
}
temp -= myVectors[i].size();
}
throw std::out_of_range("Array access out of bounds!");
}

Writing MATLAB arrays in C/C++

The MATLAB code samples part of background of an grayscale image by creating a cell array that is backgroundSample{1}, backgroundSample{2}, ... , backgroundSample{9}. Here halfRows and halfCols is the half size of the image.
Since backgroundSample is an array that contains nine 2-D matrices. It confused me that how to write this code in C/C++. Can I get the elements of backgroundSample{i} using something like backgroundSample[i].elements[m][n]?
MATLAB code:
offset = [-60, -20, 20, 60];
for i = 1: 1: 3
for j = 1: 1: 3
backgroundSample{(i - 1) * 3 + j} =
background(halfRows + offset(i): halfRows + offset(i + 1), ...
halfCols + offset(j): halfCols + offset(j + 1));
end;
end;
EDIT:
As we can assign a matrix simply by A = B in MATLAB. For an example, backgroundSample{1} = background(60: 100, 60: 100) in my question and this assignment is in the loops of i: 1→3 and j: 1→3. However, when assigning a matrix in C/C++, it should assign every element one by one. Maybe like this:
for(int i = 0; i < 3; i++)
for(int j = 0; n < 3; j++)
// to get every elements
for(int m = 0 ...)
for(int n = 0 ...)
// not sure whether there is such usage of "->" in array
backgroundSample[(i - 1) * 3 + j]->elements[m][n] = background[i iteration][j iteration]
So there are conflicts between indices of matrix backgroundSample[m][n] and background[i][j]. How to resolve the issue?
The simplest way to implement what you're describing is to declare a multidimensional array:
int backgroundSample[9][3][3];
where the dimensions of each 2-D matrix is assumed to be 3×3. To access the (m, n) element in the k-th matrix, you write backgroundSample[k][m][n], e.g:
for (int m = 0; m < 3; ++m)
{
for(int n = 0; n < 3; ++n)
{
backgroundSample[(i - 1) * 3 + j][m][n] = background[i][j];
}
}
Alternatively, if each sample in this array stores more information, you can declare a structure:
typedef struct
{
int elements[3][3];
// More fields...
} TSample;
and then create an array of these:
TSample backgroundSample[9];
To access an element you would write backgroundSample[k].elements[m][n].
There's also the possibility of allocating the memory dynamically (during runtime, meaning that you don't know how much of these structures you have in advance):
TSample* backgroundSample;
In C++ the actual process of memory allocation would look like this:
backgroundSample = new TSample[9];
Accessing an element would be done by writing backgroundSample[k]->elements[m][n]. Notice the array operator -> which accesses the field elements by dereferencing the pointer backgroundSample[k].
Note: each call to new needs to be accompanied by a matching call to delete when done in order to release the memory, i.e:
delete[] backgroundSample;
Hope that helps!

bsort example from programming pearls

In Programming Pearls there is an algorithm that sorts varying length arrays but sorts in time proportional to the sum of their length. For example, if we have a record array x[0...n-1], and each record has an integer length and a pointer to array bit[0...length-1].
The code is implemented this way:
void bsort(l, u, depth){
if (l >= u)
return ;
for (i = l; i <= u; i++){
if (x[i].length < depth)
swap(i, l++);
}
m = l;
for (int i = l; i < u; i++){
if (x[i].bit[depth] == 0)
swap(i, m++);
}
bsort(l, m - 1, depth + 1);
bsort(m, u, depth + 1);
}
My question is that, given the record:
x[6] = {"car", "bus", "snow", "earth", "dog", "mouse"}
I know how to get the string length, but what about with a bit array? How could I make a bit array suitable for this string array? And even x[i].bit[depth] how can I implement this?
Arrays of chars (or any other type, for that matter) are also arrays of bits - chars are made of bits, after all. So you don't have to create a separate array, you just have to find a way to access a given bit in the array. For that, you'll have to use some bit manipulations. You can find a few examples of how this could be done here: Any smarter way to extract from array of bits?.
Basically, you first have to figure out the byte the required bit is at, and then get that specific bit's value. Something along:
char* array = "the array";
int required_bit = 13;
int bit = required_bit & 0x7; // get the bit's offset in its byte
int byte = required_bit >> 3; // get the bit's byte
int val = (array[byte] >> bit) & 0x1; // check if the bit is 1
Now wrap this in a function (possibly with additional bound checks, to make sure the given required_bit is not outside of the array), and use with x[i].