import StdlibUnittest %{ import gyb from SwiftFloatingPointTypes import all_floating_point_types, getFtoIBounds from SwiftIntTypes import all_integer_types }% var FixedPointConversionTruncations = TestSuite("FixedPointToFloatingPointConversionTruncations") var FixedPointConversionFailures = TestSuite("FixedPointToFloatingPointConversionFailures") var FloatingPointConversionTruncations = TestSuite("FloatingPointToFloatingPointConversionTruncations") var FloatingPointConversionFailures = TestSuite("FloatingPointToFloatingPointConversionFailures") % for self_type in all_floating_point_types(): % SelfSignificandBits = self_type.bits % Self = self_type.stdlib_name % if Self == 'Float16': #if !os(macOS) && !(os(iOS) && targetEnvironment(macCatalyst)) % end % if Self == 'Float80': #if !os(Windows) && (arch(i386) || arch(x86_64)) % end % for other_type in all_floating_point_types(): % OtherSignificandBits = other_type.bits % OtherFloat = other_type.stdlib_name % if OtherFloat == 'Float16': #if !os(macOS) && !(os(iOS) && targetEnvironment(macCatalyst)) % end % if OtherFloat == 'Float80': #if !os(Windows) && (arch(i386) || arch(x86_64)) % end % if OtherSignificandBits <= SelfSignificandBits: % if OtherFloat == 'Float16': if #available(iOS 14.0, watchOS 7.0, tvOS 14.0, *) { % end FloatingPointConversionTruncations.test("${OtherFloat}To${Self}Conversion") .forEach(in: [ ${OtherFloat}.greatestFiniteMagnitude, -${OtherFloat}.greatestFiniteMagnitude, (1.0 as ${OtherFloat}).nextUp, (1.0 as ${OtherFloat}).nextDown, (-1.0 as ${OtherFloat}).nextUp, (-1.0 as ${OtherFloat}).nextDown, ]) { input in // FIXME: we should have a stronger postcondition here. let result = ${Self}(input) let resultConvertedBack = ${OtherFloat}(result) expectEqual(input, resultConvertedBack) } % if OtherFloat == 'Float16': } % end % else: % if Self == 'Float16': if #available(iOS 14.0, watchOS 7.0, tvOS 14.0, *) { % end FloatingPointConversionTruncations.test("${OtherFloat}To${Self}Conversion") .forEach(in: [ ( ${OtherFloat}.greatestFiniteMagnitude, ${Self}.infinity), (-${OtherFloat}.greatestFiniteMagnitude, -${Self}.infinity), ( (1.0 as ${OtherFloat}).nextUp, 1.0 as ${Self}), ( (1.0 as ${OtherFloat}).nextDown, 1.0 as ${Self}), ((-1.0 as ${OtherFloat}).nextUp, -1.0 as ${Self}), ((-1.0 as ${OtherFloat}).nextDown, -1.0 as ${Self}), ]) { (input, expectedResult) in expectEqual(expectedResult, ${Self}(input)) } % if Self == 'Float16': } % end % end % if 'Float16' in [Self, OtherFloat]: if #available(iOS 14.0, watchOS 7.0, tvOS 14.0, *) { % end FloatingPointConversionTruncations.test("${OtherFloat}To${Self}Conversion/special") { expectEqual( 1.0 as ${Self}, ${Self}(exactly: 1.0 as ${OtherFloat})) expectEqual(-1.0 as ${Self}, ${Self}(exactly: -1.0 as ${OtherFloat})) expectEqual( ${Self}.infinity, ${Self}( ${OtherFloat}.infinity)) expectEqual(-${Self}.infinity, ${Self}(-${OtherFloat}.infinity)) expectTrue(${Self}(${OtherFloat}.nan).isNaN) } FloatingPointConversionFailures.test("${OtherFloat}To${Self}FailableConversion") .forEach(in: [ ${OtherFloat}.greatestFiniteMagnitude, -${OtherFloat}.greatestFiniteMagnitude, (1.0 as ${OtherFloat}).nextUp, (1.0 as ${OtherFloat}).nextDown, (-1.0 as ${OtherFloat}).nextUp, (-1.0 as ${OtherFloat}).nextDown, ]) { input in let result = ${Self}(exactly: input) % if OtherSignificandBits <= SelfSignificandBits: if let result = expectNotNil(result) { // FIXME: we should have a stronger postcondition here. expectEqual(input, ${OtherFloat}(result)) } % else: expectNil(result) % end } FloatingPointConversionFailures.test("${OtherFloat}To${Self}Conversion/AlwaysSuccess") { expectEqual( 1.0 as ${Self}, ${Self}(exactly: 1.0 as ${OtherFloat})) expectEqual(-1.0 as ${Self}, ${Self}(exactly: -1.0 as ${OtherFloat})) expectEqual( ${Self}.infinity, ${Self}(exactly: ${OtherFloat}.infinity)) expectEqual(-${Self}.infinity, ${Self}(exactly: -${OtherFloat}.infinity)) expectNil(${Self}(exactly: ${OtherFloat}.nan)) } % if 'Float16' in [Self, OtherFloat]: } % end % if OtherFloat == 'Float16': #endif % end % if OtherFloat == 'Float80': #endif % end % end # for in all_floating_point_types (Other) #if _pointerBitWidth(_32) % int_types = all_integer_types(32) #elseif _pointerBitWidth(_64) % int_types = all_integer_types(64) #else _UnimplementedError() #endif % for int_ty in int_types: % OtherInt = int_ty.stdlib_name extension ${OtherInt} { % if Self == 'Float16': @available(iOS 14.0, watchOS 7.0, tvOS 14.0, *) @available(macOS, unavailable) % end static var _test${Self}Conversion: [(${OtherInt}, ${OtherInt}, ${OtherInt}?)] { if bitWidth > ${Self}.significandBitCount + 1 { let bitOffset = ${Self}.significandBitCount + 1 let limit: ${OtherInt} = ~(~0 << bitOffset) let over: ${OtherInt} = 1 + limit << 1 return [ (0, 0, 0), (limit, limit, limit), (over, over + 1, nil), % if int_ty.is_signed: (-limit, -limit, -limit), (-over, -(over + 1), nil), % end ] } else { return [ (0, 0, 0), (.min, .min, .min), (.max, .max, .max), ] } } } % if Self == 'Float16': if #available(iOS 14.0, watchOS 7.0, tvOS 14.0, *) { % end FixedPointConversionTruncations.test("${OtherInt}to${Self}") .forEach(in: ${OtherInt}._test${Self}Conversion) { value, roundedExpectation, exactExpectation in let roundedResult = ${Self}(value) expectEqual(roundedResult, ${Self}(roundedExpectation)) let exactResult = ${Self}(exactly: value) if let expectation = exactExpectation { expectEqual(exactResult!, ${Self}(expectation)) } else { expectNil(exactResult) } } % if Self == 'Float16': } % end % end # for in int_types % if Self == 'Float16': #endif % end % if Self == 'Float80': #endif % end % end # for in all_floating_point_types (Self) runAllTests()