Skip to content

[gardening][Measurement] Move operators into types #1349

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 30, 2017
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
288 changes: 158 additions & 130 deletions Foundation/Measurement.swift
Original file line number Diff line number Diff line change
Expand Up @@ -72,176 +72,204 @@ extension Measurement where UnitType : Dimension {

}

/// Add two measurements of the same Unit.
/// - precondition: The `unit` of `lhs` and `rhs` must be `isEqual`.
/// - returns: A measurement of value `lhs.value + rhs.value` and unit `lhs.unit`.
public func +<UnitType>(lhs: Measurement<UnitType>, rhs: Measurement<UnitType>) -> Measurement<UnitType> {
if lhs.unit.isEqual(rhs.unit) {
return Measurement(value: lhs.value + rhs.value, unit: lhs.unit)
} else {
fatalError("Attempt to add measurements with non-equal units")
extension Measurement {
/// Add two measurements of the same Unit.
/// - precondition: The `unit` of `lhs` and `rhs` must be `isEqual`.
/// - returns: A measurement of value `lhs.value + rhs.value` and unit `lhs.unit`.
public static func +(lhs: Measurement<UnitType>, rhs: Measurement<UnitType>) -> Measurement<UnitType> {
if lhs.unit.isEqual(rhs.unit) {
return Measurement(value: lhs.value + rhs.value, unit: lhs.unit)
} else {
fatalError("Attempt to add measurements with non-equal units")
}
}
}

/// Add two measurements of the same Dimension.
///
/// If the `unit` of the `lhs` and `rhs` are `isEqual`, then this returns the result of adding the `value` of each `Measurement`. If they are not equal, then this will convert both to the base unit of the `Dimension` and return the result as a `Measurement` of that base unit.
/// - returns: The result of adding the two measurements.
public func +<UnitType : Dimension>(lhs: Measurement<UnitType>, rhs: Measurement<UnitType>) -> Measurement<UnitType> {
if lhs.unit.isEqual(rhs.unit) {
return Measurement(value: lhs.value + rhs.value, unit: lhs.unit)
} else {
let lhsValueInTermsOfBase = lhs.unit.converter.baseUnitValue(fromValue: lhs.value)
let rhsValueInTermsOfBase = rhs.unit.converter.baseUnitValue(fromValue: rhs.value)
return Measurement(value: lhsValueInTermsOfBase + rhsValueInTermsOfBase, unit: type(of: lhs.unit).baseUnit())
extension Measurement where UnitType : Dimension {
/// Add two measurements of the same Dimension.
///
/// If the `unit` of the `lhs` and `rhs` are `isEqual`, then this returns the result of adding the `value` of each `Measurement`. If they are not equal, then this will convert both to the base unit of the `Dimension` and return the result as a `Measurement` of that base unit.
/// - returns: The result of adding the two measurements.
public static func +(lhs: Measurement<UnitType>, rhs: Measurement<UnitType>) -> Measurement<UnitType> {
if lhs.unit.isEqual(rhs.unit) {
return Measurement(value: lhs.value + rhs.value, unit: lhs.unit)
} else {
let lhsValueInTermsOfBase = lhs.unit.converter.baseUnitValue(fromValue: lhs.value)
let rhsValueInTermsOfBase = rhs.unit.converter.baseUnitValue(fromValue: rhs.value)
return Measurement(value: lhsValueInTermsOfBase + rhsValueInTermsOfBase, unit: type(of: lhs.unit).baseUnit())
}
}
}

/// Subtract two measurements of the same Unit.
/// - precondition: The `unit` of `lhs` and `rhs` must be `isEqual`.
/// - returns: A measurement of value `lhs.value - rhs.value` and unit `lhs.unit`.
public func -<UnitType>(lhs: Measurement<UnitType>, rhs: Measurement<UnitType>) -> Measurement<UnitType> {
if lhs.unit.isEqual(rhs.unit) {
return Measurement(value: lhs.value - rhs.value, unit: lhs.unit)
} else {
fatalError("Attempt to subtract measurements with non-equal units")
extension Measurement {
/// Subtract two measurements of the same Unit.
/// - precondition: The `unit` of `lhs` and `rhs` must be `isEqual`.
/// - returns: A measurement of value `lhs.value - rhs.value` and unit `lhs.unit`.
public static func -(lhs: Measurement<UnitType>, rhs: Measurement<UnitType>) -> Measurement<UnitType> {
if lhs.unit.isEqual(rhs.unit) {
return Measurement(value: lhs.value - rhs.value, unit: lhs.unit)
} else {
fatalError("Attempt to subtract measurements with non-equal units")
}
}
}

/// Subtract two measurements of the same Dimension.
///
/// If the `unit` of the `lhs` and `rhs` are `==`, then this returns the result of subtracting the `value` of each `Measurement`. If they are not equal, then this will convert both to the base unit of the `Dimension` and return the result as a `Measurement` of that base unit.
/// - returns: The result of adding the two measurements.
public func -<UnitType : Dimension>(lhs: Measurement<UnitType>, rhs: Measurement<UnitType>) -> Measurement<UnitType> {
if lhs.unit == rhs.unit {
return Measurement(value: lhs.value - rhs.value, unit: lhs.unit)
} else {
let lhsValueInTermsOfBase = lhs.unit.converter.baseUnitValue(fromValue: lhs.value)
let rhsValueInTermsOfBase = rhs.unit.converter.baseUnitValue(fromValue: rhs.value)
return Measurement(value: lhsValueInTermsOfBase - rhsValueInTermsOfBase, unit: type(of: lhs.unit).baseUnit())
extension Measurement where UnitType : Dimension {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure that having a lot of new extensions is ideal. Could we move this inside the existing extension on line 47?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Every single method seems to be in its own extension although some are using a conditional conformance so this is consistent. However maybe a followup PR could merge them so there are only two extensions.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Every single method seems to be in its own extension although some are using a conditional conformance so this is consistent. However maybe a followup PR could merge them so there are only two extensions.

Yep I'm going to do that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK as long as this PR isn't the end then 👍

/// Subtract two measurements of the same Dimension.
///
/// If the `unit` of the `lhs` and `rhs` are `==`, then this returns the result of subtracting the `value` of each `Measurement`. If they are not equal, then this will convert both to the base unit of the `Dimension` and return the result as a `Measurement` of that base unit.
/// - returns: The result of adding the two measurements.
public static func -(lhs: Measurement<UnitType>, rhs: Measurement<UnitType>) -> Measurement<UnitType> {
if lhs.unit == rhs.unit {
return Measurement(value: lhs.value - rhs.value, unit: lhs.unit)
} else {
let lhsValueInTermsOfBase = lhs.unit.converter.baseUnitValue(fromValue: lhs.value)
let rhsValueInTermsOfBase = rhs.unit.converter.baseUnitValue(fromValue: rhs.value)
return Measurement(value: lhsValueInTermsOfBase - rhsValueInTermsOfBase, unit: type(of: lhs.unit).baseUnit())
}
}
}

/// Multiply a measurement by a scalar value.
/// - returns: A measurement of value `lhs.value * rhs` with the same unit as `lhs`.
public func *<UnitType>(lhs: Measurement<UnitType>, rhs: Double) -> Measurement<UnitType> {
return Measurement(value: lhs.value * rhs, unit: lhs.unit)
}

/// Multiply a scalar value by a measurement.
/// - returns: A measurement of value `lhs * rhs.value` with the same unit as `rhs`.
public func *<UnitType>(lhs: Double, rhs: Measurement<UnitType>) -> Measurement<UnitType> {
return Measurement(value: lhs * rhs.value, unit: rhs.unit)
}
extension Measurement {
/// Multiply a measurement by a scalar value.
/// - returns: A measurement of value `lhs.value * rhs` with the same unit as `lhs`.
public static func *(lhs: Measurement<UnitType>, rhs: Double) -> Measurement<UnitType> {
return Measurement(value: lhs.value * rhs, unit: lhs.unit)
}

/// Divide a measurement by a scalar value.
/// - returns: A measurement of value `lhs.value / rhs` with the same unit as `lhs`.
public func /<UnitType>(lhs: Measurement<UnitType>, rhs: Double) -> Measurement<UnitType> {
return Measurement(value: lhs.value / rhs, unit: lhs.unit)
}
/// Multiply a scalar value by a measurement.
/// - returns: A measurement of value `lhs * rhs.value` with the same unit as `rhs`.
public static func *(lhs: Double, rhs: Measurement<UnitType>) -> Measurement<UnitType> {
return Measurement(value: lhs * rhs.value, unit: rhs.unit)
}

/// Divide a scalar value by a measurement.
/// - returns: A measurement of value `lhs / rhs.value` with the same unit as `rhs`.
public func /<UnitType>(lhs: Double, rhs: Measurement<UnitType>) -> Measurement<UnitType> {
return Measurement(value: lhs / rhs.value, unit: rhs.unit)
}
/// Divide a measurement by a scalar value.
/// - returns: A measurement of value `lhs.value / rhs` with the same unit as `lhs`.
public static func /(lhs: Measurement<UnitType>, rhs: Double) -> Measurement<UnitType> {
return Measurement(value: lhs.value / rhs, unit: lhs.unit)
}

/// Compare two measurements of the same `Unit`.
/// - returns: `true` if `lhs.value == rhs.value && lhs.unit == rhs.unit`.
public func ==<UnitType>(lhs: Measurement<UnitType>, rhs: Measurement<UnitType>) -> Bool {
return lhs.value == rhs.value && lhs.unit == rhs.unit
}
/// Divide a scalar value by a measurement.
/// - returns: A measurement of value `lhs / rhs.value` with the same unit as `rhs`.
public static func /(lhs: Double, rhs: Measurement<UnitType>) -> Measurement<UnitType> {
return Measurement(value: lhs / rhs.value, unit: rhs.unit)
}

/// 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 func ==<UnitType : Dimension>(lhs: Measurement<UnitType>, rhs: Measurement<UnitType>) -> 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 `Unit`.
/// - returns: `true` if `lhs.value == rhs.value && lhs.unit == rhs.unit`.
public static func ==(lhs: Measurement<UnitType>, rhs: Measurement<UnitType>) -> 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 func <<UnitType>(lhs: Measurement<UnitType>, rhs: Measurement<UnitType>) -> Bool {
return lhs.value < rhs.value
extension Measurement where UnitType : Dimension {
/// 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<UnitType>, rhs: Measurement<UnitType>) -> 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 func <<UnitType : Dimension>(lhs: Measurement<UnitType>, rhs: Measurement<UnitType>) -> Bool {
if lhs.unit == rhs.unit {
extension Measurement {
/// 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<UnitType>, rhs: Measurement<UnitType>) -> Bool {
return lhs.value < rhs.value
} else {
let rhsInLhs = rhs.converted(to: lhs.unit)
return lhs.value < rhsInLhs.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 func ><UnitType>(lhs: Measurement<UnitType>, rhs: Measurement<UnitType>) -> Bool {
return lhs.value > rhs.value
extension Measurement where UnitType : Dimension {
/// 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<UnitType>, rhs: Measurement<UnitType>) -> 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 func ><UnitType : Dimension>(lhs: Measurement<UnitType>, rhs: Measurement<UnitType>) -> Bool {
if lhs.unit == rhs.unit {
extension Measurement {
/// 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<UnitType>, rhs: Measurement<UnitType>) -> Bool {
return lhs.value > rhs.value
} else {
let rhsInLhs = rhs.converted(to: lhs.unit)
return lhs.value > rhsInLhs.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 func <=<UnitType>(lhs: Measurement<UnitType>, rhs: Measurement<UnitType>) -> Bool {
return lhs.value <= rhs.value
extension Measurement where UnitType : Dimension {
/// 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<UnitType>, rhs: Measurement<UnitType>) -> 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 func <=<UnitType : Dimension>(lhs: Measurement<UnitType>, rhs: Measurement<UnitType>) -> Bool {
if lhs.unit == rhs.unit {
extension Measurement {
/// 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<UnitType>, rhs: Measurement<UnitType>) -> Bool {
return lhs.value <= rhs.value
} else {
let rhsInLhs = rhs.converted(to: lhs.unit)
return lhs.value <= rhsInLhs.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 func >=<UnitType>(lhs: Measurement<UnitType>, rhs: Measurement<UnitType>) -> Bool {
return lhs.value >= rhs.value
extension Measurement where UnitType : Dimension {
/// 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<UnitType>, rhs: Measurement<UnitType>) -> 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 func >=<UnitType : Dimension>(lhs: Measurement<UnitType>, rhs: Measurement<UnitType>) -> Bool {
if lhs.unit == rhs.unit {
extension Measurement {
/// 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<UnitType>, rhs: Measurement<UnitType>) -> Bool {
return lhs.value >= rhs.value
} else {
let rhsInLhs = rhs.converted(to: lhs.unit)
return lhs.value >= rhsInLhs.value
}
}

extension Measurement where UnitType : Dimension {
/// 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<UnitType>, rhs: Measurement<UnitType>) -> Bool {
if lhs.unit == rhs.unit {
return lhs.value >= rhs.value
} else {
let rhsInLhs = rhs.converted(to: lhs.unit)
return lhs.value >= rhsInLhs.value
}
}
}

Expand Down