Skip to content

Commit

Permalink
Support array copy between different datatypes (#1641) (#1762)
Browse files Browse the repository at this point in the history
Fixes #1641:

- Add functions to support array copy between different data types.
- Add tests covering all possible scenarios of data type conversion.
- Add separate tests with source and destination arrays of non-matching sizes.
- Add separate tests with Fortran ordering.
  • Loading branch information
VaradRengaraj authored and EmilyBourne committed May 7, 2024
1 parent 450383e commit 7d14f69
Show file tree
Hide file tree
Showing 5 changed files with 2,543 additions and 9 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@ Contributors
* Priyabrata Mondal
* Farouk Ech-Charef
* Mustapha Belbiad
* Varadarajan Rengaraj
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file.

### Fixed

- #1762 : Fix array copy between different data types.
- #1792 : Fix array unpacking.
- #1795 : Fix bug when returning slices in C.

Expand Down
178 changes: 172 additions & 6 deletions pyccel/stdlib/ndarrays/ndarrays.c
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,175 @@ bool is_same_shape(t_ndarray a, t_ndarray b)
return (true);
}

#define COPY_DATA_FROM_(SRC_TYPE) \
void copy_data_from_##SRC_TYPE(t_ndarray **ds, t_ndarray src, uint32_t offset, bool elem_wise_cp) \
{ \
t_ndarray *dest = *ds; \
switch(dest->type) \
{ \
case nd_bool: \
if(elem_wise_cp == false)\
{ \
for(int64_t i = 0; i < src.length; i++) \
dest->nd_bool[i + offset] = (bool)src.nd_##SRC_TYPE[i]; \
}\
else \
{\
for(int64_t i = 0; i < src.length; i++) \
dest->nd_bool[element_index(*dest, i, dest->nd) + offset] = (bool)src.nd_##SRC_TYPE[element_index(src, i, src.nd)]; \
}\
break; \
case nd_int8: \
if(elem_wise_cp == false)\
{ \
for(int64_t i = 0; i < src.length; i++) \
dest->nd_int8[i + offset] = (int8_t)src.nd_##SRC_TYPE[i]; \
}\
else \
{\
for(int64_t i = 0; i < src.length; i++) \
dest->nd_int8[element_index(*dest, i, dest->nd) + offset] = (int8_t)src.nd_##SRC_TYPE[element_index(src, i, src.nd)]; \
}\
break; \
case nd_int16: \
if(elem_wise_cp == false)\
{ \
for(int64_t i = 0; i < src.length; i++) \
dest->nd_int16[i + offset] = (int16_t)src.nd_##SRC_TYPE[i]; \
}\
else \
{\
for(int64_t i = 0; i < src.length; i++) \
dest->nd_int16[element_index(*dest, i, dest->nd) + offset] = (int16_t)src.nd_##SRC_TYPE[element_index(src, i, src.nd)]; \
}\
break; \
case nd_int32: \
if(elem_wise_cp == false)\
{ \
for(int64_t i = 0; i < src.length; i++) \
dest->nd_int32[i + offset] = (int32_t)src.nd_##SRC_TYPE[i]; \
}\
else \
{\
for(int64_t i = 0; i < src.length; i++) \
dest->nd_int32[element_index(*dest, i, dest->nd) + offset] = (int32_t)src.nd_##SRC_TYPE[element_index(src, i, src.nd)]; \
}\
break; \
case nd_int64: \
if(elem_wise_cp == false)\
{ \
for(int64_t i = 0; i < src.length; i++) \
dest->nd_int64[i + offset] = (int64_t)src.nd_##SRC_TYPE[i]; \
}\
else \
{\
for(int64_t i = 0; i < src.length; i++) \
dest->nd_int64[element_index(*dest, i, dest->nd) + offset] = (int64_t)src.nd_##SRC_TYPE[element_index(src, i, src.nd)]; \
}\
break; \
case nd_float: \
if(elem_wise_cp == false)\
{ \
for(int64_t i = 0; i < src.length; i++) \
dest->nd_float[i + offset] = (float)src.nd_##SRC_TYPE[i]; \
}\
else \
{\
for(int64_t i = 0; i < src.length; i++) \
dest->nd_float[element_index(*dest, i, dest->nd) + offset] = (float)src.nd_##SRC_TYPE[element_index(src, i, src.nd)]; \
}\
break; \
case nd_double: \
if(elem_wise_cp == false)\
{ \
for(int64_t i = 0; i < src.length; i++) \
dest->nd_double[i + offset] = (double)src.nd_##SRC_TYPE[i]; \
}\
else \
{\
for(int64_t i = 0; i < src.length; i++) \
dest->nd_double[element_index(*dest, i, dest->nd) + offset] = (double)src.nd_##SRC_TYPE[element_index(src, i, src.nd)]; \
}\
break; \
case nd_cfloat: \
if(elem_wise_cp == false)\
{ \
for(int64_t i = 0; i < src.length; i++) \
dest->nd_cfloat[i + offset] = (float complex)src.nd_##SRC_TYPE[i]; \
}\
else \
{\
for(int64_t i = 0; i < src.length; i++) \
dest->nd_cfloat[element_index(*dest, i, dest->nd) + offset] = (float complex)src.nd_##SRC_TYPE[element_index(src, i, src.nd)]; \
}\
break; \
case nd_cdouble: \
if(elem_wise_cp == false)\
{ \
for(int64_t i = 0; i < src.length; i++) \
dest->nd_cdouble[i + offset] = (double complex)src.nd_##SRC_TYPE[i]; \
}\
else \
{\
for(int64_t i = 0; i < src.length; i++) \
dest->nd_cdouble[element_index(*dest, i, dest->nd) + offset] = (double complex)src.nd_##SRC_TYPE[element_index(src, i, src.nd)]; \
}\
break; \
} \
}

