| exception InvalidConversion | |
| module I8_ = | |
| struct | |
| let sat_s x = min (max x (-0x80)) 0x7f | |
| let sat_u x = min (max x 0) 0xff | |
| let wrap_i16 x = I8.of_int_s (I16.to_int_s x) | |
| let wrap_i32 x = I8.of_int_s (I32.to_int_s x) | |
| let narrow_sat_i16_s x = I8.of_int_s (sat_s (I16.to_int_s x)) | |
| let narrow_sat_i16_u x = I8.of_int_u (sat_u (I16.to_int_s x)) | |
| let narrow_sat_i32_s x = I8.of_int_s (sat_s (I32.to_int_s x)) | |
| let narrow_sat_i32_u x = I8.of_int_u (sat_u (I32.to_int_s x)) | |
| end | |
| module I16_ = | |
| struct | |
| let sat_s x = min (max x (-0x8000)) 0x7fff | |
| let sat_u x = min (max x 0) 0xffff | |
| let extend_i8_s x = I16.of_int_s (I8.to_int_s x) | |
| let extend_i8_u x = I16.of_int_u (I8.to_int_u x) | |
| let wrap_i32 x = I16.of_int_s (I32.to_int_s x) | |
| let narrow_sat_i32_s x = I16.of_int_s (sat_s (I32.to_int_s x)) | |
| let narrow_sat_i32_u x = I16.of_int_u (sat_u (I32.to_int_s x)) | |
| end | |
| module I32_ = | |
| struct | |
| let sat_s x = Int64.min (Int64.max x (-0x8000_0000L)) 0x7fff_ffffL | |
| let sat_u x = Int64.min (Int64.max x 0L) 0xffff_ffffL | |
| let extend_i8_s x = I32.of_int_s (I8.to_int_s x) | |
| let extend_i8_u x = I32.of_int_u (I8.to_int_u x) | |
| let extend_i16_s x = I32.of_int_s (I16.to_int_s x) | |
| let extend_i16_u x = I32.of_int_u (I16.to_int_u x) | |
| let wrap_i64 x = Int64.to_int32 x | |
| let narrow_sat_i64_s x = Int64.to_int32 (sat_s x) | |
| let narrow_sat_i64_u x = Int64.to_int32 (sat_u x) | |
| let trunc_f32_s x = | |
| if F32.ne x x then | |
| raise InvalidConversion | |
| else | |
| let xf = F32.to_float x in | |
| if xf >= -.Int32.(to_float min_int) || xf < Int32.(to_float min_int) then | |
| raise Ixx.Overflow | |
| else | |
| Int32.of_float xf | |
| let trunc_f32_u x = | |
| if F32.ne x x then | |
| raise InvalidConversion | |
| else | |
| let xf = F32.to_float x in | |
| if xf >= -.Int32.(to_float min_int) *. 2.0 || xf <= -1.0 then | |
| raise Ixx.Overflow | |
| else | |
| Int64.(to_int32 (of_float xf)) | |
| let trunc_f64_s x = | |
| if F64.ne x x then | |
| raise InvalidConversion | |
| else | |
| let xf = F64.to_float x in | |
| if xf >= -.Int32.(to_float min_int) | |
| || xf <= Int32.(to_float min_int) -. 1.0 then | |
| raise Ixx.Overflow | |
| else | |
| Int32.of_float xf | |
| let trunc_f64_u x = | |
| if F64.ne x x then | |
| raise InvalidConversion | |
| else | |
| let xf = F64.to_float x in | |
| if xf >= -.Int32.(to_float min_int) *. 2.0 || xf <= -1.0 then | |
| raise Ixx.Overflow | |
| else | |
| Int64.(to_int32 (of_float xf)) | |
| let trunc_sat_f32_s x = | |
| if F32.ne x x then | |
| 0l | |
| else | |
| let xf = F32.to_float x in | |
| if xf < Int32.(to_float min_int) then | |
| Int32.min_int | |
| else if xf >= -.Int32.(to_float min_int) then | |
| Int32.max_int | |
| else | |
| Int32.of_float xf | |
| let trunc_sat_f32_u x = | |
| if F32.ne x x then | |
| 0l | |
| else | |
| let xf = F32.to_float x in | |
| if xf <= -1.0 then | |
| 0l | |
| else if xf >= -.Int32.(to_float min_int) *. 2.0 then | |
| -1l | |
| else | |
| Int64.(to_int32 (of_float xf)) | |
| let trunc_sat_f64_s x = | |
| if F64.ne x x then | |
| 0l | |
| else | |
| let xf = F64.to_float x in | |
| if xf < Int32.(to_float min_int) then | |
| Int32.min_int | |
| else if xf >= -.Int32.(to_float min_int) then | |
| Int32.max_int | |
| else | |
| Int32.of_float xf | |
| let trunc_sat_f64_u x = | |
| if F64.ne x x then | |
| 0l | |
| else | |
| let xf = F64.to_float x in | |
| if xf <= -1.0 then | |
| 0l | |
| else if xf >= -.Int32.(to_float min_int) *. 2.0 then | |
| -1l | |
| else | |
| Int64.(to_int32 (of_float xf)) | |
| let reinterpret_f32 = F32.to_bits | |
| end | |
| module I64_ = | |
| struct | |
| let extend_i32_s x = Int64.of_int32 x | |
| let extend_i32_u x = Int64.logand (Int64.of_int32 x) 0x0000_0000_ffff_ffffL | |
| let trunc_f32_s x = | |
| if F32.ne x x then | |
| raise InvalidConversion | |
| else | |
| let xf = F32.to_float x in | |
| if xf >= -.Int64.(to_float min_int) || xf < Int64.(to_float min_int) then | |
| raise Ixx.Overflow | |
| else | |
| Int64.of_float xf | |
| let trunc_f32_u x = | |
| if F32.ne x x then | |
| raise InvalidConversion | |
| else | |
| let xf = F32.to_float x in | |
| if xf >= -.Int64.(to_float min_int) *. 2.0 || xf <= -1.0 then | |
| raise Ixx.Overflow | |
| else if xf >= -.Int64.(to_float min_int) then | |
| Int64.(logxor (of_float (xf -. 0x1p63)) min_int) | |
| else | |
| Int64.of_float xf | |
| let trunc_f64_s x = | |
| if F64.ne x x then | |
| raise InvalidConversion | |
| else | |
| let xf = F64.to_float x in | |
| if xf >= -.Int64.(to_float min_int) || xf < Int64.(to_float min_int) then | |
| raise Ixx.Overflow | |
| else | |
| Int64.of_float xf | |
| let trunc_f64_u x = | |
| if F64.ne x x then | |
| raise InvalidConversion | |
| else | |
| let xf = F64.to_float x in | |
| if xf >= -.Int64.(to_float min_int) *. 2.0 || xf <= -1.0 then | |
| raise Ixx.Overflow | |
| else if xf >= -.Int64.(to_float min_int) then | |
| Int64.(logxor (of_float (xf -. 0x1p63)) min_int) | |
| else | |
| Int64.of_float xf | |
| let trunc_sat_f32_s x = | |
| if F32.ne x x then | |
| 0L | |
| else | |
| let xf = F32.to_float x in | |
| if xf < Int64.(to_float min_int) then | |
| Int64.min_int | |
| else if xf >= -.Int64.(to_float min_int) then | |
| Int64.max_int | |
| else | |
| Int64.of_float xf | |
| let trunc_sat_f32_u x = | |
| if F32.ne x x then | |
| 0L | |
| else | |
| let xf = F32.to_float x in | |
| if xf <= -1.0 then | |
| 0L | |
| else if xf >= -.Int64.(to_float min_int) *. 2.0 then | |
| -1L | |
| else if xf >= -.Int64.(to_float min_int) then | |
| Int64.(logxor (of_float (xf -. 0x1p63)) min_int) | |
| else | |
| Int64.of_float xf | |
| let trunc_sat_f64_s x = | |
| if F64.ne x x then | |
| 0L | |
| else | |
| let xf = F64.to_float x in | |
| if xf < Int64.(to_float min_int) then | |
| Int64.min_int | |
| else if xf >= -.Int64.(to_float min_int) then | |
| Int64.max_int | |
| else | |
| Int64.of_float xf | |
| let trunc_sat_f64_u x = | |
| if F64.ne x x then | |
| 0L | |
| else | |
| let xf = F64.to_float x in | |
| if xf <= -1.0 then | |
| 0L | |
| else if xf >= -.Int64.(to_float min_int) *. 2.0 then | |
| -1L | |
| else if xf >= -.Int64.(to_float min_int) then | |
| Int64.(logxor (of_float (xf -. 0x1p63)) min_int) | |
| else | |
| Int64.of_float xf | |
| let reinterpret_f64 = F64.to_bits | |
| end | |
| module F32_ = | |
| struct | |
| let demote_f64 x = | |
| let xf = F64.to_float x in | |
| if xf = xf then F32.of_float xf else | |
| let nan64bits = F64.to_bits x in | |
| let sign = Int64.(shift_left (shift_right_logical nan64bits 63) 31) in | |
| let significand = Int64.(shift_right_logical (shift_left nan64bits 12) 41) in | |
| let fields = Int64.logor sign significand in | |
| let nan32bits = Int32.logor 0x7fc0_0000l (I32_.wrap_i64 fields) in | |
| F32.of_bits nan32bits | |
| let convert_i32_s x = | |
| F32.of_float (Int32.to_float x) | |
| (* | |
| * Similar to convert_i64_u below, the high half of the i32 range are beyond | |
| * the range where f32 can represent odd numbers, though we do need to adjust | |
| * the least significant bit to round correctly. | |
| *) | |
| let convert_i32_u x = | |
| F32.of_float Int32.( | |
| if x >= zero then to_float x else | |
| to_float (logor (shift_right_logical x 1) (logand x 1l)) *. 2.0 | |
| ) | |
| (* | |
| * Values that are too large would get rounded when represented in f64, | |
| * but double rounding via i64->f64->f32 can produce inaccurate results. | |
| * Hence, for large values we shift right but make sure to accumulate the lost | |
| * bits in the least significant bit, such that rounding still is correct. | |
| *) | |
| let convert_i64_s x = | |
| F32.of_float Int64.( | |
| if abs x < 0x10_0000_0000_0000L then to_float x else | |
| let r = if logand x 0xfffL = 0L then 0L else 1L in | |
| to_float (logor (shift_right x 12) r) *. 0x1p12 | |
| ) | |
| let convert_i64_u x = | |
| F32.of_float Int64.( | |
| if I64.lt_u x 0x10_0000_0000_0000L then to_float x else | |
| let r = if logand x 0xfffL = 0L then 0L else 1L in | |
| to_float (logor (shift_right_logical x 12) r) *. 0x1p12 | |
| ) | |
| let reinterpret_i32 = F32.of_bits | |
| end | |
| module F64_ = | |
| struct | |
| let promote_f32 x = | |
| let xf = F32.to_float x in | |
| if xf = xf then F64.of_float xf else | |
| let nan32bits = I64_.extend_i32_u (F32.to_bits x) in | |
| let sign = Int64.(shift_left (shift_right_logical nan32bits 31) 63) in | |
| let significand = Int64.(shift_right_logical (shift_left nan32bits 41) 12) in | |
| let fields = Int64.logor sign significand in | |
| let nan64bits = Int64.logor 0x7ff8_0000_0000_0000L fields in | |
| F64.of_bits nan64bits | |
| let convert_i32_s x = | |
| F64.of_float (Int32.to_float x) | |
| (* | |
| * Unlike the other convert_u functions, the high half of the i32 range is | |
| * within the range where f32 can represent odd numbers, so we can't do the | |
| * shift. Instead, we can use int64 signed arithmetic. | |
| *) | |
| let convert_i32_u x = | |
| F64.of_float Int64.(to_float (logand (of_int32 x) 0x0000_0000_ffff_ffffL)) | |
| let convert_i64_s x = | |
| F64.of_float (Int64.to_float x) | |
| (* | |
| * Values in the low half of the int64 range can be converted with a signed | |
| * conversion. The high half is beyond the range where f64 can represent odd | |
| * numbers, so we can shift the value right, adjust the least significant | |
| * bit to round correctly, do a conversion, and then scale it back up. | |
| *) | |
| let convert_i64_u x = | |
| F64.of_float Int64.( | |
| if x >= zero then to_float x else | |
| to_float (logor (shift_right_logical x 1) (logand x 1L)) *. 2.0 | |
| ) | |
| let reinterpret_i64 = F64.of_bits | |
| end |