@@ -411,15 +411,16 @@ def _do_scaling(self):
411
411
def _iu2iu (self ):
412
412
# (u)int to (u)int scaling
413
413
mn , mx = self .finite_range ()
414
- if self ._out_dtype .kind == 'u' :
414
+ out_dt = self ._out_dtype
415
+ if out_dt .kind == 'u' :
415
416
# We're checking for a sign flip. This can only work for uint
416
417
# output, because, for int output, the abs min of the type is
417
- # greater than the abs max, so the data either fit into the range
418
- # (tested for in _do_scaling), or this test can't pass
419
- # Need abs that deals with max neg ints. abs problem only arises
420
- # when all the data is set to max neg integer value
421
- imax = np . iinfo (self ._out_dtype ). max
422
- if mx <= 0 and int_abs (mn ) <= imax : # sign flip enough?
418
+ # greater than the abs max, so the data either fits into the range
419
+ # (tested for in _do_scaling), or this test can't pass. Need abs
420
+ # that deals with max neg ints. abs problem only arises when all
421
+ # the data is set to max neg integer value
422
+ o_min , o_max = shared_range (self .scaler_dtype , out_dt )
423
+ if mx <= 0 and int_abs (mn ) <= as_int ( o_max ) : # sign flip enough?
423
424
# -1.0 * arr will be in scaler_dtype precision
424
425
self .slope = - 1.0
425
426
return
@@ -563,15 +564,19 @@ def _iu2iu(self):
563
564
# range may be greater than the largest integer for this type.
564
565
# as_int needed to work round numpy 1.4.1 int casting bug
565
566
out_dtype = self ._out_dtype
566
- t_min , t_max = np .iinfo (out_dtype ).min , np .iinfo (out_dtype ).max
567
- type_range = as_int (t_max ) - as_int (t_min )
567
+ # Options in this method are scaling using intercept only. These will
568
+ # have to pass through ``self.scaler_dtype`` (because the intercept is
569
+ # in this type).
570
+ o_min , o_max = [as_int (v )
571
+ for v in shared_range (self .scaler_dtype , out_dtype )]
572
+ type_range = o_max - o_min
568
573
mn2mx = mx - mn
569
574
if mn2mx <= type_range : # might offset be enough?
570
- if t_min == 0 : # uint output - take min to 0
575
+ if o_min == 0 : # uint output - take min to 0
571
576
# decrease offset with floor_exact, meaning mn >= t_min after
572
577
# subtraction. But we may have pushed the data over t_max,
573
578
# which we check below
574
- inter = floor_exact (mn - t_min , self .scaler_dtype )
579
+ inter = floor_exact (mn - o_min , self .scaler_dtype )
575
580
else : # int output - take midpoint to 0
576
581
# ceil below increases inter, pushing scale up to 0.5 towards
577
582
# -inf, because ints have abs min == abs max + 1
@@ -581,15 +586,16 @@ def _iu2iu(self):
581
586
inter = floor_exact (midpoint , self .scaler_dtype )
582
587
# Need to check still in range after floor_exact-ing
583
588
int_inter = as_int (inter )
584
- assert mn - int_inter >= t_min
585
- if mx - int_inter <= t_max :
589
+ assert mn - int_inter >= o_min
590
+ if mx - int_inter <= o_max :
586
591
self .inter = inter
587
592
return
588
593
# Try slope options (sign flip) and then range scaling
589
594
super (SlopeInterArrayWriter , self )._iu2iu ()
590
595
591
596
def _range_scale (self , in_min , in_max ):
592
- """ Calculate scaling, intercept based on data range and output type """
597
+ """ Calculate scaling, intercept based on data range and output type
598
+ """
593
599
if in_max == in_min : # Only one number in array
594
600
self .slope = 1.
595
601
self .inter = in_min
@@ -604,10 +610,10 @@ def _range_scale(self, in_min, in_max):
604
610
in_min , in_max = np .array ([in_min , in_max ], dtype = big_float )
605
611
in_range = np .diff ([in_min , in_max ])
606
612
else : # max possible (u)int range is 2**64-1 (int64, uint64)
607
- # int_to_float covers this range. On windows longdouble is the same
608
- # as double so in_range will be 2**64 - thus overestimating slope
609
- # slightly. Casting to int needed to allow in_max-in_min to be larger than
610
- # the largest (u)int value
613
+ # int_to_float covers this range. On windows longdouble is the
614
+ # same as double so in_range will be 2**64 - thus overestimating
615
+ # slope slightly. Casting to int needed to allow in_max-in_min to
616
+ # be larger than the largest (u)int value
611
617
in_min , in_max = as_int (in_min ), as_int (in_max )
612
618
in_range = int_to_float (in_max - in_min , big_float )
613
619
# Cast to float for later processing.
@@ -624,13 +630,13 @@ def _range_scale(self, in_min, in_max):
624
630
# raise an error when writing
625
631
out_min , out_max = shared_range (working_dtype , out_dtype )
626
632
out_min , out_max = np .array ((out_min , out_max ), dtype = big_float )
627
- # We want maximum precision for the calculations. Casting will
628
- # not lose precision because min/max are of fp type.
633
+ # We want maximum precision for the calculations. Casting will not lose
634
+ # precision because min/max are of fp type.
629
635
assert [v .dtype .kind for v in (out_min , out_max )] == ['f' , 'f' ]
630
636
out_range = out_max - out_min
631
637
"""
632
- Think of the input values as a line starting (left) at in_min and ending
633
- (right) at in_max.
638
+ Think of the input values as a line starting (left) at in_min and
639
+ ending (right) at in_max.
634
640
635
641
The output values will be a line starting at out_min and ending at
636
642
out_max.
@@ -666,20 +672,20 @@ def _range_scale(self, in_min, in_max):
666
672
We can't change the range of the saved data (the whole range of the
667
673
integer type) or the range of the output data (the values we input). We
668
674
can change the intermediate values ``saved_data * slope`` by choosing
669
- the sign of the slope to match the in_min or in_max to the left or right
670
- end of the saved data range.
675
+ the sign of the slope to match the in_min or in_max to the left or
676
+ right end of the saved data range.
671
677
672
- If the out_dtype is signed int, then abs(out_min) = abs(out_max) + 1 and
673
- the absolute value and therefore precision for values at the left and
674
- right of the saved data range are very similar (e.g. -128 * slope, 127 *
675
- slope respectively).
678
+ If the out_dtype is signed int, then abs(out_min) = abs(out_max) + 1
679
+ and the absolute value and therefore precision for values at the left
680
+ and right of the saved data range are very similar (e.g. -128 * slope,
681
+ 127 * slope respectively).
676
682
677
- If the out_dtype is unsigned int, then the absolute value at the left is
678
- 0 and the precision is much higher than for the right end of the range
679
- (e.g. 0 * slope, 255 * slope).
683
+ If the out_dtype is unsigned int, then the absolute value at the left
684
+ is 0 and the precision is much higher than for the right end of the
685
+ range (e.g. 0 * slope, 255 * slope).
680
686
681
- If the out_dtype is unsigned int then we choose the sign of the slope to
682
- match the smaller of the in_min, in_max to the zero end of the saved
687
+ If the out_dtype is unsigned int then we choose the sign of the slope
688
+ to match the smaller of the in_min, in_max to the zero end of the saved
683
689
range.
684
690
"""
685
691
if out_min == 0 and np .abs (in_max ) < np .abs (in_min ):
0 commit comments