Hi, I have trouble using pointers - c

This C code works fine in Codeblocks but not in other environments. I think Codeblocks automatically uses pointer and modifies the code
return (Result){sum, mean, var}; << This part has an error in visual studio.
error C4576: a parenthesized type followed by an initializer list is a non-standard explicit type conversion syntax
Would there be any suggestion that can fix the code to use pointers? Thank you for reading my question!
#include<stdio.h>
#define SIZE 6
typedef struct Result {
float sum, mean, variance;
}Result;
Result Statistics(int a[]);
int main()
{
int array[SIZE] = { 1,2,3,4,5,6 };
Result result;
result = Statistics(array);
printf("Sum=%.2f\n", result.sum);
printf("Mean=%.2f\n", result.mean);
printf("Variance=%.2f\n", result.variance);
return 0;
}
Result Statistics(int a[])
{
float sum, mean, var, sum2, diff;
int i;
for (sum = 0, i = 0; i < SIZE; i++) {
sum += (float)a[i];
}
mean = sum / SIZE;
for (sum2 = 0, i = 0; i < SIZE; i++) {
diff = (float)a[i] - mean;
sum2 += diff * diff;
}
var = sum2 / SIZE;
return (Result){sum, mean, var};
}

Your compiler does not support standard C. Change
return (Result){sum, mean, var};
to:
{
Result temp = {sum, mean, var};
return temp;
}

Related

Invalid operands in sigmoid function

I am working on a Neural Network, and when trying to do the sigmoid function, it shows an error which I do not understand: invalid operands to binary ^ (have 'double' and 'int'). Here's my piece of code:
double neuron(const int num_in, const double input[num_in], const double weight[num_in], const double bias) {
int i;
int asubj = 0;
int zsubj;
for (i = 0; i < num_in; i++)
{
asubj = asubj + input[i]*weight[i]+bias;
}
zsubj = (1)/(1 - (int)(M_E)^(-asubj)); // When I run the program, it stops here, I don
return 0;
}
Any help would be much appreciated.
As noted elsewhere ^ is exclusive-or operator in C. The following might do what you want a little better:
double neuron(const int num_in,
const double input[num_in],
const double weight[num_in],
const double bias)
{
int i;
double asubj = 0.0;
double zsubj;
for (i = 0; i < num_in; i++)
asubj = asubj + input[i]*weight[i]+bias;
zsubj = 1.0 / (1.0 - pow(M_E, -asubj));
return 0;
}
Note that the code above retains the return 0; at the end shown in the original function.

How to use a nested if else statements in a for loop in c

I'm having issues with my for statement. I'm trying to have a nested if else statement inside and I'm using pointers. I've tried everything and I've looked all over the internet. I've placed comments beside the lines with errors but if you see something else that's wrong please let me know. Thank you
#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
void getinput(double*xptr, int*nptr)
{
int flag;
do
{
flag = TRUE;
printf("What is the value of x and the number of terms:");
scanf("%lf %i", xptr, nptr);
if (*nptr <= 0)
{
printf("The number of terms must be positive\n");
flag = FALSE;
}
}
while(flag == FALSE);
}
double sinHyper(double *xptr, int *nptr) {
int i;
double sum;
double ti;
i = 0;
ti = 0;
for (i = 0; i < *nptr; i = i+1)// I'm getting a Warning: comparioson between pointer and integer
{
if (i == 0)
{
sum = xptr;
} else {
ti = 2*i+1;
ti = ti*2*i;
ti = (xptr*xptr)/ti;// I'm getting a error: invalid operands to binary * (have 'double*' and 'double*')
sum = ti*sum;
}
}
return (sum);
}
void main() {
int n;
double x;
double sinhx;
getinput(&x, &n);
sinhx = sinHyper(&x, &n);
printf("For an x of %.0f with %i terms the sinh(x) is %f", x, n, sinhx);
return 0;
}
You forgot to dereference your pointers in several places.
The fact that this line compiles
sum = xptr;
should not mislead you: C lets you convert a pointer to a number with only a warning, while in most cases this is an error. This line should be
sum = *xptr;
It does not let you multiply pointers, so the expression where you square your pointer is an error:
(xptr*xptr)
You should either dereference the pointer twice, i.e. write
((*xptr)*(*xptr))
or make a separate variable for the current value of *xptr and use it instead:
const double x = *xptr;
ti = (x*x)/ti;
Note: This exercise should be purely theoretical, because sinHyper does not change *xptr or *nptr. Therefore, you should pass them as values, not as pointers:
double sinHyper(const double x, const int n) {
...
}
...
sinhx = sinHyper(x, n);

