C++/CUDA equation printing incorrect answer - c++

currently I am trying to print out the answer to an equation using CUDA.
This equation is (x+y)^2 / xy
An example of the outputs I am getting are in this image attached.
__global__ void proof() {
int x = 1;
int y = 1;
int multi_number = 1000;
while (true) {
long eq = ((pow(x + y, 2)) / (x * y));
if (y >= multi_number) {
if (x >= multi_number) {
printf("\nProof is true for all cases.");
break;
}
}
if (x >= multi_number) {
x = 1;
y = y + 1;
}
printf("\nEquation being used: (%d", x);
printf("+%d", y);
printf(")^2 / %d", x);
printf("*%d", y);
printf(" >= 4");
printf("\n%d", eq); // printing the equations answer
if (eq < 4) {
printf("\nProof Failed: %d", x);
printf(", %d", y);
break;
}
x = x + 1;
}
}
I have currently tried rewriting the equation in multiple different ways, this did not work.
For the failed test (55+55)^2 / 55*55 I was expecting 4 to be printed instead of 3.
An example of a correct answer would be (1+1)^2 / 1*1 = 4

In a nutshell, pow() (in CUDA device code, at least) does not have the accuracy you need/desire when using truncation. I just answered a very similar question here.
The reason for the failure is that the result of ((pow(x + y, 2)) / (x * y)) (evaluated at the point (55,55)) is not 4 like you would expect, it is 3, when converted to a long value via truncation.
According to my testing, you can work around this by changing this line:
long eq = ((pow(x + y, 2)) / (x * y));
to this:
long eq = ((x+y)*(x+y)) / (x * y);

Try this code
#include <stdio.h>
#include <cuda_runtime.h>
__global__ void calculate(float x, float y, float *result)
{
*result = (x + y) * (x + y) / (x * y);
}
int main(void)
{
float x = 3.0, y = 2.0;
float result;
cudaMalloc((void **)&x, sizeof(float));
cudaMalloc((void **)&y, sizeof(float));
cudaMalloc((void **)&result, sizeof(float));
cudaMemcpy(x, &x, sizeof(float), cudaMemcpyHostToDevice);
cudaMemcpy(y, &y, sizeof(float), cudaMemcpyHostToDevice);
calculate<<<1,1>>>(x, y, result);
cudaMemcpy(&result, result, sizeof(float), cudaMemcpyDeviceToHost);
cudaFree(x);
cudaFree(y);
cudaFree(result);
printf("The result of the calculation is %f\n", result);
return 0;
}

Related

How do I fix this bug with arctanx function in c++

I've recently been given a problem by my teacher about some mathematical equation / formula called the arctanx formula. The question is:
According to the Arctanx(x) = x - ((x ^ 3) / 3) + ((x ^ 5) / 5) - ((x ^
7) / 7) + ...and π = 6 * arctanx(1 / sqrt(3)), Create function arctanx(x)
, and find pi when the last "number"(like this ((x ^ y) / y)) is right before
and bigger than 10 ^ -6, or you can say that no "number" can be smaller than
that number without being smaller than 10 ^ -6.
I tried to code it out, but there is a bug in it.
# include<iostream>
# include<math.h>
using namespace std;
float arctanx() {
long double pi = 3.1415926535897;
int i = 0; // 0 = +, 1 = -
float sum = 0;
float lsum;
for (int y = 1; y < pi; y += 2) {
if (lsum > 0.000001) {
if (i == 0) {
lsum = pow(1 / sqrt(3), y) / y;
sum += pow(1 / sqrt(3), y) / y;
i++;
} else if (i == 1) {
lsum = pow(1 / sqrt(3), y) / y;
sum -= pow(1 / sqrt(3), y) / y;
i--;
}
} else {
break;
}
}
sum = sum * 6;
return sum;
}
int main() {
cout << arctanx();
return 0;
}
It should have a output of some number not equal to zero, but I got 0 from running this.
Your program has Undefined Behavior because you are using the uninitialized float lsum; in the comparison if (lsum > 0.000001).
What probably happens in your case is that lsum happens to be less than or equal to 0.000001 and your for immediately breaks without doing anything causing your function to return 0 * 6 which is obviously 0.
Create function arctanx(x)
The function defined in the posted code doesn't accept any parameter, it just uses the hardwired (and repeated) value 1 / sqrt(3) and tries to return an approximated value of π instead of the arctangent of x.
It also has undefined behavior, beeing lsum uninitialized (therefore having an indeterminate value) when it is first used in the comparison inside the loop.
Consider this implementation, but be advised that this particular polinomial expansion diverges for values of x greater than 1.
#include <iostream>
#include <iomanip>
#include <cmath>
double arctanx(double x);
int main()
{
double pi = 6.0 * arctanx(1.0 / std::sqrt(3));
std::cout << std::setprecision(8) << pi << '\n';
}
double arctanx(double x)
{
// You can take advantage of a running power, instad of calculating
// pow(x, i) at every iteration
double sq_x = x * x;
double pow_x = x * sq_x;
double err = 1e-6;
// Instead of keeping track of the alternating sign, you can use
// two separate partial sums
double sum_pos_term = x;
double sum_neg_term = 0.0;
for (int i = 3; i < 33; i += 2) // <- Limit the number of iterations
{
if (pow_x < err * i)
break;
sum_neg_term += pow_x / i;
i += 2;
pow_x *= sq_x;
if (pow_x < err * i)
break;
sum_pos_term += pow_x / i;
pow_x *= sq_x;
}
return sum_pos_term - sum_neg_term;
}

