diff --git a/stdlib/public/SDK/Foundation/Measurement.swift b/stdlib/public/SDK/Foundation/Measurement.swift index 77d5232bc8495..06d9dd5d00ba0 100644 --- a/stdlib/public/SDK/Foundation/Measurement.swift +++ b/stdlib/public/SDK/Foundation/Measurement.swift @@ -110,71 +110,6 @@ extension Measurement where UnitType : Dimension { return Measurement(value: lhsValueInTermsOfBase - rhsValueInTermsOfBase, unit: type(of: lhs.unit).baseUnit()) } } - - /// Compare two measurements of the same `Dimension`. - /// - /// If `lhs.unit == rhs.unit`, returns `lhs.value == rhs.value`. Otherwise, converts `rhs` to the same unit as `lhs` and then compares the resulting values. - /// - returns: `true` if the measurements are equal. - public static func ==(lhs: Measurement, rhs: Measurement) -> Bool { - if lhs.unit == rhs.unit { - return lhs.value == rhs.value - } else { - let rhsInLhs = rhs.converted(to: lhs.unit) - return lhs.value == rhsInLhs.value - } - } - - /// Compare two measurements of the same `Dimension`. - /// - /// If `lhs.unit == rhs.unit`, returns `lhs.value < rhs.value`. Otherwise, converts `rhs` to the same unit as `lhs` and then compares the resulting values. - /// - returns: `true` if `lhs` is less than `rhs`. - public static func <(lhs: Measurement, rhs: Measurement) -> Bool { - if lhs.unit == rhs.unit { - return lhs.value < rhs.value - } else { - let rhsInLhs = rhs.converted(to: lhs.unit) - return lhs.value < rhsInLhs.value - } - } - - /// Compare two measurements of the same `Dimension`. - /// - /// If `lhs.unit == rhs.unit`, returns `lhs.value > rhs.value`. Otherwise, converts `rhs` to the same unit as `lhs` and then compares the resulting values. - /// - returns: `true` if `lhs` is greater than `rhs`. - public static func >(lhs: Measurement, rhs: Measurement) -> Bool { - if lhs.unit == rhs.unit { - return lhs.value > rhs.value - } else { - let rhsInLhs = rhs.converted(to: lhs.unit) - return lhs.value > rhsInLhs.value - } - } - - /// Compare two measurements of the same `Dimension`. - /// - /// If `lhs.unit == rhs.unit`, returns `lhs.value < rhs.value`. Otherwise, converts `rhs` to the same unit as `lhs` and then compares the resulting values. - /// - returns: `true` if `lhs` is less than or equal to `rhs`. - public static func <=(lhs: Measurement, rhs: Measurement) -> Bool { - if lhs.unit == rhs.unit { - return lhs.value <= rhs.value - } else { - let rhsInLhs = rhs.converted(to: lhs.unit) - return lhs.value <= rhsInLhs.value - } - } - - /// Compare two measurements of the same `Dimension`. - /// - /// If `lhs.unit == rhs.unit`, returns `lhs.value >= rhs.value`. Otherwise, converts `rhs` to the same unit as `lhs` and then compares the resulting values. - /// - returns: `true` if `lhs` is greater or equal to `rhs`. - public static func >=(lhs: Measurement, rhs: Measurement) -> Bool { - if lhs.unit == rhs.unit { - return lhs.value >= rhs.value - } else { - let rhsInLhs = rhs.converted(to: lhs.unit) - return lhs.value >= rhsInLhs.value - } - } } @available(OSX 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *) @@ -225,38 +160,42 @@ extension Measurement { return Measurement(value: lhs / rhs.value, unit: rhs.unit) } - /// Compare two measurements of the same `Unit`. - /// - returns: `true` if `lhs.value == rhs.value && lhs.unit == rhs.unit`. - public static func ==(lhs: Measurement, rhs: Measurement) -> Bool { - return lhs.value == rhs.value && lhs.unit == rhs.unit - } - - /// Compare two measurements of the same `Unit`. - /// - note: This function does not check `==` for the `unit` property of `lhs` and `rhs`. - /// - returns: `lhs.value < rhs.value` - public static func <(lhs: Measurement, rhs: Measurement) -> Bool { - return lhs.value < rhs.value - } - - /// Compare two measurements of the same `Unit`. - /// - note: This function does not check `==` for the `unit` property of `lhs` and `rhs`. - /// - returns: `lhs.value > rhs.value` - public static func >(lhs: Measurement, rhs: Measurement) -> Bool { - return lhs.value > rhs.value - } - - /// Compare two measurements of the same `Unit`. - /// - note: This function does not check `==` for the `unit` property of `lhs` and `rhs`. - /// - returns: `lhs.value <= rhs.value` - public static func <=(lhs: Measurement, rhs: Measurement) -> Bool { - return lhs.value <= rhs.value + /// Compare two measurements of the same `Dimension`. + /// + /// If `lhs.unit == rhs.unit`, returns `lhs.value == rhs.value`. Otherwise, converts `rhs` to the same unit as `lhs` and then compares the resulting values. + /// - returns: `true` if the measurements are equal. + public static func ==(_ lhs: Measurement, _ rhs: Measurement) -> Bool { + if lhs.unit == rhs.unit { + return lhs.value == rhs.value + } else { + if let lhsDimensionalUnit = lhs.unit as? Dimension, + let rhsDimensionalUnit = rhs.unit as? Dimension { + if type(of: lhsDimensionalUnit).baseUnit() == type(of: rhsDimensionalUnit).baseUnit() { + let lhsValueInTermsOfBase = lhsDimensionalUnit.converter.baseUnitValue(fromValue: lhs.value) + let rhsValueInTermsOfBase = rhsDimensionalUnit.converter.baseUnitValue(fromValue: rhs.value) + return lhsValueInTermsOfBase == rhsValueInTermsOfBase + } + } + return false + } } /// Compare two measurements of the same `Unit`. - /// - note: This function does not check `==` for the `unit` property of `lhs` and `rhs`. - /// - returns: `lhs.value >= rhs.value` - public static func >=(lhs: Measurement, rhs: Measurement) -> Bool { - return lhs.value >= rhs.value + /// - returns: `true` if the measurements can be compared and the `lhs` is less than the `rhs` converted value. + public static func <(lhs: Measurement, rhs: Measurement) -> Bool { + if lhs.unit == rhs.unit { + return lhs.value < rhs.value + } else { + if let lhsDimensionalUnit = lhs.unit as? Dimension, + let rhsDimensionalUnit = rhs.unit as? Dimension { + if type(of: lhsDimensionalUnit).baseUnit() == type(of: rhsDimensionalUnit).baseUnit() { + let lhsValueInTermsOfBase = lhsDimensionalUnit.converter.baseUnitValue(fromValue: lhs.value) + let rhsValueInTermsOfBase = rhsDimensionalUnit.converter.baseUnitValue(fromValue: rhs.value) + return lhsValueInTermsOfBase < rhsValueInTermsOfBase + } + } + fatalError("Attempt to compare measurements with non-equal dimensions") + } } } diff --git a/test/1_stdlib/TestMeasurement.swift b/test/1_stdlib/TestMeasurement.swift index 600edc4d8536d..f4653ddc25cc2 100644 --- a/test/1_stdlib/TestMeasurement.swift +++ b/test/1_stdlib/TestMeasurement.swift @@ -126,6 +126,27 @@ class TestMeasurement : TestMeasurementSuper { // Just make sure we get a result at all here expectFalse(result.isEmpty) } + + func testEquality() { + let fiveKM = Measurement(value: 5, unit: UnitLength.kilometers) + let fiveSeconds = Measurement(value: 5, unit: UnitDuration.seconds) + let fiveThousandM = Measurement(value: 5000, unit: UnitLength.meters) + + expectTrue(fiveKM == fiveThousandM) + expectEqual(fiveKM, fiveThousandM) + expectFalse(fiveKM == fiveSeconds) + } + + func testComparison() { + let fiveKM = Measurement(value: 5, unit: UnitLength.kilometers) + let fiveThousandM = Measurement(value: 5000, unit: UnitLength.meters) + let sixKM = Measurement(value: 6, unit: UnitLength.kilometers) + let sevenThousandM = Measurement(value: 7000, unit: UnitLength.meters) + + expectTrue(fiveKM < sixKM) + expectTrue(fiveKM < sevenThousandM) + expectTrue(fiveKM <= fiveThousandM) + } } #if !FOUNDATION_XCTEST @@ -136,6 +157,8 @@ if #available(OSX 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *) { MeasurementTests.test("testOperators") { TestMeasurement().testOperators() } MeasurementTests.test("testUnits") { TestMeasurement().testUnits() } MeasurementTests.test("testMeasurementFormatter") { TestMeasurement().testMeasurementFormatter() } + MeasurementTests.test("testEquality") { TestMeasurement().testEquality() } + MeasurementTests.test("testComparison") { TestMeasurement().testComparison() } runAllTests() } #endif