From 4bf32c6501c0411d8be0998dde499d39de6ff6c2 Mon Sep 17 00:00:00 2001 From: fanasina Date: Wed, 24 Jan 2024 19:01:00 +0100 Subject: [PATCH] add opencl product tensor, update contracted product cl, test precision float and double in tools --- tensor_t/src/tensor_t/cl_tensor_t.c | 149 ++++++++-------- tensor_t/test/is_good.c | 259 +++++++++++++++++++++++----- ytest_t/libytest.so | Bin 558784 -> 558784 bytes ytools_t/src/tools_t/tools_t.c | 5 +- 4 files changed, 303 insertions(+), 110 deletions(-) diff --git a/tensor_t/src/tensor_t/cl_tensor_t.c b/tensor_t/src/tensor_t/cl_tensor_t.c index 98af652..0234702 100644 --- a/tensor_t/src/tensor_t/cl_tensor_t.c +++ b/tensor_t/src/tensor_t/cl_tensor_t.c @@ -3,71 +3,16 @@ #define MAX_SOURCE_SIZE (0x100000) - -#define CL_GEN_FUNC_TENSOR(type)\ - tensor_##type* CREATE_CL_TENSOR_##type(dimension *dim){\ - tensor_##type *r_tens=malloc(sizeof(tensor_##type));\ - updateRankDim(dim);\ - r_tens->dim = dim;\ - r_tens->x = malloc(sizeof(type)*dim->rank);\ - return r_tens;\ - }\ -\ -\ -void cl_tensorProd_##type(tensor_##type **MM, tensor_##type *M0, tensor_##type *M1) { \ - dimension *dd; \ - add_dimension(&dd, M0->dim, M1->dim); \ - (*MM)=CREATE_TENSOR_##type(dd); \ - tensor_##type *M = *MM; \ - size_t m_idx;\ - for(size_t i=0; idim->rank; ++i){\ - for(size_t j=0; jdim->rank; ++j){\ - m_idx= i*M1->dim->rank + 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<...=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 cl_tensorContractnProd_##type(tensor_##type** MM, tensor_##type *M0, tensor_##type *M1, size_t contractionNumber) {\ -\ - size_t len0 = M0->dim->size - contractionNumber;\ - size_t len1 = M1->dim->size - 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->perm, 0, len0, 0);\ - subArray(tsub1, M1->dim->perm, 0, len1, contractionNumber);\ - subArray(tDk1, M1->dim->perm, 0, contractionNumber, 0);\ - subArray(tDk0, M0->dim->perm, 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_dimension(&dM, dM0, dM1);\ - \ - dimension *dd;\ - add_dimension(&dd, dSub0, dSub1);\ - updateRankDim(dd);\ - *MM = CREATE_TENSOR_##type(dd);\ - tensor_##type *M= *MM;\ -\ - \ -/* Load the kernel source code into the array source_str*/ \ +#define CL_GEN_SETUP_(type,file_cl_src,func_cl_name)\ + /* Load the kernel source code into the array source_str*/ \ FILE *fp; \ char *source_str; \ size_t source_size; \ \ - fp = fopen("/media/fanasina/corsair480/progr_/ytest/y_PROJECT/tensor_t/src/tensor_t/kernel_ProdContractnTensor.cl", "r"); \ + /*fp = fopen("../src/kernel_ProdTensor.cl", "r");*/ \ + fp = fopen(file_cl_src, "r"); \ if (!fp) { \ - perror("kernel_ProdContractnTensor.cl");\ + perror(file_cl_src);\ fprintf(stderr, "Failed to load kernel. \n"); \ exit(1); \ } \ @@ -114,21 +59,23 @@ void cl_tensorContractnProd_##type(tensor_##type** MM, tensor_##type *M0, tensor ret = clBuildProgram(program, 1, &device_id, NULL, NULL, NULL); \ size_t len; clGetProgramBuildInfo(program, device_id, CL_PROGRAM_BUILD_LOG, NULL, NULL, &len);\ char *log = malloc(sizeof(char)*len);\ - clGetProgramBuildInfo(program, device_id, CL_PROGRAM_BUILD_LOG, len, log, NULL);\ + clGetProgramBuildInfo(program, device_id, CL_PROGRAM_BUILD_LOG, len, log, NULL);\ printf("log: %s \n",log);\ \ /*/ Create the OpenCL kernel */ \ - char func_cl_name[250]; sprintf(func_cl_name,"prodContractnTensorLin_%s", #type); \ + /*char func_cl_name[250]; sprintf(func_cl_name,"prodTensorLin_%s", #type);*/ \ printf("cl_func_type = %s\n",func_cl_name); \ cl_kernel kernel = clCreateKernel(program, func_cl_name, &ret); \ - \ + + /*/ Set the arguments of the kernel */ \ - ret = clSetKernelArg(kernel, 0, sizeof(size_t), (void *)&(dSub1->rank)); \ - ret = clSetKernelArg(kernel, 1, sizeof(size_t), (void *)&(dM->rank)); \ - ret = clSetKernelArg(kernel, 2, sizeof(cl_mem), (void *)&M0_mem_obj); \ - ret = clSetKernelArg(kernel, 3, sizeof(cl_mem), (void *)&M1_mem_obj); \ - ret = clSetKernelArg(kernel, 4, sizeof(cl_mem), (void *)&M_mem_obj); \ - \ + /*ret = clSetKernelArg(kernel, 0, sizeof(size_t), (void *)&(M1->dim->rank)); \ + ret = clSetKernelArg(kernel, 1, sizeof(cl_mem), (void *)&M0_mem_obj); \ + ret = clSetKernelArg(kernel, 2, sizeof(cl_mem), (void *)&M1_mem_obj); \ + ret = clSetKernelArg(kernel, 3, sizeof(cl_mem), (void *)&M_mem_obj); \ + */ + +#define CL_EXEC_KERNEL(type)\ /*/ Execute the OpenCL kernel on the list */ \ size_t global_item_size = M->dim->rank; /*/ Process the entire lists */ \ size_t local_item_size = 1; /*64;*/ /*/ Divide work items into groups of 64 */ \ @@ -149,8 +96,72 @@ void cl_tensorContractnProd_##type(tensor_##type** MM, tensor_##type *M0, tensor ret = clReleaseMemObject(M_mem_obj); \ ret = clReleaseCommandQueue(command_queue); \ ret = clReleaseContext(context); \ + +#define CL_GEN_FUNC_TENSOR(type)\ +\ +\ +void cl_tensorProd_##type(tensor_##type **MM, tensor_##type *M0, tensor_##type *M1) { \ + dimension *dd; \ + add_dimension(&dd, M0->dim, M1->dim); \ + (*MM)=CREATE_TENSOR_##type(dd); \ + tensor_##type *M = *MM; \ + char *file_cl_src = "../src/kernel_ProdTensor.cl"; \ + char *func_cl_name = "prodTensorLin_" #type; \ + CL_GEN_SETUP_(type,file_cl_src,func_cl_name);\ + /*/ Set the arguments of the kernel */ \ + ret = clSetKernelArg(kernel, 0, sizeof(size_t), (void *)&(M1->dim->rank)); \ + ret = clSetKernelArg(kernel, 1, sizeof(cl_mem), (void *)&M0_mem_obj); \ + ret = clSetKernelArg(kernel, 2, sizeof(cl_mem), (void *)&M1_mem_obj); \ + ret = clSetKernelArg(kernel, 3, sizeof(cl_mem), (void *)&M_mem_obj); \ + CL_EXEC_KERNEL(type);\ +} \ +\ +/* M[x0,x1,x3..xn] X M[y0,y1,y3..ym] = M[z0,z1...zp] (deep = l > 0) /exists 1<= l<...=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 cl_tensorContractnProd_##type(tensor_##type** MM, tensor_##type *M0, tensor_##type *M1, size_t contractionNumber) {\ +\ + size_t len0 = M0->dim->size - contractionNumber;\ + size_t len1 = M1->dim->size - 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->perm, 0, len0, 0);\ + subArray(tsub1, M1->dim->perm, 0, len1, contractionNumber);\ + subArray(tDk1, M1->dim->perm, 0, contractionNumber, 0);\ + subArray(tDk0, M0->dim->perm, 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_dimension(&dM, dM0, dM1);\ + \ + dimension *dd;\ + add_dimension(&dd, dSub0, dSub1);\ + updateRankDim(dd);\ + *MM = CREATE_TENSOR_##type(dd);\ + tensor_##type *M= *MM;\ + char *file_cl_src = "../src/kernel_ProdContractnTensor.cl"; \ + char *func_cl_name = "prodContractnTensorLin_" #type; \ + CL_GEN_SETUP_(type,file_cl_src,func_cl_name);\ + \ + /*/ Set the arguments of the kernel */ \ + ret = clSetKernelArg(kernel, 0, sizeof(size_t), (void *)&(dSub1->rank)); \ + ret = clSetKernelArg(kernel, 1, sizeof(size_t), (void *)&(dM->rank)); \ + ret = clSetKernelArg(kernel, 2, sizeof(cl_mem), (void *)&M0_mem_obj); \ + ret = clSetKernelArg(kernel, 3, sizeof(cl_mem), (void *)&M1_mem_obj); \ + ret = clSetKernelArg(kernel, 4, sizeof(cl_mem), (void *)&M_mem_obj); \ + \ + CL_EXEC_KERNEL(type);\ +\ } \ CL_GEN_FUNC_TENSOR(TYPE_FLOAT); CL_GEN_FUNC_TENSOR(TYPE_DOUBLE); + + diff --git a/tensor_t/test/is_good.c b/tensor_t/test/is_good.c index 92b328c..5f82ae3 100644 --- a/tensor_t/test/is_good.c +++ b/tensor_t/test/is_good.c @@ -85,10 +85,7 @@ TEST(tensorProd ){ print_tensor_float(M,"M"); - size_t x_idx=0, m_idx; - for(size_t i=0; idim->rank; ++i){ - EXPECT_EQ_TYPE_FLOAT(Mn->x[i],M->x[i]); - } + EXPECT_ARRAY_EQ_TYPE_FLOAT(M->x,M->dim->rank,Mn->x,Mn->dim->rank); print_tensor_float(Mn,"Mn"); } @@ -141,13 +138,13 @@ TEST(tensorContractnProd_TYPE_FLOAT2 ){ dimension *d0=create_dim(3); dimension *d1=create_dim(3); - d0->perm[0]=5; - d0->perm[1]=2; //3; - d0->perm[2]=3; + d0->perm[0]=35; + d0->perm[1]=32; //3; + d0->perm[2]=23; - d1->perm[0]=2; - d1->perm[1]=3;//3; - d1->perm[2]=4; + d1->perm[0]=32; + d1->perm[1]=23;//3; + d1->perm[2]=44; updateRankDim(d0); updateRankDim(d1); @@ -161,23 +158,23 @@ TEST(tensorContractnProd_TYPE_FLOAT2 ){ for(size_t i=0; idim->rank;++i) M0->x[i]=i*0.1 +1; for(size_t i=0; idim->rank;++i) M1->x[i]=i*0.003 + 2; - print_tensor_float(M0,"M0"); - print_tensor_float(M1,"M1"); +// print_tensor_float(M0,"M0"); +// print_tensor_float(M1,"M1"); tensor_TYPE_FLOAT *M; tensor_TYPE_FLOAT *MnO; tensorContractnProd_TYPE_FLOAT(&M, M0,M1,2); - print_tensor_float(M,"M"); +// print_tensor_float(M,"M"); tensorContractnProdNotOpt_TYPE_FLOAT(&MnO, M0,M1,2); - print_tensor_float(MnO,"MnO"); +// print_tensor_float(MnO,"MnO"); // for(size_t i=0;idim->rank;++i) // EXPECT_EQ_TYPE_FLOAT(M->x[i],MnO->x[i]); - EXPECT_ARRAY_EQ_TYPE_FLOAT(M->x,M->dim->rank,MnO->x,MnO->dim->rank); + //EXPECT_ARRAY_EQ_TYPE_FLOAT(M->x,M->dim->rank,MnO->x,MnO->dim->rank); } @@ -185,14 +182,14 @@ TEST(tensorContractnProd_TYPE_FLOAT2 ){ TEST(cl_tensorContractnProd_TYPE_FLOAT2 ){ dimension *d0=create_dim(3); dimension *d1=create_dim(3); + + d0->perm[0]=35; + d0->perm[1]=32; //3; + d0->perm[2]=23; - d0->perm[0]=5; - d0->perm[1]=2; //3; - d0->perm[2]=3; - - d1->perm[0]=2; - d1->perm[1]=3;//3; - d1->perm[2]=4; + d1->perm[0]=32; + d1->perm[1]=23;//3; + d1->perm[2]=44; updateRankDim(d0); updateRankDim(d1); @@ -206,23 +203,23 @@ TEST(cl_tensorContractnProd_TYPE_FLOAT2 ){ for(size_t i=0; idim->rank;++i) M0->x[i]=i*0.1 +1; for(size_t i=0; idim->rank;++i) M1->x[i]=i*0.003 + 2; - print_tensor_float(M0,"M0"); - print_tensor_float(M1,"M1"); +// print_tensor_float(M0,"M0"); +// print_tensor_float(M1,"M1"); tensor_TYPE_FLOAT *M; tensor_TYPE_FLOAT *MnO; - tensorContractnProd_TYPE_FLOAT(&M, M0,M1,2); - print_tensor_float(M,"M"); + tensorContractnProdNotOpt_TYPE_FLOAT(&M, M0,M1,2); +// print_tensor_float(M,"M"); cl_tensorContractnProd_TYPE_FLOAT(&MnO, M0,M1,2); - print_tensor_float(MnO,"MnO"); +// print_tensor_float(MnO,"MnO"); // for(size_t i=0;idim->rank;++i) // EXPECT_EQ_TYPE_FLOAT(M->x[i],MnO->x[i]); - EXPECT_ARRAY_EQ_TYPE_FLOAT(M->x,M->dim->rank,MnO->x,MnO->dim->rank); + //EXPECT_ARRAY_EQ_TYPE_FLOAT(M->x,M->dim->rank,MnO->x,MnO->dim->rank); } @@ -231,13 +228,13 @@ TEST(cl_tensorContractnProd_TYPE_DOUBLE2 ){ dimension *d0=create_dim(3); dimension *d1=create_dim(3); - d0->perm[0]=5; - d0->perm[1]=2; //3; - d0->perm[2]=3; + d0->perm[0]=125; + d0->perm[1]=52; //3; + d0->perm[2]=63; - d1->perm[0]=2; - d1->perm[1]=3;//3; - d1->perm[2]=4; + d1->perm[0]=52; + d1->perm[1]=63;//3; + d1->perm[2]=54; updateRankDim(d0); updateRankDim(d1); @@ -251,18 +248,19 @@ TEST(cl_tensorContractnProd_TYPE_DOUBLE2 ){ for(size_t i=0; idim->rank;++i) M0->x[i]=i*0.1 +1; for(size_t i=0; idim->rank;++i) M1->x[i]=i*0.003 + 2; - print_tensor_double(M0,"M0"); - print_tensor_double(M1,"M1"); + //print_tensor_double(M0,"M0"); + //print_tensor_double(M1,"M1"); tensor_TYPE_DOUBLE *M; tensor_TYPE_DOUBLE *MnO; - tensorContractnProd_TYPE_DOUBLE(&M, M0,M1,2); - print_tensor_double(M,"M"); + tensorContractnProdNotOpt_TYPE_DOUBLE(&M, M0,M1,2); + //tensorContractnProd_TYPE_DOUBLE(&M, M0,M1,2); + //print_tensor_double(M,"M"); cl_tensorContractnProd_TYPE_DOUBLE(&MnO, M0,M1,2); - print_tensor_double(MnO,"MnO"); + //print_tensor_double(MnO,"MnO"); // for(size_t i=0;idim->rank;++i) // EXPECT_EQ_TYPE_DOUBLE(M->x[i],MnO->x[i]); @@ -271,6 +269,189 @@ TEST(cl_tensorContractnProd_TYPE_DOUBLE2 ){ } + + +TEST(tensorContractnProd_TYPE_DOUBLE2 ){ + dimension *d0=create_dim(3); + dimension *d1=create_dim(3); + + d0->perm[0]=125; + d0->perm[1]=52; //3; + d0->perm[2]=63; + + d1->perm[0]=52; + d1->perm[1]=63;//3; + d1->perm[2]=54; + + updateRankDim(d0); + updateRankDim(d1); + + + tensor_TYPE_DOUBLE *M0 = CREATE_TENSOR_TYPE_DOUBLE(d0); + tensor_TYPE_DOUBLE *M1 = CREATE_TENSOR_TYPE_DOUBLE(d1); + + LOG("M0->dim->rank = %ld\n",M0->dim->rank); + LOG("M1->dim->rank = %ld\n",M1->dim->rank); + for(size_t i=0; idim->rank;++i) M0->x[i]=i*0.1 +1; + for(size_t i=0; idim->rank;++i) M1->x[i]=i*0.003 + 2; + + //print_tensor_double(M0,"M0"); + //print_tensor_double(M1,"M1"); + + tensor_TYPE_DOUBLE *M; + tensor_TYPE_DOUBLE *MnO; + + tensorContractnProd_TYPE_DOUBLE(&M, M0,M1,2); + //print_tensor_double(M,"M"); + //cl_tensorContractnProd_TYPE_DOUBLE(&MnO, M0,M1,2); + tensorContractnProdNotOpt_TYPE_DOUBLE(&MnO, M0,M1,2); + + //print_tensor_double(MnO,"MnO"); + + // for(size_t i=0;idim->rank;++i) + // EXPECT_EQ_TYPE_DOUBLE(M->x[i],MnO->x[i]); + + EXPECT_ARRAY_EQ_TYPE_DOUBLE(M->x,M->dim->rank,MnO->x,MnO->dim->rank); + + +} + +TEST(TensorProdCL){ + dimension *d0=create_dim(3); + dimension *d1=create_dim(2); + + d0->perm[0]=2; + d0->perm[1]=3; + d0->perm[2]=2; + + d1->perm[0]=2; + d1->perm[1]=3; + + updateRankDim(d0); + updateRankDim(d1); + + + tensor_TYPE_FLOAT *M0 = CREATE_TENSOR_TYPE_FLOAT(d0); + tensor_TYPE_FLOAT *M1 = CREATE_TENSOR_TYPE_FLOAT(d1); + + LOG("M0->dim->rank = %ld\n",M0->dim->rank); + LOG("M1->dim->rank = %ld\n",M1->dim->rank); + for(size_t i=0; idim->rank;++i) M0->x[i]=i*0.1 +1; + for(size_t i=0; idim->rank;++i) M1->x[i]=i*0.003 + 2; + + print_tensor_float(M0,"M0"); + print_tensor_float(M1,"M1"); + + + tensor_TYPE_FLOAT *M; + tensor_TYPE_FLOAT *Mn; + + tensorProd_TYPE_FLOAT(&M,M0,M1); + cl_tensorProd_TYPE_FLOAT(&Mn,M0,M1); + LOG("M->dim->rank = %ld\n",M->dim->rank); + + print_tensor_float(M,"M"); + + EXPECT_ARRAY_EQ_TYPE_FLOAT(M->x,M->dim->rank,Mn->x,Mn->dim->rank); + + + print_tensor_float(Mn,"Mn"); +} + +TEST(VS_cl_tensorContractnProd_TYPE_DOUBLE2 ){ + dimension *d0=create_dim(3); + dimension *d1=create_dim(3); + + d0->perm[0]=125; + d0->perm[1]=52; //3; + d0->perm[2]=63; + + d1->perm[0]=52; + d1->perm[1]=63;//3; + d1->perm[2]=154; + + updateRankDim(d0); + updateRankDim(d1); + + + tensor_TYPE_DOUBLE *M0 = CREATE_TENSOR_TYPE_DOUBLE(d0); + tensor_TYPE_DOUBLE *M1 = CREATE_TENSOR_TYPE_DOUBLE(d1); + + LOG("M0->dim->rank = %ld\n",M0->dim->rank); + LOG("M1->dim->rank = %ld\n",M1->dim->rank); + for(size_t i=0; idim->rank;++i) M0->x[i]=i*0.1 +1; + for(size_t i=0; idim->rank;++i) M1->x[i]=i*0.003 + 2; + + //print_tensor_double(M0,"M0"); + //print_tensor_double(M1,"M1"); + + //tensor_TYPE_DOUBLE *M; + tensor_TYPE_DOUBLE *MnO; + + //tensorContractnProdNotOpt_TYPE_DOUBLE(&M, M0,M1,2); + //tensorContractnProd_TYPE_DOUBLE(&M, M0,M1,2); + //print_tensor_double(M,"M"); + cl_tensorContractnProd_TYPE_DOUBLE(&MnO, M0,M1,2); + + + //print_tensor_double(MnO,"MnO"); + + // for(size_t i=0;idim->rank;++i) + // EXPECT_EQ_TYPE_DOUBLE(M->x[i],MnO->x[i]); + + //EXPECT_ARRAY_EQ_TYPE_DOUBLE(M->x,M->dim->rank,MnO->x,MnO->dim->rank); + + +} + + +TEST(VStensorContractnProd_TYPE_DOUBLE2 ){ + dimension *d0=create_dim(3); + dimension *d1=create_dim(3); + + d0->perm[0]=125; + d0->perm[1]=52; //3; + d0->perm[2]=63; + + d1->perm[0]=52; + d1->perm[1]=63;//3; + d1->perm[2]=154; + + updateRankDim(d0); + updateRankDim(d1); + + + tensor_TYPE_DOUBLE *M0 = CREATE_TENSOR_TYPE_DOUBLE(d0); + tensor_TYPE_DOUBLE *M1 = CREATE_TENSOR_TYPE_DOUBLE(d1); + + LOG("M0->dim->rank = %ld\n",M0->dim->rank); + LOG("M1->dim->rank = %ld\n",M1->dim->rank); + for(size_t i=0; idim->rank;++i) M0->x[i]=i*0.1 +1; + for(size_t i=0; idim->rank;++i) M1->x[i]=i*0.003 + 2; + + //print_tensor_double(M0,"M0"); + //print_tensor_double(M1,"M1"); + + tensor_TYPE_DOUBLE *M; + //tensor_TYPE_DOUBLE *MnO; + + tensorContractnProd_TYPE_DOUBLE(&M, M0,M1,2); + //print_tensor_double(M,"M"); + //cl_tensorContractnProd_TYPE_DOUBLE(&MnO, M0,M1,2); + //tensorContractnProdNotOpt_TYPE_DOUBLE(&MnO, M0,M1,2); + + //print_tensor_double(MnO,"MnO"); + + // for(size_t i=0;idim->rank;++i) + // EXPECT_EQ_TYPE_DOUBLE(M->x[i],MnO->x[i]); + + //EXPECT_ARRAY_EQ_TYPE_DOUBLE(M->x,M->dim->rank,MnO->x,MnO->dim->rank); + + +} + + + int main(int argc, char **argv){ diff --git a/ytest_t/libytest.so b/ytest_t/libytest.so index a3ca4f8bbf2c5082c586ecb61777e7c967cabbc8..a823520d3949423fa5accf91db48d696a831a1c1 100644 GIT binary patch delta 6769 zcmZ|Udzel29>?*u2klXAOJplFLxoIOr5d>>Mh9hesG$_kNtaV(={6-cxgB>am+z#= zwM41y(o7e*B$sq(Ax4s<5W}?NWbe8C&il)AoYNo2^Xy)~{qy^Lp56Mbwb$B@4O1I# znA&j0HS^(m1I% zEPP|ApJWXSzgy?+u9oHAJu%s1Y9*K9#9-p@-KO4pe_r_6@X5RCSZSRsYg7kb>o5Kf z^52frJ4$MPxMg0){O~KGXwJTbIZ?&3GQUrl8dWVT8=K(9pAx1crXNk1NAc-n2{RVg zo=TV{m{OE5oAD$38L$5>VJcR$tQ+D9a~&?nZaA}3(hS7~cP7m&%<7ypYjAbfq}f}| zidwH`CCxb|n%$i=wW?dzs(X{B71ryOG`-R8oixwku7@bVj7O6uAD1jingTqsGHDXH z>4T(+)L{MEq{+ndn2p^(O`06M^RuMM#dkN7$3tI`uMxGZvAZZ>V)!={*p~Ivw-n%2 z1r*@AqZHtWKU0AANeZw}Aq7|^K^_f8YFgHSa`L#uDmK~pV3lH%gT1O2n_OI7v)JV0 z`C7%MAj)86TCqvs;`Cw@xze&OYg}wH@h?p&z|gG};2)TaecMog^V(5>z3(QE-Ty+q z79aFp@_5cAk1P6<$3+j5$MB=%vHN4iCR)HCWf%o`0wc9KMRF*>S6`+8Zy!$qW=x;} zr%#~(_e|ph;H0_aar7JHucBuGd91gXJbtl~Jbv;4c}!nR9{c1KM@<2P(oGa#(H9id z;ZSX-0B7x>0K4y}0NWQ(fNve50FNH#1K`|K@Dlxg( z<+2i!j}ud)C8mHu$66&Ofw$H!F_F5Km3wuG$;9vLm6&Xt*`≠H0J$U{P}l@D_(W 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