How to code a sin progression with c? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I'm pretty new in coding and trying to write a sin progression for the uni
As a formula it looks like this:
So I tried to code it... And somehow, it calculates the radian but not the sinus... What is wrong?
#include "stdafx.h"
#include <iostream>
#include <math.h>
using namespace std;
double n, a;
int fakultaet(double a = 2 * n + 1)
{
if (a == 0)
return 1;
else
return (a * fakultaet(a - 1));
}
int _tmain(int argc, _TCHAR* argv[])
{
double sin, y, f; // sin = Sinus, y= angle, n=index
printf("please insert the angle \n");
scanf("%lf", &y);
double x = y * 3.14159265359 * 1 / 180; // x = radian measure
while (n < 5)
{
sin = pow(-1, n) * pow(x, 2 * n + 1) / fakultaet(a);
}
printf("The sinus is %lf\n", sin);
system("Pause");
return 0;
}
You are not incrementing the sin, or the n. Also hardcoding the entry value for the factorial is not good.
It should look more like this:
#include "stdafx.h"
#include <iostream>
#include <math.h>
using namespace std;
int fakultaet(double a)
{
if (a == 0)
return 1;
else
return (a * fakultaet(a - 1));
}
int main()
{
double sin = 0, y, f; // sin = Sinus, y= angle, n=index
printf("please insert the angle \n");
scanf("%lf", &y);
double x = y * 3.14159265359 * 1 / 180; // x = radian measure
for (int n = 0; n < 5; ++n)
{
sin += pow(-1, n) * pow(x, 2 * n + 1) / fakultaet(2 * n + 1);
}
printf("The sinus is %lf\n", sin);
system("Pause");
return 0;
}
I made several edits. I turned the factorial function:
int fakultaet(double a = 2 * n + 1)
into an non hardcoded version:
int fakultaet(double a)
Added the sin initialization:
double sin = 0
Changed your while loop:
while (n < 5)
Into a for which includes the increment that was missing as well:
for (int n = 0; n < 5; ++n)
Also turned the sin calculation:
sin = pow(-1, n) * pow(x, 2 * n + 1) / fakultaet(a);
Into one that sums:
sin += pow(-1, n) * pow(x, 2 * n + 1) / fakultaet(2 * n + 1);
You can get a neater and more efficient result by observing that
adjacent terms in the sum are related. We can express this as a recurrence:
T_n = - T_{n-1} x^2 /((2n+1) (2n))
T_0 = x
This is better since it avoids calls to pow and the need to make any explicit factorial calculations (fakultaet).
The code looks something like:
int main() {
...
double T = x;
double sin = T;
for(int i=1 ; i<5; ++i) {
T *= -(x*x) / ((2*i+1)*(2*i));
sin += T;
}
...
}

How do I express this?

