A int64_t value overflows in a structure in C - c

I want to create a polynomial with only one term: 6/5 and display it.
It should print this: 6/5X^0
The structure of polynomial is :
typedef struct __poly_struct_t *poly_t;
struct __poly_struct_t{
unsigned int deg;
ratio_t *coeffs;
};
Where ratio_t is an array of rational numbers, it's structure is:
typedef struct __ratio_struct_t{
int64_t num;
int64_t den;
}ratio_t;
I used two functions to construct this polynomial. polyFromRatioArray works: it prints 6/5X^0
poly_t polyFromRatioArray(ratio_t *c, unsigned int degree){
poly_t p = (struct __poly_struct_t*)malloc(sizeof(struct __poly_struct_t));
p->deg = degree;
p->coeffs = c;
return p;
}
The other one made the denominator overflowed: polyFromRatio prints 6/140218959144480X^0
poly_t polyFromRatio(ratio_t c){
return polyFromRatioArray(&c, 0);
}
Main function:
int main(){
ratio_t ra = createRatio((int64_t)6,(int64_t)5);
poly_t p1 = polyFromRatioArray(&ra, 0); // one that works
polyPrint(p1);
poly_t p2 = polyFromRatio(ra); // this doesn't
polyPrint(p2);
free(p1);
free(p2);
return 0;
}
Other fonctions involved:
ratio_t createRatio(int64_t a, int64_t b){
if(b == 0){
printf("Error : a divise by 0 \n");
exit(1);
}
ratio_t r;
int64_t pgcd = gcd(a, b); // gcd(int64_t a, int64_t b) is a function that finds pgcd using Euclid.
r.num = a/pgcd;
r.den = b/pgcd;
return r;
}
int64_t gcd(int64_t a, int64_t b){
int64_t u, v, g;
ext_eucl_div(&u, &v, &g, llabs(a), llabs(b));
return g;
}
void ext_eucl_div(int64_t *u, int64_t *v, int64_t *g, int64_t a, int64_t b){ // this function stocks pgcd of a and b in g
int64_t u1, u2, u3 , v1, v2, v3, q, t1, t2, t3;
int tour = 0;
do{
if(tour == 0){
u1 = 1; u2 = 0; u3 = a; v1 = 0; v2 = 1; v3 = b;
}
else{
u1 = v1; u2 = v2; u3 = v3; v1 = t1; v2 = t2; v3 = t3;
}
q = u3/v3;
t1 = u1 - q*v1;
t2 = u2 - q*v2;
t3 = u3%v3;
tour++;
} while(t3>=1);
*u = v1;
*v = v2;
*g = v3;
}
void polyPrint(poly_t p){
unsigned int i;
for(i=0; i<= p->deg; i++){
if(p->coeffs[i].num != 0){
printRatio(p->coeffs[i]);
if(i != p->deg) printf("X^%u + ", i);
else printf("X^%u\n", i);
}else printf("0\n");
}
}
void printRatio(ratio_t a){
printf("%" PRId64, a.num);
printf("/%" PRId64, a.den);
}
This is very strange, polyFromRatioArray and polyFromRatio seem like doing the same thing but nope.

Related

How do we import C code outputs to be used in matlab for visualisation

