Whether loop variables are always freshly created - chapel

In the following code, I'm using the variable name n for both a local variable and a loop counter:
proc main()
{
var n = 700;
writeln( "n (before loop) = ", n );
for n in 1..3 {
writeln( "n = ", n );
}
writeln( "n (after loop) = ", n );
}
and the result is
n (before loop) = 700
n = 1
n = 2
n = 3
n (after loop) = 700
Does this mean that the for loop always creates a new loop variable, in a way similar to for (int n = 1; n <= 3; n++) rather than for (n = 1; n <= 3; n++) (in C-like languages)?
(Background) I was playing with the following code using ref, and since the loop did not change the value of baa in the outer scope, I imagined that b is probably created as a new variable...
proc main()
{
var baa: int = 700;
ref b = baa;
writeln( "baa (before loop) = ", baa );
for b in 1..3 {
writeln( "b = ", b, " baa = ", baa );
}
writeln( "baa (after loop) = ", baa );
}
Result:
baa (before loop) = 700
b = 1 baa = 700
b = 2 baa = 700
b = 3 baa = 700
baa (after loop) = 700

Does this mean that the for loop always creates a new loop variable, in a way similar to for (int n = 1; n <= 3; n++) rather than for (n = 1; n <= 3; n++) (in C-like languages)?
Yes, that's right. Chapel's for, forall, and coforall loops each declare new index variables for their iterations. In the forall and coforall cases this is done out of necessity since different tasks will be executing different iterations and each will need its own copy of the index variable. Our for loops adopt the same strategy for consistency and convenience. If you want to modify an outer variable within a Chapel [co]for[all] loop, you would need to do it in the loop's body or iterator expression.
The compiler could (and perhaps should) emit a warning for cases like yours in which a loop variable shadows a variable at the same scope, to avoid confusion. If you'd like to advocate for this behavior, please consider filing a GitHub issue for it.

Related

Convert c++ function from recursive to iterations with stack

I'm trying to convert this function from recursive to iterations with stack but I can't figure out how and I keep failing
int F(int n)
{
if (n <= 1) return 1;
int a = n + F(n - 1);
cout << a << endl;
int b = n * F(n / 2);
int c = n - 2 - (a + b) % 2;
int d = F(c);
return a + b + d;
}
I tried to debug the code and break it down but luck was not on my side
edit:
these are the requirements
You are not allowed to use any built-in functions except those from: <cstdlib>, <cstdio>, <cstring>, <iostream> and <stack>.
You are not allowed to use string, vector, or anything from STL libraries except stack.
Moreover, I attempted to make multiple stack for each variable to store the results then substitute the answer but am still working on it.
Let's look at the single parts of the recursion:
We have f(n-1), f(n/2) and f(n-2-[0 or 1], no matter how big a or b might ever get. All these recursive calls fall back to a lower value.
First few values:
f(n) = 1; // n <= 1
f(2) = (2 + f(1)) + (2 * f(1)) + f(-1) // (c = 2 - 2 - 5 % 2)
= 6
f(3) = (3 + f(2)) + (3 * f(1)) + f(1) // (c = 3 - 2 - 12 % 2)
= 13
f(4) = (4 + f(3)) + (4 * f(2)) + f(1) // (c = 4 - 2 - 41 % 2)
= 42
f(5) = (5 + f(4)) + (5 * f(2)) + f(2) // (c = 5 - 2 - 77 % 2)
= 83
Obviously we can calculate a new value based on old ones – and if we calculate these first, we can simply look them up – apart from n == 2 where we'd get a negative lookup index. So we might initialise a std::vector with f(0), f(1) and f(2) (i.e. 1, 1, 6) and then iterate from 3 onwards until n calculating new values based upon the lookups of old ones:
if n <= 1:
return 1;
std::vector v({1, 1, 6});
if n >= v.size():
v.reserve(n + 1); // avoid unnecessary re-allocations
iterate i from v.size() up to n inclusive:
v.push_back(calculate, instead recursive calls look up in vector!);
return v[n];
Optimisation opportunity: If you retain results from previous calculations you don't need to re-calculate the values again and again (for the price of constantly instead of temporarily consuming quite a bit of memory!); all you have to do for is making the vector static:
static std::vector v({1, 1, 6});
// ^^^^^^
Edit – according to the edits of the question (referring to version 4):
As you are not allowed to use std::vector as proposed above instead allocate an array:
auto v = new unsigned int[std::max(3, n + 1)] { 1, 1, 6};
// I personally prefer unsigned int as negative values aren't possible anyway...
// calculate as with the vector
auto result = v[n];
delete[] v;
return result;
Keeping old values for future calls still is possible, but more complicated; you need to remember how large your array is and if n is greater than the size re-allocate a new array, copy values from old one to and delete the latter.
This approach keeps the requirements of the task as using std::stack is not explicitly requested... If that gets enforced then the algorithm won't change – solely the lookup gets pretty ugly; you need in addition to your main stack a temporary one to be able to backup the elements on top of those you want to lookup up:
// lookup the three values in DESCENDING order, each one
// as follows:
while(stack.size() > lookupIndex)
{
backup.push(stack.top());
stack.pop();
}
// now top elements have been moved away from main stack and
// backed up; the element to be looked up is moved, too;
// for illustration: consider lookupIndex == 0; what would be
// the main stack's size after popping the surplus elements???
lookupValue = backup().top();
// now as you have looked up all three values move the elements
// in the backup stack back to the main stack:
while(!backup.empty()) { /* analogously to above */ }
You can spare moving back if you are calculating the final value for n – unless you retain the main stack for future calls analogously to the static vector above (make it static analogously...).
Final note: I think more than anything else you can learn from this example how much additional effort – in coding and in runtime – you will load upon your shoulders if you chose a bad data structure compared to having chosen a suitable one...
Consider that
F(n) = 1 for all n <= 1, especially
F(0) = 1 and F(1) = 1
This is basically all you need to get the solution with a loop:
int F2(int n) {
std::vector<int> F{1,1};
for (int i=2;i <= n; ++i) {
int a = i + F[i-1];
int b = i * F[i/2];
int x = i-2-(a+b)%2; // might be negative
int d = x>0 ? F[x] : 1;
F.push_back(a+b+d);
}
return F.back();
}

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());

