Why doesn't <numeric> require/allow std::, but <cmath> does? - c++

Why, at least in my code, does <numeric> NOT require or ALLOW std::?
I'm following along with a YouTube SDL2 tutorial, and IntelliSense has squiggled all my trig functions. In the process of experimenting, I removed all the std:: and it worked and compiled fine. I decided to add #include <cmath> as well and commented out #include <numeric>, and now all the math functions again have squiggles. I reinserted the std:: and the squiggles disappeared.
I did some Google research and it seems to me that <numeric> is part of the standard library and thus should require std::.
#include "screen.h"
#include <numeric>
//#include <cmath>
void line(Screen& screen, float x1, float y1, float x2, float y2)
{
float dx = x2 - x1;
float dy = y2 - y1;
float length = float (sqrt(dx * dx + dy * dy));
float angle = float (atan2(dy, dx));
for (float i = 0; i < length; i++)
{
screen.pixel(
x1 + float (cos(angle) * i),
y1 + float (sin(angle) * i)
);
}
}
int main(int argv, char** args)
{
Screen screen;
for (int i = 0; i < 100; i++)
{
screen.pixel(rand() % 640, rand() % 480);
}
line(screen, 0, 0, 300, 300);
while (true)
{
screen.show();
screen.input();
}
return 0;
}
OK, once again, the code is NOT mine, it's a YouTube tutorial, thus it's his code, and this code compiled using <numeric> only for math functions such as sin(), cos(), atan2() and sqrt(). My one modification was to include <cmath>.
Here's my reproducible example:
//#include "screen.h"
#include <numeric>
#include <iostream>
//#include <cmath>
void line( float x1, float y1, float x2, float y2)
{
float dx = x2 - x1;
float dy = y2 - y1;
float length = float (sqrt(dx * dx + dy * dy));
float angle = float (atan2(dy, dx));
for (float i = 0; i < length; i++)
{
float tempx1 = x1 + float(cos(angle) * i);
float tempy1 = y1 + float(sin(angle) * i);
std::cout << i << " " << x1 << " " << y1 << std::endl;
}
}
int main(int argv, char** args)
{
line(2, 2, 20, 20);
return 0;
}

The C++ header <cmath> declares exactly the same Standard C math functions also declared in the C header <math.h>, with functions like pow(), ceil(), sqrt(), tan(), and constants like M_PI.
The C++ header <numeric> is completely different:
Components for performing numeric operations.
Includes support for complex number types, random number generation,
numeric (n-at-a-time) arrays, generalized numeric algorithms,
and mathematical special functions.
If you happen to have some header named numeric.h on your workstation ... it's completely unrelated to either of the above headers. For example:
Directory of c:\Ruby30-x64\include\ruby-3.0.0\ruby\internal\intern
07/09/2021 07:38 PM 1,941 numeric.h
If you want to use the Standard C library math functions sqrt() or cos() (callable from either C or C++), then you need to #include either <cmath> or <math.h>.
None of the functions in <math.h> are in the C++ namespace std, hence they don't need to be qualified with std::xxx.

Related

gsl multivariable numerical integration