program.exe (C) has stopped working

I am extremely new to C and managed to compile this program, but the exe stops working upon running. I'm really not sure what's wrong.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define TINY 1.0e-20 // A small number.
void ludcmp(float a[3][3], int n, int *indx, float *d);
void lubksb(float a[3][3], int n, int *indx, float b[]) ;
int main(){
int i,n,*indx;
float *b,d;
float a[3][3] = {
{ 1.0, 2.0, 5.0},
{-1.0, 2.0, 3.0},
{ 6.0, 0.0, 1.0}
};
ludcmp(a,n,indx,&d);
lubksb(a,n,indx,b);
for(i = 1; i = 3; i++) {
printf("%.2f",b[i]);
}
getchar();
return 0;
}
For those who were asking, the 2 functions ludcmp and lubksg are below. I got them from the numerical recipes textbook, but edited some lines to remove exclusive routines which I do not have. Specifically, they are the lines with malloc, printf, and free.
The original code came with all the loops starting with 1, which is why I also started my loop with 1. I have since changed all the loops to start from 0 instead, hopefully without introducing any new errors.
You can see the original code here:
https://github.com/saulwiggin/Numerical-Recipies-in-C/tree/master/Chapter2.Solution-of-Linear-Equations
Here is ludcmp:
void ludcmp(float a[3][3], int n, int *indx, float *d)
{
int i, imax, j, k;
float big, dum, sum, temp;
float *vv; // vv stores the implicit scaling of each row.
vv = (float *) malloc(n * sizeof(float));
*d=1.0;
for (i=0;i<n;i++) {
big=0.0;
for (j=0;j<n;j++)
if ((temp=fabs(a[i][j])) > big) big=temp;
if (big == 0.0)
{
printf("Singular matrix in routine ludcmp");
//free(vv);
}
// No nonzero largest element.
vv[i] = 1.0 / big; // Save the scaling.
}
// This is the loop over columns of Crout's method.
for (j=0;j<n;j++) {
for (i=0;i<j;i++) {
sum=a[i][j];
for (k=0;k<i;k++) sum -= a[i][k]*a[k][j];
a[i][j]=sum;
}
// Initialize for the search for largest pivot element.
big=0.0;
for (i=j;i<=n;i++) {
sum=a[i][j];
for (k=0;k<j;k++)
sum -= a[i][k]*a[k][j];
a[i][j]=sum;
if ( (dum=vv[i]*fabs(sum)) >= big) {
big=dum;
imax=i;
}
}
if (j != imax) {
for (k=0;k<n;k++) {
dum=a[imax][k];
a[imax][k]=a[j][k];
a[j][k]=dum;
}
*d = -(*d);
vv[imax]=vv[j];
}
indx[j]=imax;
if (a[j][j] == 0.0) a[j][j]=TINY;
if (j != n) {
dum=1.0/(a[j][j]);
for (i=j+1;i<n;i++) a[i][j] *= dum;
}
} // Go back for the next column in the reduction.
free(vv);
}
And lubksb:
void lubksb(float a[3][3],int n,int *indx,float b[])
{
int i,ii=0,ip,j;
float sum;
for (i=1;i<=n;i++) {
ip=indx[i];
sum=b[ip];
b[ip]=b[i];
if (ii)
for (j=ii;j<=i-1;j++) sum -= a[i][j]*b[j];
else if (sum) ii=i;
b[i]=sum;
}
for (i=n;i>=1;i--) {
sum=b[i];
for (j=i+1;j<=n;j++) sum -= a[i][j]*b[j];
b[i]=sum/a[i][i];
}
}
This is a Two Dimensional Array and you are looping as it was just one. You should do something like:
for (int i = 0; i < 3; ++i) {
for(int j = 0; j < 3; ++j) {
printf("%d %d: ", i+1, j+1);
}
}
Is bad practice to define the size of the array explicit. Try to use a constant.
And as said in the comments by #Marged:
In C arrays starts in 0
b is never assigned to anything valid when it's declared:
float *b,d;
At best, it's NULL or pointing to an invalid memory address:
I don't know what the lubksb function does:
lubksb(a,n,indx,b);
But b is clearly an invalid parameter since you never assign to it before calling this function.
And with this statement:
for(i = 1; i = 3; i++) {
printf("%.2f",b[i]);
}
As others have pointed out, array indices start at zero. But there's no evidence that b has a length of three anyway.

