I have created a simple cpp project in Visual Studio, but have encountered the follwoing linking error:
LNK2019: unresolved external symbol "public: class std::vector > __thiscall solver::euler(class point_3d (__cdecl*)(class point_3d,double),double,int,class point_3d,double)" (?euler#?$solver#Vpoint_3d####QAE?AV?$vector#Vpoint_3d##V?$allocator#Vpoint_3d###std###std##P6A?AVpoint_3d##V4#N#ZNH0N#Z
I have no idea what may be causing this and would be gratefull for any advice.
Files that constitute the project:
main.cpp
#include "point_3d.h"
#include "solver.h"
point_3d lorentz(point_3d val, double t) {
double x = 10*(val.get_y()-val.get_x());
double y = val.get_x()*(28.0- val.get_z())- val.get_y();
double z = val.get_x()* val.get_y()-(8.0/3)* val.get_z();
return point_3d(x, y, z);
}
int main(){
auto file = std::ofstream("data/results.json");
solver<point_3d> sol;
std::vector<point_3d> result = sol.euler(lorentz, 0.01, 50000, point_3d(1, 1, 1));
}
solver.h
template<typename T>
class solver{
public:
std::vector<T> euler(T (*f)(T val, double s),double h, int steps, T val, double t0 = 0.0);
std::vector<T> back_euler(T (*f)(T val, double s), double h, int steps, T val, double t0 = 0.0,int n=50);
std::vector<T> rk_2(T (*f)(T val, double s), double h, int steps, T val, double t0 = 0.0);
std::vector<T> rk_4(T (*f)(T val, double s), double h, int steps, T val, double t0 = 0.0);
};
solver.cpp
#include "solver.h"
template<typename T>
std::vector<T> solver<T>::euler(T (*f)(T val, double s), double h, int steps, T val, double t0 ) {
std::vector<T>res;
res.resize(steps + 1);
res[0] = val;
double t = t0;
for (int i = 0; i < steps;i++) {
res[i + 1] = res[i] + h * f(res[i], t);
t += h;
}
return res;
}
template<typename T>
std::vector<T> solver<T>::back_euler(T (*f)(T val, double s), double h, int steps, T val, double t0, int n) {
std::vector<T>res;
res.resize(steps + 1);
res[0] = val;
double t = t0;
for (int i = 0; i < steps; i++) {
t += h;
res[i + 1] = res[i];
for (int j = 0; j < n; j++) {
res[i + 1] += res[i] + h * f(res[i + 1],t);
}
}
return res;
}
template<typename T>
std::vector<T> solver<T>::rk_2(T (*f)(T val, double s), double h, int steps, T val, double t0) {
std::vector<T>res;
res.resize(steps + 1);
res[0] = val;
double t = t0;
for (int i = 0; i < steps; i++) {
auto k = h * f(res[i], t) / 2.0;
res[i + 1] = res[i] + h * f(k+res[i],t+h/2.0);
t += h;
}
return res;
}
template<typename T>
std::vector<T> solver<T>::rk_4(T (*f)(T val, double s), double h, int steps, T val, double t0) {
std::vector<T>res;
res.resize(steps + 1);
res[0] = val;
double t = t0;
for (int i = 0; i < steps; i++) {
auto k1 = f(res[i],t);
auto k2 = f(res[i]+h/2.0*k1, t+h/3.0);
auto k3 = f(res[i] + h / 2.0 * k2, t + 2*h / 3.0);
auto k4 = f(res[i] + h * k3, t + h);
res[i + 1] = res[i] + (k1 / 6 + k2 / 3 + k3 / 3 + k4 / 6) * h;
t += h;
}
return res;
}
point_3d.h
class point_3d{
double x;
double y;
double z;
public:
point_3d(double x, double y, double z): x(x), y(y), z(z) {};
double get_x();
double get_y();
double get_z();
point_3d operator+(point_3d other);
point_3d& operator=(point_3d other);
friend point_3d operator*(double k, point_3d p);
};
point_3d.cpp
#include "point_3d.h"
double point_3d::get_x() {
return x;
}
double point_3d::get_y() {
return y;
}
double point_3d::get_z() {
return z;
}
point_3d point_3d::operator+(point_3d other) {
double x = get_x() + other.get_x();
double y = get_y() + other.get_y();
double z = get_z() + other.get_z();
return point_3d(x, y, z);
}
point_3d& point_3d::operator=(point_3d other) {
this->x = other.get_x();
this->y = other.get_y();
this->z = other.get_z();
return *this;
}
point_3d operator*(double k, point_3d p) {
double x = p.get_x();
double y = p.get_y();
double z = p.get_z();
return point_3d(k * x, k * y, k * z);
}
You need to include vector library to use std::vector.
#include <vector>
"Unresolved symbol" means that there is a class or a function declared but not found anywhere in the project (or in the libraries it includes).
Related
I am trying to use this library for some work. In the example, which is given on their website, they use an operator for defining gradient calculation. I want to use a method,i.e., getGradient, instead of an operator. I have tried several ways, including std::bind(), &Rosenbrock::getGradient. None of them works fine. Any idea how this can be done? I don't need a full answer, just hint will be enough.
#include <Eigen/Core>
#include <iostream>
#include <LBFGS.h>
using Eigen::VectorXd;
using namespace LBFGSpp;
class Rosenbrock
{
private:
int n;
public:
Rosenbrock(int n_) : n(n_) {}
double operator()(const VectorXd& x, VectorXd& grad);
double getGradient(const VectorXd& x, VectorXd& grad);
};
double Rosenbrock::operator()(const VectorXd& x, VectorXd& grad){
double fx = 0.0;
for(int i = 0; i < n; i += 2)
{
double t1 = 1.0 - x[i];
double t2 = 10 * (x[i + 1] - x[i] * x[i]);
grad[i + 1] = 20 * t2;
grad[i] = -2.0 * (x[i] * grad[i + 1] + t1);
fx += t1 * t1 + t2 * t2;
}
return fx;
}
double Rosenbrock::getGradient(const VectorXd& x, VectorXd& grad){
double fx = 0.0;
for(int i = 0; i < n; i += 2)
{
double t1 = 1.0 - x[i];
double t2 = 10 * (x[i + 1] - x[i] * x[i]);
grad[i + 1] = 20 * t2;
grad[i] = -2.0 * (x[i] * grad[i + 1] + t1);
fx += t1 * t1 + t2 * t2;
}
return fx;
}
int main(int argc, char** argv){
const int n = 10;
// Set up parameters
LBFGSParam<double> param;
param.epsilon = 1e-6;
param.max_iterations = 100;
// Create solver and function object
LBFGSSolver<double> solver(param);
Rosenbrock fun(n);
// Initial guess
VectorXd x = VectorXd::Zero(n);
double fx;
//int niter = solver.minimize(fun, x, fx);
int niter = solver.minimize(std::bind(Rosenbrock::getGradient, fun, _1, _2), x, fx);
// I want to do something similar to this
std::cout << niter << " iterations" << std::endl;
std::cout << "x = \n" << x.transpose() << std::endl;
std::cout << "f(x) = " << fx << std::endl;
return 0;
}
What about:
struct Bind
{
Rosenbrock & impl;
template <typename X, typename Y> // Template here because I'm lazy writing the full type
double operator () (X x, Y y) { return impl.getGradient(x, y); }
Bind(Rosenbrock & impl) : impl(impl) {}
};
// Then use Bind with your solver:
Bind b(fun);
int niter = solver.minimize(b);
// Example with a template (replace X, Y by the argument signature of the method you are binding)
template <typename T, double (T::*Func)(X, Y)>
struct Bind
{
T & impl;
double operator()(X x, Y y) { return (impl.*Func)(x, y); }
Bind(T & ref) : impl(ref) {}
};
// Using like
Bind<Rosenbrock, &Rosenbrock::getGradient> b(fun);
The above Bind class can be a template. It can be a lambda. You're just redirecting the operator() to the method in the binder's operator ().
When I compile the following:
#include "stdafx.h"
#define _USE_MATH_DEFINES
#include <cmath>
#include <iostream>
using namespace std;
#define A 10
double psi(double x);
double qgaus(double(*func)(double), double a, double b);
double normalize();
double psi(double x) {
return pow(sin(M_PI_2*x/ A), 2);
}
double qgaus(double(*func)(double), double a, double b) {
double xr, xm, dx, s;
static double x[] = { 0.0, 0.1488743389, 0.4333953941, 0.6794095682,0.8650633666,0.9739065285 };
static double w[] = { 0.0, 0.2955242247, 0.2692667193, 0.2190863625,0.1494513491,0.0666713443 };
xm = 0.5*(b + a);
xr = 0.5*(b - a);
s = 0;
for (int j = 1; j <= 5; j++) {
dx = xr*x[j];
s += w[j] * ((*func)(xm + dx) + (*func)(xm - dx));
}
return s *= xr;
}
double normalize() {
double N;
N = 1 / sqrt(qgaus(psi, 0.0, A));
return N;
}
int main()
{
double Norm = normalize();
cout << Norm << endl;
return 0;
}
This code compiles without an error. However when I try to put two of the routines into a class as shown here with the changes.
class PsiC {
public:
double psi(double x);
double normalize();
};
double PsiC::normalize() {
PsiC my_psi;
double N;
N = 1 / sqrt(qgaus(my_psi.psi, 0.0, A));
return N;
}
Now using the following in main:
PsiC my_psi;
double Norm = my_psi.normalize();
cout << Norm << endl;
The statement N = 1 / sqrt(qgaus(my_psi.psi, 0.0, A)); gives the compiler error:
'func': function call missing argument list; use '&func' to create a pointer to member.
Note: I only have two member in this class now; however, I intend to add more member later.
I would like to solve a formula
which describes a complex function E extending in r-direction (as a cylindrical coordinate system) and propagating in z-direction. Due to the impossibility to rewrite it to a time derivative I wanted to solve it as
by using the following code:
// MWE_derivation.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "stdafx.h"
#define _USE_MATH_DEFINES
#include <cmath>
#include <iostream>
#include <vector>
#include <complex>
#include <fstream>
//Some typedefs
typedef std::complex<double> COMPLEX;
typedef std::vector<COMPLEX> C_VECTOR;
typedef std::vector<C_VECTOR> C_MATRIX;
//Some constants
#define L0 1.2e-6
#define C90 299792458
#define K0 (2 * M_PI / L0)
#define W0 (2 * M_PI*C90 / L0)
#define FWHM0 250e-15
#define W_PULSE 3.25e-6
#define E_VAL 1.60217662e-19
#define ME 9.10938356e-31
#define M0 0.15*ME
//const double rho0 = 0;
#define BETA0 2e-11
#define HBAR 1.0545718e-34
#define N0 3.52
#define N2 4.5e-18
#define ENERGY 2.5e-6
#define POWER 1e7
#define RANGE_TIME 3
#define RANGE_SPACE 3
//Printing function
void print_vector(const C_VECTOR &data, std::string filename)
{
std::ofstream file_out;
file_out.open(filename);
for (unsigned int j = 0; j < data.size(); j++)
file_out << data[j] << ' ';
file_out << '\n';
file_out.close();
}
//Derivative functions
COMPLEX forward_diff_first(const C_VECTOR &x, const int p0, const double dx)
{
return (x[p0 + 1] - x[p0]) / dx;
}
COMPLEX forward_diff_second(const C_VECTOR &x, const int p0, const double dx)
{
return (x[p0 + 2] - x[p0 + 1] - x[p0 + 1] + x[p0]) / (dx*dx);
}
COMPLEX backward_diff_first(const C_VECTOR &x, const int p0, const double dx)
{
return (x[p0] - x[p0 - 1]) / dx;
}
COMPLEX backward_diff_second(const C_VECTOR &x, const int p0, const double dx)
{
return (x[p0 - 2] - x[p0 - 1] - x[p0 - 1] + x[p0]) / (dx*dx);
}
COMPLEX central_diff_first(const C_VECTOR &x, const int p0, const double dx)
{
return (x[p0 + 1] - x[p0 - 1]) / (2 * dx);
}
COMPLEX central_diff_second(const C_VECTOR &x, const int p0, const double dx)
{
return (x[p0 + 2] - x[p0] - x[p0] + x[p0 - 2]) / (4 * dx*dx);
}
C_VECTOR central_diff_f(const C_VECTOR &x, const double dx)
{
C_VECTOR cdf = C_VECTOR(x.size());
cdf[0] = forward_diff_first(x, 0, dx);
cdf[x.size() - 1] = backward_diff_first(x, x.size() - 1, dx);
for (unsigned int i = 1; i < x.size() - 1; i++)
cdf[i] = central_diff_first(x, i, dx);
return cdf;
}
C_VECTOR forward_diff_f(const C_VECTOR &x, const double dx)
{
C_VECTOR cdf = C_VECTOR(x.size());
cdf[x.size() - 1] = backward_diff_first(x, x.size() - 1, dx);
for (unsigned int i = 0; i < x.size() - 1; i++)
cdf[i] = forward_diff_first(x, i, dx);
return cdf;
}
C_VECTOR backward_diff_f(const C_VECTOR &x, const double dx)
{
C_VECTOR cdf = C_VECTOR(x.size());
cdf[0] = forward_diff_first(x, 0, dx);
for (unsigned int i = 1; i < x.size(); i++)
cdf[i] = backward_diff_first(x, i, dx);
return cdf;
}
C_VECTOR central_diff_s(const C_VECTOR &x, const double dx)
{
C_VECTOR cdf = C_VECTOR(x.size());
cdf[x.size() - 1] = backward_diff_second(x, x.size() - 1, dx);
cdf[x.size() - 2] = backward_diff_second(x, x.size() - 2, dx);
cdf[0] = forward_diff_second(x, 0, dx);
cdf[1] = forward_diff_second(x, 1, dx);
for (unsigned int i = 2; i < x.size() - 2; i++)
cdf[i] = central_diff_second(x, i, dx);
return cdf;
}
//Auxiliary functions
bool isnan(const COMPLEX &in)
{
return isnan(in.real()) || isnan(in.imag());
}
template<typename T>
std::vector<T> linspace(T start_in, T end_in, int num_in)
{
double start = static_cast<double>(start_in);
double end = static_cast<double>(end_in);
double num = static_cast<double>(num_in);
double delta = (end - start) / (num - 1);
std::cout << "Temp_data created\n";
std::vector<T> linspaced(num - 1);
for (int i = 0; i < num - 1; ++i)
{
linspaced[i] = start + delta * i;
}
std::cout << "Filled linspaced\n";
linspaced.push_back(end);
std::cout << "linspaced filled finally\n";
return linspaced;
}
C_VECTOR gaussian(const double w, const std::vector<double> r, const double P0)
{
C_VECTOR ret_val(r.size());
for (unsigned int i = 0; i < r.size(); i++)
{
ret_val[i] = P0 * exp(-COMPLEX(2, 0) * r[i] * r[i] / (w*w));
}
return ret_val;
}
double get_abs(COMPLEX number)
{
return number.real()*number.real() + number.imag()*number.imag();
}
//Main function
C_VECTOR deriv_func(const C_VECTOR &in, const double dx)
{
return central_diff_f(in, dx);
}
C_VECTOR calc_steps(const C_VECTOR &in, const std::vector<double> r, const double dz, const int steps, const COMPLEX pref)
{
C_VECTOR calc_val = in;
C_VECTOR add_vec(in.size());
C_VECTOR rho_vals(in.size());
for (unsigned int i = 0; i < in.size(); i++)
rho_vals[i] = 1e20;
for (int i = 0; i < steps; i++)
{
print_vector(calc_val, "new_vec_" + std::to_string(i) + ".txt");
C_VECTOR deriv = deriv_func(calc_val, abs(r[0] - r[1]));
C_VECTOR deriv2 = central_diff_s(calc_val, abs(r[0] - r[1]));
for (unsigned int j = 1; j < in.size(); j++)
{
if (isnan(deriv[j]))
{
std::cout << "isnan value in round " << i << " detected.\n ";
return calc_val;
}
}
for (unsigned int j = 0; j < in.size(); j++)
{
double r_val = r[j] + 1e-9;
add_vec[j] = pref * dz*(deriv[j] / r_val + deriv2[j])* calc_val[j] + COMPLEX(0, 1)*(K0)*N2 / N0*get_abs(calc_val[j])*calc_val[j] - BETA0 / 2 * calc_val[j] * get_abs(calc_val[j]) - 2*M_PI*COMPLEX(0, 1)*K0*E_VAL*E_VAL/(N0*N0*M0*W0*W0)*rho_vals[j]*calc_val[j];
calc_val[j] += add_vec[j];
}
//calc_val[0] = pref * dz * (deriv[1] / r[1] + deriv2[0])*calc_val[0];
}
return calc_val;
}
int main()
{
double w = 3.25e-6;
int num_vals = 1000;
std::vector<double> r_val = linspace<double>(0.0, 3 * w, num_vals);
C_VECTOR gauss = gaussian(w, r_val, 1e-2);
print_vector(gauss, "gauss.txt");
std::cout << "pref is " << COMPLEX(0, 1 / (2 * K0)) << '\n';
C_VECTOR new_vec = calc_steps(gauss, r_val, 1e-7, 1000, COMPLEX(0, 1)/(2*K0));
print_vector(new_vec, "new_vec.txt");
return 0;
}
Unfortunately I have the problem that my derivative functions add artifacts to the function, resulting in overshooting and extremely large numbers at the borders. This can be seen in the code above with the current values, and already in iteration 2 (in the file new_vec_2.txt, at the left border). The resulting function is not smooth anymore. Adding more points only delays that problem, but does not fix it. Is there anything I can do to improve the code, and to prevent the overshooting? Or is the algorithm in fault, and I have to develop another one?
I wanted to write my own newton fractal generator.. It's using OpenCL... but that's not the problem.. my problem is that atm. only veerryy few pixels are converging.
So to explain what I've done so far:
I've selected a function I wanted to use: f(z)=z^4-1 (for testing purposes)
I've calculated the roots of this function: 1+0î, -1+0î, 0+1î, 0-1î
I've written a OpenCL Host and Kernel:
the kernel uses a struct with 4 doubles: re (real), im (imaginary), r (as abs), phi (as argument, polar angle or how you call it)
computes from resolution, zoom and global_work_id the "type" of the pixel and the intensity - where type is the root the newton method is converging to / whether it's diverging
Here's what I get rendered:
Here is the whole kernel:
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
#define pi 3.14159265359
struct complex {
double im;
double re;
double r;
double phi;
};
struct complex createComplexFromPolar(double _r, double _phi){
struct complex t;
t.r = _r;
t.phi = _phi;
t.re = cos(t.phi)*t.r;
t.im = sin(t.phi)*t.r;
return t;
}
struct complex createComplexFromKarthes(double real, double imag){
struct complex t;
t.re = real;
t.im = imag;
t.phi = atan(imag / real);
t.r = sqrt(t.re*t.re + t.im*t.im);
return t;
}
struct complex recreateComplexFromKarthes(struct complex t){
return t = createComplexFromKarthes(t.re, t.im);
}
struct complex recreateComplexFromPolar(struct complex t){
return t = createComplexFromPolar(t.r, t.phi);
}
struct complex addComplex(const struct complex z, const struct complex c){
struct complex t;
t.re = c.re + z.re;
t.im = c.im + z.im;
return recreateComplexFromKarthes(t);
}
struct complex subComplex(const struct complex z, const struct complex c){
struct complex t;
t.re = z.re - c.re;
t.im = z.im - c.im;
return recreateComplexFromKarthes(t);
}
struct complex addComplexScalar(const struct complex z, const double n){
struct complex t;
t.re = z.re + n;
return recreateComplexFromKarthes(t);
}
struct complex subComplexScalar(const struct complex z, const double n){
struct complex t;
t.re = z.re - n;
return recreateComplexFromKarthes(t);
}
struct complex multComplexScalar(const struct complex z, const double n) {
struct complex t;
t.re = z.re * n;
t.im = z.im * n;
return recreateComplexFromKarthes(t);
}
struct complex multComplex(const struct complex z, const struct complex c) {
return createComplexFromPolar(z.r*c.r, z.phi + c.phi);
}
struct complex powComplex(const struct complex z, int i){
struct complex t = z;
for (int j = 0; j < i; j++){
t = multComplex(t, z);
}
return t;
}
struct complex divComplex(const struct complex z, const struct complex c) {
return createComplexFromPolar(z.r / c.r, z.phi - c.phi);
}
bool compComplex(const struct complex z, const struct complex c, float comp){
struct complex t = subComplex(z, c);
if (fabs(t.re) <= comp && fabs(t.im) <= comp)
return true;
return false;
}
__kernel void newtonFraktal(__global const int* res, __global const int* zoom, __global int* offset, __global const double* param, __global int* result, __global int* resType){
const int x = get_global_id(0) + offset[0];
const int y = get_global_id(1) + offset[1];
const int xRes = res[0];
const int yRes = res[1];
const double a = (x - (xRes / 2)) == 0 ? 0 : (double)(zoom[0] / (x - (double)(xRes / 2)));
const double b = (y - (yRes / 2)) == 0 ? 0 : (double)(zoom[1] / (y - (double)(yRes / 2)));
struct complex z = createComplexFromKarthes(a, b);
struct complex zo = z;
struct complex c = createComplexFromKarthes(param[0], param[1]);
struct complex x1 = createComplexFromKarthes(1,0);
struct complex x2 = createComplexFromKarthes(-1, 0);
struct complex x3 = createComplexFromKarthes(0, 1);
struct complex x4 = createComplexFromKarthes(0, -1);
resType[x + xRes * y] = 3;
int i = 0;
while (i < 30000 && fabs(z.r) < 10000){
z = subComplex(z, divComplex(subComplexScalar(powComplex(z, 4), 1), multComplexScalar(powComplex(z, 3), 4)));
i++;
if (compComplex(z, x1, 0.05)){
resType[x + xRes * y] = 0;
break;
} else if (compComplex(z, x2, 0.05)){
resType[x + xRes * y] = 1;
break;
} else if (compComplex(z, x3, 0.05)){
resType[x + xRes * y] = 2;
break;
}
}
if (fabs(z.r) >= 10000){
resType[x + xRes * y] = 4;
}
result[x + xRes * y] = i;
}
And here is the coloration of the image:
const int xRes = core->getXRes();
const int yRes = core->getYRes();
for (int y = 0; y < fraktal->getHeight(); y++){
for (int x = 0; x < fraktal->getWidth(); x++){
int conDiv = genCL->result[x + y * xRes];
int type = genCL->typeRes[x + y * xRes];
if (type == 0){
//converging to x1
fraktal->setPixel(x, y, 1*conDiv, 1*conDiv, 0, 1);
} else if (type == 1){
//converging to x2
fraktal->setPixel(x, y, 0, 0, 1*conDiv, 1);
} else if (type == 2){
//converging to x3
fraktal->setPixel(x, y, 0, 1*conDiv, 0, 1);
} else if (type == 3){
//diverging and interrupted by loop end
fraktal->setPixel(x, y, 1*conDiv, 0, 0, 1);
} else {
//diverging and interrupted by z.r > 10000
fraktal->setPixel(x, y, 1, 1, 1, 0.1*conDiv);
}
}
}
I had some mistakes in the complex number computations but I check everything today again and again.. I think they should be okay now.. but what else could be the reason that there are just this few start values converging? Did I do something wrong with newton's method?
Thanks for all your help!!
Well somewhat it really helped to run the code as normal C code.. as this makes Debugging easier: so the issue were some coding issues which I have been able to solve now.. for example my pow function was corrupted and when I added or subtracted I forgot to set the imaginary part to the temp complex number .. so here's my final OpenCL kernel:
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
#define pi 3.14159265359
struct complex {
double im;
double re;
double r;
double phi;
};
struct complex createComplexFromPolar(double _r, double _phi){
struct complex t;
t.r = _r;
t.phi = _phi;
t.re = _r*cos(_phi);
t.im = _r*sin(_phi);
return t;
}
struct complex createComplexFromKarthes(double real, double imag){
struct complex t;
t.re = real;
t.im = imag;
t.phi = atan2(imag, real);
t.r = sqrt(t.re*t.re + t.im*t.im);
return t;
}
struct complex recreateComplexFromKarthes(struct complex t){
return createComplexFromKarthes(t.re, t.im);
}
struct complex recreateComplexFromPolar(struct complex t){
return createComplexFromPolar(t.r, t.phi);
}
struct complex addComplex(const struct complex z, const struct complex c){
return createComplexFromKarthes(c.re + z.re, c.im + z.im);
}
struct complex subComplex(const struct complex z, const struct complex c){
return createComplexFromKarthes(z.re - c.re, z.im - c.im);
}
struct complex addComplexScalar(const struct complex z, const double n){
return createComplexFromKarthes(z.re + n,z.im);
}
struct complex subComplexScalar(const struct complex z, const double n){
return createComplexFromKarthes(z.re - n, z.im);
}
struct complex multComplexScalar(const struct complex z, const double n){
return createComplexFromKarthes(z.re * n,z.im * n);
}
struct complex multComplex(const struct complex z, const struct complex c) {
return createComplexFromKarthes(z.re*c.re-z.im*c.im, z.re*c.im+z.im*c.re);
//return createComplexFromPolar(z.r*c.r, z.phi + c.phi);
}
struct complex powComplex(const struct complex z, int i){
struct complex t = z;
for (int j = 0; j < i-1; j++){
t = multComplex(t, z);
}
return t;
}
struct complex divComplex(const struct complex z, const struct complex c) {
return createComplexFromPolar(z.r / c.r, z.phi-c.phi);
}
bool compComplex(const struct complex z, const struct complex c, float comp){
if (fabs(z.re - c.re) <= comp && fabs(z.im - c.im) <= comp)
return true;
return false;
}
__kernel void newtonFraktal(__global const int* res, __global const int* zoom, __global int* offset, __global const double* param, __global int* result, __global int* resType){
const int x = get_global_id(0) + offset[0];
const int y = get_global_id(1) + offset[1];
const int xRes = res[0];
const int yRes = res[1];
const double a = (x - (xRes / 2)) == 0 ? 0 : (double)((x - (double)(xRes / 2)) / zoom[0]);
const double b = (y - (yRes / 2)) == 0 ? 0 : (double)((y - (double)(yRes / 2)) / zoom[1]);
struct complex z = createComplexFromKarthes(a, b);
//struct complex c = createComplexFromKarthes(param[0], param[1]);
struct complex x1 = createComplexFromKarthes(0.7071068, 0.7071068);
struct complex x2 = createComplexFromKarthes(0.7071068, -0.7071068);
struct complex x3 = createComplexFromKarthes(-0.7071068, 0.7071068);
struct complex x4 = createComplexFromKarthes(-0.7071068, -0.7071068);
struct complex f, d;
resType[x + xRes * y] = 11;
int i = 0;
while (i < 6000 && fabs(z.r) < 10000){
f = addComplexScalar(powComplex(z, 4), 1);
d = multComplexScalar(powComplex(z, 3), 3);
z = subComplex(z, divComplex(f, d));
i++;
if (compComplex(z, x1, 0.0000001)){
resType[x + xRes * y] = 0;
break;
} else if (compComplex(z, x2, 0.0000001)){
resType[x + xRes * y] = 1;
break;
} else if (compComplex(z, x3, 0.0000001)){
resType[x + xRes * y] = 2;
break;
} else if (compComplex(z, x4, 0.0000001)){
resType[x + xRes * y] = 3;
break;
}
}
if (fabs(z.r) >= 1000){
resType[x + xRes * y] = 10;
}
result[x + xRes * y] = i;
}
hope it might help someone someday.. :)
I've been trying to resolve a error for the last day or so and can't seem to work it through.
It's the kind of error that the fix is probably very easy :S
I tried to search for similar questions but the fixes don't apply.
main.c
int main(int argc, char *argv[]){
int width, height;
std::vector<Obj*> world;
world.push_back(new Sphere(Vec(0, 0, -22), 2, Vec(0.2, 0.2, 0.2), true));
(...)
return 0;
}
The error is found when I try to create a Sphere.
Relevant classes
Obj.h
class Obj
{
public:
Vec color;
bool culling;
virtual bool intersect(const Vec &ray_orig, Vec &ray_dir, float *t0 = NULL, float *t1 = NULL) = 0;
};
Sphere.h
class Sphere: public Obj
{
public:
Vec center;
float radius, radius2;
Sphere(Vec center, float radius, Vec color, bool culling);
bool intersect(const Vec &ray_orig, Vec &ray_dir, float *t0 = NULL, float *t1 = NULL);
};
Sphere.c
Sphere::Sphere(Vec center, float radius, Vec color, bool culling){
this->center = center;
this->radius = radius;
this->color = color;
this->culling = culling;
}
bool Sphere::intersect(const Vec &ray_orig, Vec &ray_dir, float *t0 = NULL, float *t1 = NULL) {...}
These second error appears when I do this->color = color;. Not sure if they are related.
Vec is a simple struct with 3 variables.
If you need more information I'll add as soon as possible.
Thank you in advance.
Jose
EDIT
Sorry for the delay.
intersect(...) is the only function in the obj class. Is there anyway to maintain the abstraction since there are several objects(sphere,box,...).
As requested here goes the definition of vec.h
vec.h
struct Vec {
float x, y, z;
Vec() {x = 0, y = 0, z = 0;}
Vec(float val) {x = val, y = val, z = val;}
Vec(float x_val,float y_val,float z_val) {x = x_val, y = y_val, z = z_val;}
Vec(const Vec& copy) : x(copy.x), y(copy.y), z(copy.z) { }
Vec operator+ (const Vec& p) const {
return Vec(x + p.x, y + p.y, z + p.z);
}
Vec operator- (const Vec& p) const {
return Vec(x - p.x, y - p.y, z - p.z);
}
Vec& operator += (const Vec& p) {
x += p.x; y += p.y; z += p.z;
return *this;
}
Vec& operator -= (const Vec& p) {
x -= p.x; y -= p.y; z -= p.z;
return *this;
}
Vec operator* (const float f) const {
return Vec(f * x, f * y, f * z);
}
Vec& operator*= (const float f) {
x *= f; y *= f; z *= f;
return *this;
}
Vec operator/ (const float f) const {
float inv = 1.f / f;
return Vec(inv * x, inv * y, inv * z);
}
Vec& operator/= (const float f) {
float inv = 1.f / f;
x *= inv; y *= inv; z *= inv;
return *this;
}
Vec& operator= (const Vec& p) {
x = p.x; y = p.y; z = p.z;
return *this;
}
bool operator== (const Vec& p) {
if(x == p.x && y == p.y && z == p.z)
return true;
return false;
}
float length_squared() const {
return x*x + y*y + z*z;
}
float length() const {
return sqrt(length_squared());
}
Vec norm() const {
float nor = x * x + y * y + z * z;
if (nor > 0) {
float invNor = 1 / sqrt(nor);
(float)x *= invNor, (float)y *= invNor, (float)z *= invNor;
}
return *this;
}
Vec cross(const Vec&b) {
return Vec(y*b.z-z*b.y,z*b.x-x*b.z,x*b.y-y*b.x);
}
float dot(const Vec& v) {
return x * v.x + y * v.y + z * v.z;
}
};
It seems the problem was indeed in the vec file.
Can't find a reasoning about the fix, but changing the Vec struct to a class fixed all the problems.
Thanks for the help.