I have been using the GSL integration package (gsl_integration.h) in attempt to integrate some multivariable function f(x,y,z) with respect to x between some limit [a,b]. In this example I have as a toy model: f(x,y,z) = xyz
I would like to output the result of this integral using a function
double integral(double a, double b, double y, double z){}
where I can keep y and z arbitrary up until this point. My attempts so far have mostly involved setting y, z equal to a constant in some predefined function and then using the
gsl_integration_qags
function to integrate over that function. However, I want to keep the values of y and z arbitrary until I define them in the above function. The closest I have got so far is as follows
#include <iostream>
#include <iomanip>
#include <fstream>
#include <vector>
#include <string>
#include <cmath>
#include <gsl/gsl_integration.h>
#include<stdio.h>
#include<math.h>
#define PI 3.1415926535897
double integrand(double x, void * params){
double y = *(double *) params;
double z = *(double *) params; // PROBLEM: this just sets z = y
double tmp = x*z*y;
return tmp;
}
double integral(double a, double b, double y, double z){
gsl_integration_workspace * w
= gsl_integration_workspace_alloc (1000);
gsl_function F;
F.function = &integrand; // Set integrand
F.params = &y, &z; // Set the parameters you wish to treat as constant in the integration
double result, error;
gsl_integration_qags (&F, a, b, 0, 1e-7, 1000,
w, &result, &error);
gsl_integration_workspace_free (w); // Free the memory
return result;
}
int main(){
std::cout << "Result "<< integral(0.0,1.0,3.0,5.0)<<std::endl;
}
This gives an output of
Result 4.5
The code sets a = 0.0, b = 1.0, y = z = 3.0 -- I want a = 0.0, b = 1.0, y = 3.0, z = 5.0, which would give a result of 7.5.
I would like to stick to GSL integration rather than boost if possible. I have also consulted https://www.gnu.org/software/gsl/doc/html/integration.html but am none-the-wiser. Any advice would be greatly appreciated, thanks.
I'm taking a guess, but it seems to me you want
double params[] = { y, z };
F.params = params;
and
double y = ((double *)params)[0];
double z = ((double *)params)[1];

In CUDA / Thrust, how can I access a vector element's neighbor during a for-each operation?

I am trying to do some scientific simulation using Thrust library in CUDA, but I got stuck in the following operation which is basically a for-each loop:
device_vector<float> In(N);
for-each In(x) in In
Out(x) = some_calculation(In(x-1),In(x),In(x+1));
end
I have already looked up stackoverflow.com and find some similar questions:
Similar questions 1
But it seems using a transform iterator is only possible when the some_calculation function is done between 2 parameters, for transform iterator passes two parameters at most.
Then, for question 2:
Similar questions 2
The discussion just ended without a conclusion.
I believe this is a simple problem because it's a natural requirements for parallel calculation. Anyone could tell me what to do?
Fancy iterators are the key to this sort of operation, which isn't all that intuitive in thrust. You can use the zip_iterator to create tuples of values which can then be iterated over, so for a typical f(x[i-1], x[i], x[i+1]) type function, you get something like this:
#include <iostream>
#include <cmath>
#include <thrust/iterator/zip_iterator.h>
#include <thrust/tuple.h>
#include <thrust/transform.h>
struct divided_diff {
float dx;
divided_diff(float _dx) : dx(_dx) {};
float operator()(const thrust::tuple<float, float, float> &in) const {
float y0 = in.get<0>();
float y1 = in.get<1>();
float y2 = in.get<2>();
return (y0 - 2.f * y1 + y2) / (dx * dx);
}
};
int main() {
const int N = 10;
const float dx = 0.1f;
float x[N], y[N], dydx[N];
for (int i = 0; i < N; ++i) {
x[i] = dx * float(i);
y[i] = std::sin(x[i]);
dydx[i] = 0.f;
}
auto begin = thrust::make_zip_iterator(thrust::make_tuple(&y[0], &y[1], &y[2]));
auto end = thrust::make_zip_iterator(thrust::make_tuple(&y[N-2], &y[N-1], &y[N]));
divided_diff f(dx);
thrust::transform(begin, end, &dydx[1], f);
for (int i = 0; i < N; ++i) {
std::cout << i << " " << dydx[i] << std::endl;
}
return 0;
}
Here the functor processes one tuple at a time, where the tuple contains the three inputs from three different starting points in the same array or iterative sequence.
EDIT: Apparently converting a host version of this code to use device constructs was proving challenging for the originally poster, so here is a version which executes everything on the device using thrust::device_vector as the base container:
#include <iostream>
#include <cmath>
#include <thrust/tuple.h>
#include <thrust/transform.h>
#include <thrust/iterator/zip_iterator.h>
#include <thrust/device_vector.h>
#include <thrust/sequence.h>
struct divided_diff {
float dx;
divided_diff(float _dx) : dx(_dx) {};
__device__
float operator()(const thrust::tuple<float, float, float> &in) {
float y0 = in.get<0>();
float y1 = in.get<1>();
float y2 = in.get<2>();
return (y0 - 2.f*y1 + y2) / (dx * dx);
}
};
struct mysinf {
__device__
float operator()(const float &x) {
return __sinf(x);
}
};
int main()
{
const int N = 10;
const float dx = 0.1f;
thrust::device_vector<float> x(N), y(N), dydx(N-2);
thrust::sequence(x.begin(), x.end(), 0.f, dx);
thrust::transform(x.begin(), x.end(), y.begin(), mysinf());
auto start = thrust::make_zip_iterator(thrust::make_tuple(y.begin(), y.begin()+1, y.begin()+2));
auto finish = thrust::make_zip_iterator(thrust::make_tuple(y.end()-2, y.end()-1, y.end()));
divided_diff f(dx);
thrust::transform( start, finish, dydx.begin(), f);
thrust::device_vector<float>::iterator it = dydx.begin();
for(; it != dydx.end(); ++it) {
float val = *it;
std::cout << val << std::endl;
}
return 0;
}

