/
Rate.swift
141 lines (116 loc) · 5.21 KB
/
Rate.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
import Foundation
/**
A ratio of two related quantities,
expressed in terms of an amount of numerator unit per single denominator unit.
*/
@available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
public struct Rate<Numerator, Denominator> where Numerator: Unit, Denominator: Unit {
/// The value of the numerator unit per single denominator unit.
public var value: Double
/// The numerator unit.
public var numeratorUnit: Numerator
/// The denominator unit.
public var denominatorUnit: Denominator
/// The rate symbol.
public var symbol: String {
return "\(self.numeratorUnit.symbol)/\(self.denominatorUnit.symbol)"
}
/**
Creates a new rate from a value,
and specified numerator and denominator units.
- Parameters:
- value: The value of the numerator unit per single denominator unit.
- unit: The numerator unit.
- per: The denominator unit.
*/
public init(value: Double, unit numeratorUnit: Numerator, per denominatorUnit: Denominator) {
self.value = value
self.numeratorUnit = numeratorUnit
self.denominatorUnit = denominatorUnit
}
/**
Creates a new rate from specified numerator and denominator measurements.
- Parameters:
- numerator: The numerator measurement.
- denominator: The denominator measurement.
- Precondition: The value of `denominator` must be greater than 0.
*/
public init(_ numerator: Measurement<Numerator>, per denominator: Measurement<Denominator>) {
precondition(denominator.value > 0)
let value = numerator.value / denominator.value
self.init(value: value, unit: numerator.unit, per: denominator.unit)
}
/**
Returns the product of the rate multiplied by the specified value.
- Parameters:
- by: The value to multiply the rate by.
*/
public func multiplied(by scalar: Double) -> Rate<Numerator, Denominator> {
return .init(value: self.value * scalar, unit: self.numeratorUnit, per: self.denominatorUnit)
}
/**
Returns the quotient of the rate divided by the specified value.
- Parameters:
- by: The value to divide the rate by.
*/
public func divided(by scalar: Double) -> Rate<Numerator, Denominator> {
return .init(value: self.value / scalar, unit: self.numeratorUnit, per: self.denominatorUnit)
}
}
@available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
extension Rate where Numerator: Dimension, Denominator: Dimension {
/**
Returns the sum of this rate and the specified rate.
- Parameters:
- rate: The rate to add to this rate.
*/
public func adding(_ rate: Rate<Numerator, Denominator>) -> Rate<Numerator, Denominator> {
return .init(value: self.value + self.numeratorUnit.converter.value(fromBaseUnitValue: rate.numeratorUnit.converter.baseUnitValue(fromValue: rate.value)), unit: self.numeratorUnit, per: self.denominatorUnit)
}
/**
Returns the difference between this rate and the specified rate.
- Parameters:
- rate: The rate to add to this rate.
*/
public func subtracting(_ rate: Rate<Numerator, Denominator>) -> Rate<Numerator, Denominator> {
return .init(value: self.value - self.numeratorUnit.converter.value(fromBaseUnitValue: rate.numeratorUnit.converter.baseUnitValue(fromValue: rate.value)), unit: self.numeratorUnit, per: self.denominatorUnit)
}
/**
Returns the product of this rate multiplied by the specified measurement.
- Parameters:
- by: The measurement to multiply this rate by.
*/
public func multiplied(by measurement: Measurement<Denominator>) -> Measurement<Numerator> {
return .init(value: Measurement(value: self.value, unit: measurement.unit).converted(to: self.denominatorUnit).value * measurement.value, unit: self.numeratorUnit)
}
}
@available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
extension Rate: CustomStringConvertible {
public var description: String {
return "\(self.value) \(self.symbol)"
}
}
@available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
public func + <T, U>(lhs: Rate<T,U>, rhs: Rate<T,U>) -> Rate<T,U> where T: Dimension, U: Dimension {
return lhs.adding(rhs)
}
@available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
public func - <T, U>(lhs: Rate<T,U>, rhs: Rate<T,U>) -> Rate<T,U> where T: Dimension, U: Dimension {
return lhs.subtracting(rhs)
}
@available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
public func * <T, U>(lhs: Rate<T,U>, rhs: Double) -> Rate<T,U> where T: Dimension, U: Dimension {
return lhs.multiplied(by: rhs)
}
@available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
public func / <T, U>(lhs: Rate<T,U>, rhs: Double) -> Rate<T,U> where T: Dimension, U: Dimension {
return lhs.divided(by: rhs)
}
@available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
public func * <T, U>(lhs: Rate<T,U>, rhs: Measurement<U>) -> Measurement<T> where T: Dimension, U: Dimension {
return lhs.multiplied(by: rhs)
}
@available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
public func * <T, U>(lhs: Measurement<U>, rhs: Rate<T,U>) -> Measurement<T> where T: Dimension, U: Dimension {
return rhs.multiplied(by: lhs)
}