Rewriting code to remove loop-carried dependence

I'm trying to rewrite this outer for loop to allow multiple threads to execute the iterations in parallel. Actually, for now I just want two threads to compute this although a more general solution would be ideal. The issue is that there's a loop carried dependence: nval[j] is added to the previous value of nval[j] along with this iteration's value of avval.
void loop_func(Arr* a, int blen, double* nval) {
// an Arr is a struct of an array and len field
assert(a->len < blen);
long long int i = 0, j = 0, jlo = 0, jhi = 0;
double avval = 0.0;
for (i = 0; i < blen; i++)
nval[i] = 0.0;
const double quot = static_cast<double>(blen) / static_cast<double>(a->len);
for (auto i = 1; i < a->len - 1; i++) {
j_lower = (int)(0.5 * (2 * i - 1) * quot);
j_upper = (int)(0.5 * (2 * i + 1) * quot);
printf("a->val index: %lld\t\tnval index: %lld-%lld\n", i, j_lower, j_upper);
avval = a->val[i] / (j_upper - j_lower + 1);
for (j = j_lower; j <= j_upper; j++) {
nval[j] += avval;
}
}
}
For convenience, I'm printing out some details that were printed via the printf above.
a->val index: 1 nval index: 1-3
a->val index: 2 nval index: 3-5
a->val index: 3 nval index: 5-7
a->val index: 4 nval index: 7-9
a->val index: 5 nval index: 9-11
a->val index: 6 nval index: 11-13
I'd ideally want to have thread 1 handle the a->val index 1-3 and thread 2 handle the a-val index 4-6.
Question 1: can anyone describe a code transformation that would remove this dependence?
Question 2: are there C/C++ tools that can do this? Maybe something built with LLVM? I will likely have a number of different situations like this where I need to do some parallel execution. Similarly, if there are general techniques that can be applied to remove such loop-carried dependencies, I'd like to learn about this more generally.

Nested for loops to iterate to the power of 2

