@@ -765,8 +765,7 @@ static inline int
765
765
AK_TM_transfer_object (TriMapObject * tm ,
766
766
bool from_src ,
767
767
PyArrayObject * array_from ,
768
- PyArrayObject * array_to ,
769
- bool clear_target
768
+ PyArrayObject * array_to
770
769
) {
771
770
Py_ssize_t one_count = from_src ? tm -> src_one_count : tm -> dst_one_count ;
772
771
TriMapOne * one_pairs = from_src ? tm -> src_one : tm -> dst_one ;
@@ -789,9 +788,6 @@ AK_TM_transfer_object(TriMapObject* tm,
789
788
else { // will convert any value to an object
790
789
pyo = PyArray_GETITEM (array_from , f );
791
790
}
792
- if (clear_target ) {
793
- Py_XDECREF (array_to_data [o -> to ]);
794
- }
795
791
array_to_data [o -> to ] = pyo ;
796
792
}
797
793
PyObject * * t ;
@@ -814,9 +810,6 @@ AK_TM_transfer_object(TriMapObject* tm,
814
810
}
815
811
while (t < t_end ) {
816
812
Py_INCREF (pyo ); // one more than we need
817
- if (clear_target ) {
818
- Py_XDECREF (* t );
819
- }
820
813
* t ++ = pyo ;
821
814
}
822
815
Py_DECREF (pyo ); // remove the extra ref
@@ -834,9 +827,6 @@ AK_TM_transfer_object(TriMapObject* tm,
834
827
else {
835
828
pyo = PyArray_GETITEM (array_from , f );
836
829
}
837
- if (clear_target ) {
838
- Py_XDECREF (* t );
839
- }
840
830
* t ++ = pyo ;
841
831
dst_pos ++ ;
842
832
}
@@ -845,6 +835,92 @@ AK_TM_transfer_object(TriMapObject* tm,
845
835
return 0 ;
846
836
}
847
837
838
+ // Returns -1 on error. Specialized transfer from any type of an array to an object array. For usage with merge, Will only transfer if the destination is not NULL.
839
+ static inline int
840
+ AK_TM_transfer_object_if_null (TriMapObject * tm ,
841
+ bool from_src ,
842
+ PyArrayObject * array_from ,
843
+ PyArrayObject * array_to
844
+ ) {
845
+ Py_ssize_t one_count = from_src ? tm -> src_one_count : tm -> dst_one_count ;
846
+ TriMapOne * one_pairs = from_src ? tm -> src_one : tm -> dst_one ;
847
+
848
+ // NOTE: could use PyArray_Scalar instead of PyArray_GETITEM if we wanted to store scalars instead of Python objects; however, that is pretty uncommon for object arrays to store PyArray_Scalars
849
+ bool f_is_obj = PyArray_TYPE (array_from ) == NPY_OBJECT ;
850
+
851
+ // the passed in object array is contiguous and have NULL (not None) in each position
852
+ PyObject * * array_to_data = (PyObject * * )PyArray_DATA (array_to );
853
+ PyObject * pyo ;
854
+ void * f ;
855
+ TriMapOne * o = one_pairs ;
856
+ TriMapOne * o_end = o + one_count ;
857
+ for (; o < o_end ; o ++ ) {
858
+ if (array_to_data [o -> to ] == NULL ) {
859
+ f = PyArray_GETPTR1 (array_from , o -> from );
860
+ if (f_is_obj ) {
861
+ pyo = * (PyObject * * )f ;
862
+ Py_INCREF (pyo );
863
+ }
864
+ else { // will convert any value to an object
865
+ pyo = PyArray_GETITEM (array_from , f );
866
+ }
867
+ array_to_data [o -> to ] = pyo ;
868
+ }
869
+ }
870
+ PyObject * * t ;
871
+ PyObject * * t_end ;
872
+ npy_intp dst_pos ;
873
+ npy_int64 f_pos ;
874
+ PyArrayObject * dst ;
875
+ for (Py_ssize_t i = 0 ; i < tm -> many_count ; i ++ ) {
876
+ t = array_to_data + tm -> many_to [i ].start ;
877
+ t_end = array_to_data + tm -> many_to [i ].stop ;
878
+
879
+ if (from_src ) {
880
+ while (t < t_end ) {
881
+ if (* t == NULL ) {
882
+ f = PyArray_GETPTR1 (array_from , tm -> many_from [i ].src );
883
+ if (f_is_obj ) {
884
+ pyo = * (PyObject * * )f ;
885
+ Py_INCREF (pyo );
886
+ }
887
+ else {
888
+ pyo = PyArray_GETITEM (array_from , f ); // given a new ref
889
+ }
890
+ * t ++ = pyo ;
891
+ }
892
+ else {
893
+ t ++ ;
894
+ }
895
+ }
896
+ }
897
+ else { // from_dst, dst is an array
898
+ dst_pos = 0 ;
899
+ dst = tm -> many_from [i ].dst ;
900
+ while (t < t_end ) {
901
+ if (* t == NULL ) {
902
+ f_pos = * (npy_int64 * )PyArray_GETPTR1 (dst , dst_pos );
903
+ f = PyArray_GETPTR1 (array_from , f_pos );
904
+ if (f_is_obj ) {
905
+ pyo = * (PyObject * * )f ;
906
+ Py_INCREF (pyo );
907
+ }
908
+ else {
909
+ pyo = PyArray_GETITEM (array_from , f );
910
+ }
911
+ * t ++ = pyo ;
912
+ dst_pos ++ ;
913
+ }
914
+ else {
915
+ t ++ ;
916
+ dst_pos ++ ;
917
+ }
918
+ }
919
+ }
920
+ }
921
+ return 0 ;
922
+ }
923
+
848
924
// Returns -1 on error.
849
925
static inline int
850
926
AK_TM_fill_object (TriMapObject * tm ,
@@ -1008,7 +1084,7 @@ AK_TM_map_no_fill(TriMapObject* tm,
1008
1084
}
1009
1085
// transfer values
1010
1086
if (dtype_is_obj ) {
1011
- if (AK_TM_transfer_object (tm , from_src , array_from , array_to , false )) {
1087
+ if (AK_TM_transfer_object (tm , from_src , array_from , array_to )) {
1012
1088
Py_DECREF ((PyObject * )array_to );
1013
1089
return NULL ;
1014
1090
}
@@ -1063,6 +1139,7 @@ TriMap_map_dst_no_fill(TriMapObject *self, PyObject *arg) {
1063
1139
static inline PyObject *
1064
1140
TriMap_map_merge (TriMapObject * tm , PyObject * args )
1065
1141
{
1142
+ // both are "from_" arrays
1066
1143
PyArrayObject * array_src ;
1067
1144
PyArrayObject * array_dst ;
1068
1145
@@ -1085,7 +1162,6 @@ TriMap_map_merge(TriMapObject *tm, PyObject *args)
1085
1162
PyErr_SetString (PyExc_TypeError , "Array dst must be 1D" );
1086
1163
return NULL ;
1087
1164
}
1088
-
1089
1165
// passing a borrowed refs; returns a new ref
1090
1166
PyArray_Descr * dtype = AK_resolve_dtype (
1091
1167
PyArray_DESCR (array_src ),
@@ -1133,12 +1209,12 @@ TriMap_map_merge(TriMapObject *tm, PyObject *args)
1133
1209
bool transfer_from_dst = PyArray_SIZE ((PyArrayObject * )tm -> final_src_fill ) != 0 ;
1134
1210
1135
1211
if (dtype_is_obj ) {
1136
- if (AK_TM_transfer_object (tm , true, array_src , array_to , false )) {
1212
+ if (AK_TM_transfer_object (tm , true, array_src , array_to )) {
1137
1213
Py_DECREF ((PyObject * )array_to );
1138
1214
return NULL ;
1139
1215
}
1140
1216
if (transfer_from_dst ) {
1141
- if (AK_TM_transfer_object (tm , false, array_dst , array_to , true )) {
1217
+ if (AK_TM_transfer_object_if_null (tm , false, array_dst , array_to )) {
1142
1218
Py_DECREF ((PyObject * )array_to );
1143
1219
return NULL ;
1144
1220
}
@@ -1223,7 +1299,7 @@ AK_TM_map_fill(TriMapObject* tm,
1223
1299
}
1224
1300
// array_from, array_to inc refed and dec refed on error
1225
1301
if (dtype_is_obj ) {
1226
- if (AK_TM_transfer_object (tm , from_src , array_from , array_to , false )) {
1302
+ if (AK_TM_transfer_object (tm , from_src , array_from , array_to )) {
1227
1303
goto error ;
1228
1304
}
1229
1305
if (AK_TM_fill_object (tm , from_src , array_to , fill_value )) {
0 commit comments