why I am getting this result in last half of array? - c

Can anyone tell me why the output ( Anew ) is:
Anew = 0.000000
Anew = 2.000000
Anew = 4.000000
Anew = 6.000000
Anew = 16.000000
Anew = 20.000000
Anew = 24.000000
Anew = 28.000000
and not :
Anew = 0.000000
Anew = 2.000000
Anew = 4.000000
Anew = 6.000000
Anew = 8.000000
Anew = 10.000000
Anew = 12.000000
Anew = 14.000000
Code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <mkl.h>
int main(int argc, const char* argv[]) {
int rows = 2, cols = 2, Layers = 2;
int PerLayerElmts = rows * cols;
float* A = malloc(PerLayerElmts * Layers * sizeof(*A));
// create A matrix
int ImagIdx;
for (int n = 0; n < Layers; n++) {
ImagIdx = 0;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
A[n * PerLayerElmts + ImagIdx] = n * PerLayerElmts + ImagIdx;
ImagIdx++;
}
}
}
// print A matrix
for (int n = 0; n < Layers; n++) {
ImagIdx = 0;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
printf("\nA = %f", A[n * PerLayerElmts + ImagIdx]);
ImagIdx++;
}
}
}
float scalar = 2.0;
size_t AddressOffset = 0;
for (int i = 0; i < Layers; i++, AddressOffset += PerLayerElmts) {
// multiply A by scalar
cblas_sscal(PerLayerElmts * Layers, scalar, A + AddressOffset, 1);
}
// print A matrix
for (int n = 0; n < Layers; n++) {
ImagIdx = 0;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
printf("\n\nAnew = %f", A[n * PerLayerElmts + ImagIdx]);
ImagIdx++;
}
}
}
printf("\n");
free(A);
return 0;
}
I am just creating a matrix and then using cblas call to multiply every element by a scalar ( 2 ).
I am doing that , using an addressoffset for the number of layers.
The problem is at the second layer where the elements are multiply by 4 and not 2!

Your way of calling cblas_sscal doesn't seem right. Instead of
cblas_sscal( PerLayerElmts * Layers , scalar , A + AddressOffset , 1 );
I would expect something like
cblas_sscal( PerLayerElmts , scalar , A + AddressOffset , 1 );
since you're calling it once for every layer.

Related

struct inner element's value assignment failed in c