I'm trying to work out how to write the following:
total = (value * 0.95 ^ 0) + (value * 0.95 ^ 1) + (value * 0.95 ^ 2) ...
or:
x = (y * z ^ 0) + (y * z ^ 1) + (y * z ^ 2) + (y * z ^ 3) ...
This expresses how to calculate x for 4 iterations, but how can I express this to work with a variable number of iterations? Obviously I could create a loop and add the values together, but I'd really like to find a single equation that solves this.
I'm using c++ but I guess this isn't really a language specific problem (sorry I literally don't know where else to ask this question!).
Any ideas?
Thanks,
Chris.
There is no need for a loop here, you "just" need to employ some maths.
Note that you can rewrite that as
y * (z0 + z1 + ... + zn)
Now, the series
z0 + z1 + ... + zn
sums to
(z(n+1) - 1) / (z - 1)
so your equation would be
x = y * (z(n+1) - 1) / (z - 1)
Equation-wise solving, this is a geometric series and can therefore be calculated with
double geometric_series(double y, double z, int N) {
return y * (std::pow(z, N) - 1.0) / (z - 1.0);
}
but the same result can be obtained with some fun C++ metaprogramming: if you know the number of iterations in advanced and you're allowed to use C++17 features and fold expressions you could do as follows
template<std::size_t... N>
double calculate_x(double y, double z, std::index_sequence<N...>) { // [0;N[
auto f = [](double y_p, double z_p, double exp) {
return y_p * std::pow(z_p, exp);
};
return (f(y, z, N) + ...);
}
template <std::size_t N>
auto calculate_x(double y, double z) {
return calculate_x(y, z, std::make_index_sequence<N>{});
}
Alternatively this can also be done with pre-C++17 templates
template <int N>
double calculate_x(double y, double z) {
return calculate_x<N-1>(y, z) + (y * std::pow(z, N - 1));
}
template <>
double calculate_x<0>(double, double) {
return 0;
}
Otherwise a simpler solution would be to just use a loop
double calculate_x_simple(double y, double z, int N) {
double ret = 0.0;
for (int i = 0 ; i < N ; ++i)
ret += y * std::pow(z, i);
return ret;
}
Driver for the code above
int main() {
// x = (y * z ^ 0) + (y * z ^ 1) + (y * z ^ 2) + (y * z ^ 3)
double y = 42.0;
double z = 44.5;
std::cout << (calculate_x<3>(y, z) == calculate_x_simple(y, z, 3)); // 1
}
As you mentioned, it seems reasonable to use a loop. But if you know the amount of iterations at compile time, you could use templates like this:
template <int n>
double foo(double y, double z)
{
return foo<n-1>(y, z) + y * std::pow(z, n);
}
template <>
double foo<-1>(double, double)
{
return 0;
}
With just a little bit of optimisation this will unfold to a single equation.
Example:
#include <iostream>
#include <cmath>
template <int n>
double foo(double y, double z)
{
return foo<n-1>(y, z) + y * std::pow(z, n);
}
template <>
double foo<-1>(double, double)
{
return 0;
}
int main()
{
std::cout << foo<2>(2,3) << std::endl;
}
Output: 26
If a loop would be the only option:
double x = 0;
int n = 5;
for(int exponent = 0; exponent <= n; ++exponent)
x += y*pow(z, exponent);
you can just use math.pow function with a for loop
#include <stdio.h>
#include <math.h>
int main(void) {
int i;
int n = 5;
double y = 0.5;
double z = 0.3;
double answer = 0;
for (i = 0 ; i < n ; i++)
answer += y * pow(z,i);
printf("%f", answer);
return 0;
}
It can be expressed as a sum from n=0 to m. It can be expressed in a single formula, according to wolframalpha.
Don't know if this fulfills your purpose, but you can use recursion(which in real terms is a loop only :) )
int x = evaluate(y, z, count);
int evaluate(y,z, count)
{
if (count <= 0)
return 0;
return (evaluate(y, z, count-1) + y*z^count);
}
Using n as the number of iterations,
#include <cmath>
double foo(double y, double z, int n)
{
double x =0;
for(int i = 0 ; i<n; ++i){
x+=y*std::pow(z,i);
}
return x;
}
Where std::pow is the power function.

terminated by signal SIGSEGV (Address boundary error) in recursive function

I'm trying to implement Karatsuba algorithm for multiplication. I'm kinda follow the pseudocode in this wiki page. But I'm always getting this error:
terminated by signal SIGSEGV (Address boundary error)
When I replaced the lines that cause the recursion to happen with something else:
z0 = multiply(a, c);
z1 = multiply(b, d);
z2 = multiply(a+b, c+d);
the error disappeared.
Here's my code:
#include <iostream>
#include <math.h>
long int multiply(int x, int y);
int get_length(int val);
int main()
{
int x = 0, y = 0;
long int result = 0;
std::cout << "Enter x: ";
std::cin >> x;
std::cout << "Enter y: ";
std::cin >> y;
result = multiply(x, y);
std::cout << "Result: " << result << std::endl;
return 0;
}
long int multiply(int x, int y)
{
if(x < 10 || y < 10) {
return x * y;
}
int x_len = get_length(x);
int y_len = get_length(y);
long int z0 = 0 , z1 = 0, z2 = 0;
int a = 0, b = 0, c = 0, d = 0;
a = x / pow(10, x_len);
b = x - (a * pow(10, x_len));
c = y / pow(10, y_len);
d = y - (c * pow(10, y_len));
z0 = multiply(a, c);
z1 = multiply(b, d);
z2 = multiply(a+b, c+d);
return (pow(10, x_len) * z0) + (pow(10, x_len/2) * (z2 - z1 - z0)) + z1;
}
int get_length(int val)
{
int count = 0;
while(val > 0) {
count++;
val /= 10;
}
return count;
}
I found the problem cause.
It was because of these lines:
a = x / pow(10, x_len);
b = x - (a * pow(10, x_len));
c = y / pow(10, y_len);
d = y - (c * pow(10, y_len));
It should be x_len / 2 instead of x_len and the same with y_len. Since it causes the recursion to be infinite.
You are using the pow function to do integer powers. It is not an integer function. Code your own pow function that's suitable for your application. For example:
int pow(int v, int q)
{
int ret = 1;
while (q > 1)
{
ret*=v;
q--;
}
return ret;
}
Make sure to put an int pow(int, int); at the top.

pow() implementation in cmath and efficient replacement [duplicate]

This question already has answers here:
The most efficient way to implement an integer based power function pow(int, int)
(21 answers)
Closed 8 years ago.
I've read that cmath calculates pow(a,b) by performing exp(b*log(a)). This should not be used when b is an integer, since it slows down calculations a lot. What alternatives are there when
calculating a lot of successive pow()s with the same constant a
it is known beforehand that b will definitely be an integer?
I am looking for fast alternatives which are efficient in these particular scenarios.
There are a number of faster alternatives I've collected over the years that typically rely on a recursive implementation of the function, and bit shifts to handle multiplication when warranted. The following provide functions tailored to integer, float and double. They come with the normal disclaimer: while faster not all possible test have been run and the user should validate input is sane before calling and on return... blah, blah, blah.. But, they are pretty darn useful:
I believe proper attribution goes to Geeks for Geeks Pow(x,n) as pointed out by blue moon. I had long since lost the links.. That looks like them. (minus a tweak or two).
/* Function to calculate x raised to the power y
Time Complexity: O(n)
Space Complexity: O(1)
Algorithmic Paradigm: Divide and conquer.
*/
int power1 (int x, unsigned int y)
{
if (y == 0)
return 1;
else if ((y % 2) == 0)
return power1 (x, y / 2) * power1 (x, y / 2);
else
return x * power1 (x, y / 2) * power1 (x, y / 2);
}
/* Function to calculate x raised to the power y in O(logn)
Time Complexity of optimized solution: O(logn)
*/
int power2 (int x, unsigned int y)
{
int temp;
if (y == 0)
return 1;
temp = power2 (x, y / 2);
if ((y % 2) == 0)
return temp * temp;
else
return x * temp * temp;
}
/* Extended version of power function that can work
for float x and negative y
*/
float powerf (float x, int y)
{
float temp;
if (y == 0)
return 1;
temp = powerf (x, y / 2);
if ((y % 2) == 0) {
return temp * temp;
} else {
if (y > 0)
return x * temp * temp;
else
return (temp * temp) / x;
}
}
/* Extended version of power function that can work
for double x and negative y
*/
double powerd (double x, int y)
{
double temp;
if (y == 0)
return 1;
temp = powerd (x, y / 2);
if ((y % 2) == 0) {
return temp * temp;
} else {
if (y > 0)
return x * temp * temp;
else
return (temp * temp) / x;
}
}
Non-recursive non-floating point answer
Replace uintmax_t/intmax_t with the type of your desire. Overflow not detected.
uintmax_t powjuu(unsigned x, unsigned y) {
uintmax_t z = 1;
uintmax_t base = x;
while (y) {
if (y & 1) { // or y%2
z *= base;
}
y >>= 1; // or y /= 2
base *= base;
}
return z;
}
intmax_t powjii(int x, int y) {
if (y < 0) {
switch (x) {
case 0:
return INTMAX_MAX;
case 1:
return 1;
case -1:
return y % 2 ? -1 : 1;
}
return 0;
}
intmax_t z = 1;
intmax_t base = x;
while (y) {
if (y & 1) {
z *= base;
}
y >>= 1;
base *= base;
}
return z;
}
You may want to check this. It's a fast algorithm to replace the pow function.