I need to use two loops in such a way that the outer loop drives the inner loop to do computations for 2,4,8,16,and 32 iterations.
for example if i=2(for outer loop)
then inner loop will iterate for 4 times
and if i=3
then inner loop will iterate for 8 times and so on.
this is the logic I m using
for ( i = 0 ; i < n ; i++ )
{
for ( c = 0 ; c <= pow(2,i) ; c=c++ )
I would really appreciate any suggestions
Compute the number of iterations of the inner loop once and reuse it instead of computing it everytime.
Don't use pow(2, i). Use the more reliable 1 << i.
Don't use c = c++. Just use c++. I am not sure c = c++ is guaranteed to be c = c+1.
for ( i = 0 ; i < n ; i++ )
{
int nextCount = (1 << i);
for ( c = 0 ; c <= nextCount ; c++ )
You can use the fact that to compute a small power of two in C++ you can use a bit shift left:
for ( i = 0 ; i < n ; i++ ) {
for ( c = 0 ; c < (1 << i) ; c++ ) {
...
}
}
The reason behind this "magic" is the same as the reason why adding a zero to the right of a decimal number multiplies the number by ten.
Note that since you start the iteration of the inner loop at zero, you need to use <, not <=. Otherwise you would iterate 2n+1 times.
You'll want to use something like everyone else has suggested:
for (int i=0 ; i<n ; i++){
for(int c=0 ; c < (1<<i) ; c++){
//do computations
}
}
The reason you want to use < instead of <= is becase <= will actually give you (2^i)+1 iterations, due to counting zero.
The reason you want to want to use the bitshift operation 1<<i, is because integers are already in base two, and adding zeros on the end is the equivelant of multiplying by two repeatedly. (1 is automatically created as an integer, while 1.0 is automatically created as a float. You could not safely do this with floats: 1.0<<1 bitshifts to 1.70141e+38, if you can get the compiler to do it.)
Finally, you want to use c++ because c++ increments c, but returns the original value, so your inner for-loop always keeps the original value and never increments.

How Recursion Works Inside a For Loop

I am new to recursion and trying to understand this code snippet. I'm studying for an exam, and this is a "reviewer" I found from Standford' CIS Education Library (From Binary Trees by Nick Parlante).
I understand the concept, but when we're recursing INSIDE THE LOOP, it all blows! Please help me. Thank you.
countTrees() Solution (C/C++)
/*
For the key values 1...numKeys, how many structurally unique
binary search trees are possible that store those keys.
Strategy: consider that each value could be the root.
Recursively find the size of the left and right subtrees.
*/
int countTrees(int numKeys) {
if (numKeys <=1) {
return(1);
}
// there will be one value at the root, with whatever remains
// on the left and right each forming their own subtrees.
// Iterate through all the values that could be the root...
int sum = 0;
int left, right, root;
for (root=1; root<=numKeys; root++) {
left = countTrees(root - 1);
right = countTrees(numKeys - root);
// number of possible trees with this root == left*right
sum += left*right;
}
return(sum);
}
Imagine the loop being put "on pause" while you go in to the function call.
Just because the function happens to be a recursive call, it works the same as any function you call within a loop.
The new recursive call starts its for loop and again, pauses while calling the functions again, and so on.
For recursion, it's helpful to picture the call stack structure in your mind.
If a recursion sits inside a loop, the structure resembles (almost) a N-ary tree.
The loop controls horizontally how many branches at generated while the recursion decides the height of the tree.
The tree is generated along one specific branch until it reaches the leaf (base condition) then expand horizontally to obtain other leaves and return the previous height and repeat.
I find this perspective generally a good way of thinking.
Look at it this way: There's 3 possible cases for the initial call:
numKeys = 0
numKeys = 1
numKeys > 1
The 0 and 1 cases are simple - the function simply returns 1 and you're done. For numkeys 2, you end up with:
sum = 0
loop(root = 1 -> 2)
root = 1:
left = countTrees(1 - 1) -> countTrees(0) -> 1
right = countTrees(2 - 1) -> countTrees(1) -> 1
sum = sum + 1*1 = 0 + 1 = 1
root = 2:
left = countTrees(2 - 1) -> countTrees(1) -> 1
right = countTrees(2 - 2) -> countTrees(0) -> 1
sum = sum + 1*1 = 1 + 1 = 2
output: 2
for numKeys = 3:
sum = 0
loop(root = 1 -> 3):
root = 1:
left = countTrees(1 - 1) -> countTrees(0) -> 1
right = countTrees(3 - 1) -> countTrees(2) -> 2
sum = sum + 1*2 = 0 + 2 = 2
root = 2:
left = countTrees(2 - 1) -> countTrees(1) -> 1
right = countTrees(3 - 2) -> countTrees(1) -> 1
sum = sum + 1*1 = 2 + 1 = 3
root = 3:
left = countTrees(3 - 1) -> countTrees(2) -> 2
right = countTrees(3 - 3) -> countTrees(0) -> 1
sum = sum + 2*1 = 3 + 2 = 5
output 5
and so on. This function is most likely O(n^2), since for every n keys, you're running 2*n-1 recursive calls, meaning its runtime will grow very quickly.
Just to remember that all the local variables, such as numKeys, sum, left, right, root are in the stack memory. When you go to the n-th depth of the recursive function , there will be n copies of these local variables. When it finishes executing one depth, one copy of these variable will be popped up from the stack.
In this way, you will understand that, the next-level depth will NOT affect the current-level depth local variables (UNLESS you are using references, but we are NOT in this particular problem).
For this particular problem, time-complexity should be carefully paid attention to. Here are my solutions:
/* Q: For the key values 1...n, how many structurally unique binary search
trees (BST) are possible that store those keys.
Strategy: consider that each value could be the root. Recursively
find the size of the left and right subtrees.
http://stackoverflow.com/questions/4795527/
how-recursion-works-inside-a-for-loop */
/* A: It seems that it's the Catalan numbers:
http://en.wikipedia.org/wiki/Catalan_number */
#include <iostream>
#include <vector>
using namespace std;
// Time Complexity: ~O(2^n)
int CountBST(int n)
{
if (n <= 1)
return 1;
int c = 0;
for (int i = 0; i < n; ++i)
{
int lc = CountBST(i);
int rc = CountBST(n-1-i);
c += lc*rc;
}
return c;
}
// Time Complexity: O(n^2)
int CountBST_DP(int n)
{
vector<int> v(n+1, 0);
v[0] = 1;
for (int k = 1; k <= n; ++k)
{
for (int i = 0; i < k; ++i)
v[k] += v[i]*v[k-1-i];
}
return v[n];
}
/* Catalan numbers:
C(n, 2n)
f(n) = --------
(n+1)
2*(2n+1)
f(n+1) = -------- * f(n)
(n+2)
Time Complexity: O(n)
Space Complexity: O(n) - but can be easily reduced to O(1). */
int CountBST_Math(int n)
{
vector<int> v(n+1, 0);
v[0] = 1;
for (int k = 0; k < n; ++k)
v[k+1] = v[k]*2*(2*k+1)/(k+2);
return v[n];
}
int main()
{
for (int n = 1; n <= 10; ++n)
cout << CountBST(n) << '\t' << CountBST_DP(n) <<
'\t' << CountBST_Math(n) << endl;
return 0;
}
/* Output:
1 1 1
2 2 2
5 5 5
14 14 14
42 42 42
132 132 132
429 429 429
1430 1430 1430
4862 4862 4862
16796 16796 16796
*/
You can think of it from the base case, working upward.
So, for base case you have 1 (or less) nodes. There is only 1 structurally unique tree that is possible with 1 node -- that is the node itself. So, if numKeys is less than or equals to 1, just return 1.
Now suppose you have more than 1 key. Well, then one of those keys is the root, some items are in the left branch and some items are in the right branch.
How big are those left and right branches? Well it depends on what is the root element. Since you need to consider the total amount of possible trees, we have to consider all configurations (all possible root values) -- so we iterate over all possible values.
For each iteration i, we know that i is at the root, i - 1 nodes are on the left branch and numKeys - i nodes are on the right branch. But, of course, we already have a function that counts the total number of tree configurations given the number of nodes! It's the function we're writing. So, recursive call the function to get the number of possible tree configurations of the left and right subtrees. The total number of trees possible with i at the root is then the product of those two numbers (for each configuration of the left subtree, all possible right subtrees can happen).
After you sum it all up, you're done.
So, if you kind of lay it out there's nothing special with calling the function recursively from within a loop -- it's just a tool that we need for our algorithm. I would also recommend (as Grammin did) to run this through a debugger and see what is going on at each step.
Each call has its own variable space, as one would expect. The complexity comes from the fact that the execution of the function is "interrupted" in order to execute -again- the same function.
This code:
for (root=1; root<=numKeys; root++) {
left = countTrees(root - 1);
right = countTrees(numKeys - root);
// number of possible trees with this root == left*right
sum += left*right;
}
Could be rewritten this way in Plain C:
root = 1;
Loop:
if ( !( root <= numkeys ) ) {
goto EndLoop;
}
left = countTrees( root -1 );
right = countTrees ( numkeys - root );
sum += left * right
++root;
goto Loop;
EndLoop:
// more things...
It is actually translated by the compiler to something like that, but in assembler. As you can see the loop is controled by a pair of variables, numkeys and root, and their values are not modified because of the execution of another instance of the same procedure. When the callee returns, the caller resumes the execution, with the same values for all values it had before the recursive call.
IMO, key element here is to understand function call frames, call stack, and how they work together.
In your example, you have bunch of local variables which are initialised but not finalised in the first call. It's important to observe those local variables to understand the whole idea. At each call, the local variables are updated and finally returned in a backwards manner (most likely it's stored in a register before each function call frame is popped off from the stack) up until it's added to the initial function call's sum variable.
The important distinction here is - where to return. If you need accumulated sum value like in your example, you cannot return inside the function which would cause to early-return/exit. However, if you depend on a value to be in a certain state, then you can check if this state is hit inside the for loop and return immediately without going all the way up.