2727
2828from pandas .core .dtypes .common import is_float_dtype , is_integer_dtype , is_scalar
2929
30- from .roperator import rdivmod
30+ from .roperator import rdivmod , rfloordiv , rmod
3131
3232
3333def fill_zeros (result , x , y , name , fill ):
@@ -85,7 +85,7 @@ def fill_zeros(result, x, y, name, fill):
8585 return result
8686
8787
88- def mask_zero_div_zero (x , y , result , copy = False ):
88+ def mask_zero_div_zero (x , y , result ):
8989 """
9090 Set results of 0 / 0 or 0 // 0 to np.nan, regardless of the dtypes
9191 of the numerator or the denominator.
@@ -95,9 +95,6 @@ def mask_zero_div_zero(x, y, result, copy=False):
9595 x : ndarray
9696 y : ndarray
9797 result : ndarray
98- copy : bool (default False)
99- Whether to always create a new array or try to fill in the existing
100- array if possible.
10198
10299 Returns
103100 -------
@@ -113,10 +110,19 @@ def mask_zero_div_zero(x, y, result, copy=False):
113110 >>> mask_zero_div_zero(x, y, result)
114111 array([ inf, nan, -inf])
115112 """
113+ if not isinstance (result , np .ndarray ):
114+ # FIXME: SparseArray would raise TypeError with np.putmask
115+ return result
116+
116117 if is_scalar (y ):
117118 y = np .array (y )
118119
119120 zmask = y == 0
121+
122+ if isinstance (zmask , bool ):
123+ # FIXME: numpy did not evaluate pointwise, seen in docs build
124+ return result
125+
120126 if zmask .any ():
121127 shape = result .shape
122128
@@ -125,12 +131,13 @@ def mask_zero_div_zero(x, y, result, copy=False):
125131 zpos_mask = zmask & ~ zneg_mask
126132
127133 nan_mask = (zmask & (x == 0 )).ravel ()
128- neginf_mask = ((zpos_mask & (x < 0 )) | (zneg_mask & (x > 0 ))).ravel ()
129- posinf_mask = ((zpos_mask & (x > 0 )) | (zneg_mask & (x < 0 ))).ravel ()
134+ with np .errstate (invalid = "ignore" ):
135+ neginf_mask = ((zpos_mask & (x < 0 )) | (zneg_mask & (x > 0 ))).ravel ()
136+ posinf_mask = ((zpos_mask & (x > 0 )) | (zneg_mask & (x < 0 ))).ravel ()
130137
131138 if nan_mask .any () or neginf_mask .any () or posinf_mask .any ():
132139 # Fill negative/0 with -inf, positive/0 with +inf, 0/0 with NaN
133- result = result .astype ("float64" , copy = copy ).ravel ()
140+ result = result .astype ("float64" , copy = False ).ravel ()
134141
135142 np .putmask (result , nan_mask , np .nan )
136143 np .putmask (result , posinf_mask , np .inf )
@@ -157,36 +164,45 @@ def dispatch_missing(op, left, right, result):
157164 -------
158165 result : ndarray
159166 """
160- opstr = "__{opname}__" .format (opname = op .__name__ ).replace ("____" , "__" )
161167 if op is operator .floordiv :
162168 # Note: no need to do this for truediv; in py3 numpy behaves the way
163169 # we want.
164170 result = mask_zero_div_zero (left , right , result )
165171 elif op is operator .mod :
166- result = fill_zeros (result , left , right , opstr , np .nan )
172+ result = fill_zeros (result , left , right , "__mod__" , np .nan )
167173 elif op is divmod :
168174 res0 = mask_zero_div_zero (left , right , result [0 ])
169- res1 = fill_zeros (result [1 ], left , right , opstr , np .nan )
175+ res1 = fill_zeros (result [1 ], left , right , "__divmod__" , np .nan )
170176 result = (res0 , res1 )
171177 return result
172178
173179
174180# FIXME: de-duplicate with dispatch_missing
175- def dispatch_fill_zeros (op , left , right , result , fill_value ):
181+ def dispatch_fill_zeros (op , left , right , result ):
176182 """
177183 Call fill_zeros with the appropriate fill value depending on the operation,
178184 with special logic for divmod and rdivmod.
179185 """
180186 if op is divmod :
181187 result = (
182- fill_zeros ( result [ 0 ], left , right , "__floordiv__" , np . inf ),
188+ mask_zero_div_zero ( left , right , result [ 0 ] ),
183189 fill_zeros (result [1 ], left , right , "__mod__" , np .nan ),
184190 )
185191 elif op is rdivmod :
186192 result = (
187- fill_zeros ( result [ 0 ] , left , right , "__rfloordiv__" , np . inf ),
193+ mask_zero_div_zero ( right , left , result [ 0 ] ),
188194 fill_zeros (result [1 ], left , right , "__rmod__" , np .nan ),
189195 )
190- else :
191- result = fill_zeros (result , left , right , op .__name__ , fill_value )
196+ elif op is operator .floordiv :
197+ # Note: no need to do this for truediv; in py3 numpy behaves the way
198+ # we want.
199+ result = mask_zero_div_zero (left , right , result )
200+ elif op is op is rfloordiv :
201+ # Note: no need to do this for rtruediv; in py3 numpy behaves the way
202+ # we want.
203+ result = mask_zero_div_zero (right , left , result )
204+ elif op is operator .mod :
205+ result = fill_zeros (result , left , right , "__mod__" , np .nan )
206+ elif op is rmod :
207+ result = fill_zeros (result , left , right , "__rmod__" , np .nan )
192208 return result
0 commit comments