Code::Blocks crashes :Process returned (0xC0000005)

I am trying to build and run the following code on code blocks, but it crashes and returns the (0xC0000005) error. I mainly suspect the usage of realloc for pointer n_k in gCRSF_gibbs function, however I am not sure how to track the source of crash. This is not my original code and I am also a noob in C. Any kind of help is appreciated.
#include <stdio.h>
#include "string.h"
#include <math.h>
#include <stdlib.h>
int BinarySearch(double probrnd, double *prob_cumsum, int Ksize) {
int k, kstart, kend;
if (probrnd <=prob_cumsum[0])
return(0);
else {
for (kstart=1, kend=Ksize-1; ; ) {
if (kstart >= kend) {
return(kend);
}
else {
k = kstart+ (kend-kstart)/2;
if (prob_cumsum[k-1]>probrnd && prob_cumsum[k]>probrnd)
kend = k-1;
else if (prob_cumsum[k-1]<probrnd && prob_cumsum[k]<probrnd)
kstart = k+1;
else
return(k);
}
}
}
return(k);}
void gCRSF_gibbs(double *z, double *n_k, double *SampleDex,
double *r, double *a, double *p,
int *Ksize, int *WordNum) {
int i, j, k;
double mass;
double *prob_cumsum;
double cum_sum, probrnd;
void *newptr;
prob_cumsum = (double *) calloc(Ksize[0],sizeof(double));
mass = r[0]*pow(p[0],-a[0]);
for (i=0;i<WordNum[0];i++){
j = (int) SampleDex[i] -1;
k = (int) z[j] -1;
if(z[j]>0){
n_k[k]--;
}
for (cum_sum=0, k=0; k<Ksize[0]; k++) {
cum_sum += n_k[k]-a[0];
prob_cumsum[k] = cum_sum;
}
if ( ((double) rand() / RAND_MAX * (cum_sum + mass) < cum_sum)){
probrnd = (double)rand()/(double)RAND_MAX*cum_sum;
k = BinarySearch(probrnd, prob_cumsum, Ksize[0]);
}
else{
for (k=0; k<Ksize[0]; k++){
if ((int) n_k[k]==0){
break;
}
}
if (k==Ksize[0]){
Ksize[0]++;
newptr = realloc(n_k,sizeof(*n_k)*Ksize[0]);
n_k = newptr;
n_k[Ksize[0]-1]=0;
prob_cumsum = realloc(prob_cumsum,sizeof(*prob_cumsum)*Ksize[0]);
}
}
z[j] = k+1;
n_k[k]++;
}
free(prob_cumsum);}
int main() {
double *z, *n_k, *sampleDex;
double *r, *a, *p;
int *Ksize, *WordNum;
z[0]=1;z[1]=1;z[2]=2;z[3]=0;z[4]=0;
n_k[0]=2;n_k[1]=1;
sampleDex[0]=4;sampleDex[1]=5;
r[0]=5;a[0]=0.5;p[0]=0.5;
Ksize[0]=2;WordNum[0]=2;
gCRSF_gibbs(z,n_k,sampleDex,r,a,p,Ksize,WordNum);
return 0;}
Let's reduce your problem to a minimal example that exhibits the same behaviour:
int main()
{
double *z;
z[0] = 1; // Undefined behaviour!
return 0;
}
Here, z is an uninitialized pointer; it points to a random location. De-referencing it, that is trying to read or write to where the pointer points to leads to undefined behavior.
You use z as an array of 5 floating-point numbers. The easiest way to fix this is to create z as a local array:
double z[5] = {1, 1, 2, 0, 0};
There are probably more errors in your code. This answer addresses only the cause of the obvious segmentation violation.
}
if (k==Ksize[0]){
Ksize[0]++;
newptr = realloc(n_k,sizeof(*n_k)*Ksize[0]);
n_k = newptr;
n_k[Ksize[0]-1]=0;
prob_cumsum = realloc(prob_cumsum,sizeof(*prob_cumsum)*Ksize[0]);
in this piece of code you forgot to add "Invade_Ukraine_Nuclear_Hollocaust_4"

Porting MMX/SSE instructions to AltiVec

Let me preface this with.. I have extremely limited experience with ASM, and even less with SIMD.
But it happens that I have the following MMX/SSE optimised code, that I would like to port across to AltiVec instructions for use on PPC/Cell processors.
This is probably a big ask.. Even though it's only a few lines of code, I've had no end of trouble trying to work out what's going on here.
The original function:
static inline int convolve(const short *a, const short *b, int n)
{
int out = 0;
union {
__m64 m64;
int i32[2];
} tmp;
tmp.i32[0] = 0;
tmp.i32[1] = 0;
while (n >= 4) {
tmp.m64 = _mm_add_pi32(tmp.m64,
_mm_madd_pi16(*((__m64 *)a),
*((__m64 *)b)));
a += 4;
b += 4;
n -= 4;
}
out = tmp.i32[0] + tmp.i32[1];
_mm_empty();
while (n --)
out += (*(a++)) * (*(b++));
return out;
}
Any tips on how I might rewrite this to use AltiVec instructions?
My first attempt (a very wrong attempt) looks something like this.. But it's not entirely (or even remotely) correct.
static inline int convolve_altivec(const short *a, const short *b, int n)
{
int out = 0;
union {
vector unsigned int m128;
int i64[2];
} tmp;
vector unsigned int zero = {0, 0, 0, 0};
tmp.i64[0] = 0;
tmp.i64[1] = 0;
while (n >= 8) {
tmp.m128 = vec_add(tmp.m128,
vec_msum(*((vector unsigned short *)a),
*((vector unsigned short *)b), zero));
a += 8;
b += 8;
n -= 8;
}
out = tmp.i64[0] + tmp.i64[1];
#endif
while (n --)
out += (*(a++)) * (*(b++));
return out;
}
You're not far off - I fixed a few minor problems, cleaned up the code a little, added a test harness, and it seems to work OK now:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <altivec.h>
static int convolve_ref(const short *a, const short *b, int n)
{
int out = 0;
int i;
for (i = 0; i < n; ++i)
{
out += a[i] * b[i];
}
return out;
}
static inline int convolve_altivec(const short *a, const short *b, int n)
{
int out = 0;
union {
vector signed int m128;
int i32[4];
} tmp;
const vector signed int zero = {0, 0, 0, 0};
assert(((unsigned long)a & 15) == 0);
assert(((unsigned long)b & 15) == 0);
tmp.m128 = zero;
while (n >= 8)
{
tmp.m128 = vec_msum(*((vector signed short *)a),
*((vector signed short *)b), tmp.m128);
a += 8;
b += 8;
n -= 8;
}
out = tmp.i32[0] + tmp.i32[1] + tmp.i32[2] + tmp.i32[3];
while (n --)
out += (*(a++)) * (*(b++));
return out;
}
int main(void)
{
const int n = 100;
vector signed short _a[n / 8 + 1];
vector signed short _b[n / 8 + 1];
short *a = (short *)_a;
short *b = (short *)_b;
int sum_ref, sum_test;
int i;
for (i = 0; i < n; ++i)
{
a[i] = rand();
b[i] = rand();
}
sum_ref = convolve_ref(a, b, n);
sum_test = convolve_altivec(a, b, n);
printf("sum_ref = %d\n", sum_ref);
printf("sum_test = %d\n", sum_test);
printf("%s\n", sum_ref == sum_test ? "PASS" : "FAIL");
return 0;
}
(Warning: all of my Altivec experience comes from working on Xbox360/PS3 - I'm not sure how different they are from other Altivec platforms).
First off, you should check your pointer alignment. Most vector loads (and stores) operations are expected to be from 16-byte aligned addresses. If they aren't, things will usually carry on without warning, but you won't get the data you were expecting.
It's possible (but slower) to do unaligned loads, but you basically have to read a bit before and after your data and combine them. See Apple's Altivec page. I've also done it before using an lvlx and lvrx load instructions, and then ORing them together.
Next up, I'm not sure your multiplies and adds are the same. I've never used either _mm_madd_pi16 or vec_msum, so I'm not positive they're equivalent. You should step through in a debugger and make sure they give you the same output for the same input data. Another possible difference is that they may treat overflow differently (e.g. modular vs. saturate).
Last but not least, you're computing 4 ints at a time instead of 2. So your union should hold 4 ints, and you should sum all 4 of them at the end.

Resources