COPY_DATA_FROM_(bool)
COPY_DATA_FROM_(int8)
COPY_DATA_FROM_(int16)
COPY_DATA_FROM_(int32)
COPY_DATA_FROM_(int64)
COPY_DATA_FROM_(float)
COPY_DATA_FROM_(double)
COPY_DATA_FROM_(cfloat)
COPY_DATA_FROM_(cdouble)

void copy_data(t_ndarray **ds, t_ndarray src, uint32_t offset, bool elem_wise_cp)
{
switch(src.type)
{
case nd_bool:
copy_data_from_bool(ds, src, offset, elem_wise_cp);
break;

case nd_int8:
copy_data_from_int8(ds, src, offset, elem_wise_cp);
break;

case nd_int16:
copy_data_from_int16(ds, src, offset, elem_wise_cp);
break;

case nd_int32:
copy_data_from_int32(ds, src, offset, elem_wise_cp);
break;

case nd_int64:
copy_data_from_int64(ds, src, offset, elem_wise_cp);
break;

case nd_float:
copy_data_from_float(ds, src, offset, elem_wise_cp);
break;

case nd_double:
copy_data_from_double(ds, src, offset, elem_wise_cp);
break;

case nd_cfloat:
copy_data_from_cfloat(ds, src, offset, elem_wise_cp);
break;

case nd_cdouble:
copy_data_from_cdouble(ds, src, offset, elem_wise_cp);
break;
}
}

void array_copy_data(t_ndarray *dest, t_ndarray src, uint32_t offset)
{
unsigned char *d = (unsigned char*)dest->raw_data;
Expand All @@ -499,15 +668,11 @@ void array_copy_data(t_ndarray *dest, t_ndarray src, uint32_t offset)
&& (src.order == order_c
|| (src.order == order_f && is_same_shape(*dest, src))))
{
memcpy(d + offset * dest->type_size, s, src.buffer_size);
copy_data(&dest, src, offset, false);
}
else
{
for (int64_t element_num = 0; element_num < src.length; ++element_num)
{
memcpy(d + ((element_index(*dest, element_num, dest->nd) + offset) * dest->type_size),
s + (element_index(src, element_num, src.nd) * src.type_size), src.type_size);
}
copy_data(&dest, src, offset, true);
}
}

Expand Down Expand Up @@ -654,3 +819,4 @@ NUMPY_AMIN_(float32, float, float)
NUMPY_AMIN_(float64, double, double)
NUMPY_AMIN_(complex64, float complex, cfloat)
NUMPY_AMIN_(complex128, double complex, cdouble)

Loading

0 comments on commit 7d14f69

Please sign in to comment.