| // RUN: rm -rf %t |
| // RUN: mkdir -p %t |
| // RUN: %gyb %s -o %t/FloatingPointConversion.swift |
| // RUN: %line-directive %t/FloatingPointConversion.swift -- %target-build-swift %t/FloatingPointConversion.swift -Xfrontend -disable-access-control -o %t/a.out_Debug |
| // RUN: %line-directive %t/FloatingPointConversion.swift -- %target-build-swift %t/FloatingPointConversion.swift -Xfrontend -disable-access-control -o %t/a.out_Release -O |
| // |
| // RUN: %line-directive %t/FloatingPointConversion.swift -- %target-run %t/a.out_Debug |
| // RUN: %line-directive %t/FloatingPointConversion.swift -- %target-run %t/a.out_Release |
| // REQUIRES: executable_test |
| |
| 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 == '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 == 'Float80': |
| #if !os(Windows) && (arch(i386) || arch(x86_64)) |
| % end |
| |
| % if OtherSignificandBits <= SelfSignificandBits: |
| |
| 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) |
| } |
| |
| % else: |
| |
| 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)) |
| } |
| |
| % 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 OtherFloat == 'Float80': |
| #endif |
| % end |
| |
| % end # for in all_floating_point_types (Other) |
| |
| %{ |
| |
| float_to_int_conversion_template = gyb.parse_template("float_to_int_conversion", |
| """ |
| % for int_ty in all_integer_types(word_bits): |
| % OtherInt = int_ty.stdlib_name |
| % OtherMin = int_ty.min |
| % OtherMax = int_ty.max |
| % (FloatMin, FloatMax) = getFtoIBounds(self_type.bits, int_ty.bits, int_ty.is_signed) |
| |
| % for testValue in [0, FloatMin, FloatMax, FloatMin - 1, FloatMax + 1, OtherMin, OtherMax]: |
| |
| % if testValue < OtherMin or testValue > OtherMax: |
| % # Can't construct `other` value, do nothing and continue. |
| |
| % elif testValue >= FloatMin and testValue <= FloatMax: |
| |
| FixedPointConversionTruncations.test("${OtherInt}to${Self}Conversion/${testValue}") { |
| expectEqual(${Self}(${testValue} as ${OtherInt}), ${testValue}) |
| } |
| |
| FixedPointConversionFailures.test("${OtherInt}to${Self}FailableConversion/${testValue}") { |
| expectEqual(${Self}(exactly: ${testValue} as ${OtherInt}), ${testValue}) |
| } |
| |
| % else: |
| |
| FixedPointConversionTruncations.test("${OtherInt}to${Self}Truncation/${testValue}") { |
| let value: ${OtherInt} = ${testValue} |
| let result = ${Self}(value) |
| expectNotEqual(${OtherInt}(result), value) |
| } |
| |
| FixedPointConversionFailures.test("${OtherInt}to${Self}Failure/${testValue}") { |
| let value: ${OtherInt} = ${testValue} |
| let result = ${Self}(exactly: value) |
| expectEqual(result, ${OtherMin} as ${Self}) |
| expectEqual(${OtherInt}(result!), value) |
| } |
| |
| % end |
| |
| % end # testValue in testValues |
| % end # for in all_integer_types (Other) |
| """) |
| }% |
| |
| #if arch(i386) || arch(arm) |
| |
| ${gyb.execute_template( |
| float_to_int_conversion_template, |
| word_bits=32, |
| **locals() |
| )} |
| |
| #elseif arch(x86_64) || arch(arm64) || arch(powerpc64) || arch(powerpc64le) || arch(s390x) |
| |
| ${gyb.execute_template( |
| float_to_int_conversion_template, |
| word_bits=64, |
| **locals() |
| )} |
| |
| #else |
| |
| _UnimplementedError() |
| |
| #endif |
| |
| % if Self == 'Float80': |
| #endif |
| % end |
| |
| % end # for in all_floating_point_types (Self) |
| |
| runAllTests() |