Need help understanding passing arguments to function - c++

I’m new to C++ and unsure about how to pass arguments to functions.
I’m using a function Distance() to calculate the distance between two nodes.
I declare the function like this:
int Distance(int x1, int y1, int x2 , int y2)
{
int distance_x = x1-x2;
int distance_y = y1- y2;
int distance = sqrt((distance_x * distance_x) + (distance_y * distance_y));
return distance;
}
In the main memory I have 2 for loops.
What I need to know is if I can pass the values like this: Distance (i, j, i+1, j+1).
for(int i = 0; i < No_Max; i++)
{
for(int j = 0; j < No_Max; j++)
{
if(Distance(i, j, i+1, j+1) <= Radio_Range) // the function
node_degree[i] = node_degree[i] + 1;
cout << node_degree[i] << endl;
}
}

Arguments to functions can be supplied as any expression which matches the type of that argument or can be cast to it.

Tips :
You should use double instead of int if you want to use sqrt :
http://www.cplusplus.com/reference/clibrary/cmath/sqrt/

It looks as if you are calling your Distance(int, int, int, int) function correctly.
The following statement will call Distance():
Distance (i, j, i+1, j+1);
This will store the value returned by Distance() in a variable:
int dist = Distance (i, j, i+1, j+1);
This will compare the value returned by Distance() (the left operand) to Radio_Range (the right operand). If the left operand is less than or equal to the right operand, it will be evaluated to 1 (true). Otherwise it will be 0 (false). If the overall value of the expression inside the if statement is non-zero, the statement or block immediately following the if statement will be executed:
if(Distance(i, j, i+1, j+1) <= Radio_Range)
//Statement;
or:
if(Distance(i, j, i+1, j+1) <= Radio_Range){
//Statement;
//Statement;
//...
}
However, the value returned by Distance() will be truncated to an integer. Thus, distance will not equal the actual distance unless (distance_x * distance_x) + (distance_y * distance_y) is a perfect square. For better precision, consider using a double. If you intend to have the function return an int, it would be wise to do an explicit type cast, e.g.:
int distance = (int)sqrt((distance_x * distance_x) + (distance_y * distance_y));
This will ensure that if you or anyone else looks at the code later on, they will not think the function is using the wrong data type.

Related

C++ dynamic array allocation and strange use of memset

I recently ran into this code in C++:
int m=5;
int n=4;
int *realfoo = new int[m+n+3];
int *foo;
foo = realfoo + n + 1;
memset(realfoo, -1, (m+n+2)*sizeof(int));
Only the variable "foo" is used in the rest of the code, "realfoo" is never used (just freed at the very end).
I can't understand what that means.
What kind of operation is foo = realfoo + n + 1;? How is it possible to assign an array plus an int?
The memset sets every value of "realfoo" to -1. How does this affect "foo"?
EDIT
Since many have asked for the entire code. Here it is:
int Wu_Alg(char *A, char *B, int m, int n)
{
int *realfp = new int[m+n+3];
int *fp, p, delta;
fp = realfp + n + 1;
memset(realfp, -1, (m+n+2)*sizeof(int));
delta = n - m;
p = -1;
while(fp[delta] != n){
p=p+1;
for(int k = -p; k <= delta-1; k++){
fp[k]=snake(A, B, m, n, k, Max(fp[k-1]+1, fp[k+1]));
}
for(int k = delta+p; k >= delta+1; k--){
fp[k] = snake(A, B, m, n, k, Max(fp[k-1]+1, fp[k+1]));
}
fp[delta] = snake(A, B, m, n, delta, Max(fp[delta-1]+1, fp[delta+1]));
}
delete [] realfp;
return delta+2*p;
}
int snake(char *A, char *B, int m, int n, int k, int j)
{
int i=j-k;
while(i < m && j < n && A[i+1] == B[j+1]){
i++;
j++;
}
return j;
}
Source: http://par.cse.nsysu.edu.tw/~lcs/Wu%20Algorithm.php
The algorithm is: https://publications.mpi-cbg.de/Wu_1990_6334.pdf
This:
foo = realfoo + n + 1;
Assigns foo to point to element n + 1 of realfoo. Using array indexing / pointer arithmetic equivalency, it's the same as:
foo = &realfoo[n + 1];
memset is not setting the value to -1. It is used to every byte to -1
You should create a loop to iterate every element to assign correctly.
for(size_t i= 0; i< m+n+3; i++){
realfoo[i] = -1;
}
What kind of operation is foo = realfoo + n + 1;?
This is an assignment operation. The left hand operand, the variable foo, is assigned a new value. The right hand operand realfoo + n + 1 provides that value.
How is it possible to assign an array plus an int?
Because the array decays to a pointer.
The memset sets every value of "realfoo" to -1.
Not quite. All except the last value is set. The last one is left uninitialised.
Note that technically each byte is set to -1. If the system uses one's complement representation of signed integers, then the value of the resulting integer will not be -1 (it would be -16'843'009 assuming a 32 bit integer and 8 bit byte).
How does this affect "foo"?
foo itself is not affected. But foo points to an object that is affected.
Bonus advice: The example program leaks memory. I recommend avoiding owning bare pointers.

