3349 lines
111 KiB
C
3349 lines
111 KiB
C
#ifndef __TOOLS_T_C_H__
|
|
#define __TOOLS_T_C_H__
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdbool.h>
|
|
#include <time.h>
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
|
|
/* to define DEBUG in gcc cli do: gcc -D DEBUG=1 or 0 if need!*/
|
|
#ifndef DEBUG
|
|
#define DEBUG 0
|
|
#endif
|
|
|
|
|
|
/* F_OUT file (stream) to log*/
|
|
#ifndef F_OUT
|
|
#define F_OUT stdout
|
|
#endif
|
|
/* F_ERR file (stream) to log*/
|
|
#ifndef F_ERR
|
|
#define F_ERR stderr
|
|
#endif
|
|
|
|
/*
|
|
#ifndef SECOND
|
|
#define SECOND 0
|
|
#endif
|
|
#ifndef NANOSECOND
|
|
#define NANOSECOND 0
|
|
#endif
|
|
|
|
double diff_timespec_seconds(struct timespec time_stop, struct timespec time_start);
|
|
double diff_timespec_milliseconds(struct timespec time_stop, struct timespec time_start);
|
|
long diff_timespec_nanoseconds(struct timespec time_stop, struct timespec time_start);
|
|
*/
|
|
|
|
#if 1
|
|
|
|
extern long int PRECISION_TYPE_FLOAT ;
|
|
extern long int PRECISION_TYPE_DOUBLE ;
|
|
extern long int PRECISION_TYPE_L_DOUBLE ;
|
|
|
|
#endif
|
|
|
|
|
|
/*void get_cursor_position(int *col, int *rows);*/
|
|
|
|
#if DEBUG
|
|
|
|
#define debug_print(fmt, ...) \
|
|
do { /*if (DEBUG)*/ fprintf(stderr, "%s:%d:%s(): " fmt, __FILE__, \
|
|
__LINE__, __func__, __VA_ARGS__); } while (0)
|
|
|
|
#define PRINT_DEBUG_(fmt, ...) \
|
|
do { /*if (DEBUG)*/ fprintf(F_ERR, "%s:%d:%s(): " fmt, __FILE__, \
|
|
__LINE__, __func__, __VA_ARGS__); } while (0)
|
|
|
|
#else
|
|
#define debug_print(fmt, ...) {}
|
|
|
|
#define PRINT_DEBUG_(fmt, ...) {}
|
|
|
|
#endif
|
|
|
|
#define error_print(fmt, ...) \
|
|
fprintf(stderr, "%s:%d:%s(): " fmt, __FILE__, \
|
|
__LINE__, __func__, __VA_ARGS__);
|
|
|
|
#define PRINT_ERROR(fmt, ...) \
|
|
fprintf(F_ERR, "%s:%d:%s(): " fmt, __FILE__, \
|
|
__LINE__, __func__, __VA_ARGS__);
|
|
|
|
#define PRINT_LOC_T(fmt, ...) \
|
|
fprintf(F_OUT, "%s:%d:%s(): " fmt, __FILE__, \
|
|
__LINE__, __func__, __VA_ARGS__);
|
|
|
|
|
|
|
|
#define TYPE_CHAR char
|
|
#define TYPE_U_CHAR unsigned char
|
|
#define TYPE_INT int
|
|
#define TYPE_U_INT unsigned int
|
|
#define TYPE_L_INT long int
|
|
#define TYPE_U_L_INT unsigned long int
|
|
#define TYPE_SIZE_T size_t
|
|
#define TYPE_FLOAT float
|
|
#define TYPE_DOUBLE double
|
|
#define TYPE_L_DOUBLE long double
|
|
#define TYPE_STRING char*
|
|
|
|
#define FREE(x) { free((x)); (x) = NULL;}
|
|
|
|
#define FOREACH(array, array_size, function)\
|
|
for(size_t _ind = 0; _ind < array_size; ++_ind) function(array[_ind]);
|
|
|
|
#define MIN(X, Y) (((Y) < (X)) ? (Y) : (X))
|
|
#define MAX(X, Y) (((Y) > (X)) ? (Y) : (X))
|
|
|
|
#define GENERATE_ALL(type)\
|
|
int COMPARE_N_##type(const void *,const void*);\
|
|
void COPY_ARRAY_##type(type* dst, const type* src, size_t array_size);\
|
|
type MAX_ARRAY_##type(const type *array, size_t array_size);\
|
|
size_t ARG_MAX_ARRAY_##type(const type *array, size_t array_size);\
|
|
type MIN_ARRAY_##type(const type *array, size_t array_size);\
|
|
size_t ARG_MIN_ARRAY_##type(const type *array, size_t array_size);\
|
|
TYPE_STRING type##_TO_STR(type var);\
|
|
|
|
|
|
GENERATE_ALL(TYPE_CHAR)
|
|
GENERATE_ALL(TYPE_U_CHAR)
|
|
GENERATE_ALL(TYPE_INT)
|
|
GENERATE_ALL(TYPE_U_INT)
|
|
GENERATE_ALL(TYPE_L_INT)
|
|
GENERATE_ALL(TYPE_U_L_INT)
|
|
GENERATE_ALL(TYPE_SIZE_T)
|
|
GENERATE_ALL(TYPE_FLOAT)
|
|
GENERATE_ALL(TYPE_DOUBLE)
|
|
GENERATE_ALL(TYPE_L_DOUBLE)
|
|
GENERATE_ALL(TYPE_STRING)
|
|
|
|
/* strto_type */
|
|
|
|
int strto_TYPE_INT(char *str, char **endptr);
|
|
unsigned int strto_TYPE_U_INT(char *str, char **endptr);
|
|
long int strto_TYPE_L_INT(char *str, char **endptr);
|
|
unsigned long int strto_TYPE_U_L_INT(char *str, char **endptr);
|
|
size_t strto_TYPE_SIZE_T(char *str, char **endptr);
|
|
float strto_TYPE_FLOAT(char *str, char **endptr);
|
|
double strto_TYPE_DOUBLE(char *str, char **endptr);
|
|
long double strto_TYPE_L_DOUBLE(char *str, char **endptr);
|
|
|
|
/*
|
|
* time calucl
|
|
*/
|
|
double diff_timespec_seconds(struct timespec time_stop, struct timespec time_start);
|
|
|
|
double diff_timespec_milliseconds(struct timespec time_stop, struct timespec time_start);
|
|
|
|
long diff_timespec_nanoseconds(struct timespec time_stop, struct timespec time_start);
|
|
|
|
|
|
#endif /*__TOOLS_T_C_H__*/
|
|
|
|
/* implementations */
|
|
|
|
/* IMPLEMENTATION_TOOLS */
|
|
|
|
|
|
#define POW 17
|
|
#define MMOD ((1 << (POW)) - 1)
|
|
#define SUBA 5
|
|
#define SUBB 8
|
|
|
|
|
|
#define GEN_TO_STR_N(type,size,format) \
|
|
TYPE_STRING type##_TO_STR(type var){ \
|
|
char *ret = malloc(size); \
|
|
/*int szret = */sprintf(ret,format,var); \
|
|
/*ret[szret]='\0'*//*no need , already by default */; \
|
|
return ret; \
|
|
}\
|
|
|
|
|
|
#define GENERATE_FUNCTION_ALL(type)\
|
|
type MAX_ARRAY_##type(const type *array, size_t size){\
|
|
if(array == NULL) return 0;\
|
|
type mx =(type)array[0];\
|
|
for(size_t i = 0; i < size; ++i)\
|
|
if(COMPARE_N_##type(&mx,&array[i]) < 0) mx =(type)array[i];\
|
|
return mx;}\
|
|
\
|
|
size_t ARG_MAX_ARRAY_##type(const type *array, size_t size){\
|
|
if(array == NULL) return 0;\
|
|
size_t i_mx = 0;\
|
|
for(size_t i = 0; i < size; ++i)\
|
|
if(COMPARE_N_##type(&array[i_mx],&array[i]) < 0) i_mx = i;\
|
|
return i_mx;}\
|
|
\
|
|
type MIN_ARRAY_##type(const type *array, size_t size){\
|
|
if(array == NULL) return 0;\
|
|
type mn =(type)array[0];\
|
|
for(size_t i = 0; i < size; ++i)\
|
|
if(COMPARE_N_##type(&mn,&array[i]) > 0) mn =(type)array[i];\
|
|
return mn;}\
|
|
\
|
|
size_t ARG_MIN_ARRAY_##type(const type *array, size_t size){\
|
|
if(array == NULL) return 0;\
|
|
size_t i_mn = 0;\
|
|
for(size_t i = 0; i < size; ++i)\
|
|
if(COMPARE_N_##type(&array[i_mn],&array[i]) > 0) i_mn = i;\
|
|
return i_mn;}\
|
|
\
|
|
|
|
|
|
|
|
|
|
#define GENERATE_FUNCTION_NUMERIC(type)\
|
|
int COMPARE_N_##type(const void *a, const void *b){ \
|
|
type diff = 0;\
|
|
if((*(type*)a > *(type*)b)){ \
|
|
diff =(*(type*)a - *(type*)b) * PRECISION_##type; \
|
|
/*char *str_diff = type##_TO_STR(diff), *str_a = type##_TO_STR(*(type*)a), *str_b = type##_TO_STR(*(type*)b);\
|
|
PRINT_DEBUG_(" diff = %s a=%s b=%s PRECISION : %ld\n",str_diff, str_a, str_b, PRECISION_##type);\
|
|
free(str_diff); free(str_a); free(str_b);\
|
|
*/ \
|
|
if(diff >= 1) return 1;\
|
|
return 0;\
|
|
}else{\
|
|
diff =(*(type*)b - *(type*)a) * PRECISION_##type; \
|
|
/*char *str_diff = type##_TO_STR(diff), *str_a = type##_TO_STR(*(type*)a), *str_b = type##_TO_STR(*(type*)b);\
|
|
PRINT_DEBUG_(" diff = %s a=%s b=%s PRECISION : %ld\n",str_diff, str_a, str_b, PRECISION_##type);\
|
|
free(str_diff); free(str_a); free(str_b);\
|
|
*/\
|
|
if(diff >= 1) return -1;\
|
|
return 0;\
|
|
}\
|
|
\
|
|
/*if (diff <= -1) return -1; \
|
|
if (diff >= 1) return 1; \
|
|
return 0; \
|
|
*/\
|
|
} \
|
|
\
|
|
void COPY_ARRAY_##type(type *dst, const type *src, size_t size){ \
|
|
for(size_t i = 0; i < size; ++i) dst[i]=src[i]; \
|
|
} \
|
|
\
|
|
|
|
|
|
|
|
|
|
#ifndef IMPLEMENTATION_TOOLS
|
|
#define IMPLEMENTATION_TOOLS()\
|
|
\
|
|
GEN_TO_STR_N(TYPE_CHAR,2,"%c")\
|
|
GEN_TO_STR_N(TYPE_U_CHAR,2,"%c")\
|
|
GEN_TO_STR_N(TYPE_INT,22,"%d")\
|
|
GEN_TO_STR_N(TYPE_U_INT,22,"%u")\
|
|
GEN_TO_STR_N(TYPE_L_INT,22,"%ld")\
|
|
GEN_TO_STR_N(TYPE_U_L_INT,22,"%lu")\
|
|
GEN_TO_STR_N(TYPE_SIZE_T,22,"%lu")\
|
|
GEN_TO_STR_N(TYPE_FLOAT,128,"%.10f")\
|
|
GEN_TO_STR_N(TYPE_DOUBLE,256,"%.30lf")\
|
|
GEN_TO_STR_N(TYPE_L_DOUBLE,256,"%.30Lf")\
|
|
\
|
|
TYPE_STRING TYPE_STRING_TO_STR(TYPE_STRING var){\
|
|
return var;\
|
|
}\
|
|
\
|
|
\
|
|
long int PRECISION_TYPE_CHAR = 1;\
|
|
long int PRECISION_TYPE_U_CHAR = 1;\
|
|
long int PRECISION_TYPE_INT = 1;\
|
|
long int PRECISION_TYPE_U_INT = 1;\
|
|
long int PRECISION_TYPE_L_INT = 1;\
|
|
long int PRECISION_TYPE_U_L_INT = 1;\
|
|
long int PRECISION_TYPE_SIZE_T = 1;\
|
|
\
|
|
long int PRECISION_TYPE_FLOAT = 100000000;\
|
|
/*long int PRECISION_TYPE_FLOAT = 100000;\
|
|
*/long int PRECISION_TYPE_DOUBLE = 100000000000;\
|
|
long int PRECISION_TYPE_L_DOUBLE = 100000000000000;\
|
|
\
|
|
\
|
|
\
|
|
\
|
|
int \
|
|
COMPARE_N_TYPE_STRING(const void *a,const void* b)\
|
|
{\
|
|
char **aa=(char**)a;\
|
|
char **bb=(char**)b;\
|
|
PRINT_DEBUG_("a=%s, b=%s\n",*aa, *bb);\
|
|
return strcmp(*aa,*bb);\
|
|
}\
|
|
\
|
|
void COPY_ARRAY_TYPE_STRING(char** dst, const char** src, size_t array_size)\
|
|
{\
|
|
for(size_t i = 0; i < array_size; ++i) strcpy(dst[i],src[i]);\
|
|
}\
|
|
\
|
|
\
|
|
GENERATE_FUNCTION_NUMERIC(TYPE_CHAR)\
|
|
GENERATE_FUNCTION_NUMERIC(TYPE_U_CHAR)\
|
|
GENERATE_FUNCTION_NUMERIC(TYPE_INT)\
|
|
GENERATE_FUNCTION_NUMERIC(TYPE_U_INT)\
|
|
GENERATE_FUNCTION_NUMERIC(TYPE_L_INT)\
|
|
GENERATE_FUNCTION_NUMERIC(TYPE_U_L_INT)\
|
|
GENERATE_FUNCTION_NUMERIC(TYPE_SIZE_T)\
|
|
GENERATE_FUNCTION_NUMERIC(TYPE_FLOAT)\
|
|
GENERATE_FUNCTION_NUMERIC(TYPE_DOUBLE)\
|
|
GENERATE_FUNCTION_NUMERIC(TYPE_L_DOUBLE)\
|
|
\
|
|
GENERATE_FUNCTION_ALL(TYPE_CHAR)\
|
|
GENERATE_FUNCTION_ALL(TYPE_U_CHAR)\
|
|
GENERATE_FUNCTION_ALL(TYPE_INT)\
|
|
GENERATE_FUNCTION_ALL(TYPE_U_INT)\
|
|
GENERATE_FUNCTION_ALL(TYPE_L_INT)\
|
|
GENERATE_FUNCTION_ALL(TYPE_U_L_INT)\
|
|
GENERATE_FUNCTION_ALL(TYPE_SIZE_T)\
|
|
GENERATE_FUNCTION_ALL(TYPE_FLOAT)\
|
|
GENERATE_FUNCTION_ALL(TYPE_DOUBLE)\
|
|
GENERATE_FUNCTION_ALL(TYPE_L_DOUBLE)\
|
|
GENERATE_FUNCTION_ALL(TYPE_STRING)\
|
|
\
|
|
/* strto_type */\
|
|
\
|
|
int strto_TYPE_INT(char *str, char **endptr){ \
|
|
return (int)strtol(str,endptr,10);\
|
|
}\
|
|
unsigned int strto_TYPE_U_INT(char *str, char **endptr){ \
|
|
return (unsigned int)strtoul(str,endptr,10);\
|
|
}\
|
|
long int strto_TYPE_L_INT(char *str, char **endptr){\
|
|
return strtol(str,endptr,10);\
|
|
}\
|
|
unsigned long int strto_TYPE_U_L_INT(char *str, char **endptr){\
|
|
return strtoul(str,endptr,10);\
|
|
}\
|
|
size_t strto_TYPE_SIZE_T(char *str, char **endptr){\
|
|
return strtoul(str,endptr,10);\
|
|
}\
|
|
float strto_TYPE_FLOAT(char *str, char **endptr){\
|
|
return strtof(str,endptr);\
|
|
}\
|
|
double strto_TYPE_DOUBLE(char *str, char **endptr){\
|
|
return strtod(str,endptr);\
|
|
}\
|
|
long double strto_TYPE_L_DOUBLE(char *str, char **endptr){\
|
|
return strtold(str,endptr);\
|
|
}\
|
|
\
|
|
\
|
|
/*\
|
|
* time section\
|
|
*/\
|
|
\
|
|
double diff_timespec_seconds(struct timespec time_stop, struct timespec time_start){\
|
|
/*PRINT_DEBUG_("\n\nstop.sec:%ld, start.sec:%ld, stop.nsec:%ld, start.nsec:%ld\n\n", time_stop.tv_sec , time_start.tv_sec, time_stop.tv_nsec , time_start.tv_nsec);*/\
|
|
return (time_stop.tv_sec - time_start.tv_sec) + 1.0e-9 * (time_stop.tv_nsec - time_start.tv_nsec);\
|
|
}\
|
|
\
|
|
double diff_timespec_milliseconds(struct timespec time_stop, struct timespec time_start){\
|
|
/*PRINT_DEBUG_("\n\nstop.sec:%ld, start.sec:%ld, stop.nsec:%ld, start.nsec:%ld\n\n", time_stop.tv_sec , time_start.tv_sec, time_stop.tv_nsec , time_start.tv_nsec);*/\
|
|
return 1.0e3 * (time_stop.tv_sec - time_start.tv_sec) + 1.0e-6 * (time_stop.tv_nsec - time_start.tv_nsec);\
|
|
}\
|
|
\
|
|
long diff_timespec_nanoseconds(struct timespec time_stop, struct timespec time_start){\
|
|
/*PRINT_DEBUG_("\n\nstop.sec:%ld, start.sec:%ld, stop.nsec:%ld, start.nsec:%ld\n\n", time_stop.tv_sec , time_start.tv_sec, time_stop.tv_nsec , time_start.tv_nsec);*/\
|
|
return 1.0e9 * (time_stop.tv_sec - time_start.tv_sec) + (time_stop.tv_nsec - time_start.tv_nsec);\
|
|
}\
|
|
\
|
|
|
|
#endif /* IMPLEMENTATION_TOOLS */
|
|
|
|
#ifndef __DIMENSION_T_H__
|
|
#define __DIMENSION_T_H__
|
|
|
|
#include "../list_t/list_t.h"
|
|
|
|
struct dimension{
|
|
size_t rank;
|
|
size_t *shape;
|
|
long int *basis;
|
|
size_t basis_rank;
|
|
size_t size;
|
|
};
|
|
|
|
|
|
|
|
bool littleEndian=true;
|
|
|
|
bool isLessEqThan(long int a, long int b) ;
|
|
bool isLessThan(long int a, long int b) ;
|
|
bool isGreatEqThan(long int a, long int b) ;
|
|
bool isGreatThan(long int a, long int b) ;
|
|
long int incr(long int i) ;
|
|
long int decr(long int i) ;
|
|
|
|
|
|
typedef struct dimension dimension ;
|
|
|
|
dimension * create_dim(size_t rank);
|
|
dimension * create_reverse_dim(size_t rank);
|
|
dimension* init_dim(size_t *t, size_t rnk);
|
|
dimension* init_copy_dim(size_t *t, size_t rnk);
|
|
dimension* clone_dim(dimension *dim);
|
|
void free_dimension(dimension *d);
|
|
|
|
bool is_equal_dim(dimension *d0, dimension *d1);
|
|
|
|
dimension* sub_minus_dim_head(dimension *t, size_t minusSubdim);
|
|
dimension* sub_minus_dim_tail(dimension *t, size_t minusSubdim);
|
|
dimension* sub_dim_head(dimension *t, size_t subdim);
|
|
dimension* sub_dim_tail(dimension *t, size_t subdim);
|
|
|
|
dimension* sub_copy_minus_dim_head(dimension *t, size_t minusSubdim);
|
|
dimension* sub_copy_minus_dim_tail(dimension *t, size_t minusSubdim);
|
|
dimension* sub_copy_dim_head(dimension *t, size_t sub_copydim);
|
|
dimension* sub_copy_dim_tail(dimension *t, size_t sub_copydim);
|
|
|
|
void split_dim_part(dimension *root, dimension **part_1, dimension **part_2, size_t pivotSplit, size_t rangeInPivot );
|
|
|
|
void add_copy_dimension(dimension **d, dimension *d0, dimension *d1);
|
|
void min_copy_dimension(dimension **d, dimension *d0, dimension *d1);
|
|
|
|
void add_dimension(dimension **d, dimension *d0, dimension *d1);
|
|
void min_dimension(dimension **d, dimension *d0, dimension *d1);
|
|
|
|
void printDebug_dimension(dimension *d, char *msg);
|
|
size_t sprint_dimension(char **dimContent, dimension *d);
|
|
|
|
void updateDim(dimension *dim);
|
|
|
|
size_t LineFromCoord(size_t *coo, dimension *dim);
|
|
size_t* CoordFromLin(size_t line, dimension *dim);
|
|
void vCoordFromLin(size_t *ret, size_t line, dimension *dim );
|
|
|
|
long int signedLineFromCoord(long *coo, dimension *dim);
|
|
long int* signedCoordFromLin(long line, dimension *dim);
|
|
void signedvCoordFromLin(long *ret, long int line, dimension *dim );
|
|
|
|
|
|
void increment_dim_var(dimension *d);
|
|
void decrement_dim_var(dimension *d);
|
|
|
|
struct list_shape_in_dim{
|
|
size_t index;
|
|
size_t shape;
|
|
struct list_shape_in_dim *next;
|
|
};
|
|
|
|
typedef struct list_shape_in_dim list_shape_in_dim;
|
|
|
|
void append_in_list_shape(list_shape_in_dim **list_p, size_t shape);
|
|
dimension * create_dim_from_list_shape( list_shape_in_dim *l_p);
|
|
|
|
dimension * create_binary_dim(size_t dimension_rank);
|
|
|
|
void free_list_shape_in_dim(list_shape_in_dim *l_p);
|
|
|
|
CREATE_HEADER_LIST(dimension)
|
|
|
|
typedef dimension * ptr_DIMENSION;
|
|
|
|
CREATE_HEADER_LIST(ptr_DIMENSION)
|
|
GEN_HEAD_PTR_LIST(ptr_DIMENSION)
|
|
|
|
/*int compare_dimension(dimension *d1, dimension *d2);*/
|
|
|
|
#endif /* __DIMENSION_T_H__*/
|
|
|
|
#ifndef min
|
|
#define min(x,y) (((x)<(y))?(x):(y))
|
|
#endif
|
|
|
|
//#ifndef IMPLEMENTATION_DIMENSION
|
|
#define IMPLEMENTATION_DIMENSION()\
|
|
\
|
|
/*littleEndian=true;*/\
|
|
\
|
|
bool isLessEqThan(long int a, long int b) { return a <= b; }\
|
|
bool isLessThan(long int a, long int b) { return a < b; }\
|
|
bool isGreatEqThan(long int a, long int b) { return a >= b; }\
|
|
bool isGreatThan(long int a, long int b) { return a > b; }\
|
|
long int incr(long int i) { return i + 1; }\
|
|
long int decr(long int i) { return i - 1; }\
|
|
\
|
|
dimension* init_dim(size_t *t, size_t rnk){\
|
|
dimension *d = malloc(sizeof(dimension));\
|
|
d->rank=rnk;\
|
|
d->shape=t;\
|
|
d->basis=NULL;\
|
|
d->basis_rank=0;\
|
|
updateDim(d);\
|
|
return d;\
|
|
}\
|
|
\
|
|
dimension* init_copy_dim(size_t *t, size_t rnk){\
|
|
if (rnk==0) return NULL;\
|
|
dimension *d = malloc(sizeof(dimension));\
|
|
d->shape=malloc(rnk * sizeof(size_t));\
|
|
d->basis=NULL;\
|
|
d->basis_rank=0;\
|
|
d->rank = rnk;\
|
|
for(size_t i=0; i<rnk; ++i) d->shape[i]=t[i];\
|
|
updateDim(d);\
|
|
return d;\
|
|
}\
|
|
dimension *\
|
|
create_dim(size_t rnk){\
|
|
if (rnk==0) return NULL;\
|
|
dimension *d = malloc(sizeof(dimension));\
|
|
d->shape=malloc(rnk * sizeof(size_t));\
|
|
d->basis=NULL;\
|
|
d->basis_rank=0;\
|
|
d->rank = rnk;\
|
|
return d;\
|
|
}\
|
|
\
|
|
dimension* clone_dim(dimension *dim){\
|
|
return init_copy_dim(dim->shape,dim->rank);\
|
|
}\
|
|
\
|
|
dimension *\
|
|
create_reverse_dim(size_t rnk){\
|
|
dimension *dim = create_dim(rnk);\
|
|
for(size_t i=0;i<rnk;++i) dim->shape[i]=rnk-1-i;\
|
|
updateDim(dim);\
|
|
return dim;\
|
|
}\
|
|
\
|
|
void free_dimension(dimension *d){\
|
|
if(d){\
|
|
if(d->shape) free(d->shape);\
|
|
if(d->basis) free(d->basis);\
|
|
free(d);\
|
|
}\
|
|
}\
|
|
\
|
|
bool is_equal_dim(dimension *d0, dimension *d1){\
|
|
if(d0->rank != d1->rank) return false;\
|
|
if(d0->size != d1->size) return false;\
|
|
for(size_t i=0;i<d0->rank; ++i)\
|
|
if(d0->shape[i] != d1->shape[i]) return false;\
|
|
\
|
|
return true;\
|
|
}\
|
|
\
|
|
dimension* sub_copy_minus_dim_head(dimension *root, size_t minusSubdim){\
|
|
if(minusSubdim < (root->rank)){\
|
|
dimension *d = init_copy_dim(root->shape, (root->rank)-minusSubdim);\
|
|
updateDim(d);\
|
|
return d;\
|
|
}\
|
|
return NULL;\
|
|
}\
|
|
\
|
|
dimension* sub_copy_minus_dim_tail(dimension *root, size_t minusSubdim){\
|
|
if(minusSubdim < (root->rank)){\
|
|
dimension *d = init_copy_dim((root->shape)+minusSubdim, (root->rank)-minusSubdim);\
|
|
updateDim(d);\
|
|
return d;\
|
|
}\
|
|
return NULL;\
|
|
}\
|
|
\
|
|
dimension* sub_copy_dim_head(dimension *root, size_t subdim){\
|
|
if(subdim < (root->rank)){\
|
|
dimension *d = init_copy_dim(root->shape, subdim);\
|
|
updateDim(d);\
|
|
return d;\
|
|
}\
|
|
return NULL;\
|
|
}\
|
|
\
|
|
dimension* sub_copy_dim_tail(dimension *root, size_t subdim){\
|
|
if(subdim < (root->rank)){\
|
|
dimension *d = init_copy_dim((root->shape)+(root->rank - subdim), subdim);\
|
|
updateDim(d);\
|
|
return d;\
|
|
}\
|
|
return NULL;\
|
|
}\
|
|
\
|
|
void add_copy_dimension(dimension **d, dimension *d0, dimension *d1) {\
|
|
(*d) = create_dim(d0->rank + d1->rank);\
|
|
for (size_t i = 0; i < d0->rank; i++) (*d)->shape[i] = d0->shape[i];\
|
|
for (size_t i = 0; i < d1->rank; i++) (*d)->shape[d0->rank + i] = d1->shape[i];\
|
|
updateDim(*d);\
|
|
}\
|
|
\
|
|
void min_copy_dimension(dimension **d, dimension *d0, dimension *d1) {\
|
|
size_t mindim = min(d0->rank,d1->rank) ;\
|
|
(*d)=create_dim(mindim);\
|
|
\
|
|
for (size_t i = 0; i < mindim; i++) {\
|
|
if (d0->shape[i] > d1->shape[i]) (*d)->shape[i] = d1->shape[i];\
|
|
else (*d)->shape[i] = d0->shape[i];\
|
|
}\
|
|
updateDim(*d);\
|
|
}\
|
|
\
|
|
\
|
|
\
|
|
\
|
|
dimension* sub_minus_dim_head(dimension *root, size_t minusSubdim){\
|
|
if(minusSubdim < (root->rank)){\
|
|
dimension *d = init_dim(root->shape, (root->rank)-minusSubdim);\
|
|
updateDim(d);\
|
|
return d;\
|
|
}\
|
|
return NULL;\
|
|
}\
|
|
dimension* sub_minus_dim_tail(dimension *root, size_t minusSubdim){\
|
|
if(minusSubdim < (root->rank)){\
|
|
dimension *d = init_dim((root->shape)+minusSubdim, (root->rank)-minusSubdim);\
|
|
updateDim(d);\
|
|
return d;\
|
|
}\
|
|
return NULL;\
|
|
}\
|
|
dimension* sub_dim_head(dimension *root, size_t subdim){\
|
|
if(subdim < (root->rank)){\
|
|
dimension *d = init_dim(root->shape, subdim);\
|
|
updateDim(d);\
|
|
return d;\
|
|
}\
|
|
return NULL;\
|
|
}\
|
|
dimension* sub_dim_tail(dimension *root, size_t subdim){\
|
|
if(subdim < (root->rank)){\
|
|
dimension *d = init_dim((root->shape)+(root->rank - subdim), subdim);\
|
|
updateDim(d);\
|
|
return d;\
|
|
}\
|
|
return NULL;\
|
|
}\
|
|
\
|
|
/*\
|
|
void split_dim_part(dimension *root, dimension **part_1, dimension **part_2, size_t rnk_nb_minus_part ) */\
|
|
void split_dim_part(dimension *root, dimension **part_1, dimension **part_2, size_t pivotSplit, size_t rangeInPivot ) {\
|
|
if(pivotSplit < root->rank){\
|
|
if(rangeInPivot < root->shape[pivotSplit]){\
|
|
/*size_t rnk_part1= (root->size * rnk_nb_minus_part)/(root->shape[(root->rank)-1]);*/\
|
|
/*printf("rnk_part1 :%ld \n",rnk_part1);*/\
|
|
*part_1 = init_copy_dim(root->shape, root->rank);\
|
|
((*part_1)->shape[pivotSplit]) -= rangeInPivot;\
|
|
updateDim(*part_1);\
|
|
/*if(rnk_nb_minus_part <2)\
|
|
*part_2 = init_copy_dim((root->shape), root->rank-1 );\
|
|
else{*/\
|
|
*part_2 = init_copy_dim((root->shape), root->rank );\
|
|
(*part_2)->shape[pivotSplit] = rangeInPivot ;\
|
|
/*}*/\
|
|
updateDim(*part_2);\
|
|
}\
|
|
}\
|
|
}\
|
|
\
|
|
void increment_dim_var(dimension *d){\
|
|
if(littleEndian){\
|
|
(d->shape[0])++;\
|
|
}\
|
|
else{\
|
|
(d->shape[d->rank - 1])++;\
|
|
}\
|
|
}\
|
|
\
|
|
\
|
|
void decrement_dim_var(dimension *d){\
|
|
if(littleEndian){\
|
|
(d->shape[0])--;\
|
|
}\
|
|
else{\
|
|
(d->shape[d->rank - 1])--;\
|
|
}\
|
|
}\
|
|
\
|
|
void add_dimension(dimension **d, dimension *d0, dimension *d1) {\
|
|
(*d) = create_dim(d0->rank + d1->rank);\
|
|
for (size_t i = 0; i < d0->rank; i++) (*d)->shape[i] = d0->shape[i];\
|
|
for (size_t i = 0; i < d1->rank; i++) (*d)->shape[d0->rank + i] = d1->shape[i];\
|
|
updateDim(*d);\
|
|
}\
|
|
\
|
|
void min_dimension(dimension **d, dimension *d0, dimension *d1) {\
|
|
if (d0->rank > d1->rank) {\
|
|
*d = d1;\
|
|
}\
|
|
else if (d0->rank < d1->rank) {\
|
|
*d = d0;\
|
|
}\
|
|
else { /* d0->rank = d1->rank*/\
|
|
*d = d0;\
|
|
for (size_t i = 0; i < d0->rank; i++) {\
|
|
if (d0->shape[i] > d1->shape[i]) (*d)->shape[i] = d1->shape[i];\
|
|
}\
|
|
}\
|
|
updateDim(*d);\
|
|
}\
|
|
\
|
|
void printDebug_dimension(dimension *d,char *msg){\
|
|
\
|
|
printf("<%p>(%s)->rank = %ld | (%s)->size = %ld \n[",d,msg,d->rank,msg,d->size);\
|
|
for(size_t i=0; i<d->rank; ++i)\
|
|
printf(" %ld,", d->shape[i]);\
|
|
printf("] \n");\
|
|
/*printf("[%ld: %ld] |", i,d->shape[i]);*/\
|
|
/* if(littleEndian)\
|
|
printf("\nlittleEndian (true): the bigest index varies first, e.g: [x0,x1,x2,...,xn] xn is the bigest index\n");\
|
|
else\
|
|
printf("\nlittleEndian (false): the lowest index varies first, e.g: [x0,x1,x2,...,xn] x0 is the lowest index\n");\
|
|
*/\
|
|
}\
|
|
\
|
|
size_t sprint_dimension(char **dimContent, dimension *d){\
|
|
if(*dimContent != NULL){\
|
|
free(*dimContent);\
|
|
*dimContent=NULL;\
|
|
}\
|
|
size_t nbch=6*d->rank+40;\
|
|
*dimContent = malloc(nbch);\
|
|
/*printf("nbCh=%ld\n",nbch);*/\
|
|
char *val=NULL;\
|
|
size_t cur=0;\
|
|
char *dimSzCh="dim->rank";\
|
|
for(size_t i=0; i<strlen(dimSzCh);++i)\
|
|
(*dimContent)[cur++]=dimSzCh[i];\
|
|
(*dimContent)[cur++]='=';\
|
|
val=TYPE_SIZE_T_TO_STR(d->rank);\
|
|
for(size_t c=0;c<strlen(val);++c)\
|
|
(*dimContent)[cur++]=val[c];\
|
|
free(val); val = NULL;\
|
|
(*dimContent)[cur++]=' ';\
|
|
(*dimContent)[cur++]='/';\
|
|
(*dimContent)[cur++]=' ';\
|
|
char *dimRkCh="dim->size";\
|
|
for(size_t i=0; i<strlen(dimRkCh);++i)\
|
|
(*dimContent)[cur++]=dimRkCh[i];\
|
|
(*dimContent)[cur++]='=';\
|
|
val=TYPE_SIZE_T_TO_STR(d->size);\
|
|
for(size_t c=0;c<strlen(val);++c)\
|
|
(*dimContent)[cur++]=val[c];\
|
|
free(val); val = NULL;\
|
|
(*dimContent)[cur++]=' ';\
|
|
(*dimContent)[cur++]='\n';\
|
|
(*dimContent)[cur++]='[';\
|
|
for(size_t i=0; i<d->rank;++i){\
|
|
(*dimContent)[cur++]=' ';\
|
|
val=TYPE_SIZE_T_TO_STR(d->shape[i]);\
|
|
for(size_t c=0;c<strlen(val);++c)\
|
|
(*dimContent)[cur++]=val[c];\
|
|
free(val); val = NULL;\
|
|
(*dimContent)[cur++]=',';\
|
|
\
|
|
}\
|
|
(*dimContent)[cur++]=']';\
|
|
\
|
|
(*dimContent)[cur++]='\n';\
|
|
(*dimContent)[cur++]='\0';\
|
|
\
|
|
return cur;\
|
|
}\
|
|
\
|
|
void updateDim(dimension *dim){\
|
|
if(dim->basis==NULL){\
|
|
\
|
|
dim->basis_rank=dim->rank+1;\
|
|
dim->basis=malloc(dim->basis_rank *sizeof(long int));\
|
|
}else if(dim->basis_rank != dim->rank+1){\
|
|
free(dim->basis);\
|
|
dim->basis_rank=dim->rank+1;\
|
|
dim->basis=malloc(dim->basis_rank *sizeof(long int));\
|
|
}\
|
|
dim->basis[dim->rank]=1;\
|
|
for(long int j=dim->rank-1; j>=0; --j){\
|
|
dim->basis[j] = dim->basis[j+1]*dim->shape[j];\
|
|
}\
|
|
dim->size=dim->basis[0];\
|
|
}\
|
|
\
|
|
/* signed */\
|
|
long int signedLineFromCoord(long int *coo, dimension *dim){\
|
|
long int begin = 0;\
|
|
long int end = dim->rank - 1;\
|
|
long int (*iter)(long int); iter = &incr;\
|
|
bool (*cond)(long int, long int); cond = &isLessEqThan;\
|
|
\
|
|
if (littleEndian) {\
|
|
begin = dim->rank - 1; end = 0;\
|
|
iter = &decr; cond = &isGreatEqThan;\
|
|
}\
|
|
\
|
|
long int pp = 1;\
|
|
long int sm = 0;\
|
|
for (long int i = begin; cond(i, end); i = iter(i)) {\
|
|
sm += (coo[i] * pp);\
|
|
pp *= dim->shape[i];\
|
|
}\
|
|
return sm;\
|
|
\
|
|
}\
|
|
\
|
|
void signedvCoordFromLin(long int *ret, long int line, dimension *dim ){\
|
|
\
|
|
long int begin = 0, end = dim->rank - 1;\
|
|
long int (*iter)(long int) = incr;\
|
|
bool (*cond)(long int, long int) = isLessThan;\
|
|
if (littleEndian == false) {\
|
|
/*if (littleEndian) {*/\
|
|
begin = dim->rank - 1; end = 0;\
|
|
iter = decr; cond = isGreatThan;\
|
|
}\
|
|
/*prlong intf("to coor begin = %d end = %d \n", begin, end);*/\
|
|
\
|
|
long int sm = line;\
|
|
long int pp = dim->size;\
|
|
for (long int i = begin; cond(i, end); i = iter(i)) {\
|
|
/*prlong intf(" i: %d ", i);*/\
|
|
pp /= dim->shape[i];\
|
|
ret[i] = sm / pp;\
|
|
sm %= pp;\
|
|
/*prlong intf("sm[%d] = %d , pp=%d ; ", i, sm, pp);*/\
|
|
}\
|
|
ret[end] = sm;\
|
|
}\
|
|
\
|
|
long int* signedCoordFromLin(long int line, dimension *dim){\
|
|
long int *ret;\
|
|
ret=malloc(dim->rank*sizeof(long int));\
|
|
signedvCoordFromLin(ret,line,dim);\
|
|
return ret;\
|
|
}\
|
|
\
|
|
/* */\
|
|
/* unsigned */\
|
|
size_t LineFromCoord(size_t *coo, dimension *dim) {\
|
|
return (long)signedLineFromCoord((long*)coo,dim);\
|
|
}\
|
|
\
|
|
void vCoordFromLin(size_t *ret, size_t line, dimension *dim ){\
|
|
signedvCoordFromLin((long*)ret, (long)line, dim);\
|
|
}\
|
|
\
|
|
size_t* CoordFromLin(size_t line, dimension *dim){\
|
|
return (size_t*)signedCoordFromLin((long)line, dim);\
|
|
}\
|
|
\
|
|
\
|
|
/* */\
|
|
\
|
|
void append_in_list_shape(list_shape_in_dim **list_p, size_t shape){\
|
|
list_shape_in_dim *lis=malloc(sizeof(list_shape_in_dim));\
|
|
lis->shape=shape;\
|
|
lis->next=NULL;\
|
|
if(*list_p == NULL){\
|
|
lis->index=0;\
|
|
*list_p = lis;\
|
|
}\
|
|
else{\
|
|
list_shape_in_dim *tmp =*list_p;\
|
|
while(tmp->next) tmp=tmp->next;\
|
|
lis->index = tmp->index +1;\
|
|
tmp->next=lis;\
|
|
}\
|
|
}\
|
|
\
|
|
dimension * create_dim_from_list_shape( list_shape_in_dim *l_p){\
|
|
\
|
|
if(l_p){\
|
|
list_shape_in_dim *tmp =l_p;\
|
|
while(tmp->next) tmp=tmp->next;\
|
|
dimension *dim=create_dim(tmp->index + 1);\
|
|
(dim)->rank = tmp->index + 1;\
|
|
tmp=l_p;\
|
|
while(tmp){\
|
|
(dim)->shape[tmp->index]=tmp->shape;\
|
|
tmp=tmp->next;\
|
|
}\
|
|
updateDim(dim);\
|
|
return dim;\
|
|
}\
|
|
return NULL;\
|
|
}\
|
|
\
|
|
dimension * create_binary_dim(size_t dimension_rank){\
|
|
dimension * dim = create_dim(dimension_rank);\
|
|
for(size_t i=0; i<dimension_rank; ++i)\
|
|
dim->shape[i]=2;\
|
|
updateDim(dim);\
|
|
return dim;\
|
|
}\
|
|
\
|
|
\
|
|
void free_list_shape_in_dim(list_shape_in_dim *l_p){\
|
|
list_shape_in_dim *tmp=l_p, *ttmp;\
|
|
while(tmp){\
|
|
ttmp = tmp;\
|
|
tmp = ttmp->next;\
|
|
free(ttmp);\
|
|
}\
|
|
}\
|
|
\
|
|
IMPLEMENTATION_LIST(dimension)\
|
|
\
|
|
IMPLEMENTATION_LIST(ptr_DIMENSION)\
|
|
GEN_FUNC_PTR_LIST_FREE(ptr_DIMENSION){\
|
|
dimension *pdim=(dimension*)arg;\
|
|
free_dimension(pdim);\
|
|
/*free(pdim);*/\
|
|
}\
|
|
\
|
|
|
|
//#endif /* IMPLEMENTATION_DIMENSION */
|
|
|
|
|
|
|
|
#ifndef __TENSOR_T__H__
|
|
#define __TENSOR_T__H__
|
|
|
|
#include <stdlib.h>
|
|
#include <time.h>
|
|
#include <pthread.h>
|
|
|
|
//#include "dimension_t/dimension_t.h"
|
|
|
|
void subArray(size_t* dst, size_t* src, size_t debDst, size_t finDst, size_t debSrc);
|
|
|
|
#define GENERATE_TENSOR_TYPE(type) \
|
|
struct tensor_##type{\
|
|
dimension *dim;\
|
|
type *x;\
|
|
};\
|
|
typedef struct tensor_##type tensor_##type;\
|
|
tensor_##type * create_tensor_##type(dimension *dim); \
|
|
tensor_##type* create_tensor_from_cpy_dim_##type(dimension *dim);\
|
|
void _recreate_tensor_if_not_the_same_dim_or_null_##type(tensor_##type **M, dimension *dd);\
|
|
tensor_##type* clone_tensor_##type(tensor_##type *tens);\
|
|
void free_tensor_##type(tensor_##type * tens); \
|
|
int copy_tensor_##type(tensor_##type * dst, tensor_##type * src);\
|
|
tensor_##type * sub_minus_tensor_head_##type(tensor_##type *rootens, size_t minuSubdim, size_t sizeInDim); \
|
|
tensor_##type * sub_minus_tensor_tail_##type(tensor_##type *rootens, size_t minuSubdim, size_t sizeInDim); \
|
|
tensor_##type * sub_tensor_head_##type(tensor_##type *rootens, size_t subdim, size_t sizeInDim); \
|
|
tensor_##type * sub_tensor_tail_##type(tensor_##type *rootens, size_t subdim, size_t sizeInDim); \
|
|
tensor_##type * sub_copy_minus_tensor_head_##type(tensor_##type *rootens, size_t minuSubdim, size_t sizeInDim); \
|
|
tensor_##type * sub_copy_minus_tensor_tail_##type(tensor_##type *rootens, size_t minuSubdim, size_t sizeInDim); \
|
|
tensor_##type * sub_copy_tensor_head_##type(tensor_##type *rootens, size_t sub_copydim, size_t sizeInDim); \
|
|
tensor_##type * sub_copy_tensor_tail_##type(tensor_##type *rootens, size_t sub_copydim, size_t sizeInDim); \
|
|
void print_tensor_msg_##type(tensor_##type *T, char *msg);\
|
|
void fprint_tensor_##type(char *file_name, tensor_##type *T);\
|
|
size_t sprint_tensor_##type(char **tensorContent,tensor_##type *T, bool withIndex);\
|
|
void split_tensor_##type(tensor_##type *Troot, tensor_##type **Tpart1, tensor_##type **Tpart2, size_t pivotSplit, size_t rangeInPivot);\
|
|
void split_copy_tensor_##type(tensor_##type *Troot, tensor_##type **Tpart1, tensor_##type **Tpart2, size_t pivotSplit, size_t rangeInPivot);\
|
|
void tensorProdNotOpt_##type(tensor_##type **MM, tensor_##type *M0, tensor_##type *M1); \
|
|
void tensorProd_##type(tensor_##type **MM, tensor_##type *M0, tensor_##type *M1); \
|
|
void tensorContractnProd_##type(tensor_##type **MM, tensor_##type *M0, tensor_##type *M1, size_t contractionNumber); \
|
|
void tensorProdThread_##type(tensor_##type **MM, tensor_##type *M0, tensor_##type *M1,size_t nbthread); \
|
|
void tensorProdThrea2d_##type(tensor_##type **MM, tensor_##type *M0, tensor_##type *M1,size_t nbthread); \
|
|
void tensorContractnProdThread_##type(tensor_##type **MM, tensor_##type *M0, tensor_##type *M1, size_t contractionNumber, size_t nbthread); \
|
|
void tensorContractnProdThreadOpt0_##type(tensor_##type **MM, tensor_##type *M0, tensor_##type *M1, size_t contractionNumber, size_t nbthread); \
|
|
void tensorContractnPro2dThread_##type(tensor_##type **MM, tensor_##type *M0, tensor_##type *M1, size_t contractionNumber, size_t nbthread); \
|
|
void tensorContractnPro2dThreadOpt0_##type(tensor_##type **MM, tensor_##type *M0, tensor_##type *M1, size_t contractionNumber, size_t nbthread); \
|
|
void tensorContractnProdNotOpt_##type(tensor_##type **MM, tensor_##type *M0, tensor_##type *M1, size_t contractionNumber); \
|
|
void tensorContractnProdOpt0_##type(tensor_##type **MM, tensor_##type *M0, tensor_##type *M1, size_t contractionNumber); \
|
|
type scalarProduct_dep_contractProd_##type(tensor_##type *M0, tensor_##type *M1, size_t nbthreads ,void (*tensorContractVar)(tensor_##type **MM, tensor_##type *M0, tensor_##type *M1, size_t contractionNumber, size_t nbthread ));\
|
|
type scalarProduct_0_##type(tensor_##type *M0, tensor_##type *M1);\
|
|
void init_random_x_##type(tensor_##type *M, type minR, type maxR, int randomRange);\
|
|
tensor_##type * parseInput_withDim_to_tensor_##type(char *input);\
|
|
void parseInputOutput_withDim_to_tensors_##type(tensor_##type **Tpart1, tensor_##type **Tpart2, char *input, size_t pivotSplit);\
|
|
void parse_file_InputOutput_withDim_to_tensors_##type(tensor_##type **Tpart1, tensor_##type **Tpart2, char *file_name_input, size_t pivotSplit);\
|
|
tensor_##type ** fromInput_to_array_tensor_##type(tensor_##type *tens);\
|
|
struct array_chainlist_##type{\
|
|
size_t index;\
|
|
type x;\
|
|
struct array_chainlist_##type *next;\
|
|
};\
|
|
typedef struct array_chainlist_##type array_chainlist_##type;\
|
|
void append_array_chainlist_##type(array_chainlist_##type **list_a, type x);\
|
|
tensor_##type * create_tensor_from_list_array_##type( array_chainlist_##type *l_a, dimension *part_dim);\
|
|
void free_array_chainlist_##type(array_chainlist_##type *l_a);\
|
|
tensor_##type * transpose_notOpt_tensor_##type(tensor_##type *org);\
|
|
tensor_##type * transpose_Opt0_tensor_##type(tensor_##type *org);\
|
|
tensor_##type * transpose_Opt1_tensor_##type(tensor_##type *org);\
|
|
tensor_##type * permute_notOpt_tensor_##type(tensor_##type *org, dimension *dshape);\
|
|
void update_1tensor_func_##type(tensor_##type *M0, \
|
|
type (*func)(type), size_t nbthread);\
|
|
void update_2tensor_func_##type(tensor_##type *M0, tensor_##type *M1, \
|
|
type (*func)(type), size_t nbthread);\
|
|
void update_3tensor_func_##type(tensor_##type *M0, tensor_##type *M1, tensor_##type *M2, \
|
|
type (*func)(type, type), size_t nbthread);\
|
|
void update_4tensor_func_##type(tensor_##type *M0, tensor_##type *M1, tensor_##type *M2, \
|
|
type (*func)(type, type, type(*f1)(type)),\
|
|
type(*f1)(type),\
|
|
size_t nbthread);\
|
|
void update_5tensor_func_##type(tensor_##type *M0, tensor_##type *M1, tensor_##type *M2, tensor_##type *M3 , \
|
|
type (*func) (type, type, type, type(*f1)(type), type (*f2)(type,type)), \
|
|
type(*f1)(type), \
|
|
type (*f2)(type,type), \
|
|
size_t nbthread);\
|
|
void update_6tensor_func_##type(tensor_##type *M0, tensor_##type *M1, \
|
|
type (*func)(type, type, type),\
|
|
type scalar,\
|
|
size_t nbthread);\
|
|
|
|
|
|
GENERATE_TENSOR_TYPE(TYPE_FLOAT);
|
|
GENERATE_TENSOR_TYPE(TYPE_DOUBLE);
|
|
GENERATE_TENSOR_TYPE(TYPE_L_DOUBLE);
|
|
|
|
|
|
#endif /* __TENSOR_T__H__ */
|
|
|
|
void subArray(size_t* dst, size_t* src, size_t debDst, size_t finDst, size_t debSrc) {
|
|
for (size_t i = debDst; i < finDst; i++) {
|
|
dst[i] = src[i + debSrc];
|
|
}
|
|
}
|
|
|
|
void concatArray(size_t* dst, size_t* src0, size_t* src1, size_t debDst, size_t debSrc0, size_t finSrc0, size_t debSrc1, size_t finSrc1) {
|
|
size_t i = debDst;
|
|
for (size_t j = debSrc0; j < finSrc0; j++) {
|
|
dst[i++] = src0[j];
|
|
}
|
|
for (size_t j = debSrc1; j < finSrc1; j++) {
|
|
dst[i++] = src1[j];
|
|
}
|
|
}
|
|
|
|
void printArraySzt(size_t *a, size_t rnk,char *msg){
|
|
printf("======== %s ======= rank: %ld\n",msg,rnk);
|
|
for(size_t i=0; i< rnk; ++i)
|
|
printf("[%ld : %ld ] ",i,a[i]);
|
|
printf("\n");
|
|
}
|
|
|
|
int checkContractProdTensorDim(dimension *d0, dimension *d1, ssize_t contractionNumber){
|
|
if((d0->rank-contractionNumber <0)||(d1->rank-contractionNumber <0)) return 0;
|
|
if(littleEndian){
|
|
ssize_t beginCommonM0=d0->rank-contractionNumber;
|
|
for(ssize_t i=0; i<contractionNumber; ++i){
|
|
if(d0->shape[beginCommonM0+i] != d1->shape[i]) return 0;
|
|
}
|
|
}else{
|
|
ssize_t beginCommonM1=d1->rank-contractionNumber;
|
|
for(ssize_t i=0; i<contractionNumber; ++i){
|
|
if(d0->shape[i] != d1->shape[beginCommonM1+i]) return 0;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
/*
|
|
bool isLessEqThan(long int a, long int b) { return a <= b; }
|
|
bool isLessThan(long int a, long int b) { return a < b; }
|
|
bool isGreatEqThan(long int a, long int b) { return a >= b; }
|
|
bool isGreatThan(long int a, long int b) { return a > b; }
|
|
long int incr(long int i) { return i + 1; }
|
|
long int decr(long int i) { return i - 1; }
|
|
*/
|
|
|
|
#define FREE_COORD_\
|
|
free(coord0);\
|
|
free(coord1);\
|
|
free(coord);\
|
|
|
|
#define FREE_t \
|
|
free( tsub0 );\
|
|
free( tsub1 );\
|
|
free( tDk1 );\
|
|
free( tDk0 );
|
|
|
|
#define FREE_dM_S_\
|
|
free_dimension(dM0);\
|
|
free_dimension(dM1);\
|
|
free_dimension(dM);\
|
|
free_dimension(dSub0);\
|
|
free_dimension(dSub1);\
|
|
|
|
#define xrand() rand()
|
|
|
|
#define GEN_FUNC_TENSOR(type)\
|
|
tensor_##type* create_tensor_##type(dimension *dim){\
|
|
tensor_##type *r_tens=malloc(sizeof(tensor_##type));\
|
|
updateDim(dim);\
|
|
r_tens->dim = dim;\
|
|
r_tens->x = malloc(sizeof(type)*dim->size);\
|
|
return r_tens;\
|
|
}\
|
|
\
|
|
void _recreate_tensor_if_not_the_same_dim_or_null_##type(tensor_##type **M, dimension *dd){\
|
|
if(*M){ \
|
|
if(!is_equal_dim((*M)->dim, dd)){\
|
|
free_tensor_##type(*M);\
|
|
(*M)=create_tensor_##type(dd);\
|
|
}else free_dimension(dd); /* because it is not used */\
|
|
}else{\
|
|
(*M)=create_tensor_##type(dd);\
|
|
}\
|
|
}\
|
|
tensor_##type* init_tensor_head_##type(tensor_##type *troot ,dimension *dim){\
|
|
tensor_##type *r_tens=malloc(sizeof(tensor_##type));\
|
|
updateDim(dim);\
|
|
r_tens->dim = dim;\
|
|
r_tens->x = troot->x;\
|
|
return r_tens;\
|
|
}\
|
|
\
|
|
tensor_##type* init_tensor_tail_##type(tensor_##type *troot ,dimension *dim){\
|
|
tensor_##type *r_tens=malloc(sizeof(tensor_##type));\
|
|
updateDim(dim);\
|
|
r_tens->dim = dim;\
|
|
r_tens->x = troot->x + ((troot->dim)->size - dim->size);\
|
|
return r_tens;\
|
|
}\
|
|
\
|
|
\
|
|
tensor_##type* init_copy_tensor_head_##type(tensor_##type *troot ,dimension *dim){\
|
|
tensor_##type *r_tens=malloc(sizeof(tensor_##type));\
|
|
updateDim(dim);\
|
|
r_tens->dim = dim;\
|
|
/*r_tens->x = troot->x;*/\
|
|
for(size_t i=0; i<dim->size;++i)\
|
|
r_tens->x[i]=troot->x[i];\
|
|
return r_tens;\
|
|
}\
|
|
\
|
|
tensor_##type* init_copy_tensor_tail_##type(tensor_##type *troot ,dimension *dim){\
|
|
tensor_##type *r_tens=malloc(sizeof(tensor_##type));\
|
|
updateDim(dim);\
|
|
r_tens->dim = dim;\
|
|
/*r_tens->x = troot->x + ((troot->dim)->size - dim->size);*/\
|
|
r_tens->x = malloc(sizeof(type)*dim->size);\
|
|
size_t dRank=(troot->dim)->size - dim->size;\
|
|
for(size_t i=0; i<dim->size;++i)\
|
|
r_tens->x[i]=troot->x[i+dRank];\
|
|
return r_tens;\
|
|
}\
|
|
\
|
|
\
|
|
tensor_##type* create_tensor_from_cpy_dim_##type(dimension *dim){\
|
|
tensor_##type *r_tens=malloc(sizeof(tensor_##type));\
|
|
r_tens->dim = init_copy_dim(dim->shape,dim->rank);\
|
|
r_tens->x = malloc(sizeof(type)*dim->size);\
|
|
return r_tens;\
|
|
}\
|
|
\
|
|
tensor_##type* clone_tensor_##type(tensor_##type *tens){\
|
|
if(tens){\
|
|
tensor_##type *r_tens=malloc(sizeof(tensor_##type));\
|
|
r_tens->dim = clone_dim(tens->dim);\
|
|
r_tens->x = malloc(sizeof(type) * (tens->dim)->size);\
|
|
for(size_t i=0; i<(tens->dim)->size;++i)\
|
|
r_tens->x[i]=tens->x[i];\
|
|
return r_tens;\
|
|
}\
|
|
return NULL;\
|
|
}\
|
|
\
|
|
int copy_tensor_##type(tensor_##type * dst, tensor_##type * src){\
|
|
if(dst!=NULL && src!=NULL){ \
|
|
int diff = dst->dim->size - src->dim->size;\
|
|
if(diff == 0) \
|
|
for(size_t i=0; i<(src->dim)->size;++i)\
|
|
dst->x[i]=src->x[i];\
|
|
return diff;\
|
|
\
|
|
}\
|
|
return -1;\
|
|
}\
|
|
\
|
|
void free_tensor_##type(tensor_##type * tens){\
|
|
if(tens){\
|
|
free_dimension(tens->dim);\
|
|
free(tens->x);\
|
|
free(tens);\
|
|
}\
|
|
}\
|
|
void init_random_x_##type(tensor_##type *M, type minR, type maxR, int randomRange){\
|
|
/*static bool initRandomFirst = true;\
|
|
if(initRandomFirst){ srand(time(NULL)); initRandomFirst = false;}*/\
|
|
int randVal;\
|
|
for(size_t i =0; i<(M->dim)->size;++i){\
|
|
randVal = xrand() % randomRange;\
|
|
M->x[i]=minR + (maxR-minR)*randVal / randomRange ;\
|
|
\
|
|
}\
|
|
}\
|
|
tensor_##type * sub_minus_tensor_head_##type(tensor_##type *rootens, size_t minuSubdim, size_t sizeInDim){\
|
|
dimension *rdim= rootens->dim;\
|
|
dimension *dS_t = sub_minus_dim_tail(rdim,rdim->rank - minuSubdim);\
|
|
if(sizeInDim < dS_t->size){\
|
|
dimension *dS_h = sub_minus_dim_head(rdim,minuSubdim);\
|
|
tensor_##type *ret_ens = malloc(sizeof(tensor_##type));\
|
|
ret_ens->dim = dS_h;\
|
|
ret_ens->x = malloc(sizeof(type)*dS_h->size);\
|
|
if(littleEndian){\
|
|
for(size_t i=0; i<dS_h->size; ++i){\
|
|
ret_ens->x[i]=rootens->x[i*dS_t->size + sizeInDim];\
|
|
\
|
|
}\
|
|
}else{\
|
|
for(size_t i=0; i<dS_h->size; ++i){\
|
|
ret_ens->x[i]=rootens->x[i + dS_h->size * sizeInDim];\
|
|
}\
|
|
}\
|
|
return ret_ens;\
|
|
}\
|
|
return NULL;\
|
|
}\
|
|
\
|
|
tensor_##type * sub_minus_tensor_tail_##type(tensor_##type *rootens, size_t minuSubdim, size_t sizeInDim){\
|
|
dimension *rdim= rootens->dim;\
|
|
dimension *dS_h = sub_minus_dim_head(rdim,rdim->rank - minuSubdim);\
|
|
if(sizeInDim < dS_h->size){\
|
|
dimension *dS_t = sub_minus_dim_tail(rdim,minuSubdim);\
|
|
tensor_##type *ret_ens = malloc(sizeof(tensor_##type));\
|
|
ret_ens->dim = dS_t;\
|
|
ret_ens->x = malloc(sizeof(type)*dS_t->size);\
|
|
if(littleEndian==false){\
|
|
for(size_t i=0; i<dS_t->size; ++i){\
|
|
ret_ens->x[i]=rootens->x[i*dS_h->size + sizeInDim];\
|
|
}\
|
|
}else{\
|
|
for(size_t i=0; i<dS_t->size; ++i){\
|
|
ret_ens->x[i]=rootens->x[i + dS_t->size * sizeInDim];\
|
|
}\
|
|
\
|
|
}\
|
|
return ret_ens;\
|
|
}\
|
|
return NULL;\
|
|
}\
|
|
\
|
|
tensor_##type * sub_tensor_head_##type(tensor_##type *rootens, size_t subdim, size_t sizeInDim){\
|
|
dimension *rdim= rootens->dim;\
|
|
dimension *dS_t = sub_dim_tail(rdim,rdim->rank - subdim);\
|
|
if(sizeInDim < dS_t->size){\
|
|
dimension *dS_h = sub_dim_head(rdim,subdim);\
|
|
tensor_##type *ret_ens = malloc(sizeof(tensor_##type));\
|
|
ret_ens->dim = dS_h;\
|
|
ret_ens->x = malloc(sizeof(type)*dS_h->size);\
|
|
if(littleEndian){\
|
|
for(size_t i=0; i<dS_h->size; ++i){\
|
|
ret_ens->x[i]=rootens->x[i*dS_t->size + sizeInDim];\
|
|
}\
|
|
}else{\
|
|
for(size_t i=0; i<dS_h->size; ++i){\
|
|
ret_ens->x[i]=rootens->x[i + dS_h->size * sizeInDim];\
|
|
}\
|
|
\
|
|
}\
|
|
return ret_ens;\
|
|
}\
|
|
return NULL;\
|
|
}\
|
|
tensor_##type * sub_tensor_tail_##type(tensor_##type *rootens, size_t subdim, size_t sizeInDim){ \
|
|
dimension *rdim= rootens->dim;\
|
|
dimension *dS_h = sub_dim_head(rdim,rdim->rank - subdim);\
|
|
if(sizeInDim < dS_h->size){\
|
|
dimension *dS_t = sub_dim_tail(rdim,subdim);\
|
|
tensor_##type *ret_ens = malloc(sizeof(tensor_##type));\
|
|
ret_ens->dim = dS_t;\
|
|
ret_ens->x = malloc(sizeof(type)*dS_t->size);\
|
|
if(littleEndian==false){\
|
|
for(size_t i=0; i<dS_t->size; ++i){\
|
|
ret_ens->x[i]=rootens->x[i*dS_h->size + sizeInDim];\
|
|
}\
|
|
}else{\
|
|
for(size_t i=0; i<dS_t->size; ++i){\
|
|
ret_ens->x[i]=rootens->x[i + dS_t->size * sizeInDim];\
|
|
}\
|
|
\
|
|
}\
|
|
return ret_ens;\
|
|
}\
|
|
return NULL;\
|
|
}\
|
|
\
|
|
tensor_##type * sub_copy_minus_tensor_head_##type(tensor_##type *rootens, size_t minuSubdim, size_t sizeInDim){\
|
|
dimension *rdim= rootens->dim;\
|
|
dimension *dS_t = sub_copy_minus_dim_tail(rdim,rdim->rank - minuSubdim);\
|
|
if(sizeInDim < dS_t->size){\
|
|
dimension *dS_h = sub_copy_minus_dim_head(rdim,minuSubdim);\
|
|
tensor_##type *ret_ens = create_tensor_##type(dS_h);\
|
|
/*malloc(sizeof(tensor_##type));\
|
|
ret_ens->dim = dS_h;\
|
|
ret_ens->x = malloc(sizeof(type)*dS_h->size);*/\
|
|
if(littleEndian){\
|
|
/*ret_ens->x = malloc(sizeof(type)*dS_h->size);\
|
|
*/for(size_t i=0; i<dS_h->size; ++i){\
|
|
ret_ens->x[i]=rootens->x[i*dS_t->size + sizeInDim];\
|
|
/*printf("%ld: [i:%ld] | %ld : [%ld ]\n",dS_t->size, i,dS_h->size,i*dS_h->size + sizeInDim);*/\
|
|
\
|
|
}\
|
|
}else{\
|
|
/*ret_ens->x = (rootens->x)+sizeInDim*dS_h->size;*/\
|
|
for(size_t i=0; i<dS_h->size; ++i){\
|
|
ret_ens->x[i]=rootens->x[i + dS_h->size * sizeInDim];\
|
|
}\
|
|
}\
|
|
free_dimension(dS_t);\
|
|
return ret_ens;\
|
|
}\
|
|
free_dimension(dS_t);\
|
|
return NULL;\
|
|
}\
|
|
\
|
|
tensor_##type * sub_copy_minus_tensor_tail_##type(tensor_##type *rootens, size_t minuSubdim, size_t sizeInDim){\
|
|
dimension *rdim= rootens->dim;\
|
|
dimension *dS_h = sub_copy_minus_dim_head(rdim,rdim->rank - minuSubdim);\
|
|
if(sizeInDim < dS_h->size){\
|
|
dimension *dS_t = sub_copy_minus_dim_tail(rdim,minuSubdim);\
|
|
tensor_##type *ret_ens = create_tensor_##type(dS_t);\
|
|
/*tensor_##type *ret_ens = malloc(sizeof(tensor_##type));\
|
|
ret_ens->dim = dS_t;\
|
|
ret_ens->x = malloc(sizeof(type)*dS_t->size);\
|
|
*/if(littleEndian==false){\
|
|
for(size_t i=0; i<dS_t->size; ++i){\
|
|
ret_ens->x[i]=rootens->x[i*dS_h->size + sizeInDim];\
|
|
}\
|
|
}else{\
|
|
/*ret_ens->x = (rootens->x)+sizeInDim*dS_t->size;*/\
|
|
for(size_t i=0; i<dS_t->size; ++i){\
|
|
ret_ens->x[i]=rootens->x[i + dS_t->size * sizeInDim];\
|
|
}\
|
|
\
|
|
}\
|
|
free_dimension(dS_h);\
|
|
return ret_ens;\
|
|
}\
|
|
free_dimension(dS_h);\
|
|
return NULL;\
|
|
}\
|
|
\
|
|
tensor_##type * sub_copy_tensor_head_##type(tensor_##type *rootens, size_t sub_copydim, size_t sizeInDim){\
|
|
/*return sub_copy_minus_tensor_head_##type(rootens,rootens->dim->rank - sub_copydim, sizeInDim);*/\
|
|
dimension *rdim= rootens->dim;\
|
|
dimension *dS_t = sub_copy_dim_tail(rdim,rdim->rank - sub_copydim);\
|
|
if(sizeInDim < dS_t->size){\
|
|
dimension *dS_h = sub_copy_dim_head(rdim,sub_copydim);\
|
|
tensor_##type *ret_ens = create_tensor_##type(dS_h);\
|
|
/*tensor_##type *ret_ens = malloc(sizeof(tensor_##type));\
|
|
ret_ens->dim = dS_h;\
|
|
ret_ens->x = malloc(sizeof(type)*dS_h->size);\
|
|
*/if(littleEndian){\
|
|
for(size_t i=0; i<dS_h->size; ++i){\
|
|
ret_ens->x[i]=rootens->x[i*dS_t->size + sizeInDim];\
|
|
/*printf("%ld: [i:%ld] | %ld : [%ld ]\n",dS_t->size, i,dS_h->size,i*dS_h->size + sizeInDim);*/\
|
|
}\
|
|
}else{\
|
|
/*ret_ens->x = (rootens->x)+sizeInDim*dS_h->size;*/\
|
|
for(size_t i=0; i<dS_h->size; ++i){\
|
|
ret_ens->x[i]=rootens->x[i + dS_h->size * sizeInDim];\
|
|
/*printf("%ld: [i:%ld] | %ld : [%ld ]\n",dS_t->size, i,dS_h->size,i*dS_h->size + sizeInDim);*/\
|
|
}\
|
|
\
|
|
}\
|
|
free_dimension(dS_t);\
|
|
return ret_ens;\
|
|
}\
|
|
free_dimension(dS_t);\
|
|
return NULL;\
|
|
}\
|
|
tensor_##type * sub_copy_tensor_tail_##type(tensor_##type *rootens, size_t sub_copydim, size_t sizeInDim){ \
|
|
/*return sub_copy_minus_tensor_tail_##type(rootens,rootens->dim->rank - sub_copydim, sizeInDim);*/\
|
|
dimension *rdim= rootens->dim;\
|
|
dimension *dS_h = sub_copy_dim_head(rdim,rdim->rank - sub_copydim);\
|
|
if(sizeInDim < dS_h->size){\
|
|
dimension *dS_t = sub_copy_dim_tail(rdim,sub_copydim);\
|
|
tensor_##type *ret_ens = create_tensor_##type(dS_t);\
|
|
/*tensor_##type *ret_ens = malloc(sizeof(tensor_##type));\
|
|
ret_ens->dim = dS_t;\
|
|
ret_ens->x = malloc(sizeof(type)*dS_t->size);\
|
|
*/if(littleEndian==false){\
|
|
for(size_t i=0; i<dS_t->size; ++i){\
|
|
ret_ens->x[i]=rootens->x[i*dS_h->size + sizeInDim];\
|
|
/*printf("%ld: [i:%ld] | %ld : [%ld ]\n",dS_t->size, i,dS_h->size,i*dS_h->size + sizeInDim);*/\
|
|
}\
|
|
}else{\
|
|
/*ret_ens->x = (rootens->x)+sizeInDim*dS_t->size;*/\
|
|
for(size_t i=0; i<dS_t->size; ++i){\
|
|
ret_ens->x[i]=rootens->x[i + dS_t->size * sizeInDim];\
|
|
/*printf("%ld: [i:%ld] | %ld : [%ld ]\n",dS_t->size, i,dS_h->size,i*dS_h->size + sizeInDim);*/\
|
|
}\
|
|
\
|
|
}\
|
|
free_dimension(dS_h);\
|
|
return ret_ens;\
|
|
}\
|
|
free_dimension(dS_h);\
|
|
return NULL;\
|
|
}\
|
|
\
|
|
void print_tensor_msg_##type(tensor_##type *T,char *msg) {\
|
|
/*size_t j=0 ,k=0*/;\
|
|
size_t *coord = malloc(sizeof(long int)*(T->dim)->rank); \
|
|
char *val=NULL;\
|
|
/*char *dimsg=malloc(512);\
|
|
sprintf(dimsg,"(%s)->dim",msg);\
|
|
printDebug_dimension(T->dim,dimsg);\
|
|
*/printf("%s\n",msg);\
|
|
long int begin , end /*, beginIter , endIter*/ ;\
|
|
long int (*iter)(long int) ;\
|
|
bool (*cond)(long int, long int) ; \
|
|
if (littleEndian ) {\
|
|
begin = (T->dim->rank) - 1; end = 0;\
|
|
iter = decr; cond = isGreatEqThan; \
|
|
/*printf("littleEndian(=true): the bigest index varies first, e.g: [x0,x1,x2,...,xn] xn is the bigest index \n");*/\
|
|
}else{\
|
|
begin = 0 ; end = (T->dim->rank) - 1; \
|
|
iter = incr; cond = isLessEqThan; \
|
|
/*printf("littleEndian(=false): the lowest index varies first, e.g: [x0,x1,x2,...,xn] x0 is the lowest index \n");*/\
|
|
}\
|
|
for(long int i=0;i<(T->dim)->size;++i){\
|
|
vCoordFromLin(coord,i,T->dim);\
|
|
if(coord[begin]==0){\
|
|
for(long int j=begin; cond(j,end); j= iter(j) ){\
|
|
if(coord[j]==0) printf("(");\
|
|
else break;\
|
|
}\
|
|
}\
|
|
/*printf(" [");\
|
|
for(size_t k=0; k<(T->dim)->rank;++k) printf(" %ld",coord[k]);\
|
|
*/val=type##_TO_STR(T->x[i]);\
|
|
printf(" |#%ld]: %s, ",i,val);\
|
|
/*printf(" %s, ",val);*/\
|
|
free(val); val=NULL;\
|
|
/*if(T->x[i] != T->x[i]){\
|
|
printf("\nALERT NAN\n");\
|
|
char c;\
|
|
scanf("%c",&c);\
|
|
}*/\
|
|
if(coord[begin]==(T->dim)->shape[begin]-1){\
|
|
size_t count=0;\
|
|
for(long int j=begin; cond(j,end); j = iter(j)){\
|
|
if(coord[j]==(T->dim)->shape[j]-1) {\
|
|
printf(")"); ++count;\
|
|
}\
|
|
else break;\
|
|
}\
|
|
if(count == (T->dim)->rank-1) printf("\n ");\
|
|
}\
|
|
}\
|
|
\
|
|
free(coord);\
|
|
printf("\n");\
|
|
/*free(dimsg);*/\
|
|
}\
|
|
\
|
|
\
|
|
void fprint_tensor_##type(char *file_name, tensor_##type *T) {\
|
|
/*size_t j=0,k=0;*/\
|
|
size_t *coord = malloc(sizeof(long int)*(T->dim)->rank); \
|
|
char *val=NULL;\
|
|
FILE *fileWrite = fopen(file_name, "w");\
|
|
if(fileWrite == NULL) {\
|
|
printf("error while opening %s\n",file_name);\
|
|
exit(1);\
|
|
}\
|
|
long int begin , end /*, beginIter, endIter*/ ;\
|
|
long int (*iter)(long int) ;\
|
|
bool (*cond)(long int, long int) ; \
|
|
if (littleEndian ) {\
|
|
begin = (T->dim->rank) - 1; end = 0;\
|
|
iter = decr; cond = isGreatEqThan; \
|
|
/*fprintf(fileWrite,"littleEndian(=true): the bigest index varies first, e.g: [x0,x1,x2,...,xn] xn is the bigest index \n");*/\
|
|
}else{\
|
|
begin = 0 ; end = (T->dim->rank) - 1; \
|
|
iter = incr; cond = isLessEqThan; \
|
|
/*fprintf(fileWrite,"littleEndian(=false): the lowest index varies first, e.g: [x0,x1,x2,...,xn] x0 is the lowest index \n");*/\
|
|
}\
|
|
fprintf(fileWrite,"[");\
|
|
for(size_t i=0; i<(T->dim)->rank; ++i)\
|
|
fprintf(fileWrite," %ld,", (T->dim)->shape[i]);\
|
|
fprintf(fileWrite,"] \n");\
|
|
\
|
|
for(long int i=0;i<(T->dim)->size;++i){\
|
|
vCoordFromLin(coord,i,T->dim);\
|
|
if(coord[begin]==0){\
|
|
for(long int j=begin; cond(j,end); j= iter(j) ){\
|
|
if(coord[j]==0) fprintf(fileWrite,"(");\
|
|
else break;\
|
|
}\
|
|
}\
|
|
if(T->x[i] != T->x[i]){\
|
|
printf("\nALERT NAN\n");\
|
|
;\
|
|
return;\
|
|
}\
|
|
/*fprintf(fileWrite," [");\
|
|
for(size_t k=0; k<(T->dim)->rank;++k) fprintf(fileWrite," %ld,",coord[k]);\
|
|
*/val=type##_TO_STR(T->x[i]);\
|
|
fprintf(fileWrite," %s, ",val);\
|
|
free(val); val=NULL;\
|
|
if(coord[begin]==(T->dim)->shape[begin]-1){\
|
|
size_t count=0;\
|
|
for(long int j=begin; cond(j,end); j = iter(j)){\
|
|
if(coord[j]==(T->dim)->shape[j]-1) {\
|
|
fprintf(fileWrite,")"); ++count;\
|
|
}\
|
|
else break;\
|
|
}\
|
|
if(count == (T->dim)->rank-1) fprintf(fileWrite,"\n ");\
|
|
}\
|
|
}\
|
|
\
|
|
free(coord);\
|
|
fprintf(fileWrite,"\n");\
|
|
fclose(fileWrite);\
|
|
}\
|
|
\
|
|
size_t sprint_tensor_##type(char **tensorContent,tensor_##type *T, bool withIndex) {\
|
|
if(*tensorContent != NULL) {\
|
|
free(*tensorContent);\
|
|
*tensorContent = NULL; \
|
|
}\
|
|
size_t rnk = ((T->dim)->size)*(32+ withIndex * 5*(T->dim)->rank + 129 );\
|
|
/*printf("malloc %ld char\n",rnk);*/\
|
|
*tensorContent = malloc(rnk ) ;\
|
|
size_t cur=0;\
|
|
size_t *coord = malloc(sizeof(long int)*(T->dim)->rank); \
|
|
char *val=NULL;\
|
|
long int begin , end /*, beginIter, endIter*/ ;\
|
|
long int (*iter)(long int) ;\
|
|
bool (*cond)(long int, long int) ; \
|
|
if (littleEndian ) {\
|
|
begin = (T->dim->rank) - 1; end = 0;\
|
|
iter = decr; cond = isGreatEqThan; \
|
|
val=malloc(128);\
|
|
sprintf(val,"littleEndian(=true): the bigest index varies first, e.g: [x0,x1,x2,...,xn] xn is the bigest index \n");\
|
|
for(size_t c=0;c<strlen(val);++c)\
|
|
(*tensorContent)[cur++]=val[c];\
|
|
free(val); val = NULL;\
|
|
}else{\
|
|
begin = 0 ; end = (T->dim->rank) - 1; \
|
|
iter = incr; cond = isLessEqThan; \
|
|
val=malloc(128);\
|
|
sprintf(val,"littleEndian(=false): the lowest index varies first, e.g: [x0,x1,x2,...,xn] x0 is the lowest index \n");\
|
|
for(size_t c=0;c<strlen(val);++c)\
|
|
(*tensorContent)[cur++]=val[c];\
|
|
free(val); val = NULL;\
|
|
}\
|
|
for(long int i=0;i<(T->dim)->size;++i){\
|
|
vCoordFromLin(coord,i,T->dim);\
|
|
if(coord[begin]==0){\
|
|
for(long int j=begin; cond(j,end); j= iter(j) ){\
|
|
if(coord[j]==0) /*printf("(")*/(*tensorContent)[cur++]='(';\
|
|
else break;\
|
|
}\
|
|
}\
|
|
if(withIndex){\
|
|
(*tensorContent)[cur++]=' ';\
|
|
(*tensorContent)[cur++]='[';\
|
|
(*tensorContent)[cur++]='{';\
|
|
for(size_t k=0; k<(T->dim)->rank;++k) {\
|
|
/*printf(" %ld,",coord[k]);*/\
|
|
val=TYPE_SIZE_T_TO_STR(coord[k]);\
|
|
for(size_t c=0;c<strlen(val);++c){\
|
|
(*tensorContent)[cur++]=' ';\
|
|
(*tensorContent)[cur++]=val[c];\
|
|
}\
|
|
free(val); val = NULL;\
|
|
(*tensorContent)[cur++]=',';\
|
|
}\
|
|
(*tensorContent)[cur++]='}';\
|
|
(*tensorContent)[cur++]='#';\
|
|
val=TYPE_SIZE_T_TO_STR(i);\
|
|
for(size_t c=0;c<strlen(val);++c)\
|
|
(*tensorContent)[cur++]=val[c];\
|
|
free(val); val = NULL;\
|
|
(*tensorContent)[cur++]=']';\
|
|
(*tensorContent)[cur++]=' ';\
|
|
}\
|
|
if(T->x[i] != T->x[i]){\
|
|
/*char *nanStr="ALERT NAN";\
|
|
for(size_t c=0;c<strlen(nanStr);++c)\
|
|
(*tensorContent)[cur++]=nanStr[c];*/\
|
|
printf(" ALERT NAN ");\
|
|
;\
|
|
/*return strlen(nanStr)*/;\
|
|
}\
|
|
val=type##_TO_STR(T->x[i]);\
|
|
/*printf(" {%ld} %s [",i,val);*/\
|
|
(*tensorContent)[cur++]=' ';\
|
|
for(size_t c=0;c<strlen(val);++c)\
|
|
(*tensorContent)[cur++]=val[c];\
|
|
free(val); val = NULL;\
|
|
(*tensorContent)[cur++]=',';\
|
|
if(coord[begin]==(T->dim)->shape[begin]-1){\
|
|
size_t count=0;\
|
|
for(long int j=begin; cond(j,end); j = iter(j)){\
|
|
if(coord[j]==(T->dim)->shape[j]-1) {/*printf(")"); */ (*tensorContent)[cur++]=')'; ++count;}\
|
|
else break;\
|
|
}\
|
|
if(count == (T->dim)->rank-1) {(*tensorContent)[cur++]='\n'; (*tensorContent)[cur++]=' ';}\
|
|
}\
|
|
}\
|
|
\
|
|
free(coord);\
|
|
/*printf("\n");*/(*tensorContent)[cur++]='\n';\
|
|
(*tensorContent)[cur++]='\0';\
|
|
return cur;\
|
|
}\
|
|
\
|
|
\
|
|
void split_tensor_##type(tensor_##type *Troot, tensor_##type **Tpart1, tensor_##type **Tpart2, size_t pivotSplit, size_t rangeInPivot){\
|
|
size_t rnk = (Troot->dim)->rank;\
|
|
if(pivotSplit < rnk){\
|
|
if( rangeInPivot < (Troot->dim)->shape[pivotSplit]){\
|
|
dimension *dpart1, *dpart2;\
|
|
split_dim_part(Troot->dim, &dpart1, &dpart2, pivotSplit, rangeInPivot);\
|
|
*Tpart1 = init_tensor_head_##type(Troot, dpart1);\
|
|
*Tpart2 = init_tensor_tail_##type(Troot, dpart2);\
|
|
}\
|
|
}\
|
|
} \
|
|
void split_copy_tensor_##type(tensor_##type *Troot, tensor_##type **Tpart1, tensor_##type **Tpart2, size_t pivotSplit, size_t rangeInPivot){\
|
|
size_t rnk = (Troot->dim)->rank;\
|
|
if(pivotSplit < rnk){\
|
|
if( rangeInPivot < (Troot->dim)->shape[pivotSplit]){\
|
|
dimension *dpart1, *dpart2;\
|
|
split_dim_part(Troot->dim, &dpart1, &dpart2, pivotSplit, rangeInPivot);\
|
|
*Tpart1 = init_copy_tensor_head_##type(Troot, dpart1);\
|
|
*Tpart2 = init_copy_tensor_tail_##type(Troot, dpart2);\
|
|
}\
|
|
}\
|
|
}\
|
|
\
|
|
void tensorProdNotOpt_##type(tensor_##type **MM, tensor_##type *M0, tensor_##type *M1) { \
|
|
dimension *dd; \
|
|
add_dimension(&dd, M0->dim, M1->dim); \
|
|
_recreate_tensor_if_not_the_same_dim_or_null_##type(MM,dd); \
|
|
tensor_##type *M = *MM; \
|
|
size_t* coord; \
|
|
coord = malloc(sizeof(size_t)*(dd->rank)); \
|
|
size_t* coord0 , lin0; \
|
|
coord0 = malloc(sizeof(size_t)* M0->dim->rank); \
|
|
size_t* coord1 , lin1; \
|
|
coord1 = malloc(sizeof(size_t)* M1->dim->rank); \
|
|
for (size_t i = 0; i < dd->size; i++) { \
|
|
vCoordFromLin(coord, i, M->dim); \
|
|
subArray(coord0, coord, 0, M0->dim->rank, 0); \
|
|
subArray(coord1, coord, 0, M1->dim->rank, M0->dim->rank); \
|
|
\
|
|
lin0=LineFromCoord(coord0, M0->dim); \
|
|
lin1=LineFromCoord(coord1, M1->dim); \
|
|
\
|
|
M->x[i] = M0->x[lin0] * M1->x[lin1]; \
|
|
/*printf(" M->x[%ld] = M0->x[%ld] * M1->x[%ld] ::: %f = %f * %f \n",i,lin0,lin1, M->x[i] , M0->x[lin0] , M1->x[lin1]);*/\
|
|
} \
|
|
FREE_COORD_ ; \
|
|
} \
|
|
\
|
|
\
|
|
void tensorProd_##type(tensor_##type **MM, tensor_##type *M0, tensor_##type *M1) { \
|
|
dimension *dd; \
|
|
add_dimension(&dd, M0->dim, M1->dim); \
|
|
_recreate_tensor_if_not_the_same_dim_or_null_##type(MM,dd); \
|
|
tensor_##type *M = *MM; \
|
|
size_t m_idx;\
|
|
for(size_t i=0; i<M0->dim->size; ++i){\
|
|
for(size_t j=0; j<M1->dim->size; ++j){\
|
|
if(littleEndian)\
|
|
m_idx= i*M1->dim->size + j ;\
|
|
else\
|
|
m_idx= i+M0->dim->size * j ;\
|
|
M->x[m_idx]=M0->x[i]*M1->x[j];\
|
|
/*printf("[%ld|%ld:(%ld,%ld)]",x_idx++,m_idx,i,j);*/\
|
|
}\
|
|
}\
|
|
} \
|
|
\
|
|
/* M[x0,x1,x3..xn] X M[y0,y1,y3..ym] = M[z0,z1...zp] (deep = l > 0) /exists 1<= l<...<l=n / xl = y0,x{l+1}=y1, x{n}=yl et zi=xi i<n-l et zj=y{j-(n-l)} j>=n-l alor p=n+m-2l\
|
|
M[x0,x1,x3..xl x{l+1}...xn] X M[xn,x{n-1},x{n-2}...xl y{l+1} ..ym] = M[x0,x1..xly{l+1}...y{n+m-2l}] (deep = l > 0)\
|
|
M[[i][j]]=sum_{[k]}M0[[i][k]]*M[[k][j]]*/\
|
|
\
|
|
void tensorContractnProd_##type(tensor_##type** MM, tensor_##type *M0, tensor_##type *M1, size_t contractionNumber) {\
|
|
/* if (!checkMatchProdtensor(M0->dim, M1->dim, contractionNumber)) {\
|
|
prsize_tf("Deep = %d\n", contractionNumber);\
|
|
}*/\
|
|
if(checkContractProdTensorDim(M0->dim, M1->dim, contractionNumber)==0){\
|
|
printf("checkContractProdTensorDim %ld contractionNumber\n", contractionNumber);\
|
|
printDebug_dimension(M0->dim, "M0 dim");\
|
|
printDebug_dimension(M1->dim, "M1 dim");\
|
|
/*getchar();*/\
|
|
}\
|
|
\
|
|
size_t len0 = M0->dim->rank - contractionNumber;\
|
|
size_t len1 = M1->dim->rank - contractionNumber;\
|
|
\
|
|
size_t* tsub0 = malloc(sizeof(size_t) *len0);\
|
|
size_t* tsub1 = malloc(sizeof(size_t) *len1);\
|
|
size_t* tDk1 = malloc(sizeof(size_t) *contractionNumber);\
|
|
size_t* tDk0 = malloc(sizeof(size_t) *contractionNumber);\
|
|
subArray(tsub0, M0->dim->shape, 0, len0, 0);\
|
|
subArray(tsub1, M1->dim->shape, 0, len1, contractionNumber);\
|
|
subArray(tDk1, M1->dim->shape, 0, contractionNumber, 0);\
|
|
subArray(tDk0, M0->dim->shape, 0, contractionNumber, len0);\
|
|
/*printArraySzt(tsub0,len0,"tsub0");\
|
|
printArraySzt(tsub1,len1,"tsub1");\
|
|
printArraySzt(tDk0,contractionNumber,"tDk0");\
|
|
printArraySzt(tDk1,contractionNumber,"tDk1");*/\
|
|
dimension *dSub0 = init_dim(tsub0, len0);\
|
|
dimension *dSub1 = init_dim(tsub1, len1);\
|
|
dimension *dM1 = init_dim(tDk1, contractionNumber);\
|
|
dimension *dM0 = init_dim(tDk0, contractionNumber);\
|
|
/*printDebug_dimension(dSub0,"dSub0");\
|
|
printDebug_dimension(dSub1,"dSub1");\
|
|
printDebug_dimension(dM0,"dM0");\
|
|
printDebug_dimension(dM1,"dM1");*/\
|
|
dimension *dM;\
|
|
min_copy_dimension(&dM, dM0, dM1);\
|
|
/*printDebug_dimension(dM,"dM");*/\
|
|
\
|
|
dimension *dd;\
|
|
add_dimension(&dd, dSub0, dSub1);\
|
|
/*printDebug_dimension(dd,"dd");*/\
|
|
updateDim(dd);\
|
|
_recreate_tensor_if_not_the_same_dim_or_null_##type(MM,dd);\
|
|
tensor_##type *M= *MM;\
|
|
\
|
|
\
|
|
\
|
|
size_t a0_id, a1_id, n0_id, n1_id;\
|
|
for (size_t i = 0; i < M->dim->size; i++) {\
|
|
if(littleEndian){\
|
|
a0_id=i/dSub1->size;\
|
|
a1_id=i%dSub1->size;\
|
|
}\
|
|
else{\
|
|
a0_id=i%dSub0->size;\
|
|
a1_id=i/dSub0->size;\
|
|
}\
|
|
M->x[i] = 0;\
|
|
for (size_t k = 0; k < dM->size; k++) {\
|
|
if(littleEndian){\
|
|
n0_id= a0_id*dM->size + k;\
|
|
n1_id= a1_id + dSub1->size * k;\
|
|
}\
|
|
else{\
|
|
n0_id= a0_id + dSub0->size * k;\
|
|
n1_id= a1_id*dM->size + k;\
|
|
}\
|
|
M->x[i] += M0->x[n0_id] * M1->x[n1_id];\
|
|
\
|
|
}\
|
|
}\
|
|
FREE_dM_S_ \
|
|
}\
|
|
\
|
|
/* M[x0,x1,x3..xn] X M[y0,y1,y3..ym] = M[z0,z1...zp] (deep = l > 0) /exists 1<= l<...<l=n / xl = y0,x{l+1}=y1, x{n}=yl et zi=xi i<n-l et zj=y{j-(n-l)} j>=n-l alor p=n+m-2l\
|
|
M[x0,x1,x3..xl x{l+1}...xn] X M[xn,x{n-1},x{n-2}...xl y{l+1} ..ym] = M[x0,x1..xly{l+1}...y{n+m-2l}] (deep = l > 0)\
|
|
M[[i][j]]=sum_{[k]}M0[[i][k]]*M[[k][j]]*/\
|
|
\
|
|
void tensorContractnProdOpt0_##type(tensor_##type** MM, tensor_##type *M0, tensor_##type *M1, size_t contractionNumber) {\
|
|
/* if (!checkMatchProdtensor(M0->dim, M1->dim, contractionNumber)) {\
|
|
prsize_tf("Deep = %d\n", contractionNumber);\
|
|
}*/\
|
|
if(checkContractProdTensorDim(M0->dim, M1->dim, contractionNumber)==0){\
|
|
printf("checkContractProdTensorDim %ld contractionNumber\n", contractionNumber);\
|
|
printDebug_dimension(M0->dim, "M0 dim");\
|
|
printDebug_dimension(M1->dim, "M1 dim");\
|
|
/*getchar();*/\
|
|
}\
|
|
\
|
|
size_t len0 = M0->dim->rank - contractionNumber;\
|
|
size_t len1 = M1->dim->rank - contractionNumber;\
|
|
\
|
|
size_t* tsub0 = malloc(sizeof(size_t) *len0);\
|
|
size_t* tsub1 = malloc(sizeof(size_t) *len1);\
|
|
size_t* tDk1 = malloc(sizeof(size_t) *contractionNumber);\
|
|
size_t* tDk0 = malloc(sizeof(size_t) *contractionNumber);\
|
|
subArray(tsub0, M0->dim->shape, 0, len0, 0);\
|
|
subArray(tsub1, M1->dim->shape, 0, len1, contractionNumber);\
|
|
subArray(tDk1, M1->dim->shape, 0, contractionNumber, 0);\
|
|
subArray(tDk0, M0->dim->shape, 0, contractionNumber, len0);\
|
|
/*printArraySzt(tsub0,len0,"tsub0");\
|
|
printArraySzt(tsub1,len1,"tsub1");\
|
|
printArraySzt(tDk0,contractionNumber,"tDk0");\
|
|
printArraySzt(tDk1,contractionNumber,"tDk1");*/\
|
|
dimension *dSub0 = init_dim(tsub0, len0);\
|
|
dimension *dSub1 = init_dim(tsub1, len1);\
|
|
dimension *dM1 = init_dim(tDk1, contractionNumber);\
|
|
dimension *dM0 = init_dim(tDk0, contractionNumber);\
|
|
/*printDebug_dimension(dSub0,"dSub0");\
|
|
printDebug_dimension(dSub1,"dSub1");\
|
|
printDebug_dimension(dM0,"dM0");\
|
|
printDebug_dimension(dM1,"dM1");*/\
|
|
dimension *dM;\
|
|
min_copy_dimension(&dM, dM0, dM1);\
|
|
/*printDebug_dimension(dM,"dM");*/\
|
|
\
|
|
dimension *dd;\
|
|
add_dimension(&dd, dSub0, dSub1);\
|
|
/*printDebug_dimension(dd,"dd");*/\
|
|
updateDim(dd);\
|
|
_recreate_tensor_if_not_the_same_dim_or_null_##type(MM,dd);\
|
|
tensor_##type *M= *MM;\
|
|
\
|
|
\
|
|
\
|
|
size_t a0_id, a1_id, n0_id, n1_id;\
|
|
for (size_t i = 0; i < M->dim->size; i++) {\
|
|
if(littleEndian){\
|
|
a0_id=i/dSub1->size;\
|
|
a1_id=i%dSub1->size;\
|
|
n0_id=a0_id*dM->size ;\
|
|
n1_id= a1_id ;\
|
|
}\
|
|
else{\
|
|
a0_id=i%dSub0->size;\
|
|
a1_id=i/dSub0->size;\
|
|
n1_id= a1_id*dM->size ;\
|
|
n0_id= a0_id ;\
|
|
}\
|
|
M->x[i] = 0;\
|
|
for (size_t k = 0; k < dM->size; k++) {\
|
|
if(littleEndian){\
|
|
/*n0_id= a0_id*dM->size + k;*/\
|
|
/*n1_id= a1_id + dSub1->size * k;*/\
|
|
/*M->x[i] += M0->x[begin0++] * M1->x[n1_id];*/\
|
|
M->x[i] += M0->x[n0_id++] * M1->x[n1_id];\
|
|
n1_id +=dSub1->size ;\
|
|
}\
|
|
else{\
|
|
/*n0_id= a0_id + dSub0->size * k;*/\
|
|
/*n1_id= a1_id*dM->size + k;*/\
|
|
/*M->x[i] += M0->x[n0_id] * M1->x[begin1++];*/\
|
|
M->x[i] += M0->x[n0_id] * M1->x[n1_id++];\
|
|
n0_id += dSub0->size ;\
|
|
}\
|
|
\
|
|
}\
|
|
}\
|
|
FREE_dM_S_ \
|
|
}\
|
|
\
|
|
struct arg_Prod_##type{\
|
|
type *M0x;\
|
|
type *M1x;\
|
|
type *Mx;\
|
|
size_t beginRange;\
|
|
size_t endRange;\
|
|
size_t MRank;\
|
|
};\
|
|
void* runProd_thread_##type(void *arg){\
|
|
struct arg_Prod_##type *arg_t = arg;\
|
|
size_t a0_id, a1_id;\
|
|
for (size_t i = arg_t->beginRange; i < arg_t->endRange; i++) {\
|
|
if(littleEndian){\
|
|
a0_id=i / arg_t->MRank;\
|
|
a1_id=i % arg_t->MRank;\
|
|
}\
|
|
else{\
|
|
a0_id=i % arg_t->MRank;\
|
|
a1_id=i / arg_t->MRank;\
|
|
}\
|
|
arg_t->Mx[i] = arg_t->M0x[a0_id] * arg_t->M1x[a1_id];\
|
|
}\
|
|
return 0;\
|
|
}\
|
|
\
|
|
\
|
|
void tensorProdThread_##type(tensor_##type **MM, tensor_##type *M0, tensor_##type *M1, size_t nbthread) { \
|
|
dimension *dd; \
|
|
add_dimension(&dd, M0->dim, M1->dim); \
|
|
_recreate_tensor_if_not_the_same_dim_or_null_##type(MM,dd); \
|
|
tensor_##type *M = *MM; \
|
|
\
|
|
\
|
|
pthread_t *thrd = malloc(nbthread * sizeof(pthread_t));\
|
|
struct arg_Prod_##type **arg_th = malloc( nbthread * sizeof(struct arg_Prod_##type *));\
|
|
\
|
|
for(size_t i = 0; i < nbthread; ++i){\
|
|
arg_th[i]=malloc(sizeof(struct arg_Prod_##type));\
|
|
arg_th[i]->M0x=M0->x;\
|
|
arg_th[i]->M1x=M1->x;\
|
|
arg_th[i]->Mx=M->x;\
|
|
arg_th[i]->beginRange = i*(M->dim->size)/nbthread ;\
|
|
arg_th[i]->endRange = (i+1)*(M->dim->size)/nbthread ;\
|
|
/*if(i < nbthread - 1 ) arg_th[i]->endRange = (i+1)*(M->dim->size)/nbthread ;\
|
|
else arg_th[i]->endRange = M->dim->size ;\
|
|
*/if(littleEndian){\
|
|
arg_th[i]->MRank = M1->dim->size;\
|
|
}\
|
|
else{\
|
|
arg_th[i]->MRank = M0->dim->size;\
|
|
}\
|
|
pthread_create(&thrd[i], NULL, runProd_thread_##type, (void*)arg_th[i]);\
|
|
}\
|
|
\
|
|
for(size_t i=0; i< nbthread; ++i){\
|
|
pthread_join(thrd[i], NULL);\
|
|
free(arg_th[i]);\
|
|
}\
|
|
\
|
|
free(thrd);\
|
|
free(arg_th);\
|
|
} \
|
|
\
|
|
struct arg_Pro2d_##type{\
|
|
type *M0x;\
|
|
type *M1x;\
|
|
type *Mx;\
|
|
size_t beginRange;\
|
|
size_t endRange;\
|
|
size_t M0Rank;\
|
|
size_t M1Rank;\
|
|
};\
|
|
void* runProd_thread2d_##type(void *arg){\
|
|
struct arg_Pro2d_##type *arg_t = arg;\
|
|
size_t k;\
|
|
for (size_t i = arg_t->beginRange; i < arg_t->endRange; i++) {\
|
|
for (size_t j = 0; j < arg_t->M1Rank; j++) {\
|
|
if(littleEndian){\
|
|
k = i * arg_t->M1Rank + j;\
|
|
}\
|
|
else{\
|
|
k =i + arg_t->M0Rank * j ;\
|
|
}\
|
|
arg_t->Mx[k] = arg_t->M0x[i] * arg_t->M1x[j];\
|
|
}\
|
|
}\
|
|
return 0;\
|
|
}\
|
|
\
|
|
void tensorProdThrea2d_##type(tensor_##type **MM, tensor_##type *M0, tensor_##type *M1, size_t nbthread) { \
|
|
dimension *dd; \
|
|
add_dimension(&dd, M0->dim, M1->dim); \
|
|
_recreate_tensor_if_not_the_same_dim_or_null_##type(MM,dd); \
|
|
tensor_##type *M = *MM; \
|
|
\
|
|
\
|
|
pthread_t *thrd = malloc(nbthread * sizeof(pthread_t));\
|
|
struct arg_Pro2d_##type **arg_th = malloc( nbthread * sizeof(struct arg_Pro2d_##type *));\
|
|
\
|
|
for(size_t i = 0; i < nbthread; ++i){\
|
|
arg_th[i]=malloc(sizeof(struct arg_Pro2d_##type));\
|
|
arg_th[i]->M0x=M0->x;\
|
|
arg_th[i]->M1x=M1->x;\
|
|
arg_th[i]->Mx=M->x;\
|
|
arg_th[i]->beginRange = i*(M0->dim->size)/nbthread ;\
|
|
arg_th[i]->endRange = (i+1)*(M0->dim->size)/nbthread ;\
|
|
/*if(i < nbthread - 1 ) arg_th[i]->endRange = (i+1)*(M0->dim->size)/nbthread ;\
|
|
else arg_th[i]->endRange = M0->dim->size ;\
|
|
*/arg_th[i]->M1Rank = M1->dim->size;\
|
|
arg_th[i]->M0Rank = M0->dim->size;\
|
|
pthread_create(&thrd[i], NULL, runProd_thread2d_##type, (void*)arg_th[i]);\
|
|
}\
|
|
\
|
|
for(size_t i=0; i< nbthread; ++i){\
|
|
pthread_join(thrd[i], NULL);\
|
|
free(arg_th[i]);\
|
|
}\
|
|
\
|
|
free(thrd);\
|
|
free(arg_th);\
|
|
} \
|
|
\
|
|
struct arg_ProdContract_##type{\
|
|
type *M0x;\
|
|
type *M1x;\
|
|
type *Mx;\
|
|
size_t beginRange;\
|
|
size_t endRange;\
|
|
size_t dSubRank;\
|
|
size_t dMRank;\
|
|
};\
|
|
void* runProdContract_thread_##type(void *arg){\
|
|
struct arg_ProdContract_##type *arg_t = arg;\
|
|
size_t a0_id, a1_id, n0_id, n1_id;\
|
|
for (size_t i = arg_t->beginRange; i < arg_t->endRange; i++) {\
|
|
if(littleEndian){\
|
|
a0_id=i/ arg_t->dSubRank;\
|
|
a1_id=i% arg_t->dSubRank;\
|
|
}\
|
|
else{\
|
|
a0_id=i% arg_t->dSubRank;\
|
|
a1_id=i/ arg_t->dSubRank;\
|
|
}\
|
|
arg_t->Mx[i] = 0;\
|
|
for (size_t k = 0; k < arg_t->dMRank; k++) {\
|
|
if(littleEndian){\
|
|
n0_id= a0_id * arg_t->dMRank + k;\
|
|
n1_id= a1_id + arg_t->dSubRank * k;\
|
|
}\
|
|
else{\
|
|
n0_id= a0_id + arg_t->dSubRank * k;\
|
|
n1_id= a1_id * arg_t->dMRank + k;\
|
|
}\
|
|
arg_t->Mx[i] += arg_t->M0x[n0_id] * arg_t->M1x[n1_id];\
|
|
}\
|
|
}\
|
|
return 0;\
|
|
}\
|
|
/* M[x0,x1,x3..xn] X M[y0,y1,y3..ym] = M[z0,z1...zp] (deep = l > 0) /exists 1<= l<...<l=n / xl = y0,x{l+1}=y1, x{n}=yl et zi=xi i<n-l et zj=y{j-(n-l)} j>=n-l alor p=n+m-2l\
|
|
M[x0,x1,x3..xl x{l+1}...xn] X M[xn,x{n-1},x{n-2}...xl y{l+1} ..ym] = M[x0,x1..xly{l+1}...y{n+m-2l}] (deep = l > 0)\
|
|
M[[i][j]]=sum_{[k]}M0[[i][k]]*M[[k][j]]*/\
|
|
\
|
|
\
|
|
void tensorContractnProdThread_##type(tensor_##type** MM, tensor_##type *M0, tensor_##type *M1, size_t contractionNumber, size_t nbthread) {\
|
|
if(checkContractProdTensorDim(M0->dim, M1->dim, contractionNumber)==0){\
|
|
printf("checkContractProdTensorDim %ld contractionNumber\n", contractionNumber);\
|
|
printDebug_dimension(M0->dim, "M0 dim");\
|
|
printDebug_dimension(M1->dim, "M1 dim");\
|
|
/*getchar();*/\
|
|
}\
|
|
size_t len0 = M0->dim->rank - contractionNumber;\
|
|
size_t len1 = M1->dim->rank - contractionNumber;\
|
|
\
|
|
size_t* tsub0 = malloc(sizeof(size_t) *len0);\
|
|
size_t* tsub1 = malloc(sizeof(size_t) *len1);\
|
|
size_t* tDk1 = malloc(sizeof(size_t) *contractionNumber);\
|
|
size_t* tDk0 = malloc(sizeof(size_t) *contractionNumber);\
|
|
subArray(tsub0, M0->dim->shape, 0, len0, 0);\
|
|
subArray(tsub1, M1->dim->shape, 0, len1, contractionNumber);\
|
|
subArray(tDk1, M1->dim->shape, 0, contractionNumber, 0);\
|
|
subArray(tDk0, M0->dim->shape, 0, contractionNumber, len0);\
|
|
dimension *dSub0 = init_dim(tsub0, len0);\
|
|
dimension *dSub1 = init_dim(tsub1, len1);\
|
|
dimension *dM1 = init_dim(tDk1, contractionNumber);\
|
|
dimension *dM0 = init_dim(tDk0, contractionNumber);\
|
|
dimension *dM;\
|
|
min_copy_dimension(&dM, dM0, dM1);\
|
|
\
|
|
dimension *dd;\
|
|
add_dimension(&dd, dSub0, dSub1);\
|
|
updateDim(dd);\
|
|
_recreate_tensor_if_not_the_same_dim_or_null_##type(MM,dd);\
|
|
tensor_##type *M= *MM;\
|
|
\
|
|
\
|
|
\
|
|
pthread_t *thrd = malloc(nbthread * sizeof(pthread_t));\
|
|
struct arg_ProdContract_##type **arg_th = malloc( nbthread * sizeof(struct arg_ProdContract_##type *));\
|
|
\
|
|
for(size_t i = 0; i < nbthread; ++i){\
|
|
arg_th[i]=malloc(sizeof(struct arg_ProdContract_##type));\
|
|
arg_th[i]->M0x=M0->x;\
|
|
arg_th[i]->M1x=M1->x;\
|
|
arg_th[i]->Mx=M->x;\
|
|
arg_th[i]->beginRange = i*(M->dim->size)/nbthread ;\
|
|
if(i < nbthread - 1 ) arg_th[i]->endRange = (i+1)*(M->dim->size)/nbthread ;\
|
|
else arg_th[i]->endRange = M->dim->size ;\
|
|
if(littleEndian){\
|
|
arg_th[i]->dSubRank = dSub1->size;\
|
|
}\
|
|
else{\
|
|
arg_th[i]->dSubRank = dSub0->size;\
|
|
}\
|
|
arg_th[i]->dMRank = dM->size;\
|
|
pthread_create(&thrd[i], NULL, runProdContract_thread_##type, (void*)arg_th[i]);\
|
|
}\
|
|
\
|
|
for(size_t i=0; i< nbthread; ++i){\
|
|
pthread_join(thrd[i], NULL);\
|
|
free(arg_th[i]);\
|
|
}\
|
|
\
|
|
free(thrd);\
|
|
free(arg_th);\
|
|
FREE_dM_S_ ; \
|
|
}\
|
|
\
|
|
\
|
|
void* runProdContractOpt0_thread_##type(void *arg){\
|
|
struct arg_ProdContract_##type *arg_t = arg;\
|
|
size_t a0_id, a1_id, n0_id, n1_id;\
|
|
for (size_t i = arg_t->beginRange; i < arg_t->endRange; i++) {\
|
|
if(littleEndian){\
|
|
a0_id=i/ arg_t->dSubRank;\
|
|
a1_id=i% arg_t->dSubRank;\
|
|
n0_id= a0_id * arg_t->dMRank ;\
|
|
n1_id= a1_id ;\
|
|
}\
|
|
else{\
|
|
a0_id=i% arg_t->dSubRank;\
|
|
a1_id=i/ arg_t->dSubRank;\
|
|
n0_id= a0_id ;\
|
|
n1_id= a1_id * arg_t->dMRank ;\
|
|
}\
|
|
arg_t->Mx[i] = 0;\
|
|
for (size_t k = 0; k < arg_t->dMRank; k++) {\
|
|
if(littleEndian){\
|
|
arg_t->Mx[i] += arg_t->M0x[n0_id++] * arg_t->M1x[n1_id];\
|
|
n1_id += arg_t->dSubRank ;\
|
|
}\
|
|
else{\
|
|
arg_t->Mx[i] += arg_t->M0x[n0_id] * arg_t->M1x[n1_id];\
|
|
n0_id += arg_t->dSubRank ;\
|
|
}\
|
|
}\
|
|
}\
|
|
return 0;\
|
|
}\
|
|
\
|
|
\
|
|
void tensorContractnProdThreadOpt0_##type(tensor_##type** MM, tensor_##type *M0, tensor_##type *M1, size_t contractionNumber, size_t nbthread) {\
|
|
if(checkContractProdTensorDim(M0->dim, M1->dim, contractionNumber)==0){\
|
|
printf("checkContractProdTensorDim %ld contractionNumber\n", contractionNumber);\
|
|
printDebug_dimension(M0->dim, "M0 dim");\
|
|
printDebug_dimension(M1->dim, "M1 dim");\
|
|
/*getchar();*/\
|
|
}\
|
|
size_t len0 = M0->dim->rank - contractionNumber;\
|
|
size_t len1 = M1->dim->rank - contractionNumber;\
|
|
\
|
|
size_t* tsub0 = malloc(sizeof(size_t) *len0);\
|
|
size_t* tsub1 = malloc(sizeof(size_t) *len1);\
|
|
size_t* tDk1 = malloc(sizeof(size_t) *contractionNumber);\
|
|
size_t* tDk0 = malloc(sizeof(size_t) *contractionNumber);\
|
|
subArray(tsub0, M0->dim->shape, 0, len0, 0);\
|
|
subArray(tsub1, M1->dim->shape, 0, len1, contractionNumber);\
|
|
subArray(tDk1, M1->dim->shape, 0, contractionNumber, 0);\
|
|
subArray(tDk0, M0->dim->shape, 0, contractionNumber, len0);\
|
|
dimension *dSub0 = init_dim(tsub0, len0);\
|
|
dimension *dSub1 = init_dim(tsub1, len1);\
|
|
dimension *dM1 = init_dim(tDk1, contractionNumber);\
|
|
dimension *dM0 = init_dim(tDk0, contractionNumber);\
|
|
dimension *dM;\
|
|
min_copy_dimension(&dM, dM0, dM1);\
|
|
\
|
|
dimension *dd;\
|
|
add_dimension(&dd, dSub0, dSub1);\
|
|
updateDim(dd);\
|
|
_recreate_tensor_if_not_the_same_dim_or_null_##type(MM,dd);\
|
|
tensor_##type *M= *MM;\
|
|
\
|
|
\
|
|
\
|
|
pthread_t *thrd = malloc(nbthread * sizeof(pthread_t));\
|
|
struct arg_ProdContract_##type **arg_th = malloc( nbthread * sizeof(struct arg_ProdContract_##type *));\
|
|
\
|
|
for(size_t i = 0; i < nbthread; ++i){\
|
|
arg_th[i]=malloc(sizeof(struct arg_ProdContract_##type));\
|
|
arg_th[i]->M0x=M0->x;\
|
|
arg_th[i]->M1x=M1->x;\
|
|
arg_th[i]->Mx=M->x;\
|
|
arg_th[i]->beginRange = i*(M->dim->size)/nbthread ;\
|
|
if(i < nbthread - 1 ) arg_th[i]->endRange = (i+1)*(M->dim->size)/nbthread ;\
|
|
else arg_th[i]->endRange = M->dim->size ;\
|
|
if(littleEndian){\
|
|
arg_th[i]->dSubRank = dSub1->size;\
|
|
}\
|
|
else{\
|
|
arg_th[i]->dSubRank = dSub0->size;\
|
|
}\
|
|
arg_th[i]->dMRank = dM->size;\
|
|
pthread_create(&thrd[i], NULL, runProdContractOpt0_thread_##type, (void*)arg_th[i]);\
|
|
}\
|
|
\
|
|
for(size_t i=0; i< nbthread; ++i){\
|
|
pthread_join(thrd[i], NULL);\
|
|
free(arg_th[i]);\
|
|
}\
|
|
\
|
|
free(thrd);\
|
|
free(arg_th);\
|
|
FREE_dM_S_ ; \
|
|
}\
|
|
\
|
|
struct arg_Pro2dContract_##type{\
|
|
type *M0x;\
|
|
type *M1x;\
|
|
type *Mx;\
|
|
size_t beginRange;\
|
|
size_t endRange;\
|
|
size_t dMRank;\
|
|
size_t dSub0Rank;\
|
|
size_t dSub1Rank;\
|
|
};\
|
|
\
|
|
void* runPro2dContract_thread_##type(void *arg){\
|
|
struct arg_Pro2dContract_##type *arg_t = arg;\
|
|
size_t n0_id, n1_id, l;\
|
|
for (size_t i = arg_t->beginRange; i < arg_t->endRange; i++) {\
|
|
for (size_t j = 0; j < arg_t->dSub1Rank; j++) {\
|
|
if(littleEndian)\
|
|
l = j + arg_t->dSub1Rank * i;\
|
|
else\
|
|
l = j * arg_t->dSub0Rank + i;\
|
|
arg_t->Mx[l] = 0;\
|
|
for (size_t k = 0; k < arg_t->dMRank; k++) {\
|
|
if(littleEndian){\
|
|
n0_id= i * arg_t->dMRank + k;\
|
|
n1_id= j + arg_t->dSub1Rank * k;\
|
|
}\
|
|
else{\
|
|
n0_id= i + arg_t->dSub0Rank * k;\
|
|
n1_id= j * arg_t->dMRank + k;\
|
|
}\
|
|
arg_t->Mx[l] += arg_t->M0x[n0_id] * arg_t->M1x[n1_id];\
|
|
}\
|
|
}\
|
|
}\
|
|
return 0;\
|
|
}\
|
|
/* M[x0,x1,x3..xn] X M[y0,y1,y3..ym] = M[z0,z1...zp] (deep = l > 0) /exists 1<= l<...<l=n / xl = y0,x{l+1}=y1, x{n}=yl et zi=xi i<n-l et zj=y{j-(n-l)} j>=n-l alor p=n+m-2l\
|
|
M[x0,x1,x3..xl x{l+1}...xn] X M[xn,x{n-1},x{n-2}...xl y{l+1} ..ym] = M[x0,x1..xly{l+1}...y{n+m-2l}] (deep = l > 0)\
|
|
M[[i][j]]=sum_{[k]}M0[[i][k]]*M[[k][j]]*/\
|
|
\
|
|
void tensorContractnPro2dThread_##type(tensor_##type** MM, tensor_##type *M0, tensor_##type *M1, size_t contractionNumber, size_t nbthread) {\
|
|
/*if(checkContractProdTensorDim(M0->dim, M1->dim, contractionNumber)==0){\
|
|
printf("checkContractProdTensorDim %ld contractionNumber\n", contractionNumber);\
|
|
}*/\
|
|
if(checkContractProdTensorDim(M0->dim, M1->dim, contractionNumber)==0){\
|
|
printf("checkContractProdTensorDim %ld contractionNumber\n", contractionNumber);\
|
|
printDebug_dimension(M0->dim, "M0 dim");\
|
|
printDebug_dimension(M1->dim, "M1 dim");\
|
|
/*getchar();*/\
|
|
}\
|
|
\
|
|
size_t len0 = M0->dim->rank - contractionNumber;\
|
|
size_t len1 = M1->dim->rank - contractionNumber;\
|
|
\
|
|
size_t* tsub0 = malloc(sizeof(size_t) *len0);\
|
|
size_t* tsub1 = malloc(sizeof(size_t) *len1);\
|
|
size_t* tDk1 = malloc(sizeof(size_t) *contractionNumber);\
|
|
size_t* tDk0 = malloc(sizeof(size_t) *contractionNumber);\
|
|
subArray(tsub0, M0->dim->shape, 0, len0, 0);\
|
|
subArray(tsub1, M1->dim->shape, 0, len1, contractionNumber);\
|
|
subArray(tDk1, M1->dim->shape, 0, contractionNumber, 0);\
|
|
subArray(tDk0, M0->dim->shape, 0, contractionNumber, len0);\
|
|
dimension *dSub0 = init_dim(tsub0, len0);\
|
|
dimension *dSub1 = init_dim(tsub1, len1);\
|
|
dimension *dM1 = init_dim(tDk1, contractionNumber);\
|
|
dimension *dM0 = init_dim(tDk0, contractionNumber);\
|
|
dimension *dM;\
|
|
min_copy_dimension(&dM, dM0, dM1);\
|
|
\
|
|
dimension *dd;\
|
|
add_dimension(&dd, dSub0, dSub1);\
|
|
updateDim(dd);\
|
|
_recreate_tensor_if_not_the_same_dim_or_null_##type(MM,dd);\
|
|
tensor_##type *M= *MM;\
|
|
\
|
|
\
|
|
\
|
|
pthread_t *thrd = malloc(nbthread * sizeof(pthread_t));\
|
|
struct arg_Pro2dContract_##type **arg_th = malloc( nbthread * sizeof(struct arg_Pro2dContract_##type *));\
|
|
\
|
|
for(size_t i = 0; i < nbthread; ++i) {\
|
|
arg_th[i] = malloc(sizeof(struct arg_Pro2dContract_##type));\
|
|
arg_th[i]->M0x=M0->x;\
|
|
arg_th[i]->M1x=M1->x;\
|
|
arg_th[i]->Mx=M->x;\
|
|
arg_th[i]->beginRange = i*(dSub0->size)/nbthread ;\
|
|
arg_th[i]->endRange = (i+1)*(dSub0->size)/nbthread ;\
|
|
arg_th[i]->dSub1Rank = dSub1->size;\
|
|
arg_th[i]->dSub0Rank = dSub0->size;\
|
|
arg_th[i]->dMRank = dM->size;\
|
|
pthread_create(&thrd[i], NULL, runPro2dContract_thread_##type, (void*)arg_th[i]);\
|
|
}\
|
|
\
|
|
for(size_t i=0; i< nbthread; ++i){\
|
|
pthread_join(thrd[i], NULL);\
|
|
free(arg_th[i]);\
|
|
}\
|
|
\
|
|
free(thrd);\
|
|
free(arg_th);\
|
|
FREE_dM_S_ ; \
|
|
}\
|
|
\
|
|
void* runPro2dContractOpt0_thread_##type(void *arg){\
|
|
struct arg_Pro2dContract_##type *arg_t = arg;\
|
|
size_t n0_id, n1_id, l;\
|
|
for (size_t i = arg_t->beginRange; i < arg_t->endRange; i++) {\
|
|
for (size_t j = 0; j < arg_t->dSub1Rank; j++) {\
|
|
if(littleEndian){\
|
|
l = j + arg_t->dSub1Rank * i;\
|
|
n0_id= i * arg_t->dMRank ;\
|
|
n1_id= j ;\
|
|
}else{\
|
|
l = j * arg_t->dSub0Rank + i;\
|
|
n0_id= i ;\
|
|
n1_id= j * arg_t->dMRank ;\
|
|
}\
|
|
arg_t->Mx[l] = 0;\
|
|
for (size_t k = 0; k < arg_t->dMRank; k++) {\
|
|
if(littleEndian){\
|
|
/*n0_id= i * arg_t->dMRank + k;\
|
|
n1_id= j + arg_t->dSub1Rank * k;*/\
|
|
arg_t->Mx[l] += arg_t->M0x[n0_id++] * arg_t->M1x[n1_id];\
|
|
n1_id += arg_t->dSub1Rank ;\
|
|
}\
|
|
else{\
|
|
/*n0_id= i + arg_t->dSub0Rank * k;\
|
|
n1_id= j * arg_t->dMRank + k;*/\
|
|
arg_t->Mx[l] += arg_t->M0x[n0_id] * arg_t->M1x[n1_id];\
|
|
n0_id += arg_t->dSub0Rank ;\
|
|
}\
|
|
}\
|
|
}\
|
|
}\
|
|
return 0;\
|
|
}\
|
|
/* M[x0,x1,x3..xn] X M[y0,y1,y3..ym] = M[z0,z1...zp] (deep = l > 0) /exists 1<= l<...<l=n / xl = y0,x{l+1}=y1, x{n}=yl et zi=xi i<n-l et zj=y{j-(n-l)} j>=n-l alor p=n+m-2l\
|
|
M[x0,x1,x3..xl x{l+1}...xn] X M[xn,x{n-1},x{n-2}...xl y{l+1} ..ym] = M[x0,x1..xly{l+1}...y{n+m-2l}] (deep = l > 0)\
|
|
M[[i][j]]=sum_{[k]}M0[[i][k]]*M[[k][j]]*/\
|
|
\
|
|
void tensorContractnPro2dThreadOpt0_##type(tensor_##type** MM, tensor_##type *M0, tensor_##type *M1, size_t contractionNumber, size_t nbthread) {\
|
|
/*if(checkContractProdTensorDim(M0->dim, M1->dim, contractionNumber)==0){\
|
|
printf("checkContractProdTensorDim %ld contractionNumber\n", contractionNumber);\
|
|
}*/\
|
|
if(checkContractProdTensorDim(M0->dim, M1->dim, contractionNumber)==0){\
|
|
printf("checkContractProdTensorDim %ld contractionNumber\n", contractionNumber);\
|
|
printDebug_dimension(M0->dim, "M0 dim");\
|
|
printDebug_dimension(M1->dim, "M1 dim");\
|
|
/*getchar();*/\
|
|
}\
|
|
\
|
|
size_t len0 = M0->dim->rank - contractionNumber;\
|
|
size_t len1 = M1->dim->rank - contractionNumber;\
|
|
\
|
|
size_t* tsub0 = malloc(sizeof(size_t) *len0);\
|
|
size_t* tsub1 = malloc(sizeof(size_t) *len1);\
|
|
size_t* tDk1 = malloc(sizeof(size_t) *contractionNumber);\
|
|
size_t* tDk0 = malloc(sizeof(size_t) *contractionNumber);\
|
|
subArray(tsub0, M0->dim->shape, 0, len0, 0);\
|
|
subArray(tsub1, M1->dim->shape, 0, len1, contractionNumber);\
|
|
subArray(tDk1, M1->dim->shape, 0, contractionNumber, 0);\
|
|
subArray(tDk0, M0->dim->shape, 0, contractionNumber, len0);\
|
|
dimension *dSub0 = init_dim(tsub0, len0);\
|
|
dimension *dSub1 = init_dim(tsub1, len1);\
|
|
dimension *dM1 = init_dim(tDk1, contractionNumber);\
|
|
dimension *dM0 = init_dim(tDk0, contractionNumber);\
|
|
dimension *dM;\
|
|
min_copy_dimension(&dM, dM0, dM1);\
|
|
\
|
|
dimension *dd;\
|
|
add_dimension(&dd, dSub0, dSub1);\
|
|
updateDim(dd);\
|
|
_recreate_tensor_if_not_the_same_dim_or_null_##type(MM,dd);\
|
|
tensor_##type *M= *MM;\
|
|
\
|
|
\
|
|
\
|
|
pthread_t *thrd = malloc(nbthread * sizeof(pthread_t));\
|
|
struct arg_Pro2dContract_##type **arg_th = malloc( nbthread * sizeof(struct arg_Pro2dContract_##type *));\
|
|
\
|
|
for(size_t i = 0; i < nbthread; ++i) {\
|
|
arg_th[i] = malloc(sizeof(struct arg_Pro2dContract_##type));\
|
|
arg_th[i]->M0x=M0->x;\
|
|
arg_th[i]->M1x=M1->x;\
|
|
arg_th[i]->Mx=M->x;\
|
|
arg_th[i]->beginRange = i*(dSub0->size)/nbthread ;\
|
|
arg_th[i]->endRange = (i+1)*(dSub0->size)/nbthread ;\
|
|
arg_th[i]->dSub1Rank = dSub1->size;\
|
|
arg_th[i]->dSub0Rank = dSub0->size;\
|
|
arg_th[i]->dMRank = dM->size;\
|
|
pthread_create(&thrd[i], NULL, runPro2dContractOpt0_thread_##type, (void*)arg_th[i]);\
|
|
}\
|
|
\
|
|
for(size_t i=0; i< nbthread; ++i){\
|
|
pthread_join(thrd[i], NULL);\
|
|
free(arg_th[i]);\
|
|
}\
|
|
\
|
|
free(thrd);\
|
|
free(arg_th);\
|
|
FREE_dM_S_ ; \
|
|
}\
|
|
void tensorContractnProdNotOpt_##type(tensor_##type** MM, tensor_##type *M0, tensor_##type *M1, size_t contractionNumber) {\
|
|
if (!checkContractProdTensorDim(M0->dim, M1->dim, contractionNumber)) {\
|
|
printf("error Deep = %ld\n", contractionNumber);\
|
|
printDebug_dimension(M0->dim, "M0 dim");\
|
|
printDebug_dimension(M1->dim, "M1 dim");\
|
|
/*getchar();*/\
|
|
}\
|
|
size_t len0 = M0->dim->rank - contractionNumber;\
|
|
size_t len1 = M1->dim->rank - contractionNumber;\
|
|
\
|
|
size_t* tsub0 = malloc(sizeof(size_t) *len0);\
|
|
size_t* tsub1 = malloc(sizeof(size_t) *len1);\
|
|
size_t* tDk1 = malloc(sizeof(size_t) *contractionNumber);\
|
|
size_t* tDk0 = malloc(sizeof(size_t) *contractionNumber);\
|
|
subArray(tsub0, M0->dim->shape, 0, len0, 0);\
|
|
subArray(tsub1, M1->dim->shape, 0, len1, contractionNumber);\
|
|
subArray(tDk1, M1->dim->shape, 0, contractionNumber, 0);\
|
|
subArray(tDk0, M0->dim->shape, 0, contractionNumber, len0);\
|
|
/*printArraySzt(tsub0,len0,"tsub0");\
|
|
printArraySzt(tsub1,len1,"tsub1");\
|
|
printArraySzt(tDk0,contractionNumber,"tDk0");\
|
|
printArraySzt(tDk1,contractionNumber,"tDk1");*/\
|
|
dimension *dSub0 = init_dim(tsub0, len0);\
|
|
dimension *dSub1 = init_dim(tsub1, len1);\
|
|
dimension *dM1 = init_dim(tDk1, contractionNumber);\
|
|
dimension *dM0 = init_dim(tDk0, contractionNumber);\
|
|
/*printDebug_dimension(dSub0,"dSub0");\
|
|
printDebug_dimension(dSub1,"dSub1");\
|
|
printDebug_dimension(dM0,"dM0");\
|
|
printDebug_dimension(dM1,"dM1");*/\
|
|
dimension *dM;\
|
|
min_copy_dimension(&dM, dM0, dM1);\
|
|
/*printDebug_dimension(dM,"dM");*/\
|
|
\
|
|
dimension *dd;\
|
|
add_dimension(&dd, dSub0, dSub1);\
|
|
/*printDebug_dimension(dd,"dd");*/\
|
|
updateDim(dd);\
|
|
_recreate_tensor_if_not_the_same_dim_or_null_##type(MM,dd);\
|
|
tensor_##type *M= *MM;\
|
|
\
|
|
size_t* coord;\
|
|
coord = malloc(sizeof(size_t)* M->dim->rank);\
|
|
\
|
|
size_t* coord0 , lin0;\
|
|
coord0 = malloc(sizeof(size_t)* len0);\
|
|
size_t* coord1, lin1;\
|
|
coord1 = malloc(sizeof(size_t)* len1);\
|
|
\
|
|
size_t* coordM0 ;\
|
|
coordM0 = malloc(sizeof(size_t)* M0->dim->rank);\
|
|
size_t* coordM1 ;\
|
|
coordM1 = malloc(sizeof(size_t)* M1->dim->rank);\
|
|
\
|
|
size_t* Koord ;\
|
|
Koord = malloc(sizeof(size_t)* contractionNumber);\
|
|
\
|
|
for (size_t i = 0; i < M->dim->size; i++) {\
|
|
vCoordFromLin(coord, i, M->dim);\
|
|
subArray(coord0, coord, 0, len0, 0);\
|
|
subArray(coord1, coord, 0, len1, len0);\
|
|
M->x[i] = 0;\
|
|
for (size_t k = 0; k < dM->size; k++) {\
|
|
vCoordFromLin(Koord, k, dM);\
|
|
concatArray(coordM0, coord0, Koord, 0, 0, len0, 0, contractionNumber);\
|
|
concatArray(coordM1, Koord, coord1, 0, 0, contractionNumber, 0, len1);\
|
|
lin0 = LineFromCoord(coordM0, M0->dim);\
|
|
lin1 = LineFromCoord(coordM1, M1->dim);\
|
|
M->x[i] += M0->x[lin0] * M1->x[lin1];\
|
|
/*printf("M[%ld]:%f += M0[%ld]:%f * M1[%ld]:%f | ",i,M->x[i],lin0,M0->x[lin0],lin1,M1->x[lin1]);*/\
|
|
/*printf("k:%ld |i:%ld |lin0:%ld | lin1:%ld | ",k,i,lin0,lin1);*/\
|
|
}\
|
|
/*printf("\n");*/\
|
|
}\
|
|
FREE_COORD_ ; \
|
|
free(coordM0);\
|
|
free(coordM1);\
|
|
free(Koord); \
|
|
FREE_dM_S_ ; \
|
|
}\
|
|
\
|
|
/* dot product = of 2 tensors same dimensions M0, M1, dim0, dim1 == contract (dim0 rank) product of M0' M1' of dim0' and dim1' / dim0->shape = [1, dim0-> shape] and dim1'->shape = [dim1->shape, 1] */ \
|
|
type scalarProduct_dep_contractProd_##type(tensor_##type *M0, tensor_##type *M1, size_t nbthreads ,void (*tensorContractVar)(tensor_##type **MM, tensor_##type *M0, tensor_##type *M1, size_t contractionNumber, size_t nbthread )){\
|
|
type ret = 0;\
|
|
if(is_equal_dim(M0->dim, M1->dim)){/* */\
|
|
dimension * d0 = create_dim(M0->dim->rank + 1);\
|
|
dimension * d1 = create_dim(M1->dim->rank + 1);\
|
|
size_t i;\
|
|
d0->shape[0] = 1;\
|
|
for(i=0; i<M0->dim->rank; ++i) d0->shape[i+1] = M0->dim->shape[i];\
|
|
for(i=0; i<M1->dim->rank; ++i) d1->shape[i] = M1->dim->shape[i];\
|
|
d1->shape[i] = 1;\
|
|
tensor_##type *M_0=create_tensor_##type(d0);\
|
|
tensor_##type *M_1=create_tensor_##type(d1);\
|
|
copy_tensor_##type(M_0,M0);\
|
|
copy_tensor_##type(M_1,M1);\
|
|
tensor_##type *M_=NULL;\
|
|
tensorContractVar(&M_,M_0,M_1,M0->dim->rank,nbthreads);\
|
|
ret = M_->x[0];\
|
|
free_tensor_##type(M_0);\
|
|
free_tensor_##type(M_1);\
|
|
free_tensor_##type(M_);\
|
|
}\
|
|
return ret;\
|
|
}\
|
|
\
|
|
type scalarProduct_0_##type(tensor_##type *M0, tensor_##type *M1){\
|
|
return scalarProduct_dep_contractProd_##type(M0,M1,4,tensorContractnProdThread_##type);\
|
|
\
|
|
}\
|
|
\
|
|
/*format_file: [dim]((x,x,a)(a,x,a)) | example:[2,3,4](((a0,b0,c0,d0)(a1,b1,c1,d1)(a2,b2,c2,d2))((e0,f0,g0,h0)(e1,f1,g1,h1)(e2,f2,g2,h2)))*/\
|
|
tensor_##type * parseInput_withDim_to_tensor_##type(char *input){\
|
|
tensor_##type *tens ;\
|
|
size_t len = strlen(input);\
|
|
list_shape_in_dim *l_p=NULL;\
|
|
size_t ss;\
|
|
char *ttmp=input;\
|
|
char *ppEnd="[";\
|
|
bool unknown_shape=false; \
|
|
for(size_t i=0; i<len ; ++i){\
|
|
if(input[i]==']') break;\
|
|
if((input[i]=='*') ||(input[i]=='_')){ unknown_shape =true; break;}\
|
|
}\
|
|
while(ppEnd && (ppEnd[0] !=']') ){\
|
|
ss = strtoul(ttmp, &ppEnd, 10);\
|
|
while(ttmp == ppEnd && ppEnd[0] !=']'){\
|
|
ttmp++;\
|
|
ss = strtoul(ttmp, &ppEnd, 10);\
|
|
}\
|
|
if(ppEnd !=ttmp )\
|
|
append_in_list_shape(&l_p,ss);\
|
|
/*printf("ss: %ld\n",ss);*/\
|
|
ttmp=ppEnd;\
|
|
}\
|
|
dimension *dim=create_dim_from_list_shape(l_p);\
|
|
/*printf("ppEnd = %s\n",ppEnd);*/\
|
|
\
|
|
ttmp++; ppEnd++;\
|
|
\
|
|
if(unknown_shape == false){\
|
|
tens = create_tensor_##type(dim);\
|
|
\
|
|
size_t i=0;\
|
|
type x;\
|
|
while(ppEnd && (ppEnd[0] !='\0') && i<dim->size){\
|
|
x = strto_##type(ttmp, &ppEnd);\
|
|
while(ttmp == ppEnd && ppEnd[0] !='\0'){\
|
|
ttmp++;\
|
|
x = strto_##type(ttmp, &ppEnd);\
|
|
}\
|
|
if(ppEnd[0]!='\0')\
|
|
(tens)->x[i] = x;\
|
|
/*printf("d: %lf\n",d);*/\
|
|
ttmp=ppEnd;\
|
|
++i;\
|
|
}\
|
|
}\
|
|
else{\
|
|
array_chainlist_##type *l_a=NULL;\
|
|
type x;\
|
|
while(ppEnd && (ppEnd[0] !='\0')){\
|
|
x = strto_##type(ttmp, &ppEnd);\
|
|
while(ttmp == ppEnd && ppEnd[0] !='\0'){\
|
|
ttmp++;\
|
|
x = strto_##type(ttmp, &ppEnd);\
|
|
}\
|
|
/*if(ppEnd[0]!='\0')*/ \
|
|
if(ppEnd != ttmp)\
|
|
append_array_chainlist_##type(&l_a, x);\
|
|
/*printf("-- x: %f\n",x);*/\
|
|
ttmp=ppEnd;\
|
|
}\
|
|
\
|
|
tens = create_tensor_from_list_array_##type(l_a,dim);\
|
|
free_dimension(dim);\
|
|
free_array_chainlist_##type(l_a);\
|
|
}\
|
|
free_list_shape_in_dim(l_p);\
|
|
return tens;\
|
|
}\
|
|
\
|
|
\
|
|
/*format_file: [*,dim1,dim2]((x,x,a)(x,a))... | example:[2,(2,3),4](((a0,b0,c0,)((a1,b1,c1))((a2,b2,c2,d2))((e0,f0,g0)(e1,f1,g1)(e2,f2,g2,h2))) ==[2,2,3][2,4]*/\
|
|
void parseInputOutput_withDim_to_tensors_##type(tensor_##type **Tpart1, tensor_##type **Tpart2, char *input, size_t pivotSplit){\
|
|
/*tensor_##type *tens ;*/\
|
|
size_t len = strlen(input);\
|
|
list_shape_in_dim *l_p=NULL;\
|
|
size_t ss;\
|
|
char *ttmp=input;\
|
|
char *ppEnd="[";\
|
|
bool unknown_shape=false; \
|
|
for(size_t i=0; i<len ; ++i){\
|
|
if(input[i]==']') break;\
|
|
if((input[i]=='*') ||(input[i]=='_')){ unknown_shape =true; break;}\
|
|
}\
|
|
while(ppEnd && (ppEnd[0] !=']') ){\
|
|
ss = strtoul(ttmp, &ppEnd, 10);\
|
|
while(ttmp == ppEnd && ppEnd[0] !=']'){\
|
|
ttmp++;\
|
|
ss = strtoul(ttmp, &ppEnd, 10);\
|
|
}\
|
|
if(ppEnd !=ttmp )\
|
|
append_in_list_shape(&l_p,ss);\
|
|
/*printf("ss: %ld\n",ss);*/\
|
|
ttmp=ppEnd;\
|
|
}\
|
|
dimension *dim=create_dim_from_list_shape(l_p);\
|
|
/*printf("ppEnd = %s\n",ppEnd);*/\
|
|
\
|
|
ttmp++; ppEnd++;\
|
|
\
|
|
if(unknown_shape == false){\
|
|
/*dimension *dim1 = create_dim(dim->rank-1);\
|
|
dimension *ddim1 = create_dim(dim->rank-2);\
|
|
dimension *ddim2 = create_dim(dim->rank-2);\
|
|
dimension *dim2 = create_dim(2);\
|
|
*/dimension *dim1 = create_dim(dim->rank-pivotSplit);\
|
|
dimension *ddim1 = create_dim(dim->rank-pivotSplit-1);\
|
|
dimension *ddim2 = create_dim(pivotSplit);\
|
|
dimension *dim2 = create_dim(pivotSplit+1);\
|
|
for(size_t i=0;i<dim1->rank;++i) dim1->shape[i] = dim->shape[i];\
|
|
for(size_t i=0;i<ddim1->rank;++i) ddim1->shape[i] = dim->shape[i+1];\
|
|
for(size_t i=0;i<ddim2->rank;++i) ddim2->shape[i] = dim->shape[ dim->rank - pivotSplit + i];\
|
|
dim2->shape[0] = dim->shape[0];\
|
|
for(size_t i=1;i<dim2->rank;++i) dim2->shape[i] = ddim2->shape[i-1];\
|
|
/*dim2->shape[1] = dim->shape[dim->rank - 1];*/\
|
|
updateDim(dim1);\
|
|
updateDim(ddim1);\
|
|
updateDim(ddim2);\
|
|
updateDim(dim2);\
|
|
*Tpart1 = create_tensor_##type(dim1);\
|
|
*Tpart2 = create_tensor_##type(dim2);\
|
|
\
|
|
size_t i1=0,i=0,j=0,i2=0;\
|
|
bool filled1=false,filled2=false;\
|
|
type x;\
|
|
while(ppEnd && (ppEnd[0] !='\0') && j<dim2->size){\
|
|
x = strto_##type(ttmp, &ppEnd);\
|
|
while(ttmp == ppEnd && ppEnd[0] !='\0'){\
|
|
ttmp++;\
|
|
x = strto_##type(ttmp, &ppEnd);\
|
|
}\
|
|
if(ppEnd[0]!='\0'){\
|
|
if(!filled1){\
|
|
++i1;\
|
|
(*Tpart1)->x[i++] = x;\
|
|
/*printf("++ x: %f, i1:%ld , rkn1: %ld\n",x,i1,ddim1->size);\
|
|
*/if(i1 == ddim1->size){\
|
|
filled1=true;\
|
|
i1=0;\
|
|
filled2=false;\
|
|
}\
|
|
}else{\
|
|
if(!filled2){\
|
|
++i2;\
|
|
(*Tpart2)->x[j++] = x;\
|
|
/*printf("-----++ x: %f, i2:%ld , rknr: %ld\n",x,i2,ddim2->size);\
|
|
*/if(i2 == ddim2->size){\
|
|
filled2=true;\
|
|
i2=0;\
|
|
filled1=false;\
|
|
}\
|
|
}\
|
|
\
|
|
}\
|
|
/*printf("d: %lf\n",d);*/\
|
|
}\
|
|
ttmp=ppEnd;\
|
|
}\
|
|
free_dimension(ddim1);\
|
|
free_dimension(ddim2);\
|
|
}\
|
|
else{\
|
|
/*dimension *ddim1 = create_dim(dim->rank-1);\
|
|
dimension *ddim2 = create_dim(1);\
|
|
for(size_t i=0;i<ddim1->rank;++i) ddim1->shape[i] = dim->shape[i];\
|
|
ddim2->shape[0] = dim->shape[dim->rank - 1];\
|
|
*/dimension *ddim1 = create_dim(dim->rank-pivotSplit);\
|
|
dimension *ddim2 = create_dim(pivotSplit);\
|
|
for(size_t i=0;i<ddim1->rank;++i) ddim1->shape[i] = dim->shape[i];\
|
|
for(size_t i=0;i<ddim2->rank;++i) ddim2->shape[i] = dim->shape[dim->rank - pivotSplit + i];\
|
|
updateDim(ddim1);\
|
|
updateDim(ddim2);\
|
|
array_chainlist_##type *l_a1=NULL;\
|
|
array_chainlist_##type *l_a2=NULL;\
|
|
size_t i1=0, /*i=0,j=0, */ i2=0;\
|
|
bool filled1=false,filled2=false;\
|
|
type x;\
|
|
while(ppEnd && (ppEnd[0] !='\0')){\
|
|
x = strto_##type(ttmp, &ppEnd);\
|
|
while(ttmp == ppEnd && ppEnd[0] !='\0'){\
|
|
ttmp++;\
|
|
x = strto_##type(ttmp, &ppEnd);\
|
|
}\
|
|
/*if(ppEnd[0]!='\0')*/ \
|
|
if(ppEnd != ttmp){\
|
|
if(!filled1){\
|
|
++i1;\
|
|
append_array_chainlist_##type(&l_a1, x);\
|
|
/*printf("++ x: %f, i1:%ld\n",x,i1);*/\
|
|
/*(*Tpart1)->x[i++] = x;*/\
|
|
if(i1 == ddim1->size){\
|
|
filled1=true;\
|
|
i1=0;\
|
|
filled2=false;\
|
|
}\
|
|
}else{\
|
|
if(!filled2){\
|
|
++i2;\
|
|
/*(*Tpart2)->x[j++] = x;*/\
|
|
append_array_chainlist_##type(&l_a2, x);\
|
|
/*printf("++ x: %f, i2:%ld\n",x,i2);*/\
|
|
if(i2 == ddim2->size){\
|
|
filled2 = true;\
|
|
i2=0;\
|
|
filled1 = false;\
|
|
}\
|
|
}\
|
|
\
|
|
}\
|
|
/*printf("d: %lf\n",d);*/\
|
|
}\
|
|
/*printf("-- x: %f\n",x);*/\
|
|
ttmp=ppEnd;\
|
|
}\
|
|
\
|
|
*Tpart1 = create_tensor_from_list_array_##type(l_a1,ddim1);\
|
|
*Tpart2 = create_tensor_from_list_array_##type(l_a2,ddim2);\
|
|
free_array_chainlist_##type(l_a1);\
|
|
free_array_chainlist_##type(l_a2);\
|
|
free_dimension(ddim1);\
|
|
free_dimension(ddim2);\
|
|
}\
|
|
free_dimension(dim);\
|
|
free_list_shape_in_dim(l_p);\
|
|
}\
|
|
\
|
|
\
|
|
/*format_file: [*,dim1,dim2]((x,x,a)(x,a))... | example:[2,(2,3),4](((a0,b0,c0,)((a1,b1,c1))((a2,b2,c2,d2))((e0,f0,g0)(e1,f1,g1)(e2,f2,g2,h2))) == with pivot 1 => [2,2,3][2,4]*/\
|
|
void parse_file_InputOutput_withDim_to_tensors_##type(tensor_##type **Tpart1, tensor_##type **Tpart2, char *file_name_input, size_t pivotSplit){\
|
|
size_t block_size=2;\
|
|
size_t block_count=4;\
|
|
char *input=malloc(block_size*block_count + 1);\
|
|
char *iinput=malloc(block_size*block_count + 256);\
|
|
FILE *f_input;\
|
|
f_input=fopen(file_name_input,"r");\
|
|
if ( f_input == NULL ) {\
|
|
fprintf( stderr, "Cannot open file: %s for reading\n",file_name_input );\
|
|
exit( -1 );\
|
|
}\
|
|
bool unknown_shape=false, broken=false; \
|
|
bool Done=false;\
|
|
int retfread = 0, curIn=0;\
|
|
while(!Done){\
|
|
retfread = fread(input, block_size, block_count, f_input) ;\
|
|
Done = (retfread != block_count);\
|
|
/*input[retfread*block_size]='\0';\
|
|
*/for(curIn=0; curIn<retfread*block_size; ++curIn) iinput[curIn]=input[curIn];\
|
|
while(!Done && ( ((iinput[curIn-1] >='0') && (iinput[curIn-1] <='9'))||(iinput[curIn-1] =='.')||(iinput[curIn-1] =='E')||(iinput[curIn-1] =='e'))){\
|
|
retfread = fread(input, 1, 1, f_input) ;\
|
|
Done = (retfread != 1);\
|
|
iinput[curIn++]=input[0];\
|
|
}\
|
|
iinput[curIn]='\0';\
|
|
size_t len = strlen(iinput);\
|
|
for(size_t i=0; i<len ; ++i){\
|
|
if(iinput[i]==']') {broken = true; break;}\
|
|
if((iinput[i]=='*') ||(iinput[i]=='_')){ \
|
|
broken=true; unknown_shape =true;\
|
|
break;\
|
|
}\
|
|
}\
|
|
Done = broken;\
|
|
}\
|
|
rewind(f_input);\
|
|
list_shape_in_dim *l_p=NULL;\
|
|
dimension *dim=NULL;\
|
|
size_t ss;\
|
|
char *ttmp;\
|
|
char *ppEnd="[";\
|
|
bool bracketsDown=false;\
|
|
size_t i1=0,i=0,j=0,i2=0;\
|
|
bool filled1=false,filled2=false;\
|
|
array_chainlist_##type *l_a1=NULL;\
|
|
array_chainlist_##type *l_a2=NULL;\
|
|
bool initDim=false;\
|
|
dimension *dim1 =NULL ;\
|
|
dimension *ddim1=NULL;\
|
|
dimension *ddim2=NULL;\
|
|
dimension *dim2=NULL ;\
|
|
Done=false;\
|
|
while(!Done){\
|
|
retfread = fread(input, block_size, block_count, f_input) ;\
|
|
Done = (retfread != block_count);\
|
|
/*input[retfread*block_size]='\0';\
|
|
*/for(curIn=0; curIn<retfread*block_size; ++curIn) iinput[curIn]=input[curIn];\
|
|
while(!Done && (((iinput[curIn-1] >='0') && (iinput[curIn-1] <='9'))||(iinput[curIn-1] =='.')||(iinput[curIn-1] =='E')||(iinput[curIn-1] =='e'))){\
|
|
retfread = fread(input, 1, 1, f_input) ;\
|
|
Done = (retfread != 1);\
|
|
iinput[curIn++] = *input;\
|
|
}\
|
|
iinput[curIn]='\0';\
|
|
ttmp=iinput;\
|
|
if( !bracketsDown){\
|
|
while(strlen(ttmp) && strlen(ppEnd) && (*ppEnd !=']') ){\
|
|
ss = strtoul(ttmp, &ppEnd, 10);\
|
|
while(ttmp == ppEnd && ppEnd[0] !=']'){\
|
|
ttmp++;\
|
|
ss = strtoul(ttmp, &ppEnd, 10);\
|
|
}\
|
|
if(ppEnd !=ttmp )\
|
|
append_in_list_shape(&l_p,ss);\
|
|
ttmp=ppEnd;\
|
|
}\
|
|
if( *ppEnd ==']'){\
|
|
dim=create_dim_from_list_shape(l_p);\
|
|
bracketsDown = true;\
|
|
ttmp++; ppEnd++;\
|
|
}\
|
|
\
|
|
}\
|
|
if(bracketsDown){\
|
|
\
|
|
if(unknown_shape == false){\
|
|
\
|
|
if(!initDim){\
|
|
dim1 = create_dim(dim->rank-pivotSplit);\
|
|
ddim1 = create_dim(dim->rank-pivotSplit-1);\
|
|
ddim2 = create_dim(pivotSplit);\
|
|
dim2 = create_dim(pivotSplit+1);\
|
|
for(size_t i=0;i<dim1->rank;++i) dim1->shape[i] = dim->shape[i];\
|
|
for(size_t i=0;i<ddim1->rank;++i) ddim1->shape[i] = dim->shape[i+1];\
|
|
for(size_t i=0;i<ddim2->rank;++i) ddim2->shape[i] = dim->shape[ dim->rank - pivotSplit + i];\
|
|
dim2->shape[0] = dim->shape[0];\
|
|
for(size_t i=1;i<dim2->rank;++i) dim2->shape[i] = ddim2->shape[i-1];\
|
|
updateDim(dim1);\
|
|
updateDim(ddim1);\
|
|
updateDim(ddim2);\
|
|
updateDim(dim2);\
|
|
*Tpart1 = create_tensor_##type(dim1);\
|
|
*Tpart2 = create_tensor_##type(dim2);\
|
|
initDim=true;\
|
|
}\
|
|
\
|
|
type x;\
|
|
while(strlen(ttmp) && j<dim2->size){ \
|
|
x = strto_##type(ttmp, &ppEnd);\
|
|
while(ttmp == ppEnd && strlen(ttmp)){\
|
|
ttmp++;\
|
|
x = strto_##type(ttmp, &ppEnd);\
|
|
}\
|
|
if(ttmp != ppEnd){\
|
|
if(!filled1){\
|
|
++i1;\
|
|
(*Tpart1)->x[i++] = x;\
|
|
if(i1 == ddim1->size){\
|
|
filled1=true;\
|
|
i1=0;\
|
|
filled2=false;\
|
|
}\
|
|
}else{\
|
|
if(!filled2){\
|
|
++i2;\
|
|
(*Tpart2)->x[j++] = x;\
|
|
if(i2 == ddim2->size){\
|
|
filled2=true;\
|
|
i2=0;\
|
|
filled1=false;\
|
|
}\
|
|
}\
|
|
\
|
|
}\
|
|
}\
|
|
ttmp=ppEnd;\
|
|
}\
|
|
if(Done){\
|
|
free_dimension(ddim1);\
|
|
free_dimension(ddim2);\
|
|
}\
|
|
}\
|
|
else{\
|
|
\
|
|
if(!initDim){\
|
|
ddim1 = create_dim(dim->rank-pivotSplit);\
|
|
ddim2 = create_dim(pivotSplit);\
|
|
for(size_t i=0;i<ddim1->rank;++i) ddim1->shape[i] = dim->shape[i];\
|
|
for(size_t i=0;i<ddim2->rank;++i) ddim2->shape[i] = dim->shape[dim->rank - pivotSplit + i];\
|
|
updateDim(ddim1);\
|
|
updateDim(ddim2);\
|
|
initDim=true;\
|
|
}\
|
|
type x= 0;\
|
|
while(ttmp && strlen(ttmp) ){ \
|
|
x = strto_##type(ttmp, &ppEnd);\
|
|
while(ttmp == ppEnd && strlen(ttmp)){\
|
|
ttmp++;\
|
|
x = strto_##type(ttmp, &ppEnd);\
|
|
}\
|
|
if(ppEnd != ttmp){\
|
|
if(!filled1){\
|
|
++i1;\
|
|
append_array_chainlist_##type(&l_a1, x);\
|
|
if(i1 == ddim1->size){\
|
|
filled1=true;\
|
|
i1=0;\
|
|
filled2=false;\
|
|
}\
|
|
}else{\
|
|
if(!filled2){\
|
|
++i2;\
|
|
append_array_chainlist_##type(&l_a2, x);\
|
|
if(i2 == ddim2->size){\
|
|
filled2 = true;\
|
|
i2=0;\
|
|
filled1 = false;\
|
|
}\
|
|
}\
|
|
\
|
|
}\
|
|
}\
|
|
ttmp=ppEnd;\
|
|
}\
|
|
\
|
|
if(Done){\
|
|
*Tpart1 = create_tensor_from_list_array_##type(l_a1,ddim1);\
|
|
*Tpart2 = create_tensor_from_list_array_##type(l_a2,ddim2);\
|
|
free_array_chainlist_##type(l_a1);\
|
|
free_array_chainlist_##type(l_a2);\
|
|
free_dimension(ddim1);\
|
|
free_dimension(ddim2);\
|
|
\
|
|
}\
|
|
}\
|
|
}\
|
|
}\
|
|
free_dimension(dim);\
|
|
free_list_shape_in_dim(l_p);\
|
|
free(input);\
|
|
free(iinput);\
|
|
fclose(f_input);\
|
|
}\
|
|
\
|
|
tensor_##type ** fromInput_to_array_tensor_##type(tensor_##type *tens){\
|
|
tensor_##type **re_tens=malloc((tens->dim)->shape[0]*sizeof(tensor_##type *));\
|
|
dimension *dim=create_dim((tens->dim)->rank - 1);\
|
|
for(size_t i=0; i<dim->rank; ++i) dim->shape[i]=(tens->dim)->shape[i+1];\
|
|
updateDim(dim);\
|
|
for(size_t i=0; i < (tens->dim)->shape[0];++i){\
|
|
re_tens[i]=create_tensor_from_cpy_dim_##type(dim);\
|
|
for(size_t j=0; j<dim->size; ++j) (re_tens[i])->x[j] = tens->x[i*(dim->size) + j ] ;\
|
|
}\
|
|
free_dimension(dim);\
|
|
return re_tens;\
|
|
}\
|
|
\
|
|
void append_array_chainlist_##type(array_chainlist_##type **list_a, type x){\
|
|
array_chainlist_##type *lis=malloc(sizeof(array_chainlist_##type));\
|
|
lis->x=x;\
|
|
lis->next=NULL;\
|
|
if(*list_a == NULL){\
|
|
lis->index=0;\
|
|
*list_a = lis;\
|
|
}\
|
|
else{\
|
|
array_chainlist_##type *tmp =*list_a;\
|
|
while(tmp->next) tmp=tmp->next;\
|
|
lis->index = tmp->index +1;\
|
|
tmp->next=lis;\
|
|
}\
|
|
}\
|
|
\
|
|
tensor_##type * create_tensor_from_list_array_##type( array_chainlist_##type *l_a, dimension *part_dim){\
|
|
if(l_a){\
|
|
array_chainlist_##type *tmp =l_a;\
|
|
while(tmp->next) tmp=tmp->next;\
|
|
size_t miss_part_d=(tmp->index + 1)/part_dim->size;\
|
|
dimension *dim=create_dim(part_dim->rank + 1);\
|
|
if(littleEndian){\
|
|
dim->shape[0]=miss_part_d;\
|
|
for(size_t i=0; i<part_dim->rank;++i) dim->shape[i+1]=part_dim->shape[i];\
|
|
}else{\
|
|
size_t i=0;\
|
|
for(i=0; i<part_dim->rank;++i) dim->shape[i]=part_dim->shape[i];\
|
|
dim->shape[i]=miss_part_d;\
|
|
\
|
|
}\
|
|
updateDim(dim);\
|
|
tensor_##type *tens= create_tensor_##type(dim);\
|
|
tmp=l_a;\
|
|
while(tmp){\
|
|
(tens)->x[tmp->index]=tmp->x;\
|
|
tmp=tmp->next;\
|
|
}\
|
|
return tens;\
|
|
}\
|
|
return NULL;\
|
|
}\
|
|
\
|
|
void free_array_chainlist_##type(array_chainlist_##type *l_a){\
|
|
array_chainlist_##type *tmp=l_a, *ttmp;\
|
|
while(tmp){\
|
|
ttmp = tmp;\
|
|
tmp = ttmp->next;\
|
|
free(ttmp);\
|
|
}\
|
|
}\
|
|
\
|
|
tensor_##type * transpose_notOpt_tensor_##type(tensor_##type *org){\
|
|
size_t dimrnk = (org->dim)->rank; \
|
|
dimension *dim_tr=create_dim(dimrnk);\
|
|
for(size_t i=0; i<dimrnk; ++i) dim_tr->shape[i]=(org->dim)->shape[(dimrnk-1)-i];\
|
|
updateDim(dim_tr);\
|
|
printDebug_dimension(dim_tr,"dim_tr");\
|
|
tensor_##type *tens_tr = create_tensor_##type(dim_tr);\
|
|
size_t *coord = malloc((dimrnk)*sizeof(size_t));\
|
|
size_t *coord_tr = malloc((dimrnk)*sizeof(size_t));\
|
|
for(size_t i=0; i<dim_tr->size; ++i){\
|
|
vCoordFromLin(coord,i,org->dim);\
|
|
for(size_t j=0; j<dimrnk;++j) coord_tr[j]=coord[dimrnk-1-j]; \
|
|
tens_tr->x[LineFromCoord(coord_tr, dim_tr)] = org->x[i];\
|
|
}\
|
|
free(coord);\
|
|
free(coord_tr);\
|
|
return tens_tr;\
|
|
}\
|
|
\
|
|
\
|
|
tensor_##type * transpose_Opt0_tensor_##type(tensor_##type *org){\
|
|
dimension *dim= org->dim;\
|
|
size_t dimrnk = dim->rank;\
|
|
dimension *dim_tr=create_dim(dimrnk);\
|
|
for(size_t i=0; i<dimrnk; ++i) dim_tr->shape[i]=dim->shape[(dimrnk-1)-i];\
|
|
/*updateDim(dim_tr);\
|
|
printDebug_dimension(dim_tr,"dim_trOpt");*/\
|
|
tensor_##type *tens_tr = create_tensor_##type(dim_tr);\
|
|
/*tensor_##type *tens_tr = CREATE_TENSOR_##type(dim_tr);*/\
|
|
long int cur_tr=0, add_tr=0, minus_tr=0;\
|
|
tens_tr->x[cur_tr] = org->x[cur_tr];\
|
|
for(size_t i=1; i<dim_tr->size; ++i){\
|
|
minus_tr =0;\
|
|
/*printf("DEBUG: cur_tr=%ld\n",cur_tr);*/\
|
|
for(size_t l=0; l<dimrnk; ++l){ \
|
|
add_tr = minus_tr + dim_tr->basis[l+1];\
|
|
if(cur_tr + add_tr < dim_tr->basis[l]){\
|
|
cur_tr += add_tr;\
|
|
/*tens_tr->x[cur_tr] = org->x[i]*/;\
|
|
/*tens_tr->x[i] = org->x[cur_tr];\
|
|
*/tens_tr->x[cur_tr] = org->x[i];\
|
|
break;\
|
|
}\
|
|
minus_tr -= (dim_tr->basis[l]-dim_tr->basis[l+1]);\
|
|
}\
|
|
/*printf("DEBUG: after cur_tr=%ld\n",cur_tr);*/\
|
|
}\
|
|
return tens_tr;\
|
|
}\
|
|
\
|
|
tensor_##type * transpose_Opt1_tensor_##type(tensor_##type *org){\
|
|
dimension *dim= org->dim;\
|
|
/*updateDim(dim);*/\
|
|
size_t dimrnk = dim->rank;\
|
|
dimension *dim_tr=create_dim(dimrnk);\
|
|
for(size_t i=0; i<dimrnk; ++i) dim_tr->shape[i]=dim->shape[(dimrnk-1)-i];\
|
|
/*updateDim(dim_tr);\
|
|
printDebug_dimension(dim_tr,"dim_trOpt");*/\
|
|
tensor_##type *tens_tr = create_tensor_##type(dim_tr);\
|
|
/*tensor_##type *tens_tr = CREATE_TENSOR_##type(dim_tr);*/\
|
|
long int cur_tr=0, add_tr=0, minus_tr=0;\
|
|
tens_tr->x[cur_tr] = org->x[cur_tr];\
|
|
for(size_t i=1; i<dim->size; ++i){\
|
|
minus_tr =0;\
|
|
/*printf("DEBUG: cur_tr=%ld\n",cur_tr);*/\
|
|
for(size_t l=0; l<dimrnk; ++l){ \
|
|
add_tr = minus_tr + dim->basis[l+1];\
|
|
if(cur_tr + add_tr < dim->basis[l]){\
|
|
cur_tr += add_tr;\
|
|
/*tens_tr->x[cur_tr] = org->x[i]*/;\
|
|
tens_tr->x[i] = org->x[cur_tr];\
|
|
break;\
|
|
}\
|
|
minus_tr -= (dim->basis[l]-dim->basis[l+1]);\
|
|
}\
|
|
/*printf("DEBUG: after cur_tr=%ld\n",cur_tr);*/\
|
|
}\
|
|
return tens_tr;\
|
|
}\
|
|
\
|
|
tensor_##type * permute_notOpt_tensor_##type(tensor_##type *org, dimension *dshape){\
|
|
size_t dimrnk = (org->dim)->rank; \
|
|
dimension *dim_tr=create_dim(dimrnk);\
|
|
for(size_t i=0; i<dimrnk; ++i) dim_tr->shape[i]=(org->dim)->shape[(dimrnk-1)-i];\
|
|
updateDim(dim_tr);\
|
|
printDebug_dimension(dim_tr,"dim_tr");\
|
|
tensor_##type *tens_tr = create_tensor_##type(dim_tr);\
|
|
size_t *coord = malloc((dimrnk)*sizeof(size_t));\
|
|
size_t *coord_tr = malloc((dimrnk)*sizeof(size_t));\
|
|
for(size_t i=0; i<dim_tr->size; ++i){\
|
|
vCoordFromLin(coord,i,org->dim);\
|
|
for(size_t j=0; j<dimrnk;++j) coord_tr[j]=coord[dshape->shape[j]]; \
|
|
tens_tr->x[LineFromCoord(coord_tr, dim_tr)] = org->x[i];\
|
|
}\
|
|
free(coord);\
|
|
free(coord_tr);\
|
|
return tens_tr;\
|
|
}\
|
|
struct arg_1Update_##type{\
|
|
type *M0x;\
|
|
size_t beginRange;\
|
|
size_t endRange;\
|
|
type (*func)(type);\
|
|
};\
|
|
void* run1UpdatCalcfunc_thread_##type(void *arg){\
|
|
struct arg_1Update_##type *arg_t = arg;\
|
|
for (size_t i = arg_t->beginRange; i < arg_t->endRange; i++) {\
|
|
arg_t->M0x[i] = arg_t->func(arg_t->M0x[i]);\
|
|
}\
|
|
return 0;\
|
|
}\
|
|
\
|
|
void update_1tensor_func_##type(tensor_##type *M0, type (*func)(type), size_t nbthread){\
|
|
\
|
|
pthread_t *thrd = malloc(nbthread * sizeof(pthread_t));\
|
|
struct arg_1Update_##type **arg_th = malloc( nbthread * sizeof(struct arg_1Update_##type *));\
|
|
\
|
|
for(size_t i = 0; i < nbthread; ++i){\
|
|
arg_th[i]=malloc(sizeof(struct arg_1Update_##type));\
|
|
arg_th[i]->M0x=M0->x;\
|
|
arg_th[i]->func=func;\
|
|
arg_th[i]->beginRange = i*(M0->dim->size)/nbthread ;\
|
|
arg_th[i]->endRange = (i+1)*(M0->dim->size)/nbthread ;\
|
|
\
|
|
pthread_create(&thrd[i], NULL, run1UpdatCalcfunc_thread_##type, (void*)arg_th[i]);\
|
|
}\
|
|
\
|
|
for(size_t i=0; i< nbthread; ++i){\
|
|
pthread_join(thrd[i], NULL);\
|
|
free(arg_th[i]);\
|
|
}\
|
|
\
|
|
free(thrd);\
|
|
free(arg_th);\
|
|
} \
|
|
\
|
|
struct arg_2Update_##type{\
|
|
type *M0x;\
|
|
type *M1x;\
|
|
size_t beginRange;\
|
|
size_t endRange;\
|
|
type (*func)(type);\
|
|
};\
|
|
void* run2UpdatCalcfunc_thread_##type(void *arg){\
|
|
struct arg_2Update_##type *arg_t = arg;\
|
|
for (size_t i = arg_t->beginRange; i < arg_t->endRange; i++) {\
|
|
arg_t->M0x[i] = arg_t->func(arg_t->M1x[i]);\
|
|
}\
|
|
return 0;\
|
|
}\
|
|
\
|
|
void update_2tensor_func_##type(tensor_##type *M0, tensor_##type *M1, type (*func)(type), size_t nbthread){\
|
|
if ( is_equal_dim(M0->dim,M1->dim)){ \
|
|
pthread_t *thrd = malloc(nbthread * sizeof(pthread_t));\
|
|
struct arg_2Update_##type **arg_th = malloc( nbthread * sizeof(struct arg_2Update_##type *));\
|
|
\
|
|
for(size_t i = 0; i < nbthread; ++i){\
|
|
arg_th[i]=malloc(sizeof(struct arg_2Update_##type));\
|
|
arg_th[i]->M0x=M0->x;\
|
|
arg_th[i]->M1x=M1->x;\
|
|
arg_th[i]->func=func;\
|
|
arg_th[i]->beginRange = i*(M0->dim->size)/nbthread ;\
|
|
arg_th[i]->endRange = (i+1)*(M0->dim->size)/nbthread ;\
|
|
\
|
|
pthread_create(&thrd[i], NULL, run2UpdatCalcfunc_thread_##type, (void*)arg_th[i]);\
|
|
}\
|
|
\
|
|
for(size_t i=0; i< nbthread; ++i){\
|
|
pthread_join(thrd[i], NULL);\
|
|
free(arg_th[i]);\
|
|
}\
|
|
\
|
|
free(thrd);\
|
|
free(arg_th);\
|
|
}\
|
|
} \
|
|
\
|
|
struct arg_3Update_##type{\
|
|
type *M0x;\
|
|
type *M1x;\
|
|
type *M2x;\
|
|
size_t beginRange;\
|
|
size_t endRange;\
|
|
type (*func)(type, type);\
|
|
};\
|
|
void* run3UpdatCalcfunc_thread_##type(void *arg){\
|
|
struct arg_3Update_##type *arg_t = arg;\
|
|
for (size_t i = arg_t->beginRange; i < arg_t->endRange; i++) {\
|
|
arg_t->M0x[i] = arg_t->func(arg_t->M1x[i], arg_t->M2x[i]);\
|
|
}\
|
|
return 0;\
|
|
}\
|
|
\
|
|
void update_3tensor_func_##type(tensor_##type *M0, tensor_##type *M1, tensor_##type *M2, type (*func)(type,type), size_t nbthread){\
|
|
if ( is_equal_dim(M0->dim,M1->dim) && (is_equal_dim(M0->dim, M2->dim))){ \
|
|
pthread_t *thrd = malloc(nbthread * sizeof(pthread_t));\
|
|
struct arg_3Update_##type **arg_th = malloc( nbthread * sizeof(struct arg_3Update_##type *));\
|
|
\
|
|
for(size_t i = 0; i < nbthread; ++i){\
|
|
arg_th[i]=malloc(sizeof(struct arg_3Update_##type));\
|
|
arg_th[i]->M0x=M0->x;\
|
|
arg_th[i]->M1x=M1->x;\
|
|
arg_th[i]->M2x=M2->x;\
|
|
arg_th[i]->func=func;\
|
|
arg_th[i]->beginRange = i*(M0->dim->size)/nbthread ;\
|
|
arg_th[i]->endRange = (i+1)*(M0->dim->size)/nbthread ;\
|
|
\
|
|
pthread_create(&thrd[i], NULL, run3UpdatCalcfunc_thread_##type, (void*)arg_th[i]);\
|
|
}\
|
|
\
|
|
for(size_t i=0; i< nbthread; ++i){\
|
|
pthread_join(thrd[i], NULL);\
|
|
free(arg_th[i]);\
|
|
}\
|
|
\
|
|
free(thrd);\
|
|
free(arg_th);\
|
|
}\
|
|
} \
|
|
\
|
|
\
|
|
struct arg_4Update_##type{\
|
|
type *M0x;\
|
|
type *M1x;\
|
|
type *M2x;\
|
|
size_t beginRange;\
|
|
size_t endRange;\
|
|
type (*func)(type, type, type(*f1)(type));\
|
|
type(*f1)(type);\
|
|
};\
|
|
void* run4UpdatCalcfunc_thread_##type(void *arg){\
|
|
struct arg_4Update_##type *arg_t = arg;\
|
|
for (size_t i = arg_t->beginRange; i < arg_t->endRange; i++) {\
|
|
arg_t->M0x[i] = arg_t->func(arg_t->M1x[i], arg_t->M2x[i], arg_t->f1);\
|
|
}\
|
|
return 0;\
|
|
}\
|
|
\
|
|
void update_4tensor_func_##type(tensor_##type *M0, tensor_##type *M1, tensor_##type *M2, \
|
|
type (*func)(type, type, type(*f1)(type)),\
|
|
type(*f1)(type),\
|
|
size_t nbthread){\
|
|
/*printf(" sizeM0=%ld , size M2:%ld ; iseq :%d \n",(M0->dim)->size,(M2->dim)->size,is_equal_dim(M0->dim,M2->dim) );\
|
|
*/\
|
|
/* printDebug_dimension(M0->dim," dim M0 in update4 "); \
|
|
printDebug_dimension(M2->dim," dim M2 in update4 "); \
|
|
*/if ( is_equal_dim(M0->dim, M1->dim) /*&& (is_equal_dim(M0->dim, M2->dim))*/){ \
|
|
/*printDebug_dimension(M0->dim," dim M0 in update4 "); \
|
|
*/pthread_t *thrd = malloc(nbthread * sizeof(pthread_t));\
|
|
struct arg_4Update_##type **arg_th = malloc( nbthread * sizeof(struct arg_4Update_##type *));\
|
|
\
|
|
for(size_t i = 0; i < nbthread; ++i){\
|
|
arg_th[i]=malloc(sizeof(struct arg_4Update_##type));\
|
|
arg_th[i]->M0x=M0->x;\
|
|
arg_th[i]->M1x=M1->x;\
|
|
arg_th[i]->M2x=M2->x;\
|
|
arg_th[i]->func=func;\
|
|
arg_th[i]->f1=f1;\
|
|
arg_th[i]->beginRange = i*(M0->dim->size)/nbthread ;\
|
|
arg_th[i]->endRange = (i+1)*(M0->dim->size)/nbthread ;\
|
|
\
|
|
pthread_create(&thrd[i], NULL, run4UpdatCalcfunc_thread_##type, (void*)arg_th[i]);\
|
|
}\
|
|
\
|
|
for(size_t i=0; i< nbthread; ++i){\
|
|
pthread_join(thrd[i], NULL);\
|
|
free(arg_th[i]);\
|
|
}\
|
|
\
|
|
free(thrd);\
|
|
free(arg_th);\
|
|
}\
|
|
} \
|
|
\
|
|
struct arg_5Update_##type{\
|
|
type *M0x;\
|
|
type *M1x;\
|
|
type *M2x;\
|
|
type *M3x;\
|
|
size_t beginRange;\
|
|
size_t endRange;\
|
|
type (*func)(type, type, type, type(*f1)(type), type (*f2)(type,type) );\
|
|
type(*f1)(type);\
|
|
type (*f2)(type,type);\
|
|
};\
|
|
void* run5UpdatCalcfunc_thread_##type(void *arg){\
|
|
struct arg_5Update_##type *arg_t = arg;\
|
|
for (size_t i = arg_t->beginRange; i < arg_t->endRange; i++) {\
|
|
arg_t->M0x[i] = arg_t->func(arg_t->M1x[i], arg_t->M2x[i], arg_t->M3x[i], arg_t->f1, arg_t->f2);\
|
|
}\
|
|
return 0;\
|
|
}\
|
|
\
|
|
void update_5tensor_func_##type(tensor_##type *M0, tensor_##type *M1, tensor_##type *M2, tensor_##type *M3 , \
|
|
type (*func) (type, type, type, type(*f1)(type), type (*f2)(type,type)), \
|
|
type(*f1)(type), \
|
|
type (*f2)(type,type), \
|
|
size_t nbthread){\
|
|
if ( is_equal_dim(M0->dim,M1->dim) && (is_equal_dim(M0->dim, M2->dim))&& (is_equal_dim(M0->dim, M3->dim))){ \
|
|
pthread_t *thrd = malloc(nbthread * sizeof(pthread_t));\
|
|
struct arg_5Update_##type **arg_th = malloc( nbthread * sizeof(struct arg_5Update_##type *));\
|
|
/*printDebug_dimension(M0->dim," dim M0 in update5 "); */ \
|
|
for(size_t i = 0; i < nbthread; ++i){\
|
|
arg_th[i]=malloc(sizeof(struct arg_5Update_##type));\
|
|
arg_th[i]->M0x=M0->x;\
|
|
arg_th[i]->M1x=M1->x;\
|
|
arg_th[i]->M2x=M2->x;\
|
|
arg_th[i]->M3x=M3->x;\
|
|
arg_th[i]->func=func;\
|
|
arg_th[i]->f1=f1;\
|
|
arg_th[i]->f2=f2;\
|
|
arg_th[i]->beginRange = i*(M0->dim->size)/nbthread ;\
|
|
arg_th[i]->endRange = (i+1)*(M0->dim->size)/nbthread ;\
|
|
\
|
|
pthread_create(&thrd[i], NULL, run5UpdatCalcfunc_thread_##type, (void*)arg_th[i]);\
|
|
}\
|
|
\
|
|
for(size_t i=0; i< nbthread; ++i){\
|
|
pthread_join(thrd[i], NULL);\
|
|
free(arg_th[i]);\
|
|
}\
|
|
\
|
|
free(thrd);\
|
|
free(arg_th);\
|
|
}\
|
|
} \
|
|
\
|
|
\
|
|
struct arg_6Update_##type{\
|
|
type *M0x;\
|
|
type *M1x;\
|
|
size_t beginRange;\
|
|
size_t endRange;\
|
|
type (*func)(type, type, type);\
|
|
type scalar;\
|
|
};\
|
|
void* run6UpdatCalcfunc_thread_##type(void *arg){\
|
|
struct arg_6Update_##type *arg_t = arg;\
|
|
for (size_t i = arg_t->beginRange; i < arg_t->endRange; i++) {\
|
|
arg_t->M0x[i] = arg_t->func(arg_t->M0x[i], arg_t->M1x[i], arg_t->scalar);\
|
|
}\
|
|
return 0;\
|
|
}\
|
|
\
|
|
void update_6tensor_func_##type(tensor_##type *M0, tensor_##type *M1, \
|
|
type (*func)(type, type, type),\
|
|
type scalar,\
|
|
size_t nbthread){\
|
|
/*printf(" sizeM0=%ld , size M2:%ld ; iseq :%d \n",(M0->dim)->size,(M2->dim)->size,is_equal_dim(M0->dim,M2->dim) );\
|
|
*/\
|
|
/* printDebug_dimension(M0->dim," dim M0 in update6 "); \
|
|
printDebug_dimension(M2->dim," dim M2 in update6 "); \
|
|
*/if ( is_equal_dim(M0->dim, M1->dim) /*&& (is_equal_dim(M0->dim, M2->dim))*/){ \
|
|
/*printDebug_dimension(M0->dim," dim M0 in update6 "); \
|
|
*/pthread_t *thrd = malloc(nbthread * sizeof(pthread_t));\
|
|
struct arg_6Update_##type **arg_th = malloc( nbthread * sizeof(struct arg_6Update_##type *));\
|
|
\
|
|
for(size_t i = 0; i < nbthread; ++i){\
|
|
arg_th[i]=malloc(sizeof(struct arg_6Update_##type));\
|
|
arg_th[i]->M0x=M0->x;\
|
|
arg_th[i]->M1x=M1->x;\
|
|
arg_th[i]->func=func;\
|
|
arg_th[i]->scalar=scalar;\
|
|
arg_th[i]->beginRange = i*(M0->dim->size)/nbthread ;\
|
|
arg_th[i]->endRange = (i+1)*(M0->dim->size)/nbthread ;\
|
|
\
|
|
pthread_create(&thrd[i], NULL, run6UpdatCalcfunc_thread_##type, (void*)arg_th[i]);\
|
|
}\
|
|
\
|
|
for(size_t i=0; i< nbthread; ++i){\
|
|
pthread_join(thrd[i], NULL);\
|
|
free(arg_th[i]);\
|
|
}\
|
|
\
|
|
free(thrd);\
|
|
free(arg_th);\
|
|
}\
|
|
} \
|
|
\
|
|
|
|
|
|
//#ifdef IMPLEMENTATION_TENSOR
|
|
#define IMPLEMENTATION_TENSOR()\
|
|
\
|
|
/*IMPLEMENTATION_DIMENSION()*/\
|
|
\
|
|
\
|
|
GEN_FUNC_TENSOR(TYPE_FLOAT);\
|
|
GEN_FUNC_TENSOR(TYPE_DOUBLE);\
|
|
GEN_FUNC_TENSOR(TYPE_L_DOUBLE);\
|
|
|
|
|
|
//#endif /* IMPLEMENTATION_TENSOR */
|
|
|