Define binary operations that have a domain, like divide. They have no reduce, outer or accumulate. Parameters ---------- mbfunc : function The function for which to define a masked version. Made available as ``_DomainedBinaryOperation.f``. domain : class i
| 1123 | |
| 1124 | |
| 1125 | class _DomainedBinaryOperation(_MaskedUFunc): |
| 1126 | """ |
| 1127 | Define binary operations that have a domain, like divide. |
| 1128 | |
| 1129 | They have no reduce, outer or accumulate. |
| 1130 | |
| 1131 | Parameters |
| 1132 | ---------- |
| 1133 | mbfunc : function |
| 1134 | The function for which to define a masked version. Made available |
| 1135 | as ``_DomainedBinaryOperation.f``. |
| 1136 | domain : class instance |
| 1137 | Default domain for the function. Should be one of the ``_Domain*`` |
| 1138 | classes. |
| 1139 | fillx : scalar, optional |
| 1140 | Filling value for the first argument, default is 0. |
| 1141 | filly : scalar, optional |
| 1142 | Filling value for the second argument, default is 0. |
| 1143 | |
| 1144 | """ |
| 1145 | |
| 1146 | def __init__(self, dbfunc, domain, fillx=0, filly=0): |
| 1147 | """abfunc(fillx, filly) must be defined. |
| 1148 | abfunc(x, filly) = x for all x to enable reduce. |
| 1149 | """ |
| 1150 | super().__init__(dbfunc) |
| 1151 | self.domain = domain |
| 1152 | self.fillx = fillx |
| 1153 | self.filly = filly |
| 1154 | ufunc_domain[dbfunc] = domain |
| 1155 | ufunc_fills[dbfunc] = (fillx, filly) |
| 1156 | |
| 1157 | def __call__(self, a, b, *args, **kwargs): |
| 1158 | "Execute the call behavior." |
| 1159 | # Get the data |
| 1160 | (da, db) = (getdata(a), getdata(b)) |
| 1161 | # Get the result |
| 1162 | with np.errstate(divide='ignore', invalid='ignore'): |
| 1163 | result = self.f(da, db, *args, **kwargs) |
| 1164 | # Get the mask as a combination of the source masks and invalid |
| 1165 | m = ~umath.isfinite(result) |
| 1166 | m |= getmask(a) |
| 1167 | m |= getmask(b) |
| 1168 | # Apply the domain |
| 1169 | domain = ufunc_domain.get(self.f, None) |
| 1170 | if domain is not None: |
| 1171 | m |= domain(da, db) |
| 1172 | # Take care of the scalar case first |
| 1173 | if not m.ndim: |
| 1174 | if m: |
| 1175 | return masked |
| 1176 | else: |
| 1177 | return result |
| 1178 | # When the mask is True, put back da if possible |
| 1179 | # any errors, just abort; impossible to guarantee masked values |
| 1180 | try: |
| 1181 | np.copyto(result, 0, casting='unsafe', where=m) |
| 1182 | # avoid using "*" since this may be overlaid |