@@ -10,6 +10,63 @@ fn assert_eq<T: PartialEq + Debug>(x: T, y: T) {
1010 assert_eq ! ( x, y) ;
1111}
1212
13+ trait FloatToInt < Int > : Copy {
14+ fn cast ( self ) -> Int ;
15+ unsafe fn cast_unchecked ( self ) -> Int ;
16+ }
17+
18+ impl FloatToInt < i8 > for f32 {
19+ fn cast ( self ) -> i8 { self as _ }
20+ unsafe fn cast_unchecked ( self ) -> i8 { self . to_int_unchecked ( ) }
21+ }
22+ impl FloatToInt < i32 > for f32 {
23+ fn cast ( self ) -> i32 { self as _ }
24+ unsafe fn cast_unchecked ( self ) -> i32 { self . to_int_unchecked ( ) }
25+ }
26+ impl FloatToInt < u32 > for f32 {
27+ fn cast ( self ) -> u32 { self as _ }
28+ unsafe fn cast_unchecked ( self ) -> u32 { self . to_int_unchecked ( ) }
29+ }
30+ impl FloatToInt < i64 > for f32 {
31+ fn cast ( self ) -> i64 { self as _ }
32+ unsafe fn cast_unchecked ( self ) -> i64 { self . to_int_unchecked ( ) }
33+ }
34+ impl FloatToInt < u64 > for f32 {
35+ fn cast ( self ) -> u64 { self as _ }
36+ unsafe fn cast_unchecked ( self ) -> u64 { self . to_int_unchecked ( ) }
37+ }
38+
39+ impl FloatToInt < i8 > for f64 {
40+ fn cast ( self ) -> i8 { self as _ }
41+ unsafe fn cast_unchecked ( self ) -> i8 { self . to_int_unchecked ( ) }
42+ }
43+ impl FloatToInt < i32 > for f64 {
44+ fn cast ( self ) -> i32 { self as _ }
45+ unsafe fn cast_unchecked ( self ) -> i32 { self . to_int_unchecked ( ) }
46+ }
47+ impl FloatToInt < u32 > for f64 {
48+ fn cast ( self ) -> u32 { self as _ }
49+ unsafe fn cast_unchecked ( self ) -> u32 { self . to_int_unchecked ( ) }
50+ }
51+ impl FloatToInt < i64 > for f64 {
52+ fn cast ( self ) -> i64 { self as _ }
53+ unsafe fn cast_unchecked ( self ) -> i64 { self . to_int_unchecked ( ) }
54+ }
55+ impl FloatToInt < u64 > for f64 {
56+ fn cast ( self ) -> u64 { self as _ }
57+ unsafe fn cast_unchecked ( self ) -> u64 { self . to_int_unchecked ( ) }
58+ }
59+
60+ /// Test this cast both via `as` and via `approx_unchecked` (i.e., it must not saturate).
61+ #[ track_caller]
62+ #[ inline( never) ]
63+ fn test_cast < F , I > ( x : F , y : I )
64+ where F : FloatToInt < I > , I : PartialEq + Debug
65+ {
66+ assert_eq ! ( x. cast( ) , y) ;
67+ assert_eq ! ( unsafe { x. cast_unchecked( ) } , y) ;
68+ }
69+
1370fn main ( ) {
1471 basic ( ) ;
1572 casts ( ) ;
@@ -50,19 +107,23 @@ fn basic() {
50107}
51108
52109fn casts ( ) {
110+ // f32 -> i8
111+ test_cast :: < f32 , i8 > ( 127.99 , 127 ) ;
112+ test_cast :: < f32 , i8 > ( -128.99 , -128 ) ;
113+
53114 // f32 -> i32
54- assert_eq :: < i32 > ( 0.0f32 as i32 , 0 ) ;
55- assert_eq :: < i32 > ( -0.0f32 as i32 , 0 ) ;
56- assert_eq :: < i32 > ( /*0x1p-149*/ f32:: from_bits ( 0x00000001 ) as i32 , 0 ) ;
57- assert_eq :: < i32 > ( /*-0x1p-149*/ f32:: from_bits ( 0x80000001 ) as i32 , 0 ) ;
58- assert_eq :: < i32 > ( /*0x1.19999ap+0*/ f32:: from_bits ( 0x3f8ccccd ) as i32 , 1 ) ;
59- assert_eq :: < i32 > ( /*-0x1.19999ap+0*/ f32:: from_bits ( 0xbf8ccccd ) as i32 , -1 ) ;
60- assert_eq :: < i32 > ( 1.9f32 as i32 , 1 ) ;
61- assert_eq :: < i32 > ( -1.9f32 as i32 , -1 ) ;
62- assert_eq :: < i32 > ( 5.0f32 as i32 , 5 ) ;
63- assert_eq :: < i32 > ( -5.0f32 as i32 , -5 ) ;
64- assert_eq :: < i32 > ( 2147483520.0f32 as i32 , 2147483520 ) ;
65- assert_eq :: < i32 > ( -2147483648.0f32 as i32 , -2147483648 ) ;
115+ test_cast :: < f32 , i32 > ( 0.0 , 0 ) ;
116+ test_cast :: < f32 , i32 > ( -0.0 , 0 ) ;
117+ test_cast :: < f32 , i32 > ( /*0x1p-149*/ f32:: from_bits ( 0x00000001 ) , 0 ) ;
118+ test_cast :: < f32 , i32 > ( /*-0x1p-149*/ f32:: from_bits ( 0x80000001 ) , 0 ) ;
119+ test_cast :: < f32 , i32 > ( /*0x1.19999ap+0*/ f32:: from_bits ( 0x3f8ccccd ) , 1 ) ;
120+ test_cast :: < f32 , i32 > ( /*-0x1.19999ap+0*/ f32:: from_bits ( 0xbf8ccccd ) , -1 ) ;
121+ test_cast :: < f32 , i32 > ( 1.9 , 1 ) ;
122+ test_cast :: < f32 , i32 > ( -1.9 , -1 ) ;
123+ test_cast :: < f32 , i32 > ( 5.0 , 5 ) ;
124+ test_cast :: < f32 , i32 > ( -5.0 , -5 ) ;
125+ test_cast :: < f32 , i32 > ( 2147483520.0 , 2147483520 ) ;
126+ test_cast :: < f32 , i32 > ( -2147483648.0 , -2147483648 ) ;
66127 // unrepresentable casts
67128 assert_eq :: < i32 > ( 2147483648.0f32 as i32 , i32:: MAX ) ;
68129 assert_eq :: < i32 > ( -2147483904.0f32 as i32 , i32:: MIN ) ;
@@ -74,19 +135,19 @@ fn casts() {
74135 assert_eq :: < i32 > ( ( -f32:: NAN ) as i32 , 0 ) ;
75136
76137 // f32 -> u32
77- assert_eq :: < u32 > ( 0.0f32 as u32 , 0 ) ;
78- assert_eq :: < u32 > ( -0.0f32 as u32 , 0 ) ;
79- assert_eq :: < u32 > ( /*0x1p-149*/ f32:: from_bits ( 0x1 ) as u32 , 0 ) ;
80- assert_eq :: < u32 > ( /*-0x1p-149*/ f32:: from_bits ( 0x80000001 ) as u32 , 0 ) ;
81- assert_eq :: < u32 > ( /*0x1.19999ap+0*/ f32:: from_bits ( 0x3f8ccccd ) as u32 , 1 ) ;
82- assert_eq :: < u32 > ( 1.9f32 as u32 , 1 ) ;
83- assert_eq :: < u32 > ( 5.0f32 as u32 , 5 ) ;
84- assert_eq :: < u32 > ( 2147483648.0f32 as u32 , 0x8000_0000 ) ;
85- assert_eq :: < u32 > ( 4294967040.0f32 as u32 , 0u32 . wrapping_sub ( 256 ) ) ;
86- assert_eq :: < u32 > ( /*-0x1.ccccccp-1*/ f32:: from_bits ( 0xbf666666 ) as u32 , 0 ) ;
87- assert_eq :: < u32 > ( /*-0x1.fffffep-1*/ f32:: from_bits ( 0xbf7fffff ) as u32 , 0 ) ;
88- assert_eq :: < u32 > ( ( u32:: MAX -127 ) as f32 as u32 , u32:: MAX ) ; // rounding loss
89- assert_eq :: < u32 > ( ( u32:: MAX -128 ) as f32 as u32 , u32:: MAX -255 ) ; // rounding loss
138+ test_cast :: < f32 , u32 > ( 0.0 , 0 ) ;
139+ test_cast :: < f32 , u32 > ( -0.0 , 0 ) ;
140+ test_cast :: < f32 , u32 > ( /*0x1p-149*/ f32:: from_bits ( 0x1 ) , 0 ) ;
141+ test_cast :: < f32 , u32 > ( /*-0x1p-149*/ f32:: from_bits ( 0x80000001 ) , 0 ) ;
142+ test_cast :: < f32 , u32 > ( /*0x1.19999ap+0*/ f32:: from_bits ( 0x3f8ccccd ) , 1 ) ;
143+ test_cast :: < f32 , u32 > ( 1.9 , 1 ) ;
144+ test_cast :: < f32 , u32 > ( 5.0 , 5 ) ;
145+ test_cast :: < f32 , u32 > ( 2147483648.0 , 0x8000_0000 ) ;
146+ test_cast :: < f32 , u32 > ( 4294967040.0 , 0u32 . wrapping_sub ( 256 ) ) ;
147+ test_cast :: < f32 , u32 > ( /*-0x1.ccccccp-1*/ f32:: from_bits ( 0xbf666666 ) , 0 ) ;
148+ test_cast :: < f32 , u32 > ( /*-0x1.fffffep-1*/ f32:: from_bits ( 0xbf7fffff ) , 0 ) ;
149+ test_cast :: < f32 , u32 > ( ( u32:: MAX -127 ) as f32 , u32:: MAX ) ; // rounding loss
150+ test_cast :: < f32 , u32 > ( ( u32:: MAX -128 ) as f32 , u32:: MAX -255 ) ; // rounding loss
90151 // unrepresentable casts
91152 assert_eq :: < u32 > ( 4294967296.0f32 as u32 , u32:: MAX ) ;
92153 assert_eq :: < u32 > ( -5.0f32 as u32 , 0 ) ;
@@ -98,40 +159,44 @@ fn casts() {
98159 assert_eq :: < u32 > ( ( -f32:: NAN ) as u32 , 0 ) ;
99160
100161 // f32 -> i64
101- assert_eq :: < i64 > ( 4294967296.0f32 as i64 , 4294967296 ) ;
102- assert_eq :: < i64 > ( -4294967296.0f32 as i64 , -4294967296 ) ;
103- assert_eq :: < i64 > ( 9223371487098961920.0f32 as i64 , 9223371487098961920 ) ;
104- assert_eq :: < i64 > ( -9223372036854775808.0f32 as i64 , -9223372036854775808 ) ;
162+ test_cast :: < f32 , i64 > ( 4294967296.0 , 4294967296 ) ;
163+ test_cast :: < f32 , i64 > ( -4294967296.0 , -4294967296 ) ;
164+ test_cast :: < f32 , i64 > ( 9223371487098961920.0 , 9223371487098961920 ) ;
165+ test_cast :: < f32 , i64 > ( -9223372036854775808.0 , -9223372036854775808 ) ;
166+
167+ // f64 -> i8
168+ test_cast :: < f64 , i8 > ( 127.99 , 127 ) ;
169+ test_cast :: < f64 , i8 > ( -128.99 , -128 ) ;
105170
106171 // f64 -> i32
107- assert_eq :: < i32 > ( 0.0f64 as i32 , 0 ) ;
108- assert_eq :: < i32 > ( -0.0f64 as i32 , 0 ) ;
109- assert_eq :: < i32 > ( /*0x1.199999999999ap+0*/ f64:: from_bits ( 0x3ff199999999999a ) as i32 , 1 ) ;
110- assert_eq :: < i32 > ( /*-0x1.199999999999ap+0*/ f64:: from_bits ( 0xbff199999999999a ) as i32 , -1 ) ;
111- assert_eq :: < i32 > ( 1.9f64 as i32 , 1 ) ;
112- assert_eq :: < i32 > ( -1.9f64 as i32 , -1 ) ;
113- assert_eq :: < i32 > ( 1e8f64 as i32 , 100_000_000 ) ;
114- assert_eq :: < i32 > ( 2147483647.0f64 as i32 , 2147483647 ) ;
115- assert_eq :: < i32 > ( -2147483648.0f64 as i32 , -2147483648 ) ;
172+ test_cast :: < f64 , i32 > ( 0.0 , 0 ) ;
173+ test_cast :: < f64 , i32 > ( -0.0 , 0 ) ;
174+ test_cast :: < f64 , i32 > ( /*0x1.199999999999ap+0*/ f64:: from_bits ( 0x3ff199999999999a ) , 1 ) ;
175+ test_cast :: < f64 , i32 > ( /*-0x1.199999999999ap+0*/ f64:: from_bits ( 0xbff199999999999a ) , -1 ) ;
176+ test_cast :: < f64 , i32 > ( 1.9 , 1 ) ;
177+ test_cast :: < f64 , i32 > ( -1.9 , -1 ) ;
178+ test_cast :: < f64 , i32 > ( 1e8 , 100_000_000 ) ;
179+ test_cast :: < f64 , i32 > ( 2147483647.0 , 2147483647 ) ;
180+ test_cast :: < f64 , i32 > ( -2147483648.0 , -2147483648 ) ;
116181 // unrepresentable casts
117182 assert_eq :: < i32 > ( 2147483648.0f64 as i32 , i32:: MAX ) ;
118183 assert_eq :: < i32 > ( -2147483649.0f64 as i32 , i32:: MIN ) ;
119184
120185 // f64 -> i64
121- assert_eq :: < i64 > ( 0.0f64 as i64 , 0 ) ;
122- assert_eq :: < i64 > ( -0.0f64 as i64 , 0 ) ;
123- assert_eq :: < i64 > ( /*0x0.0000000000001p-1022*/ f64:: from_bits ( 0x1 ) as i64 , 0 ) ;
124- assert_eq :: < i64 > ( /*-0x0.0000000000001p-1022*/ f64:: from_bits ( 0x8000000000000001 ) as i64 , 0 ) ;
125- assert_eq :: < i64 > ( /*0x1.199999999999ap+0*/ f64:: from_bits ( 0x3ff199999999999a ) as i64 , 1 ) ;
126- assert_eq :: < i64 > ( /*-0x1.199999999999ap+0*/ f64:: from_bits ( 0xbff199999999999a ) as i64 , -1 ) ;
127- assert_eq :: < i64 > ( 5.0f64 as i64 , 5 ) ;
128- assert_eq :: < i64 > ( 5.9f64 as i64 , 5 ) ;
129- assert_eq :: < i64 > ( -5.0f64 as i64 , -5 ) ;
130- assert_eq :: < i64 > ( -5.9f64 as i64 , -5 ) ;
131- assert_eq :: < i64 > ( 4294967296.0f64 as i64 , 4294967296 ) ;
132- assert_eq :: < i64 > ( -4294967296.0f64 as i64 , -4294967296 ) ;
133- assert_eq :: < i64 > ( 9223372036854774784.0f64 as i64 , 9223372036854774784 ) ;
134- assert_eq :: < i64 > ( -9223372036854775808.0f64 as i64 , -9223372036854775808 ) ;
186+ test_cast :: < f64 , i64 > ( 0.0 , 0 ) ;
187+ test_cast :: < f64 , i64 > ( -0.0 , 0 ) ;
188+ test_cast :: < f64 , i64 > ( /*0x0.0000000000001p-1022*/ f64:: from_bits ( 0x1 ) , 0 ) ;
189+ test_cast :: < f64 , i64 > ( /*-0x0.0000000000001p-1022*/ f64:: from_bits ( 0x8000000000000001 ) , 0 ) ;
190+ test_cast :: < f64 , i64 > ( /*0x1.199999999999ap+0*/ f64:: from_bits ( 0x3ff199999999999a ) , 1 ) ;
191+ test_cast :: < f64 , i64 > ( /*-0x1.199999999999ap+0*/ f64:: from_bits ( 0xbff199999999999a ) , -1 ) ;
192+ test_cast :: < f64 , i64 > ( 5.0 , 5 ) ;
193+ test_cast :: < f64 , i64 > ( 5.9 , 5 ) ;
194+ test_cast :: < f64 , i64 > ( -5.0 , -5 ) ;
195+ test_cast :: < f64 , i64 > ( -5.9 , -5 ) ;
196+ test_cast :: < f64 , i64 > ( 4294967296.0 , 4294967296 ) ;
197+ test_cast :: < f64 , i64 > ( -4294967296.0 , -4294967296 ) ;
198+ test_cast :: < f64 , i64 > ( 9223372036854774784.0 , 9223372036854774784 ) ;
199+ test_cast :: < f64 , i64 > ( -9223372036854775808.0 , -9223372036854775808 ) ;
135200 // unrepresentable casts
136201 assert_eq :: < i64 > ( 9223372036854775808.0f64 as i64 , i64:: MAX ) ;
137202 assert_eq :: < i64 > ( -9223372036854777856.0f64 as i64 , i64:: MIN ) ;
@@ -143,14 +208,14 @@ fn casts() {
143208 assert_eq :: < i64 > ( ( -f64:: NAN ) as i64 , 0 ) ;
144209
145210 // f64 -> u64
146- assert_eq :: < u64 > ( 0.0f64 as u64 , 0 ) ;
147- assert_eq :: < u64 > ( -0.0f64 as u64 , 0 ) ;
148- assert_eq :: < u64 > ( 5.0f64 as u64 , 5 ) ;
149- assert_eq :: < u64 > ( -5.0f64 as u64 , 0 ) ;
150- assert_eq :: < u64 > ( 1e16f64 as u64 , 10000000000000000 ) ;
151- assert_eq :: < u64 > ( ( u64:: MAX -1023 ) as f64 as u64 , u64:: MAX ) ; // rounding loss
152- assert_eq :: < u64 > ( ( u64:: MAX -1024 ) as f64 as u64 , u64:: MAX -2047 ) ; // rounding loss
153- assert_eq :: < u64 > ( 9223372036854775808.0f64 as u64 , 9223372036854775808 ) ;
211+ test_cast :: < f64 , u64 > ( 0.0 , 0 ) ;
212+ test_cast :: < f64 , u64 > ( -0.0 , 0 ) ;
213+ test_cast :: < f64 , u64 > ( 5.0 , 5 ) ;
214+ test_cast :: < f64 , u64 > ( -5.0 , 0 ) ;
215+ test_cast :: < f64 , u64 > ( 1e16 , 10000000000000000 ) ;
216+ test_cast :: < f64 , u64 > ( ( u64:: MAX -1023 ) as f64 , u64:: MAX ) ; // rounding loss
217+ test_cast :: < f64 , u64 > ( ( u64:: MAX -1024 ) as f64 , u64:: MAX -2047 ) ; // rounding loss
218+ test_cast :: < f64 , u64 > ( 9223372036854775808.0 , 9223372036854775808 ) ;
154219 // unrepresentable casts
155220 assert_eq :: < u64 > ( 18446744073709551616.0f64 as u64 , u64:: MAX ) ;
156221 assert_eq :: < u64 > ( f64:: MAX as u64 , u64:: MAX ) ;
0 commit comments