i have a C code that finds the solution of a function using the methode of bisection and Newton Raphson, and i want to compare the results using graphs ( i am asked to do so in matlab as it's a school project ), but i have no idea how.
here's my code :
`
#include <stdio.h>
#include <math.h>
#include<stdio.h>
#include<math.h>
float F0 (float V)
{
float J0 = 1e-15;
float n = 0.68;
float V0 = 0.025;
int E = 1;
int R = 100;
return (E-V-R*J0*(exp(n*V/V0)-1));
}
float F1 (float V)
{
float J0 = 1e-15;
float n = 0.68;
float V0 = 0.025;
int E = 1;
int R = 100;
return (-1-n*R*J0/V0*exp(n*V/V0));
}
void Dichotomie (float *V, float a, float b, int *itr)
{
*V=(a+b)/2;
++(*itr);
printf("Iteration no. %3d V = %7.5f\n", *itr, *V);
}
void Newton(int itr, int maxmitr, float h, float V0, float V1, float err)
{
for (itr=1; itr<=maxmitr; itr++)
{
h=F0(V0)/F1(V0);
V1=V0-h;
printf("Iteration no. %3d, V = %9.6f\n", itr, V1);
if (fabs(h) < 2*err)
{
printf("After %3d iterations, root = %8.6f\n", itr, V1);
return;
}
V0=V1;
}
printf(" The required solution does not converge or iterations are insufficient\n");
return;
}
int main ()
{
float J0 = 1e-15;
float n = 0.68;
float V0 = 0.025;
int E = 1;
int R = 100;
int itr = 0, maxmitr;
float V, a, b, err, V1;
float h;
a = 0;
b = 1;
err = 0.000001;
maxmitr = 100;
Newton(itr, maxmitr,h,V0,V1,err);
Dichotomie (&V, a, b, &itr);
do
{
if (F0(a)*F0(V) < 0)
b=V;
else
a=V;
Dichotomie (&V1, a, b, &itr);
if (fabs(V1-V) < 2*err)
{
printf("After %d iterations, root = %6.6f\n", itr, V1);
return 0;
}
V=V1;
}
while (itr < maxmitr);
printf("The solution does not converge or iterations are not sufficient");
return 1;
}
`
I read some documentations about this in the Matlab website, and i found that there is a function block in Simulink to be used, but i have no idea how Simulink works.

OpenMP paralleling GSL Ordinary Differential Equations calculation

I'm trying to parallelize my code, but i got errors. I need to calc a Cauchy problem (it's already done) but than i need to parallelize it using OpenMP lib.
I've tried to write some code with OpenMP, but it's not working.
I've created a struct to collect result.
struct Dots {
double par;
double x;
double y;
};
This is my target function with parameter.
int ode_func (double x, const double y[], double f[], void *params)
{
double mu = *(int *)params;
f[0] = x + 2 * y[0] / (1 + mu * mu);
return GSL_SUCCESS;
}
This is the main function. I currently didn't find a way how to create a array of arrays of struct, but this is not the main problem.
void calc_cauchy_problem(struct Dots ArrayOfDots[], double x_start, double x_end, double y_start,
int count) {
int dim = 1;
double x = x_start;
double y[1] = {y_start};
int mu = 5;
int param = 0;
gsl_odeiv2_system sys = {ode_func, NULL, dim, &param};
gsl_odeiv2_driver * d = gsl_odeiv2_driver_alloc_y_new (&sys,
gsl_odeiv2_step_rkf45, 1e-6, 1e-6, 0.0);
int status = 0;
#pragma omp parallel for shared(ArrayOfDots) private(sys, param, d, status)
for (int param = 1; param < mu; param++) {
gsl_odeiv2_system sys = {ode_func, NULL, dim, &param};
gsl_odeiv2_driver * d = gsl_odeiv2_driver_alloc_y_new (&sys,
gsl_odeiv2_step_rkf45, 1e-6, 1e-6, 0.0);
for (int i = 1; i <= count; i++)
{
double xi = x_start + i * (x_end - x_start) / count;
int status = gsl_odeiv2_driver_apply(d, &x, xi, y);
if (status != GSL_SUCCESS)
{
printf ("error, return value=%d\n", status);
break;
}
// ArrayOfDots[i].par = mu;
// ArrayOfDots[i].x = xi;
// ArrayOfDots[i].y = y[0];
}
gsl_odeiv2_driver_free (d);
}
}
The main
int main() {
double x_start = 0;
double x_end = 10;
double y_start = 0;
int count = 10;
struct Dots ArrayOfDots[count];
calc_cauchy_problem(ArrayOfDots, x_start, x_end, y_start, count);
return 0;
}
It's compiled successfully with this gcc main.c -o main -fopenmp -lgsl -std=gnu11 but when i launch it i got error
gsl: driver.c:354: ERROR: integration limits and/or step direction not consistent
Default GSL error handler invoked.
I think that the main problem with this #pragma omp parallel for shared(ArrayOfDots) private(sys, param, d, status) but i have no idea how to rewrite this in the other way.
Thanks for your responses.
UPD:
With Kaveh Vahedipour help my code partially start to work. It means that half of my for cycle start to work.
UPD UPD:
After another investigations i had the following code:
It's compile and run, but i got Process finished with exit code 4 and printf("Elapsed time = %f\n", omp_get_wtime() - start_time); don't print anything.
struct Dots {
double par;
double x;
double y;
};
int ode_func (double x, const double y[], double f[], void *params)
{
double mu = *(int *)params;
f[0] = (x + 2 * y[0]) / (1 + mu * mu);
return GSL_SUCCESS;
}
void calc_cauchy_problem(double x_start, double x_end, double y_start,
int count, int param1, int param2) {
int dim = 1;
double x = x_start;
double y[1] = {y_start};
int param = param1;
int j = 0;
int status = 0;
char filename[10];
#pragma omp parallel for private(param, status, x, y)
for (param = param1; param <= param2; param++) {
struct Dots ArrayOfDots[count];
gsl_odeiv2_system sys = {ode_func, NULL, dim, &param};
gsl_odeiv2_driver * d =
gsl_odeiv2_driver_alloc_y_new (&sys, gsl_odeiv2_step_rkf45, 1e-6, 1e-6, 0.0);
for (int i = 1; i <= count; i++) {
double xi = x_start + i * (x_end - x_start) / count;
int status = gsl_odeiv2_driver_apply(d, &x, xi, y);
if (status != GSL_SUCCESS)
{
printf ("error, return value=%d\n", status);
break;
}
ArrayOfDots[i].par = param;
ArrayOfDots[i].x = xi;
ArrayOfDots[i].y = y[0];
}
gsl_odeiv2_driver_free (d);
}
}
int main() {
double start_time = omp_get_wtime();
double x_start = 0;
double x_end = 10;
double y_start = 0;
const int count = 500;
int param1 = 1;
int param2 = 10;
calc_cauchy_problem(x_start, x_end, y_start, count, param1, param2);
printf("Elapsed time = %f\n", omp_get_wtime() - start_time);
return 0;
}
Add x to private loop vars: private(sys, param, d, status, x). Please get back to me, if you still experience issues.
void calc_cauchy_problem(double x_start, double x_end, double y_start,
int count, int param1, int param2) {
int dim = 1;
double x = x_start;
double y[1] = {y_start};
int param = param1;
int j = 0;
int status = 0;
char filename[10];
#pragma omp parallel for private(param, status, x, y)
for (param = param1; param <= param2; param++) {
struct Dots ArrayOfDots[count];
gsl_odeiv2_system sys = {ode_func, NULL, dim, &param};
gsl_odeiv2_driver * d =
gsl_odeiv2_driver_alloc_y_new (&sys, gsl_odeiv2_step_rkf45, 1e-6, 1e-6, 0.0);
for (int i = 1; i <= count; i++) {
double xi = x_start + i * (x_end - x_start) / count;
int status = gsl_odeiv2_driver_apply(d, &x, xi, y);
if (status != GSL_SUCCESS)
{
printf ("error, return value=%d\n", status);
break;
}
ArrayOfDots[i].par = param;
ArrayOfDots[i].x = xi;
ArrayOfDots[i].y = y[0];
}
//write_data_to_file(param, count, ArrayOfDots);
for (int i = 0; i < count; ++i) {
printf ("%d: %f, %f, %f\n", omp_get_thread_num(),
ArrayOfDots[i].par, ArrayOfDots[i].x, ArrayOfDots[i].y);
}
gsl_odeiv2_driver_free (d);
}
}
Seems like this version works fine. I think problem was with this struct Dots ArrayOfDots[count]; and when i try to push values to this struct.
ArrayOfDots[i].par = param;
ArrayOfDots[i].x = xi;
ArrayOfDots[i].y = y[0];
Here is the full code.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <omp.h>
// GSL lib includes
#include <gsl/gsl_sf_bessel.h>
#include <gsl/gsl_errno.h>
#include <gsl/gsl_matrix.h>
#include <gsl/gsl_odeiv2.h>
int ode_func (double x, const double y[], double f[], void *params)
{
double mu = *(int *)params;
f[0] = (x + 2 * y[0]) / (1 + mu * mu);
return GSL_SUCCESS;
}
void calc_cauchy_problem(double x_start, double x_end, double y_start,
int count, int param1, int param2) {
#pragma omp parallel for
for(int param = param1; param < param2; param++) {
gsl_odeiv2_system sys = {ode_func, NULL, 1, &param};
gsl_odeiv2_driver * d =
gsl_odeiv2_driver_alloc_y_new (&sys, gsl_odeiv2_step_rk8pd,
1e-6, 1e-6, 0.0);
int i;
double x = x_start, x1 = x_end;
double y[1] = { y_start };
for (i = 1; i <= count; i++)
{
double xi = i * x1 / count;
int status = gsl_odeiv2_driver_apply (d, &x, xi, y);
if (status != GSL_SUCCESS)
{
printf ("error, return value=%d\n", status);
break;
}
// printf ("%d %d %.5e %.5e\n", omp_get_thread_num(), param, x, y[0]);
}
gsl_odeiv2_driver_free (d);
}
}
int main() {
double start_time = omp_get_wtime();
double x_start = 0;
double x_end = 10;
double y_start = 0;
const int count = 100000;
int param1 = 1;
int param2 = 20;
calc_cauchy_problem(x_start, x_end, y_start, count, param1, param2);
printf("Elapsed time = %f\n", omp_get_wtime() - start_time);
return 0;
}
Really thanks to Kaveh Vahedipour.

