@@ -28,9 +28,11 @@ def float_to_int(arr, int_type, nan2zero=True, infmax=False):
28
28
Array of floating point type
29
29
int_type : object
30
30
Numpy integer type
31
- nan2zero : {True, False}
31
+ nan2zero : {True, False, None }
32
32
Whether to convert NaN value to zero. Default is True. If False, and
33
- NaNs are present, raise CastingError
33
+ NaNs are present, raise CastingError. If None, do not check for NaN
34
+ values and pass through directly to the ``astype`` casting mechanism.
35
+ In this last case, the resulting value is undefined.
34
36
infmax : {False, True}
35
37
If True, set np.inf values in `arr` to be `int_type` integer maximum
36
38
value, -np.inf as `int_type` integer minimum. If False, set +/- infs to
@@ -72,13 +74,16 @@ def float_to_int(arr, int_type, nan2zero=True, infmax=False):
72
74
# Deal with scalar as input; fancy indexing needs 1D
73
75
shape = arr .shape
74
76
arr = np .atleast_1d (arr )
75
- mn , mx = _cached_int_clippers (flt_type , int_type )
76
- nans = np .isnan (arr )
77
- have_nans = np .any (nans )
78
- if not nan2zero and have_nans :
79
- raise CastingError ('NaNs in array, nan2zero not True' )
77
+ mn , mx = int_clippers (flt_type , int_type )
78
+ if nan2zero is None :
79
+ seen_nans = False
80
+ else :
81
+ nans = np .isnan (arr )
82
+ seen_nans = np .any (nans )
83
+ if nan2zero == False and seen_nans :
84
+ raise CastingError ('NaNs in array, nan2zero is False' )
80
85
iarr = np .clip (np .rint (arr ), mn , mx ).astype (int_type )
81
- if have_nans :
86
+ if seen_nans :
82
87
iarr [nans ] = 0
83
88
if not infmax :
84
89
return iarr .reshape (shape )
@@ -89,6 +94,9 @@ def float_to_int(arr, int_type, nan2zero=True, infmax=False):
89
94
return iarr .reshape (shape )
90
95
91
96
97
+ # Cache range values
98
+ _SHARED_RANGES = {}
99
+
92
100
def int_clippers (flt_type , int_type ):
93
101
""" Min and max in float type that are >=min, <=max in integer type
94
102
@@ -98,10 +106,12 @@ def int_clippers(flt_type, int_type):
98
106
99
107
Parameters
100
108
----------
101
- flt_type : object
102
- numpy floating point type
103
- int_type : object
104
- numpy integer type
109
+ flt_type : dtype specifier
110
+ A dtype specifier referring to a numpy floating point type. For
111
+ example, ``f4``, ``np.dtype('f4')``, ``np.float32`` are equivalent.
112
+ int_type : dtype specifier
113
+ A dtype specifier referring to a numpy integer type. For example,
114
+ ``i4``, ``np.dtype('i4')``, ``np.int32`` are equivalent
105
115
106
116
Returns
107
117
-------
@@ -111,23 +121,31 @@ def int_clippers(flt_type, int_type):
111
121
mx : object
112
122
Number of type `flt_type` that is the maximum value in the range of
113
123
`int_type`, such that ``mx.astype(int_type)`` <= max of `int_type`
124
+
125
+ Examples
126
+ --------
127
+ >>> shared_range(np.float32, np.int32)
128
+ (-2147483648.0, 2147483520.0)
129
+ >>> shared_range('f4', 'i4')
130
+ (-2147483648.0, 2147483520.0)
114
131
"""
132
+ flt_type = np .dtype (flt_type ).type
133
+ int_type = np .dtype (int_type ).type
134
+ key = (flt_type , int_type )
135
+ # Used cached value if present
136
+ try :
137
+ return _SHARED_RANGES [key ]
138
+ except KeyError :
139
+ pass
115
140
ii = np .iinfo (int_type )
116
- return floor_exact (ii .min , flt_type ), floor_exact (ii .max , flt_type )
117
-
118
-
119
- # Cache clip values
120
- FLT_INT_CLIPS = {}
121
-
122
- def _cached_int_clippers (flt_type , int_type ):
123
- if not (flt_type , int_type ) in FLT_INT_CLIPS :
124
- FLT_INT_CLIPS [flt_type , int_type ] = int_clippers (flt_type , int_type )
125
- return FLT_INT_CLIPS [(flt_type , int_type )]
141
+ mn_mx = floor_exact (ii .min , flt_type ), floor_exact (ii .max , flt_type )
142
+ _SHARED_RANGES [key ] = mn_mx
143
+ return mn_mx
126
144
127
- # ---------------------------------------------------------------------------
128
- # Routines to work out the next lowest representable intger in floating point
145
+ # ----------------------------------------------------------------------------
146
+ # Routines to work out the next lowest representable integer in floating point
129
147
# types.
130
- # ---------------------------------------------------------------------------
148
+ # ----------------------------------------------------------------------------
131
149
132
150
try :
133
151
_float16 = np .float16
0 commit comments