@@ -181,6 +181,9 @@ def zeros(shape, dtype=None):
181181
182182def absolute (x ):
183183 x = get_ov_output (x )
184+ x_type = x .get_element_type ()
185+ if x_type == Type .boolean :
186+ return OpenVINOKerasTensor (x )
184187 return OpenVINOKerasTensor (ov_opset .absolute (x ).output (0 ))
185188
186189
@@ -191,11 +194,10 @@ def abs(x):
191194
192195def all (x , axis = None , keepdims = False ):
193196 x = get_ov_output (x )
197+ x , axis = _resolve_axis (x , axis )
194198 if axis is None :
195- flatten_shape = ov_opset .constant ([- 1 ], Type .i32 ).output (0 )
196- x = ov_opset .reshape (x , flatten_shape , False ).output (0 )
197- axis = 0
198- axis = ov_opset .constant (axis , Type .i32 ).output (0 )
199+ return OpenVINOKerasTensor (x )
200+ x = ov_opset .convert (x , Type .boolean ).output (0 )
199201 return OpenVINOKerasTensor (
200202 ov_opset .reduce_logical_and (x , axis , keepdims ).output (0 )
201203 )
@@ -207,11 +209,10 @@ def angle(x):
207209
208210def any (x , axis = None , keepdims = False ):
209211 x = get_ov_output (x )
212+ x , axis = _resolve_axis (x , axis )
210213 if axis is None :
211- flatten_shape = ov_opset .constant ([- 1 ], Type .i32 ).output (0 )
212- x = ov_opset .reshape (x , flatten_shape , False ).output (0 )
213- axis = 0
214- axis = ov_opset .constant (axis , Type .i32 ).output (0 )
214+ return OpenVINOKerasTensor (x )
215+ x = ov_opset .convert (x , Type .boolean ).output (0 )
215216 return OpenVINOKerasTensor (
216217 ov_opset .reduce_logical_or (x , axis , keepdims ).output (0 )
217218 )
@@ -256,6 +257,17 @@ def _resolve_axis(x, axis):
256257 return x , axis
257258
258259
260+ def _upcast_type_if_needed (x ):
261+ x_type = x .get_element_type ()
262+ if x_type == Type .boolean :
263+ x = ov_opset .convert (x , Type .i32 ).output (0 )
264+ elif x_type in (Type .i8 , Type .i16 ):
265+ x = ov_opset .convert (x , Type .i32 ).output (0 )
266+ elif x_type in (Type .u8 , Type .u16 ):
267+ x = ov_opset .convert (x , Type .u32 ).output (0 )
268+ return x
269+
270+
259271def append (x1 , x2 , axis = None ):
260272 x1 , x2 = get_ov_output (x1 ), get_ov_output (x2 )
261273 x1 , x2 = _align_operand_types (x1 , x2 , "append()" )
@@ -616,11 +628,18 @@ def cbrt(x):
616628
617629def ceil (x ):
618630 x = get_ov_output (x )
619- return OpenVINOKerasTensor (ov_opset .ceil (x ).output (0 ))
631+ x_type = x .get_element_type ()
632+ if x_type .is_integral ():
633+ x = ov_opset .convert (x , OPENVINO_DTYPES [config .floatx ()]).output (0 )
634+ ceiling = ov_opset .ceil (x ).output (0 )
635+ return OpenVINOKerasTensor (ceiling )
620636
621637
622638def clip (x , x_min , x_max ):
623639 x = get_ov_output (x )
640+ x_type = x .get_element_type ()
641+ if x_type == Type .boolean :
642+ x = ov_opset .convert (x , Type .i32 ).output (0 )
624643 x_min = get_ov_output (x_min , x .get_element_type ())
625644 x_max = get_ov_output (x_max , x .get_element_type ())
626645 clip_by_min = ov_opset .maximum (x , x_min ).output (0 )
@@ -1012,25 +1031,52 @@ def isclose(x1, x2, rtol=1e-5, atol=1e-8, equal_nan=False):
10121031
10131032
10141033def isfinite (x ):
1015- x = get_ov_output (x )
1016- return OpenVINOKerasTensor (ov_opset .is_finite (x ).output (0 ))
1034+ # NOTE: openvino has an is_finite operation but it does not properly
1035+ # catch np.inf and -np.inf as not finite values. Hence we bootstrap here. If
1036+ # that ever changes, we could simplify this to just call that operation.
1037+ inf_values = get_ov_output (isinf (x ))
1038+ nan_values = get_ov_output (isnan (x ))
1039+ all_non_finite_values = ov_opset .logical_or (inf_values , nan_values ).output (
1040+ 0
1041+ )
1042+ is_finite = ov_opset .logical_not (all_non_finite_values ).output (0 )
1043+ return OpenVINOKerasTensor (is_finite )
10171044
10181045
10191046def isin (x1 , x2 , assume_unique = False , invert = False ):
10201047 raise NotImplementedError ("`isin` is not supported with openvino backend" )
10211048
10221049
10231050def isinf (x ):
1024- x = get_ov_output (x )
1025- return OpenVINOKerasTensor (ov_opset .is_inf (x ).output (0 ))
1051+ pos_inf = get_ov_output (isposinf (x ))
1052+ neg_inf = get_ov_output (isneginf (x ))
1053+ inf = ov_opset .logical_or (pos_inf , neg_inf ).output (0 )
1054+ return OpenVINOKerasTensor (inf )
10261055
10271056
10281057def isnan (x ):
10291058 x = get_ov_output (x )
1059+ x_type = x .get_element_type ()
1060+ if x_type .is_integral ():
1061+ x = ov_opset .convert (x , OPENVINO_DTYPES [config .floatx ()])
10301062 return OpenVINOKerasTensor (ov_opset .is_nan (x ).output (0 ))
10311063
10321064
10331065def isneginf (x ):
1066+ return _is_inf (x , pos = False )
1067+
1068+
1069+ def isposinf (x ):
1070+ return _is_inf (x )
1071+
1072+
1073+ def _is_inf (x , pos = True ):
1074+ # NOTE: there is an ov_opset.is_inf but it does not catch
1075+ # numpy infinite values like np.inf and -np.inf, hence why we have this
1076+ # if this ever changes in OpenVINO, we can do this instead:
1077+ # ov_opset.is_inf(x, {"detect_positive": pos, "detect_negative": not pos})
1078+ # for each infinite sign
1079+ inf_value = np .inf if pos else - np .inf
10341080 x = get_ov_output (x )
10351081 x_type = x .get_element_type ()
10361082
@@ -1043,26 +1089,19 @@ def isneginf(x):
10431089
10441090 if x_type == Type .bf16 :
10451091 x_f32 = ov_opset .convert (x , Type .f32 ).output (0 )
1046- neg_inf = ov_opset .constant (- np . inf , Type .f32 ).output (0 )
1047- is_neg_inf = ov_opset .equal (x_f32 , neg_inf ).output (0 )
1092+ inf = ov_opset .constant (inf_value , Type .f32 ).output (0 )
1093+ is_inf = ov_opset .equal (x_f32 , inf ).output (0 )
10481094 else :
10491095 if x_type == Type .f16 :
1050- neg_inf = ov_opset .constant (- np . inf , Type .f16 ).output (0 )
1096+ inf = ov_opset .constant (inf_value , Type .f16 ).output (0 )
10511097 elif x_type == Type .f32 :
1052- neg_inf = ov_opset .constant (- np . inf , Type .f32 ).output (0 )
1098+ inf = ov_opset .constant (inf_value , Type .f32 ).output (0 )
10531099 elif x_type == Type .f64 :
1054- neg_inf = ov_opset .constant (- np . inf , Type .f64 ).output (0 )
1100+ inf = ov_opset .constant (inf_value , Type .f64 ).output (0 )
10551101 else :
1056- neg_inf = ov_opset .constant (- np .inf , Type .f32 ).output (0 )
1057- is_neg_inf = ov_opset .equal (x , neg_inf ).output (0 )
1058-
1059- return OpenVINOKerasTensor (is_neg_inf )
1060-
1061-
1062- def isposinf (x ):
1063- raise NotImplementedError (
1064- "`isposinf` is not supported with openvino backend"
1065- )
1102+ inf = ov_opset .constant (inf_value , Type .f32 ).output (0 )
1103+ is_inf = ov_opset .equal (x , inf ).output (0 )
1104+ return OpenVINOKerasTensor (is_inf )
10661105
10671106
10681107def isreal (x ):
@@ -1746,23 +1785,10 @@ def prod(x, axis=None, keepdims=False, dtype=None):
17461785 x = ov_opset .convert (x , ov_dtype ).output (0 )
17471786 # Otherwise, apply dtype promotion rules before reduction.
17481787 else :
1749- x_type = x .get_element_type ()
1750- if x_type == Type .boolean :
1751- x = ov_opset .convert (x , Type .i32 ).output (0 )
1752- elif x_type in (Type .i8 , Type .i16 ):
1753- x = ov_opset .convert (x , Type .i32 ).output (0 )
1754- elif x_type in (Type .u8 , Type .u16 ):
1755- x = ov_opset .convert (x , Type .u32 ).output (0 )
1756-
1788+ x = _upcast_type_if_needed (x )
1789+ x , axis = _resolve_axis (x , axis )
17571790 if axis is None :
1758- flatten_shape = ov_opset .constant ([- 1 ], Type .i32 ).output (0 )
1759- x = ov_opset .reshape (x , flatten_shape , False ).output (0 )
1760- axis = 0
1761-
1762- if isinstance (axis , tuple ):
1763- axis = list (axis )
1764- axis = ov_opset .constant (axis , Type .i32 ).output (0 )
1765-
1791+ return OpenVINOKerasTensor (x )
17661792 # Compute the product
17671793 result = ov_opset .reduce_prod (x , axis , keepdims ).output (0 )
17681794
@@ -2323,12 +2349,19 @@ def negative(x):
23232349
23242350def square (x ):
23252351 x = get_ov_output (x )
2352+ x_type = x .get_element_type ()
2353+ if x_type == Type .boolean :
2354+ x = ov_opset .convert (x , Type .i32 ).output (0 )
23262355 const_two = ov_opset .constant (2 , x .get_element_type ()).output (0 )
23272356 return OpenVINOKerasTensor (ov_opset .power (x , const_two ).output (0 ))
23282357
23292358
23302359def sqrt (x ):
23312360 x = get_ov_output (x )
2361+ x_type = x .get_element_type ()
2362+ if x_type .is_integral ():
2363+ ov_type = OPENVINO_DTYPES [config .floatx ()]
2364+ x = ov_opset .convert (x , ov_type ).output (0 )
23322365 return OpenVINOKerasTensor (ov_opset .sqrt (x ).output (0 ))
23332366
23342367
@@ -2339,6 +2372,8 @@ def squeeze(x, axis=None):
23392372 for idx , dim in enumerate (x .get_partial_shape ()):
23402373 if dim == 1 :
23412374 axis .append (idx )
2375+ if isinstance (axis , tuple ):
2376+ axis = list (axis )
23422377 axis = ov_opset .constant (axis , Type .i32 ).output (0 )
23432378 return OpenVINOKerasTensor (ov_opset .squeeze (x , axis ).output (0 ))
23442379
@@ -2385,12 +2420,12 @@ def var(x, axis=None, keepdims=False):
23852420
23862421def sum (x , axis = None , keepdims = False ):
23872422 x = get_ov_output (x )
2423+ x , axis = _resolve_axis (x , axis )
23882424 if axis is None :
2389- flatten_shape = ov_opset .constant ([- 1 ], Type .i32 ).output (0 )
2390- x = ov_opset .reshape (x , flatten_shape , False ).output (0 )
2391- axis = 0
2392- axis = ov_opset .constant (axis , Type .i32 ).output (0 )
2393- return OpenVINOKerasTensor (ov_opset .reduce_sum (x , axis , keepdims ).output (0 ))
2425+ return OpenVINOKerasTensor (x )
2426+ x = _upcast_type_if_needed (x )
2427+ summed_value = ov_opset .reduce_sum (x , axis , keepdims ).output (0 )
2428+ return OpenVINOKerasTensor (summed_value )
23942429
23952430
23962431def eye (N , M = None , k = 0 , dtype = None ):
0 commit comments