Directed graph: (non simple) path with the maximum weight

A directed and weighted graph is saved in a file through the list of its edges with the following format: v1 val v2, where indicating that v1 is connected to v2 with an edge with weight val(int > 0).
This is an example of the input file
fF 1 123
A0 2 fF
A0 5 h9
h9 3 123
123 2 F2
123 4 d1
F2 3 Dd
F2 4 d1
d1 2 Dd
d1 4 xd
d1 1 h9
Dd 5 xd
xd 4 A0
F2 3 fF
I have to write a C program that:
read the file and save the graph in an appropriate data structure
after receiving two vertices v1 and v2 and two ints k and p (k<=p), print the path thath starts in v1 and ends in v2 which respects the following constraints
is maximum the sum of the weights
are re-crossed at least k vertices
the complessive number of the re-crossing is at least p
the path ends when it arrives on the destination vertex
I solved the first point but I have no idea for the second. This is all the code I wrote:
main.c
#include <stdio.h>
#include <stdlib.h>
#include "graph.h"
void main() {
int k = 1, p = 1;
char v1[21], v2[21];
graph_t G = GRAPHread("file.txt");
printf("Insert 2 vertex");
scanf("%s %s", v1, v2);
GRAPHfindPath(G, k, p, v1, v2);
}
edge.h
#ifndef EDGE_H
#define EDGE_H
typedef struct edge_s { int v; int w; int wt; } edge_t;
edge_t EDGEcreate(int v, int w, int wt);
#endif
edge.c
#include "edge.h"
edge_t EDGEcreate(int v, int w, int wt) {
edge_t e;
e.v = v;
e.w = w;
e.wt = wt;
return e;
}
ST.h
#ifndef ST_H
#define ST_H
typedef struct symbletable_s *st_t;
int STinsert(st_t st, char *key);
int STsearch(st_t st, char *k);
st_t STinit(int maxN);
#endif
ST.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ST.h"
struct symbletable_s { char **a; int M; };
st_t STinit(int maxN) {
int i;
st_t st = malloc(sizeof(*st));
st->M = maxN;
st->a = malloc(sizeof(char *)*st->M);
return st;
}
int hash(char *k, int M) {
int h = 0, base = 127;
for (; *k != '\0'; k++) h = (base*h + *k) % M;
return h;
}
int full(st_t st, int i) {
if (st->a[i] == NULL) return 1;
return 0;
}
int STinsert(st_t st, char *key) {
int i = hash(key, st->M);
while (full(st,i))
i = (i + 1) % st->M;
st->a[i] = malloc(sizeof(char)*(strlen(key) + 1));
memcpy(st->a[i], key, strlen(key) + 1);
return i;
}
int STsearch(st_t st, char *k) {
int i = hash(k, st->M);
while (full(st, i)) {
if (strcmp(k, st->a[i]) == 0) return i;
else i = (i + 1) % st->M;
}
return -1;
}
graph.h
#ifndef GRAPH_H
#define GRAPH_H
typedef struct graph_s *graph_t;
graph_t GRAPHread(char *s);
void GRAPHfindPath(graph_t G, int k, int p, char *v1, char *v2);
#endif
graph.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "graph.h"
#include "ST.h"
#include "edge.h"
#define MAX 21
typedef struct node_s *link;
struct node_s { int v; int wt; link next; };
struct graph_s {
int V;
int E;
link *adj_l;
link z;
st_t tab;
};
link NEW(int v, int wt, link next) {
link x = malloc(sizeof *x);
x->v = v;
x->next = next;
x->wt = wt;
return x;
}
graph_t GRAPHinit(int V) {
int v;
graph_t G = malloc(sizeof *G);
G->V = V; G->E = 0; G->z = NEW(-1, -1, NULL);
G->adj_l = malloc(G->V*sizeof(link));
for (v = 0; v < G->V; v++)
G->adj_l[v] = G->z;
G->tab = STinit(V);
return G;
}
void insertE(graph_t G, edge_t e) {
int v = e.v, w = e.w, wt = e.wt;
G->adj_l[v] = NEW(w, wt, G->adj_l[v]);
G->adj_l[w] = NEW(v, wt, G->adj_l[w]);
G->E++;
}
graph_t GRAPHread(char *s) {
graph_t G;
char src[MAX], dst[MAX];
char v1[MAX], v2[MAX];
int nE = 0, i, i1, i2, wt;
FILE *fp = fopen(s, "r");
while (fscanf(fp, "%*s %*d %*s") != EOF)
nE++;
rewind(fp);
G = GRAPHinit(nE * 2);
for (i = 0; i < nE; i++) {
fscanf(fp, "%s %d %s", src, &wt, dst);
i1 = STinsert(G->tab, src);
i2 = STinsert(G->tab, dst);
insertE(G, EDGEcreate(i1, i2, wt));
}
fclose(fp);
return G;
}
void GRAPHfindPath(graph_t G, int k, int p, char *v1, char *v2) {
}

