Skip to content

Commit 9c08d24

Browse files
Support array copy between different datatypes (pyccel#1641) (pyccel#1762)
Fixes pyccel#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.
1 parent 8c77c1d commit 9c08d24

File tree

5 files changed

+2543
-9
lines changed

5 files changed

+2543
-9
lines changed

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,4 @@ Contributors
3030
* Priyabrata Mondal
3131
* Farouk Ech-Charef
3232
* Mustapha Belbiad
33+
* Varadarajan Rengaraj

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ All notable changes to this project will be documented in this file.
1515
### Fixed
1616

1717
- #1720 : Fix Undefined Variable error when the function definition is after the variable declaration.
18+
- #1762 : Fix array copy between different data types.
1819
- #1763 Use `np.result_type` to avoid mistakes in non-trivial NumPy type promotion rules.
1920
- Fix some cases where a Python built-in type is returned in place of a NumPy type.
2021
- Stop printing numbers with more decimal digits than their precision.

pyccel/stdlib/ndarrays/ndarrays.c

Lines changed: 172 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,175 @@ bool is_same_shape(t_ndarray a, t_ndarray b)
490490
return (true);
491491
}
492492

493+
#define COPY_DATA_FROM_(SRC_TYPE) \
494+
void copy_data_from_##SRC_TYPE(t_ndarray **ds, t_ndarray src, uint32_t offset, bool elem_wise_cp) \
495+
{ \
496+
t_ndarray *dest = *ds; \
497+
switch(dest->type) \
498+
{ \
499+
case nd_bool: \
500+
if(elem_wise_cp == false)\
501+
{ \
502+
for(int64_t i = 0; i < src.length; i++) \
503+
dest->nd_bool[i + offset] = (bool)src.nd_##SRC_TYPE[i]; \
504+
}\
505+
else \
506+
{\
507+
for(int64_t i = 0; i < src.length; i++) \
508+
dest->nd_bool[element_index(*dest, i, dest->nd) + offset] = (bool)src.nd_##SRC_TYPE[element_index(src, i, src.nd)]; \
509+
}\
510+
break; \
511+
case nd_int8: \
512+
if(elem_wise_cp == false)\
513+
{ \
514+
for(int64_t i = 0; i < src.length; i++) \
515+
dest->nd_int8[i + offset] = (int8_t)src.nd_##SRC_TYPE[i]; \
516+
}\
517+
else \
518+
{\
519+
for(int64_t i = 0; i < src.length; i++) \
520+
dest->nd_int8[element_index(*dest, i, dest->nd) + offset] = (int8_t)src.nd_##SRC_TYPE[element_index(src, i, src.nd)]; \
521+
}\
522+
break; \
523+
case nd_int16: \
524+
if(elem_wise_cp == false)\
525+
{ \
526+
for(int64_t i = 0; i < src.length; i++) \
527+
dest->nd_int16[i + offset] = (int16_t)src.nd_##SRC_TYPE[i]; \
528+
}\
529+
else \
530+
{\
531+
for(int64_t i = 0; i < src.length; i++) \
532+
dest->nd_int16[element_index(*dest, i, dest->nd) + offset] = (int16_t)src.nd_##SRC_TYPE[element_index(src, i, src.nd)]; \
533+
}\
534+
break; \
535+
case nd_int32: \
536+
if(elem_wise_cp == false)\
537+
{ \
538+
for(int64_t i = 0; i < src.length; i++) \
539+
dest->nd_int32[i + offset] = (int32_t)src.nd_##SRC_TYPE[i]; \
540+
}\
541+
else \
542+
{\
543+
for(int64_t i = 0; i < src.length; i++) \
544+
dest->nd_int32[element_index(*dest, i, dest->nd) + offset] = (int32_t)src.nd_##SRC_TYPE[element_index(src, i, src.nd)]; \
545+
}\
546+
break; \
547+
case nd_int64: \
548+
if(elem_wise_cp == false)\
549+
{ \
550+
for(int64_t i = 0; i < src.length; i++) \
551+
dest->nd_int64[i + offset] = (int64_t)src.nd_##SRC_TYPE[i]; \
552+
}\
553+
else \
554+
{\
555+
for(int64_t i = 0; i < src.length; i++) \
556+
dest->nd_int64[element_index(*dest, i, dest->nd) + offset] = (int64_t)src.nd_##SRC_TYPE[element_index(src, i, src.nd)]; \
557+
}\
558+
break; \
559+
case nd_float: \
560+
if(elem_wise_cp == false)\
561+
{ \
562+
for(int64_t i = 0; i < src.length; i++) \
563+
dest->nd_float[i + offset] = (float)src.nd_##SRC_TYPE[i]; \
564+
}\
565+
else \
566+
{\
567+
for(int64_t i = 0; i < src.length; i++) \
568+
dest->nd_float[element_index(*dest, i, dest->nd) + offset] = (float)src.nd_##SRC_TYPE[element_index(src, i, src.nd)]; \
569+
}\
570+
break; \
571+
case nd_double: \
572+
if(elem_wise_cp == false)\
573+
{ \
574+
for(int64_t i = 0; i < src.length; i++) \
575+
dest->nd_double[i + offset] = (double)src.nd_##SRC_TYPE[i]; \
576+
}\
577+
else \
578+
{\
579+
for(int64_t i = 0; i < src.length; i++) \
580+
dest->nd_double[element_index(*dest, i, dest->nd) + offset] = (double)src.nd_##SRC_TYPE[element_index(src, i, src.nd)]; \
581+
}\
582+
break; \
583+
case nd_cfloat: \
584+
if(elem_wise_cp == false)\
585+
{ \
586+
for(int64_t i = 0; i < src.length; i++) \
587+
dest->nd_cfloat[i + offset] = (float complex)src.nd_##SRC_TYPE[i]; \
588+
}\
589+
else \
590+
{\
591+
for(int64_t i = 0; i < src.length; i++) \
592+
dest->nd_cfloat[element_index(*dest, i, dest->nd) + offset] = (float complex)src.nd_##SRC_TYPE[element_index(src, i, src.nd)]; \
593+
}\
594+
break; \
595+
case nd_cdouble: \
596+
if(elem_wise_cp == false)\
597+
{ \
598+
for(int64_t i = 0; i < src.length; i++) \
599+
dest->nd_cdouble[i + offset] = (double complex)src.nd_##SRC_TYPE[i]; \
600+
}\
601+
else \
602+
{\
603+
for(int64_t i = 0; i < src.length; i++) \
604+
dest->nd_cdouble[element_index(*dest, i, dest->nd) + offset] = (double complex)src.nd_##SRC_TYPE[element_index(src, i, src.nd)]; \
605+
}\
606+
break; \
607+
} \
608+
}
609+
610+
COPY_DATA_FROM_(bool)
611+
COPY_DATA_FROM_(int8)
612+
COPY_DATA_FROM_(int16)
613+
COPY_DATA_FROM_(int32)
614+
COPY_DATA_FROM_(int64)
615+
COPY_DATA_FROM_(float)
616+
COPY_DATA_FROM_(double)
617+
COPY_DATA_FROM_(cfloat)
618+
COPY_DATA_FROM_(cdouble)
619+
620+
void copy_data(t_ndarray **ds, t_ndarray src, uint32_t offset, bool elem_wise_cp)
621+
{
622+
switch(src.type)
623+
{
624+
case nd_bool:
625+
copy_data_from_bool(ds, src, offset, elem_wise_cp);
626+
break;
627+
628+
case nd_int8:
629+
copy_data_from_int8(ds, src, offset, elem_wise_cp);
630+
break;
631+
632+
case nd_int16:
633+
copy_data_from_int16(ds, src, offset, elem_wise_cp);
634+
break;
635+
636+
case nd_int32:
637+
copy_data_from_int32(ds, src, offset, elem_wise_cp);
638+
break;
639+
640+
case nd_int64:
641+
copy_data_from_int64(ds, src, offset, elem_wise_cp);
642+
break;
643+
644+
case nd_float:
645+
copy_data_from_float(ds, src, offset, elem_wise_cp);
646+
break;
647+
648+
case nd_double:
649+
copy_data_from_double(ds, src, offset, elem_wise_cp);
650+
break;
651+
652+
case nd_cfloat:
653+
copy_data_from_cfloat(ds, src, offset, elem_wise_cp);
654+
break;
655+
656+
case nd_cdouble:
657+
copy_data_from_cdouble(ds, src, offset, elem_wise_cp);
658+
break;
659+
}
660+
}
661+
493662
void array_copy_data(t_ndarray *dest, t_ndarray src, uint32_t offset)
494663
{
495664
unsigned char *d = (unsigned char*)dest->raw_data;
@@ -499,15 +668,11 @@ void array_copy_data(t_ndarray *dest, t_ndarray src, uint32_t offset)
499668
&& (src.order == order_c
500669
|| (src.order == order_f && is_same_shape(*dest, src))))
501670
{
502-
memcpy(d + offset * dest->type_size, s, src.buffer_size);
671+
copy_data(&dest, src, offset, false);
503672
}
504673
else
505674
{
506-
for (int64_t element_num = 0; element_num < src.length; ++element_num)
507-
{
508-
memcpy(d + ((element_index(*dest, element_num, dest->nd) + offset) * dest->type_size),
509-
s + (element_index(src, element_num, src.nd) * src.type_size), src.type_size);
510-
}
675+
copy_data(&dest, src, offset, true);
511676
}
512677
}
513678

@@ -654,3 +819,4 @@ NUMPY_AMIN_(float32, float, float)
654819
NUMPY_AMIN_(float64, double, double)
655820
NUMPY_AMIN_(complex64, float complex, cfloat)
656821
NUMPY_AMIN_(complex128, double complex, cdouble)
822+

0 commit comments

Comments
 (0)