Use of Undeclared Identifier "angle"?

I am making a program that converts rectangular coordinates into polar coordinates and whenever I go to run the program it tells me that the "angle" is undeclared even though I am sure I have declared it. As well I know that the program isn't returning anything, I just want to be able to run it for now.
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <ctime>
#include <cmath>
using namespace std;
double random_float(double min, double max);
void rect_to_polar(double x, double y, double &distance, double &angle);
int main() {
double x, y;
x = random_float(-1, 1);
y = random_float(-1, 1);
rect_to_polar(x, y, distance, angle);
}
double random_float(double min, double max) {
unsigned int n = 2;
srand(n);
return ((double(rand()) / double(RAND_MAX)) * (max - min)) + min;
}
void rect_to_polar(double x, double y, double &distance, double &angle) {
const double toDegrees = 180.0/3.141593;
distance = sqrt(x*x + y*y);
angle = atan(y/x) * toDegrees;
}
You did not declare anything called angle in your main(), but still used the name angle there. Thus the error.
You might want to read up on scopes.
You should declare distance and angle in your main.
int main() {
double x, y, angle, distance;
x = random_float(-1, 1);
y = random_float(-1, 1);
rect_to_polar(x, y, distance, angle);
}

Infinite loop calculating cubic root

I'm trying to make a function that calculates the cubic root through Newton's method but I seem to have an infinite loop here for some reason?
#include <iostream>
#include <math.h>
using namespace std;
double CubicRoot(double x, double e);
int main()
{
cout << CubicRoot(5,0.00001);
}
double CubicRoot(double x, double e)
{
double y = x;
double Ynew;
do
{
Ynew = y-((y*y)-(x/y))/((2*y)+(x/(y*y)));
cout << Ynew;
} while (abs(Ynew-y)/y>=e);
return Ynew;
}
You have not updated your y variable while iteration.
Also using abs is quite dangerous as it could round to integer on some compilers.
EDIT
To clarify what I've mean: using abs with <math.h> could cause implicit type conversion problems with different compiles (see comment below). And truly c++ style would be using the <cmath> header as suggested in comments (thanks for that response).
The minimum changes to your code will be:
double CubicRoot(double x, double e)
{
double y = x;
double Ynew = x;
do
{
y = Ynew;
Ynew = y-((y*y)-(x/y))/((2*y)+(x/(y*y)));
cout << Ynew;
} while (fabs(Ynew-y)/y>=e);
return Ynew;
}
You can change
Ynew = y-((y*y)-(x/y))/((2*y)+(x/(y*y)));
to the equivalent, but more recognizable expression
Ynew = y*(y*y*y+2*x)/(2*y*y*y+x)
which is the Halley method for f(y)=y^3-x and has third order convergence.