context: https://stackoverflow.com/a/72238514/15603477
#include<stdio.h>
#include<stdlib.h>
#define MAT_SIZE 2
#define MAT_COUNT 3
typedef double mat[MAT_SIZE][MAT_SIZE];
typedef struct matList{
const char *name;
mat matrix;
}matList;
void init_mat(mat m)
{
for(int i = 0; i < MAT_SIZE; i++){
for(int j = 0; j < MAT_SIZE; j++){
m[i][j] = i * 2.1 + (double) j + 1.1;
printf("(i,j)=%f\n",m[i][j]);
}
}
}
//allocate matList.
matList *create_mat(const char *name)
{
matList *tempMat = malloc(sizeof *tempMat);
if(tempMat != NULL)
{
tempMat->name = name;
init_mat(tempMat->matrix);
}
return tempMat;
}
// freematList
void free_matList(matList **mats)
{
if(mats){
for(int i = 0; i < MAT_COUNT; i++){
free(mats[i]);
}
}
}
// return non zero if successful
int allocate_matList(matList **mats)
{
if(mats){
mats[0] = create_mat("MAT_A");
mats[1] = create_mat("MAT_B");
mats[2] = create_mat("MAT_C");
if(mats[0] && mats[1] && mats[2])
return 1;
}
}
int main(void)
{
matList *mats[MAT_COUNT];
if(allocate_matList(mats)){
printf("mat[2] name: %s\n",mats[2]->name);
size_t row = sizeof(mats[2]->matrix) / sizeof (mats[2]->matrix[0]);
size_t col = sizeof(mats[2]->matrix[0]) / sizeof(mats[2]->matrix[0][0]);
printf("row: %ld col: %ld\n",row,col);
for(size_t i = 0; i < row; i++){
for(size_t j = 0; j < col; j++){
printf("%f\t",mats[2]->matrix[row][col]);
}
printf("\n");
}
}
free_matList(mats);
exit(EXIT_SUCCESS);
}
There would be MAT_COUNT of struct matList. each matList's matrix is identical.
expected last print result would be:
1.100000 2.100000
3.200000 4.200000
now the last printf return
0.000000 0.000000
0.000000 0.000000
which means that the values assignment of matrix failed?
(gdb) break 23
Breakpoint 1 at 0x11d9: file array_struct170.c, line 23.
(gdb) s
The program is not being run.
(gdb) run
Starting program: /home/jian/helloc/a.out
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Breakpoint 1, init_mat (m=0x5555555592a8) at array_struct170.c:23
23 for(int i = 0; i < MAT_SIZE; i++){
(gdb) s
24 for(int j = 0; j < MAT_SIZE; j++){
(gdb) s
25 m[i][j] = i * 2.1 + (double) j + 1.1;
(gdb) print m[i][j]
$1 = 0
now I guess the line have problem is
m[i][j] = i * 2.1 + (double) j + 1.1;
for(size_t i = 0; i < row; i++){
for(size_t j = 0; j < col; j++){
printf("%f\t",mats[2]->matrix[row][col]); // <- look closely!
}
printf("\n");
Since row is 2 and col is 2, you are trying to print out matrix[2][2], which is out of bounds. You probably wanted matrix[i][j] instead of matrix[row][col].
By the way, valgrind caught this immediately.

As a result of processing arrays -nan(ind)

I am writing a program that creates arrays of a given length and manipulates them. You cannot use other libraries.
First, an array M1 of length N is formed, after which an array M2 of length N is formed/2.
In the M1 array, the division by Pi operation is applied to each element, followed by elevation to the third power.
Then, in the M2 array, each element is alternately added to the previous one, and the tangent modulus operation is applied to the result of addition.
After that, exponentiation is applied to all elements of the M1 and M2 array with the same indexes and the resulting array is sorted by dwarf sorting.
And at the end, the sum of the sines of the elements of the M2 array is calculated, which, when divided by the minimum non-zero element of the M2 array, give an even number.
The problem is that the result X gives is -nan(ind). I can't figure out exactly where the error is.
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
const int A = 441;
const double PI = 3.1415926535897931159979635;
inline void dwarf_sort(double* array, int size) {
size_t i = 1;
while (i < size) {
if (i == 0) {
i = 1;
}
if (array[i - 1] <= array[i]) {
++i;
}
else
{
long tmp = array[i];
array[i] = array[i - 1];
array[i - 1] = tmp;
--i;
}
}
}
inline double reduce(double* array, int size) {
size_t i;
double min = RAND_MAX, sum = 0;
for (i = 0; i < size; ++i) {
if (array[i] < min && array[i] != 0) {
min = array[i];
}
}
for (i = 0; i < size; ++i) {
if ((int)(array[i] / min) % 2 == 0) {
sum += sin(array[i]);
}
}
return sum;
}
int main(int argc, char* argv[])
{
int i, N, j;
double* M1 = NULL, * M2 = NULL, * M2_copy = NULL;
double X;
unsigned int seed = 0;
N = atoi(argv[1]); /* N равен первому параметру командной строки */
M1 = malloc(N * sizeof(double));
M2 = malloc(N / 2 * sizeof(double));
M2_copy = malloc(N / 2 * sizeof(double));
for (i = 0; i < 100; i++)
{
seed = i;
srand(i);
/*generate*/
for (j = 0; j < N; ++j) {
M1[j] = (rand_r(&seed) % A) + 1;
}
for (j = 0; j < N / 2; ++j) {
M2[j] = (rand_r(&seed) % (10 * A)) + 1;
}
/*map*/
for (j = 0; j < N; ++j)
{
M1[j] = pow(M1[j] / PI, 3);
}
for (j = 0; j < N / 2; ++j) {
M2_copy[j] = M2[j];
}
M2[0] = fabs(tan(M2_copy[0]));
for (j = 0; j < N / 2; ++j) {
M2[j] = fabs(tan(M2[j] + M2_copy[j]));
}
/*merge*/
for (j = 0; j < N / 2; ++j) {
M2[j] = pow(M1[j], M2[j]);
}
/*sort*/
dwarf_sort(M2, N / 2);
/*sort*/
X = reduce(M2, N / 2);
}
printf("\nN=%d.\n", N);
printf("X=%f\n", X);
return 0;
}
Knowledgeable people, does anyone see where my mistake is? I think I'm putting the wrong data types to the variables, but I still can't solve the problem.
Replace the /* merge */ part with this:
/*merge*/
for (j = 0; j < N / 2; ++j) {
printf("%f %f ", M1[j], M2[j]);
M2[j] = pow(M1[j], M2[j]);
printf("%f\n", M2[j]);
}
This will print the values and the results of the pow operation. You'll see that some of these values are huge resulting in an capacity overflow of double.
Something like pow(593419.97, 31.80) will not end well.

Array values changing without reason

This is my code for Project Euler: Problem 11
int main(int argc, char** argv) {
char stevila [1600] = "08022297381500400075040507785212507791084949994017811857608717409843694804566200814931735579142993714067538830034913366552709523046011426924685601325671370236912231167151676389419236542240402866331380244732609903450244753353783684203517125032988128642367102638406759547066183864706726206802621220956394396308409166499421245558056673992697177878968314883489637221362309750076442045351400613397343133957817532822753167159403800462161409535692163905429635314755588824001754243629855786560048357189070544443744602158515417581980816805944769287392138652177704895540045208839735991607975732162626793327986688366887576220720346336746551232639353690442167338253911249472180846293240627636206936417230238834629969826759857404361620733529783190017431497148868116235705540170547183515469169233486143520189196748";
int stevilaGrid [20][20];
int stevilaRacunanje[4][4];
int stevecPoStevilih = 0;
for (int i = 0; i < 20; i++) {
for (int j = 0; j < 20; j++) {
stevilaGrid[i][j] = (stevila[stevecPoStevilih] - 48)*10 + stevila[stevecPoStevilih + 1] - 48;
stevecPoStevilih += 2;
}
}
int rezultat [10];
int najvecji = 0;
int trenutni;
int temp = 0;
for (int i = 0; i < 17; i++) {
for (int j = 0; j < 17; j++) {
//problems start here
for (int k = 0; k < 5; k++) {
for (int l = 0; l < 5; l++) {
temp = stevilaGrid[i + k][j + l];
stevilaRacunanje[k][l] = temp;
}
}
for (int k = 0; k < 5; k++) {
rezultat[k] = stevilaRacunanje[k][0] * stevilaRacunanje[k][1] * stevilaRacunanje[k][2] * stevilaRacunanje[k][3];
rezultat[k+4] = stevilaRacunanje[0][k] * stevilaRacunanje[1][k] * stevilaRacunanje[2][k] * stevilaRacunanje[3][k];
}
rezultat[8] = stevilaRacunanje[0][0] * stevilaRacunanje[1][1] * stevilaRacunanje[2][2] * stevilaRacunanje[3][3];
rezultat[9] = stevilaRacunanje[0][3] * stevilaRacunanje[1][2] * stevilaRacunanje[2][1] * stevilaRacunanje[3][0];
for (int k = 0; k < 10; k++) {
trenutni = rezultat[k];
if(trenutni > najvecji){
najvecji = trenutni;
}
}
}
}
printf("Najvecji zmnozek: %d", najvecji);
return (EXIT_SUCCESS);
}
First I convert the string of numbers into a 2D int array.
Then I try to divide the grid into smaller 4x4 squares with which I can work more easily. That is where the problems start (as marked in the code).
At the very beginning (*i=0,j=0;k=4,j=0*) something strange starts to happen. The values in *stevilaGrid[][]* start to change randomly and seemingly without a reason.
Can somebody please explain this to me. I have tested this behavior on Windows with Cygwin 64bit and Ubuntu with GCC 64bit.
[i + k][j + l];
When i==16 and k==4 or j==16 and j==4 you'll be hitting element [20]
Your array only goes 0...19

get pointer to sub array in 4 dimensional array

I have declared a 4 dimensional array : int board[3][3][3][3]
How can I get a pointer to the sub array, for example I tried something like this :
int sub_board[3][3] = board[1][2];
but it didn't work and I couldn't find any way to get a pointer to the sub array.
There are 2 ways to get a pointer to a sub array:
int (*sub_board)[3][3] = &board[1][2];
sub_board points to a sub array with known dimensions, but its elements must be dereferenced as (*sub_board)[i][j].
Alternately, you can use a pointer to the beginning of the sub array, but without an embedded notion of the number of elements:
int (*sub_array)[3] = board[1][2];
The elements are more intuitively accessed as sub_array[i][j], but the range for i cannot be statically checked at compile time.
Here is an illustration of how these work. For clarity, I have used different sizes for the different dimensions:
#include <stdint.h>
#include <stdio.h>
int main(void) {
int board[2][3][4][5];
int (*sub_board)[4][5] = &board[1][2];
int (*sub_array)[5] = board[1][2];
int n = 0;
for (int i0 = 0; i0 < 2; i0++) {
for (int i1 = 0; i1 < 3; i1++) {
for (int i2 = 0; i2 < 4; i2++) {
for (int i3 = 0; i3 < 5; i3++) {
board[i0][i1][i2][i3] = n++;
}
}
}
}
printf("board = %p\n", (void*)board);
printf("sub array board[1][2] should be at offset 1 * 3 * 4 * 5 + 2 * 4 * 5 = %d\n",
1 * 3 * 4 * 5 + 2 * 4 * 5);
printf("sub_board = %p\n", (void*)sub_board);
printf("offset = %lld\n", (long long int)(((intptr_t)sub_board - (intptr_t)board) / (int)sizeof(int)));
printf("sub_array = %p\n", (void*)sub_board);
printf("offset = %lld\n", (long long int)(((intptr_t)sub_array - (intptr_t)board) / (int)sizeof(int)));
printf("addressing using board:\n");
for (int i2 = 0; i2 < 4; i2++) {
for (int i3 = 0; i3 < 5; i3++) {
printf("%8d", board[1][2][i2][i3]);
}
printf("\n");
}
printf("\n");
printf("addressing using sub_board:\n");
for (int i2 = 0; i2 < 4; i2++) {
for (int i3 = 0; i3 < 5; i3++) {
printf("%8d", (*sub_board)[i2][i3]);
}
printf("\n");
}
printf("\n");
printf("addressing using sub_array:\n");
for (int i2 = 0; i2 < 4; i2++) {
for (int i3 = 0; i3 < 5; i3++) {
printf("%8d", sub_array[i2][i3]);
}
printf("\n");
}
printf("\n");
return 0;
}
If you want to copy the sub-array
int sub[3][3];
memcpy(sub, board[1][2], sizeof sub);
The syntax should be:
int (*sub_board)[3] = board[1][2];

Loading an Integer Array into a SIMD register

at the moment I'm trying to load an integer array into a SIMD register using SSE.
I have an aligned 32-bit integer array Ai and want to load 4 consecutive elements into a SIMD register Xi. However, the values stored in Xi after executing _mm_load_si128 are garbage except for the first one.
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <immintrin.h>
// number has to be divisible by 4 without remainder
#define VECTOR_SIZE 8
int main() {
__attribute__((aligned (16))) int32_t *Ai = (int32_t*) malloc(VECTOR_SIZE * sizeof(int32_t));
for(int i = 0; i < VECTOR_SIZE; i++) {
Ai[i] = rand() % 100000;
}
__m128i Xi;
for(int i = 0; i < VECTOR_SIZE; i+=4) {
Xi = _mm_load_si128((__m128i*) &Ai[i]);
// show content of Xi and Ai
for(int j = 0; j < 4; j++) {
printf("Xi[%d] = %d\t Ai[%d] = %d\n", j, Xi[j], i+j, Ai[i+j]);
}
}
free(Ai);
}
Here is an example output:
Xi[0] = 16807 Ai[0] = 16807
Xi[1] = 50073 Ai[1] = 75249
Xi[2] = 1489217992 Ai[2] = 50073
Xi[3] = 1346391152 Ai[3] = 43658
Xi[0] = 8930 Ai[4] = 8930
Xi[1] = 27544 Ai[5] = 11272
Xi[2] = 1489217992 Ai[6] = 27544
Xi[3] = 1346391168 Ai[7] = 50878
What is wrong?
You probably meant this when you were coming up with your example:
union {
__m128i m128;
int32_t i32[4];
} Xi;
for(int i = 0; i < VECTOR_SIZE; i+=4) {
Xi.m128 = _mm_load_si128((__m128i*) &Ai[i]);
// show content of Xi and Ai
for(int j = 0; j < 4; j++) {
printf("Xi[%d] = %d\t Ai[%d] = %d\n", j, Xi.i32[j], i+j, Ai[i+j]);
}
}
Here is the example output:
Xi[0] = 89383 Ai[0] = 89383
Xi[1] = 30886 Ai[1] = 30886
Xi[2] = 92777 Ai[2] = 92777
Xi[3] = 36915 Ai[3] = 36915
Xi[0] = 47793 Ai[4] = 47793
Xi[1] = 38335 Ai[5] = 38335
Xi[2] = 85386 Ai[6] = 85386
Xi[3] = 60492 Ai[7] = 60492

Resources