segmentation fault (core dumped) in recursive algorithm

This is a program to calculate a definite integral using numerical quadrature method (I don't know if this is the right translation):
#include <math.h>
#include <stdio.h>
float f(float x){
float y;
y = 4/(+x*x);
return y;
}
void quadra(float a, float b, float *Q, float *E, float f(float)){
float q1, q2, m, h, fa, fb;
h = b - a;
fa = f(a);
fb = f(b);
q1 = (fa+fb)*h/2.;
m = (a+b)/2.;
q2 = ( (fa+2*f(m)+fb) ) *h/4;
*Q = q2;
*E = fabs(q2-q1)/3;
}
void scambia(float *x, float *y) {
float z;
z = *x;
*x = *y;
*y = z;
return;
}
void sort(float x[], int n) {
int flag=1, k=n-1, i;
while (flag == 1 && k > 0) {
flag = 0;
for (i=0; i<k; i++) {
if (x[i]>x[i+1]) {
scambia(&x[i], &x[i+1]);
flag = 1;
}
}
k = k-1;
}
return;
}
int intautri(float A, float B, float TOL, int MAXFUN, float *Q, float *E, int *N, float FUN(float)){
void sort(float [], int);
void quadra(float, float, float*, float*, float(float));
float Q1,Q2,c,d,Iold,Eold,E0,E1,E2,alist[100],blist[100],qlist[100],elist[100];
int n, flag;
quadra(A, B, &Q1, &E0,FUN);
*N = 3;
n = 1;
alist[n] = A;
blist[n] = B;
qlist[n] = Q1;
elist[n] = E0;
*Q = Q1;
*E = E0;
if (*E<=TOL || *N>=MAXFUN){
flag = 1;
}else{
c = alist[n];
d = blist[n];
Iold = qlist[n];
Eold = elist[n];
n = n-1;
quadra(c, (c+d)/2, &Q1, &E1, FUN);
quadra((c+d)/2, d, &Q2, &E2, FUN);
*Q = *Q - Iold + Q1 + Q2;
*E = *E - Eold + E1 + E2;
*N = *N + 6;
intautri(A , B, TOL, MAXFUN, Q, E, N, FUN);
alist[n+1] = c;
blist[n+1] = (c+d)/2;
qlist[n+1] = Q1;
elist[n+1] = E1;
alist[n+2] = (c+d)/2;
blist[n+2] = d;
qlist[n+2] = Q2;
elist[n+2] = E2;
n = n+2;
sort(alist, n);
sort(blist, n);
sort(qlist, n);
sort(elist, n);
flag = 0;
}
;
return flag;
}
int main(){
int intautri(float, float, float, int, float *, float *, int*, float(float));
float TOL, MAXFUN, A, B,Q,E;
int N, J;
float f(float);
A = 0;
B = 1;
TOL = 0.0001;
MAXFUN = 200;
J = intautri(A, B, TOL, MAXFUN, &Q, &E, &N, f);
printf("%d\n", J);
printf("%d\n", N);
printf("%f\n", Q);
return 0;
}
Anyway I compile without problems that code, but when I run it "segmentation fault (core dumped)" appears on terminal. I know that error could depend by memory allocation but I don't understand what is wrong...can you help me??
You have an exit condition in intautri:
if (*E<=TOL || *N>=MAXFUN){
but in the beginning of the function you also have:
*N = 3;
This means that your second exit condition will never fire. Without attempting to understand the logic of the code, I believe that you should:
Initialize N in main().
Remove the *N = 3 assignment in intautri().

Rounding long decimal values in c programming

I am stuck up with this problem.
I get double values in some variables which are as follows:
a = 0.76271469999999997000
b = 0.66698279999999999000
c = 0.34262199999999998000
I need to round these to
rounded_a = 0.762714700000000
rounded_b = 0.666982800000000
rounded_c = 0.342622000000000
How should I go about doing this?
#include <stdio.h>
#include <math.h>
double round_n(double x, int n){
double wk;
wk = pow(10.0, (double)n);
return round(x * wk)/wk;//c99 function
}
int main(void){
double a, b, c;
a = 0.76271469999999997000;
b = 0.66698279999999999000;
c = 0.34262199999999998000;
a = round_n(a, 7);
b = round_n(b, 7);
c = round_n(c, 7);
printf("a=%.8lf\nb=%.8lf\nc=%.8lf", a, b, c);
return 0;
}
Here is the code I use:
int64_t __pow10_arr[18] = { 1l, 10l, 100l, 1000l, 10000l, 100000l,
1000000l, 10000000, 100000000l, 1000000000l, 10000000000l, 100000000000l,
1000000000000l, 10000000000000l, 100000000000000l, 1000000000000000l, 10000000000000000l, 100000000000000000l };
double roundToNfractions ( double val, int n )
{
if (n<0 || n >= ( sizeof (__pow10_arr)/ sizeof (int64_t) ) ) {
// log error however you wish to
return val;
}
val *= __pow10_arr[n];
val += 0.5;
val = (uint64_t) val;
val /= __pow10_arr[n];
return val;
}

Resources