Composite Simpson's Rule in C++

I've been trying to write a function to approximate an the value of an integral using the Composite Simpson's Rule.
template <typename func_type>
double simp_rule(double a, double b, int n, func_type f){
int i = 1; double area = 0;
double n2 = n;
double h = (b-a)/(n2-1), x=a;
while(i <= n){
area = area + f(x)*pow(2,i%2 + 1)*h/3;
x+=h;
i++;
}
area -= (f(a) * h/3);
area -= (f(b) * h/3);
return area;
}
What I do is multiply each value of the function by either 2 or 4 (and h/3) with pow(2,i%2 + 1) and subtract off the edges as these should only have a weight of 1.
At first, I thought it worked just fine, however, when I compared it to my Trapezoidal Method function it was way more inaccurate which shouldn't be the case.
This is a simpler version of a code I previously wrote which had the same problem, I thought that if I cleaned it up a little the problem would go away, but alas. From another post, I get the idea that there's something going on with the types and the operations I'm doing on them which results in loss of precision, but I just don't see it.
Edit:
For completeness, I was running it for e^x from 1 to zero
\\function to be approximated
double f(double x){ double a = exp(x); return a; }
int main() {
int n = 11; //this method works best for odd values of n
double e = exp(1);
double exact = e-1; //value of integral of e^x from 0 to 1
cout << simp_rule(0,1,n,f) - exact;
The Simpson's Rule uses this approximation to estimate a definite integral:
Where
and
So that there are n + 1 equally spaced sample points xi.
In the posted code, the parameter n passed to the function appears to be the number of points where the function is sampled (while in the previous formula n is the number of intervals, that's not a problem).
The (constant) distance between the points is calculated correctly
double h = (b - a) / (n - 1);
The while loop used to sum the weighted contributes of all the points iterates from x = a up to a point with an ascissa close to b, but probably not exactly b, due to rounding errors. This implies that the last calculated value of f, f(x_n), may be slightly different from the expected f(b).
This is nothing, though, compared to the error caused by the fact that those end points are summed inside the loop with the starting weight of 4 and then subtracted after the loop with weight 1, while all the inner points have their weight switched. As a matter of fact, this is what the code calculates:
Also, using
pow(2, i%2 + 1)
To generate the sequence 4, 2, 4, 2, ..., 4 is a waste, in terms of efficency, and may add (depending on the implementation) other unnecessary rounding errors.
The following algorithm shows how to obtain the same (fixed) result, without a call to that library function.
template <typename func_type>
double simpson_rule(double a, double b,
int n, // Number of intervals
func_type f)
{
double h = (b - a) / n;
// Internal sample points, there should be n - 1 of them
double sum_odds = 0.0;
for (int i = 1; i < n; i += 2)
{
sum_odds += f(a + i * h);
}
double sum_evens = 0.0;
for (int i = 2; i < n; i += 2)
{
sum_evens += f(a + i * h);
}
return (f(a) + f(b) + 2 * sum_evens + 4 * sum_odds) * h / 3;
}
Note that this function requires the number of intervals (e.g. use 10 instead of 11 to obtain the same results of OP's function) to be passed, not the number of points.
Testable here.
The above excellent and accepted solution could benefit from liberal use of std::fma() and templatize on the floating point type.
https://en.cppreference.com/w/cpp/numeric/math/fma
#include <cmath>
template <typename fptype, typename func_type>
double simpson_rule(fptype a, fptype b,
int n, // Number of intervals
func_type f)
{
fptype h = (b - a) / n;
// Internal sample points, there should be n - 1 of them
fptype sum_odds = 0.0;
for (int i = 1; i < n; i += 2)
{
sum_odds += f(std::fma(i,h,a));
}
fptype sum_evens = 0.0;
for (int i = 2; i < n; i += 2)
{
sum_evens += f(std::fma(i,h,a);
}
return (std::fma(2,sum_evens,f(a)) +
std::fma(4,sum_odds,f(b))) * h / 3;
}

Undoing a recursion tree

SHORT How should I reduce (optimize) the number of needed operations in my code?
LONGER For research, I programmed a set of a equations in C++ to output a sequence if it fits the model. On the very inside of the code is this function, called MANY times during run-time:
int Weight(int i, int q, int d){
int j, sum = 0;
if (i <= 0)
return 0;
else if (i == 1)
return 1;
for (j = 1; j <= d; j++){
sum += Weight((i - j), q, d);
}
sum = 1 + ((q - 1) * sum);
return sum;
}
So based on the size of variable d, the size of the index i, and how many times this function is called in the rest of the code, many redundant calculations are done. How should I go about reducing the number of calculations?
Ideally, for example, after Weight(5, 3, 1) is calculated, how would I tell the computer to substitute in its value rather than recalculate its value when I call for Weight(6, 3, 1), given that the function is defined recursively?
Would multidimensional vectors work in this case to store the values? Should I just print the values to a file to be read off? I have yet to encounter an overflow with the input sizes I'm giving it, but would a tail-recursion help optimize it?
Note: I am still learning how to program, and I'm amazed I was even able to get the model right in the first place.
You may use memoization
int WeightImpl(int i, int q, int d); // forward declaration
// Use memoization and use `WeightImpl` for the real computation
int Weight(int i, int q, int d){
static std::map<std::tuple<int, int, int>, int> memo;
auto it = memo.find(std::make_tuple(i, q, d));
if (it != memo.end()) {
return it->second;
}
const int res = WeightImpl(i, q, d);
memo[std::make_tuple(i, q, d)] = res;
return res;
}
// Do the real computation
int WeightImpl(int i, int q, int d){
int j, sum = 0;
if (i <= 0)
return 0;
else if (i == 1)
return 1;
for (j = 1; j <= d; j++){
sum += Weight((i - j), q, d); // Call the memoize version to save intermediate result
}
sum = 1 + ((q - 1) * sum);
return sum;
}
Live Demo
Note: As you use recursive call, you have to be cautious with which version to call to really memoize each intermediate computation. I mean that the recursive function should be modified to not call itself but the memoize version of the function. For non-recursive function, memoization can be done without modification of the real function.
You could use an array to store the intermediate values. For example, for certain d and q have an array that contains the value of Weight(i, q, d) at index i.
If you initialize the array items at -1 you can then do in your function for example
if(sum_array[i] != -1){ // if the value is pre-calculated
sum += sum_array[i];
}
else{
sum += Weight((i - j), q, d);
}

R and C++ iteration

I'm trying to write a function that runs a loop in C++ from R using Rcpp.
I have a matrix Z which is one row shorter than the matrix OUT that the function is supposed to return because each position of first row of OUT will be given by the scalar sigma_0.
The function is supposed to implement a differential equation. Each iteration depends on a value from the matrix Z as well as a previously generated value of the matrix OUT.
What I've got is this:
cppFunction('
NumericMatrix sim(NumericMatrix Z, long double sigma_0, long double delta, long double omega, long double gamma) {
int nrow = Z.nrow() + 1, ncol = Z.ncol();
NumericMatrix out(nrow, ncol);
for(int q = 0; q < ncol; q++) {
out(0, q) = sigma_0;
}
for(int i = 0; i < ncol; i++) {
for(int j = 1; j < nrow; j++) {
long double z = Z(j - 1, i);
long double sigma = out(j - 1, i);
out(j, i) = pow(abs(z * sigma) - gamma * z * sigma, delta);
}
}
return out;
}
')
Unfortunately I'm fairly certain it doesn't work. The function runs but the values calculated are incorrect - I've checked with simple examples in Excel and plain R-coding. I've stripped the main differentialequation apart trying to build it up step by step to see when the implementation i Excel and R using C++ starts to differ. Which seems to be when I start using the abs() function and power() function but I simply can't narrow the problem down. Any help would be greatly appreciated - also I might mention this is the first time for me using C++ and C++ along with R.
I think you want fabs rather than abs. abs operates on ints, while fabs operates on doubles / floats.

Saving an array value into a double variable

Greetings everyone. Having an issue compiling my script containing the following function. Three errors occur, all on the same line where I set distance += to distances [][]:
error C2108: subscript is not of integral type
error C2108: subscript is not of integral type
error C2297: '+=' : illegal, right operand has type 'double (*)[15]'
Assistance would be much appriciated.
double S_initial;
double distances [15][15];
double order [15];
void Initialize()
{
double x, y ,z;
double distance = 0;
for (int i = 0; i <= 14; i++)
{
x = order [i];
y = order [i + 1];
distance += distances [x][y];
}
S_initial = distance;
}
Well, the array subscripts x and y are not of an integral type like int, but of type double:
double x, y, z;
...
distance += distances[x][y];
And something like the 1.46534th element of an array doesn't make sense, so the compiler complains.
x and y are not integers... You need to pass integers as array subscripts.
Stop using double and use int instead.
Or if you have to use double in the order array, you need to decide how to round any non-integer value that may be found in order to a int. Math.Floor, Math.Ceiling etc.
You cannot use floating point numbers to index into arrays. Use int or even better size_t.
for (int i = 0; i <= 14; i++)
{
x = order [i];
y = order [i + 1]; /* when i = 14, you invoke UB */
distance += distances [x][y];
}
On to the second part:
double order [15];
is uninitialized and hence invokes UB, when used.