I'm having problems with this error in pyopencl:
pyopencl.RuntimeError: clBuildProgram failed: invalid binary -
Build on <pyopencl.Device 'GeForce GTX 470' on 'NVIDIA CUDA' at 0x263c1b0>:
ptxas application ptx input, line 116; error : Call has wrong number of parameters
ptxas fatal : Ptx assembly aborted due to errors
here is the piece of Python code:
u_buf = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=u)
v_buf = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=v)
d_dev = cl_array.to_device(queue, delta)
cont_buf = cl.Buffer(ctx, mf.READ_WRITE, size=cont1.nbytes)
P_buf = cl.Buffer(ctx, mf.WRITE_ONLY, size=P.nbytes)
sigma_buf = cl.Buffer(ctx, mf.READ_WRITE, size=sigma.nbytes)
cl.enqueue_write_buffer(queue, sigma_buf, sigma)
kernel = cl.Program(ctx, forward_kernel).build()
kernel.forward(queue, u.shape, None, u_buf, v_buf, d_dev.data, numpy.int16(l), cont_buf, P_buf, sigma_buf)
and the beginning of my kernel:
__kernel void forward(__global const int *u,
__global const int *v,
__global int *d,
const int l,
int cont,
__global int *P,
__global int *sigma )
{
int gid = get_global_id(0);
...
u, v, d, P, sigma are numpy arrays, l is an integer (np.int_), cont1 is meant to be a bool value.
I am not 100% sure what you are about to do, but maybe the following example, which runs on my machhine, helps:
import numpy as np
import pyopencl as cl
import pyopencl.array as cl_array
N = 100
deviceID = 0
platformID = 0
workGroup=(1,1)
dev = cl.get_platforms()[platformID].get_devices()[deviceID]
ctx = cl.Context([dev])
queue = cl.CommandQueue(ctx)
mf = cl.mem_flags
u = np.zeros([N], dtype = int)
v = np.ones([N], dtype = int)
delta = v - u
cont1 = np.int(4)
l = np.int32(3)
P = v
sigma = v
u_buf = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=u)
v_buf = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=v)
d_dev = cl_array.to_device(queue, delta)
P_buf = cl.Buffer(ctx, mf.WRITE_ONLY, size=P.nbytes)
sigma_buf = cl.Buffer(ctx, mf.READ_WRITE, size=sigma.nbytes)
cl.enqueue_write_buffer(queue, sigma_buf, sigma)
prg = cl.Program(ctx, """__kernel void forward(__global const int *u,
__global const int *v,
__global int *d,
int l,
int cont,
__global int *P,
__global int *sigma )
{
int gid = get_global_id(0);
d[gid] = gid;
}""").build()
prg.forward(queue, u.shape, None, u_buf, v_buf, d_dev.data, np.int32(l), np.int32(cont1), P_buf, sigma_buf)
Related
I'm trying to write a pyopencl script to compute Thomas' cyclically symmetric attractor.
The function for which is
x' = sin(y)-bx
y' = sin(z)-by
z' = sin(x)-bz
I have written an implementation in python3 that works, albeit slowly. This is the output I want to get:
working solution
and this is the output from my pyopencl implementation:
broken opencl implementation
I believe I'm encountering some kind of rounding error or approximation error on the sine function, so i tried casting everything to a double with no success. The other possibility I can see is that I am making some mistake in outputting the values reached as the function iterates, but I don't know what it would be.
Here is the kernel in question.
#pragma OPENCL EXTENSION cl_khr_byte_addressable_store : enable
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
__kernel void thomas(__global float3 *a,
__global float3 *output, ulong const maxiter, float const stepSize, float const b )
{
int gid = get_global_id(0);
double x = a[gid][0];
double y = a[gid][1];
double z = a[gid][2];
double x1,y1,z1 = 0.0;
for(int citer = 0; citer<maxiter;citer++){
x1 = x+stepSize*(sin(y)-b*x);
y1 = y+stepSize*(sin(z)-b*y);
z1 = z+stepSize*(sin(x)-b*z);
output[gid*maxiter+citer][0]=x1;
output[gid*maxiter+citer][1]=y1;
output[gid*maxiter+citer][2]=z1;
x = x1;
y = y1;
z = z1;
}
}
a is an array of starting values and the output is an array with length a*maxiter
I expect the output of the pyopencl implementation to match the python3 implementation, but it seems to output a shape only in the xy plane, whose relation to the 3d shape is uncertain to me.
edit: here is the rest of the code for the offending program
import numpy as np
import pyopencl as cl
import open3d as o3d
def calc_thomas_opencl(npoints, stepSize, maxiter, b):
ballRadius = .5
ctx = cl.create_some_context()
queue = cl.CommandQueue(ctx)
mf = cl.mem_flags
points = []
for point in range(npoints):
x1 = np.random.rand()-.5
x2 = np.random.rand()-.5
x3 = np.random.rand()-.5
u = np.random.rand()
fac = ballRadius*u**.3/(np.sqrt(x1**2+x2**2+x3**2))
point = (x1*fac,x2*fac,x3*fac)
points.append(point)
a=np.array(points,dtype = np.float32)
print(a[0])
a_opencl = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=a)
output = np.zeros([npoints*maxiter,3])
output_opencl = cl.Buffer(ctx, mf.WRITE_ONLY, output.nbytes)
prg = cl.Program(ctx, """
#pragma OPENCL EXTENSION cl_khr_byte_addressable_store : enable
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
__kernel void thomas(__global float3 *a,
__global float3 *output, ulong const maxiter, float const stepSize, float const b )
{
int gid = get_global_id(0);
double x = a[gid][0];
double y = a[gid][1];
double z = a[gid][2];
double x1,y1,z1 = 0.0;
for(int citer = 0; citer<maxiter;citer++){
x1 = x+stepSize*(sin(y)-b*x);
y1 = y+stepSize*(sin(z)-b*y);
z1 = z+stepSize*(sin(x)-b*z);
output[gid*maxiter+citer][0]=x1;
output[gid*maxiter+citer][1]=y1;
output[gid*maxiter+citer][2]=z1;
x = x1;
y = y1;
z = z1;
}
}
""").build()
prg.thomas(queue, (npoints,), None, a_opencl,
output_opencl, np.uint64(maxiter), np.float32(stepSize), np.float32(b))
cl.enqueue_copy(queue, output, output_opencl).wait()
return output
xyz = calc_thomas_opencl(1000,.05,1000,.2)
pcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(xyz)
o3d.visualization.draw_geometries([pcd])
The problem was in
output = np.zeros([npoints*maxiter,3])
it needed to be
output = np.zeros([npoints*maxiter,3], dtype = np.float32)
I calculating ((A^B)/C)%M, but my code is not working when A,B,C,M are large in numbers. This code is giving right answer when A,B,C,D is small int.
What is wrong here?
Here C and M is co-prime
Sample input
2 3 4 5
Sample output
2
Code fails for these input
969109092 60139073 122541116 75884463
C program
#include <stdio.h>
int d,x,y;
Modular exponential (A^B)%M
int power(int A, int B, int M)
{
long long int result=1;
while(B>0)
{
if(B % 2 ==1)
{
result=(result * A)%M;
}
A=(A*A)%M;
B=B/2;
}
return result;
}
Modular multiplicative inverse
void extendedEuclid(int A, int B)
{
if(B == 0)
{
d = A;
x = 1;
y = 0;
}
else
{
extendedEuclid(B,A%B);
int temp = x;
x = y;
y = temp - (A/B)*y;
}
}
int modInv(int A, int M)
{
extendedEuclid(A,M);
return (x%M+M)%M;
}
main()
int main()
{
int A,B,C,M;
scanf("%d %d %d %d",&A,&B,&C,&M);
int inv = modInv(C,M)%M;
printf("%d\n",inv);
long long int p = (power(A,B,M))%M;
printf("%d\n",p);
long long int ans = (p * inv)%M;
//printf("%d",((modInv(C,M)*(power(A,B,M))))%M);
printf("%lld",ans);
return 0;
}
Code has at least the following issues:
int overflow in A*A. Code needs to calculate the product A*A using wider math. That is why code works with small values, but not large.
// A=(A*A)%M;
A = ((long long)A*A) % M;
// or
A = (1LL*A*A) % M;
Wrong print specifier. This implies compiler warnings are not fully enabled. Save time, Enable them all.
long long int p = (power(A,B,M))%M;
// printf("%d\n",p);
printf("%lld\n",p);
Code is amiss with negative values. Rather than patch that int hole, use unsigned types.
unsigned power(unsigned A, unsigned B, unsigned M) {
unsigned long long result = 1;
...
Failed corner case in power(A,0,1). result should be 0 when M==1.
// long long int result=1;
long long int result=1%M;
Test version with fixes noted in comments:
#include <stdio.h>
int d,x,y;
int power(int A, int B, int M)
{
long long int result=1;
long long int S = A; /* fix */
while(B>0)
{
if(B % 2 ==1)
{
result=(result * S)%M; /* fix */
}
S=(S*S)%M; /* fix */
B=B/2;
}
return (int)result;
}
void extendedEuclid(int A, int B)
{
int temp; /* C */
if(B == 0)
{
d = A;
x = 1;
y = 0;
}
else
{
extendedEuclid(B,A%B);
temp = x;
x = y;
y = temp - (A/B)*y;
}
}
int modInv(int A, int M)
{
extendedEuclid(A,M);
/* x = x%M; ** not needed */
if (x < 0) /* fix */
x += M; /* fix */
return (x); /* fix */
}
int main()
{
int A,B,C,M; /* C */
int inv, p, ans; /* C */
A = 969109092; /* 2^2 × 3^2 ×7 × 1249 × 3079 */
B = 60139073; /* 60139073 */
C = 122541116; /* 2^2 × 1621 × 18899 */
M = 75884463; /* 3^2 × 8431607 */
inv = modInv(C,M)%M; /* 15543920 */
printf("%d\n",inv);
p = power(A,B,M)%M; /* 6704397 */
printf("%d\n",p);
ans = (unsigned)(((unsigned long long)p * inv)%M); /* fix 22271562 */
printf("%d\n",ans);
return 0;
}
The value of int is probably not large enough, try with long, or double.
Be careful because power returns an int not long long int
You can try the mod_inv C function :
// return a modular multiplicative inverse of n with respect to the modulus.
// return 0 if the linear congruence has no solutions.
unsigned mod_inv(unsigned ra, unsigned rb) {
unsigned rc, sa = 1, sb = 0, sc, i = 0;
if (rb > 1) do {
rc = ra % rb;
sc = sa - (ra / rb) * sb;
sa = sb, sb = sc;
ra = rb, rb = rc;
} while (++i, rc);
sa *= (i *= ra == 1) != 0;
sa += (i & 1) * sb;
return sa;
}
This is basically the standard algorithm, to avoid overflows the signs are stored into the d variable, you could use a struct to do this. Also, when n = 1 and mod = 0 the output is 0, not 1, i think we have not many computations to execute modulo 0.
The modular multiplicative inverse of an integer N modulo m is an integer n such as the inverse of N modulo m equals n, if a modular inverse exists then it is unique. To calculate the value of the modulo inverse, use the extended euclidean algorithm which finds solutions to the Bezout identity.
Example of usage :
#include <assert.h>
int main(void) {
unsigned n, mod, res;
n = 52, mod = 107;
res = mod_inv(n, mod);
assert(res == 35); // 35 is a solution of the linear congruence.
n = 66, mod = 123;
res = mod_inv(n, mod);
assert(res == 0); // 66 does note have an inverse modulo 123.
}
/*
n = 7 and mod = 45 then res = 13 so 1 == ( 13 * 7 ) % 45
n = 52 and mod = 107 then res = 35 so 1 == ( 35 * 52 ) % 107
n = 213 and mod = 155 then res = 147 so 1 == ( 147 * 213 ) % 155
n = 392 and mod = 45 then res = 38 so 1 == ( 38 * 392 ) % 45
n = 687 and mod = 662 then res = 53 so 1 == ( 53 * 687 ) % 662
n = 451 and mod = 799 then res = 512 so 1 == ( 512 * 451 ) % 799
n = 1630 and mod = 259 then res = 167 so 1 == ( 167 * 1630 ) % 259
n = 4277 and mod = 4722 then res = 191 so 1 == ( 191 * 4277 ) % 4722
*/
Source
I have some data and I need to fit a second order "polynomial" in 1/x to it using C and GSL, but I don't really understand how to do it.
The documentation for GSL is, unfortunately, not very helpful, I have read it for a few hours now, but I don't seem to be getting closer to the solution.
Google doesn't turn up anything useful either, and I really don't know what to do anymore.
Could you maybe give me some hints on how to accomplish this, or where even to look?
Thanks
Edit 1: The main problem basically is that
Sum n : a_n*x^(-1)
is not a polynomial, so basic fitting or solving algorithms won't work correctly. That's what I tried, using the code for quadratic fitting from this link, also substituting x->1/x, but it didn't work.
May be it's a bit too late for you to read this. However, I post my answer anyway for other people looking for enlightenment.
I suppose, that this basic example can help you. First of all, you have to read about this method of non-linear fitting since you have to adapt the code for any of your own problem.
Second, it's a bit not really clear for me from your post what function you use.
For the sake of clarity let's consider
a1/x + a2/x**2
where a1 and a2 - your parameters.
Using that slightly modified code from the link above ( I replaced 1/x with 1/(x + 0.1) to avoid singularities but it doesn't really change the picture):
#include <stdlib.h>
#include <stdio.h>
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>
#include <gsl/gsl_matrix.h>
#include <gsl/gsl_vector.h>
#include <gsl/gsl_blas.h>
#include <gsl/gsl_multifit_nlinear.h>
/* number of data points to fit */
#define N 40
#define FIT(i) gsl_vector_get(w->x, i)
#define ERR(i) sqrt(gsl_matrix_get(covar,i,i))
struct data
{
size_t n;
double * y;
};
int expb_f (const gsl_vector * x, void *data, gsl_vector * f)
{
size_t n = ((struct data *)data)->n;
double *y = ((struct data *)data)->y;
double A_1 = gsl_vector_get (x, 0);
double A_2 = gsl_vector_get (x, 1);
size_t i;
for (i = 0; i < n; i++)
{
/* Model Yi = A_1 / x + A_2 / x**2 */
double t = i;
double Yi = A_1 / (t + 0.1) +A_2 / (t*t + 0.2*t + 0.01) ;
gsl_vector_set (f, i, Yi - y[i]);
}
return GSL_SUCCESS;
}
int expb_df (const gsl_vector * x, void *data, gsl_matrix * J)
{
size_t n = ((struct data *)data)->n;
double A_1 = gsl_vector_get (x, 0);
double A_2 = gsl_vector_get (x, 1);
size_t i;
for (i = 0; i < n; i++)
{
/* Jacobian matrix J(i,j) = dfi / dxj, */
/* where fi = (Yi - yi)/sigma[i], */
/* Yi = A_1 / (t + 0.1) +A_2 / (t*t + 0.2*t + 0.01) */
/* and the xj are the parameters (A_1,A_2) */
double t = i;
double e = 1 / (t + 0.1);
double e1 = 1 / (t*t + 0.2*t + 0.01);
gsl_matrix_set (J, i, 0, e);
gsl_matrix_set (J, i, 1, e1);
}
return GSL_SUCCESS;
}
void callback(const size_t iter, void *params, const gsl_multifit_nlinear_workspace *w)
{
gsl_vector *f = gsl_multifit_nlinear_residual(w);
gsl_vector *x = gsl_multifit_nlinear_position(w);
double rcond;
/* compute reciprocal condition number of J(x) */
gsl_multifit_nlinear_rcond(&rcond, w);
fprintf(stderr, "iter %2zu: A_1 = % e A_2 = % e cond(J) = % e, |f(x)| = % e \n", iter, gsl_vector_get(x, 0), gsl_vector_get(x, 1), 1.0 / rcond, gsl_blas_dnrm2(f));
}
int main (void)
{
const gsl_multifit_nlinear_type *T = gsl_multifit_nlinear_trust;
gsl_multifit_nlinear_workspace *w;
gsl_multifit_nlinear_fdf fdf;
gsl_multifit_nlinear_parameters fdf_params = gsl_multifit_nlinear_default_parameters();
const size_t n = N;
const size_t p = 2;
gsl_vector *f;
gsl_matrix *J;
gsl_matrix *covar = gsl_matrix_alloc (p, p);
double y[N], weights[N];
struct data d = { n, y };
double x_init[2] = { 1.0, 1.0 }; /* starting values */
gsl_vector_view x = gsl_vector_view_array (x_init, p);
gsl_vector_view wts = gsl_vector_view_array(weights, n);
gsl_rng * r;
double chisq, chisq0;
int status, info;
size_t i;
const double xtol = 1e-8;
const double gtol = 1e-8;
const double ftol = 0.0;
gsl_rng_env_setup();
r = gsl_rng_alloc(gsl_rng_default);
/* define the function to be minimized */
fdf.f = expb_f;
fdf.df = expb_df; /* set to NULL for finite-difference Jacobian */
fdf.fvv = NULL; /* not using geodesic acceleration */
fdf.n = n;
fdf.p = p;
fdf.params = &d;
/* this is the data to be fitted */
for (i = 0; i < n; i++)
{
double t = i;
double yi = (0.1 + 3.2/(t + 0.1))/(t + 0.1);
double si = 0.1 * yi;
double dy = gsl_ran_gaussian(r, si);
weights[i] = 1.0 / (si * si);
y[i] = yi + dy;
printf ("% e % e \n",t + 0.1, y[i]);
};
/* allocate workspace with default parameters */
w = gsl_multifit_nlinear_alloc (T, &fdf_params, n, p);
/* initialize solver with starting point and weights */
gsl_multifit_nlinear_winit (&x.vector, &wts.vector, &fdf, w);
/* compute initial cost function */
f = gsl_multifit_nlinear_residual(w);
gsl_blas_ddot(f, f, &chisq0);
/* solve the system with a maximum of 20 iterations */
status = gsl_multifit_nlinear_driver(20, xtol, gtol, ftol, callback, NULL, &info, w);
/* compute covariance of best fit parameters */
J = gsl_multifit_nlinear_jac(w);
gsl_multifit_nlinear_covar (J, 0.0, covar);
/* compute final cost */
gsl_blas_ddot(f, f, &chisq);
fprintf(stderr, "summary from method '%s/%s'\n", gsl_multifit_nlinear_name(w), gsl_multifit_nlinear_trs_name(w));
fprintf(stderr, "number of iterations: %zu \n", gsl_multifit_nlinear_niter(w));
fprintf(stderr, "function evaluations: %zu \n", fdf.nevalf);
fprintf(stderr, "Jacobian evaluations: %zu \n", fdf.nevaldf);
fprintf(stderr, "reason for stopping: %s \n", (info == 1) ? "small step size" : "small gradient");
fprintf(stderr, "initial |f(x)| = % e \n", sqrt(chisq0));
fprintf(stderr, "final |f(x)| = % e \n", sqrt(chisq));
{
double dof = n - p;
double c = GSL_MAX_DBL(1, sqrt(chisq / dof));
fprintf(stderr, "chisq/dof = % e \n", chisq / dof);
fprintf (stderr, "A_1 = % f +/- % f \n", FIT(0), c*ERR(0));
fprintf (stderr, "A_2 = % f +/- % f \n", FIT(1), c*ERR(1));
}
fprintf (stderr, "status = %s \n", gsl_strerror (status));
gsl_multifit_nlinear_free (w);
gsl_matrix_free (covar);
gsl_rng_free (r);
return 0;
}
Results of simulations
Unfortunately, Gnuplot doesn't want to fit this data for some reason. Usually it gives the same function up to certain decimal numbers and helps to verify your code.
I'm working on non-linear differential equation using GSL. The thing is I'm quite new on C stuffs. I just adapted the sample on GNU site into the equation I'm interested in right now.
This is the equation:
d2x/dt2 + r*dx/dy + cos(x) + v*cos(2*x+0.4) E1*sin(wt) + E2*sin(2*w*t+a) = 0
What I am stuck is I have no idea how to plug in multiple parameters in the codes. Moreover, I don't know how to employ cosine or sine function in this code.
I tried to figure out this problem, by searching on Google all the way. I couldn't find any thing that helps me.
#include <stdio.h>
#include <gsl/gsl_errno.h>
#include <math.h>
#include <gsl/gsl_math.h>
#include <gsl/gsl_matrix.h>
#include <gsl/gsl_odeiv2.h>
int func (double t, const double x[], double y[], void *params)
{
double r = *(double *)params;
double v = *(double *)params;
double w = *(double *)params;
double E1 = *(double *)params;
double E2 = *(double *)params;
double a = *(double *)params;
y[0] = x[1];
y[1] = -r*x[1] - cos(x[0]) - v*cos(2*x[0]+0.4) - E1*sin(w*t) - E2*sin(2*w*t+a);
return GSL_SUCCESS;
}
int jac (double t, const double x[], double *dydx, double dydt[], void *params)
{
double r = *(double *)params;
double v = *(double *)params;
double w = *(double *)params;
double E1 = *(double *)params;
double E2 = *(double *)params;
double a = *(double *)params;
gsl_matrix_view dydx_mat = gsl_matrix_view_array (dydx, 2, 2);
gsl_matrix * m = &dydx_mat.matrix;
gsl_matrix_set (m, 0, 0, 0.0);
gsl_matrix_set (m, 0, 1, 1.0);
gsl_matrix_set (m, 1, 0, sin(x[0]) + 2*v*sin(2*x[0]+0.4));
gsl_matrix_set (m, 1, 1, -r);
dydt[0] = 0.0;
dydt[1] = 0.0;
return GSL_SUCCESS;
}
int main (void)
{
double r = 0.0;
double v = 0.0;
double w = 2.4;
double E1 = -2.3;
double E2 = 0;
double a = 0.7;
gsl_odeiv2_system sys = {func, jac, 2, &r, &v, &w, &E1, &E2, &a};
gsl_odeiv2_driver *d = gsl_odeiv2_driver_alloc_x_new (&sys, gsl_odeiv2_step_rk8pd, 1e-6, 1e-6, 0.0);
int i;
double t = 0.0, t1 = 10000;
double x[2] = {0.0, 0.0};
for (i = 1 ; i<=10000; i++)
{
double ti = i*t1/10000;
int status = gsl_odeiv2_driver_apply (d, &t, ti, x);
if (status != GSL_SUCCESS)
{
printf("error, return value%d\n", status);
break;
}
printf("%.5e %.5e %.5e\n", t, x[0], x[1]);
}
gsl_odeiv2_driver_free (d);
return 0;
}
The params argument is a pointer (address / memory location) to some arbitrary data structure. In the example from the GSL documentation, their equation contained only one parameter, which means it's okay to just pass the address of a double-precision number.
However, for your problem, you need to access 6 different parameters. You can't access every parameter with the same address!
/* this doesn't work! */
double r = *(double *)params;
double v = *(double *)params;
double w = *(double *)params;
double E1 = *(double *)params;
double E2 = *(double *)params;
double a = *(double *)params;
Since all the addresses are the same, you are referring to the same number. To remedy this, you can either: store all the parameters in an array of length 6, or store them in a predefined data structure. The latter approach is more readable so I will demonstrate that.
First define a data type to specify what parameters you will store:
struct param_type {
double r;
double v;
double w;
double E1;
double E2;
double a;
};
Now, create a structure of this type in the main function and store the actual values of the parameter:
struct param_type my_params = {r, v, w, E1, E2, a};
When defining the system, you store a pointer to that struct param_type:
gsl_odeiv2_system sys = {func, jac, 2, &my_params};
To use the parameter inside func and jac, you simply cast the params argument from a generic pointer (void *) to a pointer for your specific data type (struct param_type *):
struct param_type *my_params_pointer = params;
(Note that in C++ this must be written with an explicit cast.) Finally, you can access the parameters via:
double r = my_params_pointer->r;
double v = my_params_pointer->v;
double w = my_params_pointer->w;
double E1 = my_params_pointer->E1;
double E2 = my_params_pointer->E2;
double a = my_params_pointer->a;
The arrow -> is used here instead of the dot . because my_params_pointer is a pointer and needs to be dereferenced before use.
If you are working with parameters, most likely they are of the same type (double). In that case this can be solved too using an array and then access the elements from func and/or jac.
Another option could be use a gsl_vector and then "get" the values inside the functions. This will involve use free.
I have some exe application. This app has an exporting table and export a bunch of functions. I'd like to use some of them. For example, I need to use ABS function. I opened Ida Pro, looked at pseudocode, and i have the next one:
double __cdecl ABS(double *a1, double *a2)
{
if ( *a2 < 0.0 )
{
*a1 = -1.0 * *a2;
}
else
{
*a1 = *a2;
*(a1 + 4) = *(a2 + 4);
}
return *a1;
}
Then i wrote prototype:
typedef double (*ABS)(double *,double *);
int _tmain(int argc,_TCHAR* argv[])
{
HINSTANCE hMod = LoadLibrary(L"exe.exe");
if (hMod!=NULL)
{
ABS func = (ABS)GetProcAddress(HMod,"ABS");
if (func!=NULL)
{
double x=0;
double y =-2;
double z = func(&x,&y);
}
}
return 0;
}
prototype in my project:
typedef double (*ABS)(double *, double *);
ok, hMod and func not NULL, but al a result I have an error (while reading memory) or some not right values. (exmpl: 483435, -343524)
Help me, please, to correct this situation
Here origin Ida pro pseudosode:
double __cdecl ABS(int a1, int a2)
{
if ( *(double *)a2 < 0.0 )
{
*(double *)a1 = -1.0 * *(double *)a2;
}
else
{
*(_DWORD *)a1 = *(_DWORD *)a2;
*(_DWORD *)(a1 + 4) = *(_DWORD *)(a2 + 4);
}
return *(double *)a1;
}
I thought it is equal to my optimization
PS: *(a1 + 4) = *(a2 + 4); is not means that we move address? Becouse we move pointer values