Error when passing a function to a function and using a header file

I am getting the following error message when I try to run the following code when I try to add the function RK4 using a header file.
C:\Documents\C code\RK4\addRK4.h|7|error: expected ')' before '(' token|
There are a bunch of other error messages after that but I don't think they are important. I can't figure out what's wrong, especially since when I define the prototype of RK4 in main.cpp, everything runs just fine. The relevant code is below. Any help on this matter (or if you have any other suggestions since I am pretty new to c++) would be greatly appreciated!
main.cpp
#include <iostream>
#include <fstream>
#include <Eigen/Dense>
#include "gnuplot.h"
#include "addfitzhough.h"
#include "addRK4.h"
using namespace std;
using namespace Eigen;
int main()
{
//int mydims = 2;
double u = 0;
double *Iion;
double h = .5;
double y1ans[800];
double y2ans[800];
double tans[800];
Vector2d ycurr;
Vector2d Ynot, yplus;
Ynot << .2,
.1;
y1ans[0] = Ynot(0);
y2ans[0] = Ynot(1);
tans[0] = 0.0;
for(int i = 1;i<800;i++){
tans[i] = tans[i-1] + h;
ycurr << y1ans[i-1],
y2ans[i-1];
yplus = RK4(fitzhough,tans[i],ycurr,h,u,Iion,2);
y1ans[i] = yplus(0);
y2ans[i] = yplus(1);
}
}
addRK4.h
#ifndef RK4
#define RK4
using namespace Eigen;
VectorXd RK4(VectorXd (*f) (double t, Vector2d Y, double u, double * Iion), double t, VectorXd z, double h, double u, double *Iion, int d);
#endif // RK4
RK4.cpp
#include <Eigen/Dense>
using namespace std;
using namespace Eigen;
Vector2d RK4(Vector2d (*f)(double, Vector2d, double, double*), double t, VectorXd z, double h, double u, double *Iion, int d){
VectorXd Y1(d), Y2(d), Y3(d), Y4(d), Y1buf(d), Y2buf(d), Y3buf(d);
Y1 = z;
Y1buf = (*f)(t,Y1,u, Iion);
Y2 = z + 0.5*h*Y1buf;
Y2buf = (*f)(t+.5*h,Y2,u, Iion);
Y3 = z + 0.5*h*Y2buf;
Y3buf = (*f)(t+.5*h,Y3,u, Iion);
Y4 = z + h*Y3buf;
Vector2d yn = z + (h/6.0)*(Y1buf + 2.0*Y2buf + 2.0*Y3buf + (*f)(t+h,Y4,u, Iion));
return yn;
}
fitzhough.cpp
#include <Eigen/Dense>
using namespace std;
using namespace Eigen;
Vector2d fitzhough(double t, Vector2d Y, double u, double * Iion){
Vector2d dy;
double v = Y(0);
double w = Y(1);
double a = .13;
double b = .013;
double c1 = .26;
double c2 = .1;
double d = 1.0;
dy(0) = c1*v*(v-a)*(1-v)-c2*w*v + u;
dy(1) = b*(v-d*w);
*Iion = dy(0)-u;
return dy;
}
You have a symbol clash.
You #define the symbol RK4 and then you try to create a function with that name. Because you have defined it as an empty macro, it will be replaced with nothing. Then the compiler sees this as your function declaration:
VectorXd (VectorXd (*f) (double t, Vector2d Y, double u, double * Iion), double t, VectorXd z, double h, double u, double *Iion, int d);
It's a good idea to add extra characters for your header cages. Something like:
#ifndef RK4__H
#define RK4__H
It appears to be something wrong with the types Vector2d and VectorXd.
Edit: good catch #Paddy. Leaving the rest of the answer here since it is still valid.
Also, your declaration in addRK4.h doesnt match the definition in RK4.cpp. This will be the next error you will be fixing.