├── .editorconfig ├── .gitignore ├── LICENSE ├── Package.swift ├── README.md ├── Sources └── SwiftMeasurement │ ├── DimensionalSystem │ ├── DimensionalExponents.swift │ ├── DimensionalMeasurement.swift │ └── DimensionalUnit.swift │ ├── Measurement+Extensions.swift │ ├── MeasurementConvertible.swift │ └── Units │ ├── UnitAcceleration.swift │ ├── UnitAngle.swift │ ├── UnitArea.swift │ ├── UnitConcentrationMass.swift │ ├── UnitDispersion.swift │ ├── UnitDuration.swift │ ├── UnitElectricCharge.swift │ ├── UnitElectricCurrent.swift │ ├── UnitElectricPotentialDifference.swift │ ├── UnitElectricResistance.swift │ ├── UnitEnergy.swift │ ├── UnitFrequency.swift │ ├── UnitFuelEfficiency.swift │ ├── UnitIlluminance.swift │ ├── UnitInformationStorage.swift │ ├── UnitLength.swift │ ├── UnitMass.swift │ ├── UnitPower.swift │ ├── UnitPressure.swift │ ├── UnitSpeed.swift │ ├── UnitTemperature.swift │ └── UnitVolume.swift └── Tests └── SwiftMeasurementTests ├── DimensionalSystemTests.swift ├── Measurement+ExtensionsTests.swift ├── SwiftMeasurementTests.swift └── Units ├── UnitAccelerationTests.swift ├── UnitAngleTests.swift ├── UnitAreaTests.swift ├── UnitConcentrationMassTests.swift ├── UnitDispersionTests.swift ├── UnitDurationTests.swift ├── UnitElectricChargeTests.swift ├── UnitElectricCurrentTests.swift ├── UnitElectricPotentialDifferenceTests.swift ├── UnitElectricResistanceTests.swift ├── UnitEnergyTests.swift ├── UnitFrequencyTests.swift ├── UnitFuelEfficiencyTests.swift ├── UnitIlluminanceTests.swift ├── UnitInformationStorageTests.swift ├── UnitLengthTests.swift ├── UnitMassTests.swift ├── UnitPowerTests.swift ├── UnitPressureTests.swift ├── UnitSpeedTests.swift ├── UnitTemperatureTests.swift └── UnitVolumeTests.swift /.editorconfig: -------------------------------------------------------------------------------- 1 | # https://editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | end_of_line = lf 7 | insert_final_newline = true 8 | trim_trailing_whitespace = true 9 | 10 | [*.swift] 11 | indent_style = space 12 | indent_size = 4 13 | tab_width = 4 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | # Xcode 4 | 5 | ## User settings 6 | xcuserdata/ 7 | 8 | ## Obj-C/Swift specific 9 | *.hmap 10 | 11 | ## App packaging 12 | *.ipa 13 | *.dSYM.zip 14 | *.dSYM 15 | 16 | ## Playgrounds 17 | timeline.xctimeline 18 | playground.xcworkspace 19 | 20 | # Swift Package Manager 21 | # 22 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 23 | # Packages/ 24 | # Package.pins 25 | # Package.resolved 26 | # *.xcodeproj 27 | # 28 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata 29 | # hence it is not needed unless you have added a package configuration file to your project 30 | .swiftpm 31 | 32 | .build/ 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2021 Ken Tominaga 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.10 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "SwiftMeasurement", 7 | 8 | platforms: [ 9 | .macOS(.v14), 10 | .iOS(.v17), 11 | .tvOS(.v17), 12 | .watchOS(.v10), 13 | .visionOS(.v1) 14 | ], 15 | 16 | products: [ 17 | .library( 18 | name: "SwiftMeasurement", 19 | targets: [ 20 | "SwiftMeasurement", 21 | ] 22 | ), 23 | ], 24 | 25 | targets: [ 26 | .target( 27 | name: "SwiftMeasurement" 28 | ), 29 | 30 | .testTarget( 31 | name: "SwiftMeasurementTests", 32 | dependencies: [ 33 | "SwiftMeasurement", 34 | ] 35 | ), 36 | ] 37 | ) 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SwiftMeasurement 2 | 3 | The best way to deal with Measurements and Units in Swift. 4 | 5 | Measurements and Units are introduced in iOS 10. 6 | * [Measurements and Units - WWDC 2016 - Videos - Apple Developer](https://developer.apple.com/videos/play/wwdc2016/238/) 7 | 8 | ## Features 9 | 10 | - Support for all units declared in the Foundation framework 11 | - Easy conversion between different units 12 | - Simple and intuitive API for working with measurements 13 | - **Dimensional Analysis System** for type-safe calculations between different units 14 | - **Automatic dimensional tracking** for operations like speed × time = distance 15 | - **Math operations** for physical quantities with different dimensions 16 | - **Smart conversion system** that understands physical relationships 17 | 18 | ## Usage 19 | 20 | ### Basic Operations 21 | 22 | - before 23 | ```swift 24 | Measurement(value: 3, unit: .kilometers) + Measurement(value: 4, unit: .kilometers) 25 | ``` 26 | 27 | - after 28 | ```swift 29 | 3.kilometers + 4.kilometers 30 | ``` 31 | 32 | ### Dimensional Calculations 33 | 34 | ```swift 35 | // Speed × Duration = Length 36 | let speed = 60.0.kilometersPerHour 37 | let time = 2.5.hours 38 | let distance = speed * time // returns an AnyMeasurement 39 | 40 | // Convert to a specific measurement type 41 | if let distanceInKm = distance.asLength?.converted(to: .kilometers) { 42 | print("Distance: \(distanceInKm)") // 150.0 km 43 | } 44 | 45 | // Length × Length = Area 46 | let length = 10.0.meters 47 | let width = 5.0.meters 48 | let area = length * width 49 | 50 | if let areaInSqM = area.asArea?.converted(to: .squareMeters) { 51 | print("Area: \(areaInSqM)") // 50.0 m² 52 | } 53 | ``` 54 | 55 | ## Installation 56 | 57 | ### Swift Package Manager (Recommended) 58 | 59 | The [Swift Package Manager](https://swift.org/package-manager/) is the recommended way to add SwiftMeasurement to your project. 60 | 61 | 1. In Xcode, select File > Add Package Dependencies... 62 | 2. Enter the repository URL: `https://github.com/ken0nek/SwiftMeasurement.git` 63 | 3. Select "Up to Next Major Version" with the current version 64 | 4. Click "Add Package" 65 | 66 | You can also add SwiftMeasurement as a dependency directly in your `Package.swift` file: 67 | 68 | ```swift 69 | dependencies: [ 70 | .package(url: "https://github.com/ken0nek/SwiftMeasurement.git", from: "2.0.0") 71 | ] 72 | ``` 73 | 74 | Then add the dependency to your target: 75 | 76 | ```swift 77 | .target( 78 | name: "YourTarget", 79 | dependencies: ["SwiftMeasurement"] 80 | ) 81 | ``` 82 | 83 | ### Swift Package Manager (Command Line) 84 | 85 | You can also add SwiftMeasurement using the Swift Package Manager command line: 86 | 87 | ```bash 88 | swift package add-dependency https://github.com/ken0nek/SwiftMeasurement.git 89 | ``` 90 | 91 | ## License 92 | 93 | SwiftMeasurement is available under the MIT license. See the LICENSE file for more info. 94 | -------------------------------------------------------------------------------- /Sources/SwiftMeasurement/DimensionalSystem/DimensionalExponents.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// Represents dimensional exponents for physical quantities based on SI units 4 | public struct DimensionalExponents: Equatable, Hashable { 5 | // Base SI dimensions 6 | public var length: Int // L (meter) 7 | public var time: Int // T (second) 8 | public var mass: Int // M (kilogram) 9 | public var current: Int // I (ampere) 10 | public var temperature: Int // Θ (kelvin) 11 | public var amount: Int // N (mole) 12 | public var luminosity: Int // J (candela) 13 | 14 | public init( 15 | length: Int = 0, 16 | time: Int = 0, 17 | mass: Int = 0, 18 | current: Int = 0, 19 | temperature: Int = 0, 20 | amount: Int = 0, 21 | luminosity: Int = 0 22 | ) { 23 | self.length = length 24 | self.time = time 25 | self.mass = mass 26 | self.current = current 27 | self.temperature = temperature 28 | self.amount = amount 29 | self.luminosity = luminosity 30 | } 31 | 32 | // Add dimensions 33 | public static func + (lhs: DimensionalExponents, rhs: DimensionalExponents) -> DimensionalExponents { 34 | return DimensionalExponents( 35 | length: lhs.length + rhs.length, 36 | time: lhs.time + rhs.time, 37 | mass: lhs.mass + rhs.mass, 38 | current: lhs.current + rhs.current, 39 | temperature: lhs.temperature + rhs.temperature, 40 | amount: lhs.amount + rhs.amount, 41 | luminosity: lhs.luminosity + rhs.luminosity 42 | ) 43 | } 44 | 45 | // Subtract dimensions 46 | public static func - (lhs: DimensionalExponents, rhs: DimensionalExponents) -> DimensionalExponents { 47 | return DimensionalExponents( 48 | length: lhs.length - rhs.length, 49 | time: lhs.time - rhs.time, 50 | mass: lhs.mass - rhs.mass, 51 | current: lhs.current - rhs.current, 52 | temperature: lhs.temperature - rhs.temperature, 53 | amount: lhs.amount - rhs.amount, 54 | luminosity: lhs.luminosity - rhs.luminosity 55 | ) 56 | } 57 | 58 | // Multiply by scalar 59 | public static func * (lhs: DimensionalExponents, rhs: Int) -> DimensionalExponents { 60 | return DimensionalExponents( 61 | length: lhs.length * rhs, 62 | time: lhs.time * rhs, 63 | mass: lhs.mass * rhs, 64 | current: lhs.current * rhs, 65 | temperature: lhs.temperature * rhs, 66 | amount: lhs.amount * rhs, 67 | luminosity: lhs.luminosity * rhs 68 | ) 69 | } 70 | 71 | // Check if dimensions are dimensionless 72 | public var isDimensionless: Bool { 73 | return length == 0 && time == 0 && mass == 0 && current == 0 && 74 | temperature == 0 && amount == 0 && luminosity == 0 75 | } 76 | 77 | // String representation 78 | public var description: String { 79 | var components: [String] = [] 80 | 81 | if length != 0 { components.append("L^\(length)") } 82 | if time != 0 { components.append("T^\(time)") } 83 | if mass != 0 { components.append("M^\(mass)") } 84 | if current != 0 { components.append("I^\(current)") } 85 | if temperature != 0 { components.append("Θ^\(temperature)") } 86 | if amount != 0 { components.append("N^\(amount)") } 87 | if luminosity != 0 { components.append("J^\(luminosity)") } 88 | 89 | return components.isEmpty ? "dimensionless" : components.joined(separator: "·") 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /Sources/SwiftMeasurement/DimensionalSystem/DimensionalMeasurement.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// A type-erased measurement that can be converted to a specific unit type 4 | public struct DimensionalMeasurement: Equatable, Hashable, Comparable { 5 | /// The value of the quantity in base units 6 | public let value: Double 7 | 8 | /// The dimensional signature of the quantity 9 | public let dimensions: DimensionalExponents 10 | 11 | /// Initialize with a value and dimension exponents 12 | public init(value: Double, dimensions: DimensionalExponents) { 13 | self.value = value 14 | self.dimensions = dimensions 15 | } 16 | 17 | /// Create from a Foundation Measurement 18 | public init(_ measurement: Measurement) { 19 | self.value = measurement.converted(to: UnitType.baseUnit()).value 20 | self.dimensions = UnitType.dimensions 21 | } 22 | 23 | // MARK: - Mathematical Operations 24 | 25 | /// Multiply two measurements 26 | public static func * (lhs: DimensionalMeasurement, rhs: DimensionalMeasurement) -> DimensionalMeasurement { 27 | return DimensionalMeasurement( 28 | value: lhs.value * rhs.value, 29 | dimensions: lhs.dimensions + rhs.dimensions 30 | ) 31 | } 32 | 33 | /// Divide two measurements 34 | public static func / (lhs: DimensionalMeasurement, rhs: DimensionalMeasurement) -> DimensionalMeasurement { 35 | return DimensionalMeasurement( 36 | value: lhs.value / rhs.value, 37 | dimensions: lhs.dimensions - rhs.dimensions 38 | ) 39 | } 40 | 41 | /// Raise to a power 42 | public func power(_ exponent: Int) -> DimensionalMeasurement { 43 | return DimensionalMeasurement( 44 | value: pow(value, Double(exponent)), 45 | dimensions: dimensions * exponent 46 | ) 47 | } 48 | 49 | /// Take the square root 50 | public func squareRoot() -> DimensionalMeasurement? { 51 | // Check if all exponents are even numbers 52 | let halfExponents = DimensionalExponents( 53 | length: dimensions.length / 2, 54 | time: dimensions.time / 2, 55 | mass: dimensions.mass / 2, 56 | current: dimensions.current / 2, 57 | temperature: dimensions.temperature / 2, 58 | amount: dimensions.amount / 2, 59 | luminosity: dimensions.luminosity / 2 60 | ) 61 | 62 | // Verify that we don't have fractional exponents 63 | guard halfExponents * 2 == dimensions else { 64 | return nil 65 | } 66 | 67 | return DimensionalMeasurement( 68 | value: Darwin.sqrt(value), 69 | dimensions: halfExponents 70 | ) 71 | } 72 | 73 | // MARK: - Conversion Methods 74 | 75 | /// Convert to a specific Foundation Measurement type 76 | public func convert(to unitType: T.Type) -> Measurement? { 77 | // Check if dimensions match 78 | guard T.dimensions == dimensions else { 79 | return nil 80 | } 81 | 82 | return Measurement(value: value, unit: T.baseUnit()) 83 | } 84 | 85 | /// Create dimensionless quantity (scalar) 86 | public static func dimensionless(_ value: Double) -> DimensionalMeasurement { 87 | return DimensionalMeasurement(value: value, dimensions: DimensionalExponents()) 88 | } 89 | 90 | // MARK: - Equatable Protocol Implementation 91 | 92 | public static func == (lhs: DimensionalMeasurement, rhs: DimensionalMeasurement) -> Bool { 93 | // First check if dimensions match 94 | guard lhs.dimensions == rhs.dimensions else { 95 | return false 96 | } 97 | 98 | // Then check if values are equal (using some epsilon for floating point comparison) 99 | let epsilon = 1e-10 100 | return abs(lhs.value - rhs.value) < epsilon 101 | } 102 | 103 | // MARK: - Hashable Protocol Implementation 104 | 105 | public func hash(into hasher: inout Hasher) { 106 | hasher.combine(value) 107 | hasher.combine(dimensions) 108 | } 109 | 110 | // MARK: - Comparable Protocol Implementation 111 | 112 | public static func < (lhs: DimensionalMeasurement, rhs: DimensionalMeasurement) -> Bool { 113 | // Can only compare measurements with the same dimensions 114 | guard lhs.dimensions == rhs.dimensions else { 115 | fatalError("Cannot compare measurements with different dimensions") 116 | } 117 | 118 | return lhs.value < rhs.value 119 | } 120 | 121 | // MARK: - Convenience Type Conversions 122 | 123 | public var asLength: Measurement? { 124 | return convert(to: UnitLength.self) 125 | } 126 | 127 | public var asArea: Measurement? { 128 | return convert(to: UnitArea.self) 129 | } 130 | 131 | public var asVolume: Measurement? { 132 | return convert(to: UnitVolume.self) 133 | } 134 | 135 | public var asDispersion: Measurement? { 136 | return convert(to: UnitDispersion.self) 137 | } 138 | 139 | public var asDuration: Measurement? { 140 | return convert(to: UnitDuration.self) 141 | } 142 | 143 | public var asFrequency: Measurement? { 144 | return convert(to: UnitFrequency.self) 145 | } 146 | 147 | public var asSpeed: Measurement? { 148 | return convert(to: UnitSpeed.self) 149 | } 150 | 151 | public var asAcceleration: Measurement? { 152 | return convert(to: UnitAcceleration.self) 153 | } 154 | 155 | public var asMass: Measurement? { 156 | return convert(to: UnitMass.self) 157 | } 158 | 159 | public var asConcentrationMass: Measurement? { 160 | return convert(to: UnitConcentrationMass.self) 161 | } 162 | 163 | public var asEnergy: Measurement? { 164 | return convert(to: UnitEnergy.self) 165 | } 166 | 167 | public var asPower: Measurement? { 168 | return convert(to: UnitPower.self) 169 | } 170 | 171 | public var asPressure: Measurement? { 172 | return convert(to: UnitPressure.self) 173 | } 174 | 175 | public var asElectricCurrent: Measurement? { 176 | return convert(to: UnitElectricCurrent.self) 177 | } 178 | 179 | public var asElectricPotentialDifference: Measurement? { 180 | return convert(to: UnitElectricPotentialDifference.self) 181 | } 182 | 183 | public var asElectricResistance: Measurement? { 184 | return convert(to: UnitElectricResistance.self) 185 | } 186 | 187 | public var asElectricCharge: Measurement? { 188 | return convert(to: UnitElectricCharge.self) 189 | } 190 | 191 | public var asTemperature: Measurement? { 192 | return convert(to: UnitTemperature.self) 193 | } 194 | 195 | public var asIlluminance: Measurement? { 196 | return convert(to: UnitIlluminance.self) 197 | } 198 | 199 | public var asAngle: Measurement? { 200 | return convert(to: UnitAngle.self) 201 | } 202 | 203 | public var asInformationStorage: Measurement? { 204 | return convert(to: UnitInformationStorage.self) 205 | } 206 | 207 | public var asFuelEfficiency: Measurement? { 208 | return convert(to: UnitFuelEfficiency.self) 209 | } 210 | } 211 | 212 | // MARK: - Operator Overloads for Foundation Measurements 213 | 214 | /// Multiply Foundation measurements with different unit types 215 | public func * ( 216 | lhs: Measurement, 217 | rhs: Measurement 218 | ) -> DimensionalMeasurement { 219 | return DimensionalMeasurement(lhs) * DimensionalMeasurement(rhs) 220 | } 221 | 222 | /// Divide Foundation measurements with different unit types 223 | public func / ( 224 | lhs: Measurement, 225 | rhs: Measurement 226 | ) -> DimensionalMeasurement { 227 | return DimensionalMeasurement(lhs) / DimensionalMeasurement(rhs) 228 | } 229 | 230 | // MARK: - Extension Methods for Foundation.Measurement 231 | 232 | extension Measurement where UnitType: Dimension & DimensionalUnit { 233 | /// Convert to a dimensional measurement 234 | public var dimensionalMeasurement: DimensionalMeasurement { 235 | return DimensionalMeasurement(self) 236 | } 237 | } 238 | -------------------------------------------------------------------------------- /Sources/SwiftMeasurement/DimensionalSystem/DimensionalUnit.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// Protocol for unit types that have defined dimensions 4 | public protocol DimensionalUnit { 5 | /// The dimensional exponents of the unit 6 | static var dimensions: DimensionalExponents { get } 7 | } 8 | 9 | // MARK: - Length-Based Units 10 | 11 | // Length - [L] 12 | extension UnitLength: DimensionalUnit { 13 | public static var dimensions: DimensionalExponents { 14 | return DimensionalExponents(length: 1) 15 | } 16 | } 17 | 18 | // Area - [L²] 19 | extension UnitArea: DimensionalUnit { 20 | public static var dimensions: DimensionalExponents { 21 | return DimensionalExponents(length: 2) 22 | } 23 | } 24 | 25 | // Volume - [L³] 26 | extension UnitVolume: DimensionalUnit { 27 | public static var dimensions: DimensionalExponents { 28 | return DimensionalExponents(length: 3) 29 | } 30 | } 31 | 32 | // Speed - [L·T⁻¹] 33 | extension UnitSpeed: DimensionalUnit { 34 | public static var dimensions: DimensionalExponents { 35 | return DimensionalExponents(length: 1, time: -1) 36 | } 37 | } 38 | 39 | // Acceleration - [L·T⁻²] 40 | extension UnitAcceleration: DimensionalUnit { 41 | public static var dimensions: DimensionalExponents { 42 | return DimensionalExponents(length: 1, time: -2) 43 | } 44 | } 45 | 46 | // Dispersion - [L⁻¹] 47 | extension UnitDispersion: DimensionalUnit { 48 | public static var dimensions: DimensionalExponents { 49 | return DimensionalExponents(length: -1) 50 | } 51 | } 52 | 53 | // MARK: - Time-Based Units 54 | 55 | // Duration - [T] 56 | extension UnitDuration: DimensionalUnit { 57 | public static var dimensions: DimensionalExponents { 58 | return DimensionalExponents(time: 1) 59 | } 60 | } 61 | 62 | // Frequency - [T⁻¹] 63 | extension UnitFrequency: DimensionalUnit { 64 | public static var dimensions: DimensionalExponents { 65 | return DimensionalExponents(time: -1) 66 | } 67 | } 68 | 69 | // MARK: - Mass-Based Units 70 | 71 | // Mass - [M] 72 | extension UnitMass: DimensionalUnit { 73 | public static var dimensions: DimensionalExponents { 74 | return DimensionalExponents(mass: 1) 75 | } 76 | } 77 | 78 | // Concentration Mass - [M·L⁻³] 79 | extension UnitConcentrationMass: DimensionalUnit { 80 | public static var dimensions: DimensionalExponents { 81 | return DimensionalExponents(length: -3, mass: 1) 82 | } 83 | } 84 | 85 | // MARK: - Energy and Power 86 | 87 | // Energy - [M·L²·T⁻²] 88 | extension UnitEnergy: DimensionalUnit { 89 | public static var dimensions: DimensionalExponents { 90 | return DimensionalExponents(length: 2, time: -2, mass: 1) 91 | } 92 | } 93 | 94 | // Power - [M·L²·T⁻³] 95 | extension UnitPower: DimensionalUnit { 96 | public static var dimensions: DimensionalExponents { 97 | return DimensionalExponents(length: 2, time: -3, mass: 1) 98 | } 99 | } 100 | 101 | // Pressure - [M·L⁻¹·T⁻²] 102 | extension UnitPressure: DimensionalUnit { 103 | public static var dimensions: DimensionalExponents { 104 | return DimensionalExponents(length: -1, time: -2, mass: 1) 105 | } 106 | } 107 | 108 | // MARK: - Electrical Units 109 | 110 | // Electric Current - [I] 111 | extension UnitElectricCurrent: DimensionalUnit { 112 | public static var dimensions: DimensionalExponents { 113 | return DimensionalExponents(current: 1) 114 | } 115 | } 116 | 117 | // Electric Charge - [I·T] 118 | extension UnitElectricCharge: DimensionalUnit { 119 | public static var dimensions: DimensionalExponents { 120 | return DimensionalExponents(time: 1, current: 1) 121 | } 122 | } 123 | 124 | // Electric Potential Difference - [M·L²·T⁻³·I⁻¹] 125 | extension UnitElectricPotentialDifference: DimensionalUnit { 126 | public static var dimensions: DimensionalExponents { 127 | return DimensionalExponents(length: 2, time: -3, mass: 1, current: -1) 128 | } 129 | } 130 | 131 | // Electric Resistance - [M·L²·T⁻³·I⁻²] 132 | extension UnitElectricResistance: DimensionalUnit { 133 | public static var dimensions: DimensionalExponents { 134 | return DimensionalExponents(length: 2, time: -3, mass: 1, current: -2) 135 | } 136 | } 137 | 138 | // MARK: - Other SI Base Units 139 | 140 | // Temperature - [Θ] 141 | extension UnitTemperature: DimensionalUnit { 142 | public static var dimensions: DimensionalExponents { 143 | return DimensionalExponents(temperature: 1) 144 | } 145 | } 146 | 147 | // Illuminance - [L⁻²·J] 148 | extension UnitIlluminance: DimensionalUnit { 149 | public static var dimensions: DimensionalExponents { 150 | return DimensionalExponents(length: -2, luminosity: 1) 151 | } 152 | } 153 | 154 | // MARK: - Dimensionless and Special Units 155 | 156 | // Angle - [dimensionless] 157 | extension UnitAngle: DimensionalUnit { 158 | public static var dimensions: DimensionalExponents { 159 | return DimensionalExponents() 160 | } 161 | } 162 | 163 | // Information Storage - [dimensionless] 164 | extension UnitInformationStorage: DimensionalUnit { 165 | public static var dimensions: DimensionalExponents { 166 | return DimensionalExponents() 167 | } 168 | } 169 | 170 | // Fuel Efficiency - [L⁻²] 171 | extension UnitFuelEfficiency: DimensionalUnit { 172 | public static var dimensions: DimensionalExponents { 173 | return DimensionalExponents(length: -2) 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /Sources/SwiftMeasurement/Measurement+Extensions.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | // MARK: - Initializers 4 | 5 | extension Measurement where UnitType: Unit { 6 | 7 | public init(value: Int, unit: UnitType) { 8 | self.init(value: Double(value), unit: unit) 9 | } 10 | 11 | public init(value: Float, unit: UnitType) { 12 | self.init(value: Double(value), unit: unit) 13 | } 14 | } 15 | 16 | // MARK: - ExpressibleByFloatLiteral 17 | 18 | extension Measurement: @retroactive ExpressibleByFloatLiteral where UnitType: Dimension { 19 | 20 | public init(floatLiteral value: Double) { 21 | self.init(value: value, unit: UnitType.baseUnit()) 22 | } 23 | } 24 | 25 | // MARK: - ExpressibleByIntegerLiteral 26 | 27 | extension Measurement: @retroactive ExpressibleByIntegerLiteral where UnitType: Dimension { 28 | public init(integerLiteral value: Int) { 29 | self.init(floatLiteral: Double(value)) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Sources/SwiftMeasurement/MeasurementConvertible.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public protocol MeasurementConvertible { 4 | func measurement(as unit: UnitType) -> Measurement 5 | } 6 | 7 | extension Double: MeasurementConvertible { 8 | public func measurement(as unit: UnitType) -> Measurement { 9 | return Measurement(value: self, unit: unit) 10 | } 11 | } 12 | 13 | extension Float: MeasurementConvertible { 14 | public func measurement(as unit: UnitType) -> Measurement { 15 | return Measurement(value: Double(self), unit: unit) 16 | } 17 | } 18 | 19 | extension Int: MeasurementConvertible { 20 | public func measurement(as unit: UnitType) -> Measurement { 21 | return Measurement(value: Double(self), unit: unit) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Sources/SwiftMeasurement/Units/UnitAcceleration.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension MeasurementConvertible { 4 | 5 | var metersPerSecondSquared: Measurement { 6 | return measurement(as: UnitAcceleration.metersPerSecondSquared) 7 | } 8 | 9 | var gravity: Measurement { 10 | return measurement(as: UnitAcceleration.gravity) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Sources/SwiftMeasurement/Units/UnitAngle.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension MeasurementConvertible { 4 | 5 | var degrees: Measurement { 6 | return measurement(as: UnitAngle.degrees) 7 | } 8 | 9 | var arcMinutes: Measurement { 10 | return measurement(as: UnitAngle.arcMinutes) 11 | } 12 | 13 | var arcSeconds: Measurement { 14 | return measurement(as: UnitAngle.arcSeconds) 15 | } 16 | 17 | var radians: Measurement { 18 | return measurement(as: UnitAngle.radians) 19 | } 20 | 21 | var gradians: Measurement { 22 | return measurement(as: UnitAngle.gradians) 23 | } 24 | 25 | var revolutions: Measurement { 26 | return measurement(as: UnitAngle.revolutions) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Sources/SwiftMeasurement/Units/UnitArea.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension MeasurementConvertible { 4 | 5 | var squareMegameters: Measurement { 6 | return measurement(as: UnitArea.squareMegameters) 7 | } 8 | 9 | var squareKilometers: Measurement { 10 | return measurement(as: UnitArea.squareKilometers) 11 | } 12 | 13 | var squareMeters: Measurement { 14 | return measurement(as: UnitArea.squareMeters) 15 | } 16 | 17 | var squareCentimeters: Measurement { 18 | return measurement(as: UnitArea.squareCentimeters) 19 | } 20 | 21 | var squareMillimeters: Measurement { 22 | return measurement(as: UnitArea.squareMillimeters) 23 | } 24 | 25 | var squareMicrometers: Measurement { 26 | return measurement(as: UnitArea.squareMicrometers) 27 | } 28 | 29 | var squareNanometers: Measurement { 30 | return measurement(as: UnitArea.squareNanometers) 31 | } 32 | 33 | var squareInches: Measurement { 34 | return measurement(as: UnitArea.squareInches) 35 | } 36 | 37 | var squareFeet: Measurement { 38 | return measurement(as: UnitArea.squareFeet) 39 | } 40 | 41 | var squareYards: Measurement { 42 | return measurement(as: UnitArea.squareYards) 43 | } 44 | 45 | var squareMiles: Measurement { 46 | return measurement(as: UnitArea.squareMiles) 47 | } 48 | 49 | var acres: Measurement { 50 | return measurement(as: UnitArea.acres) 51 | } 52 | 53 | var ares: Measurement { 54 | return measurement(as: UnitArea.ares) 55 | } 56 | 57 | var hectares: Measurement { 58 | return measurement(as: UnitArea.hectares) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Sources/SwiftMeasurement/Units/UnitConcentrationMass.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension MeasurementConvertible { 4 | 5 | var gramsPerLiter: Measurement { 6 | return measurement(as: UnitConcentrationMass.gramsPerLiter) 7 | } 8 | 9 | var milligramsPerDeciliter: Measurement { 10 | return measurement(as: UnitConcentrationMass.milligramsPerDeciliter) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Sources/SwiftMeasurement/Units/UnitDispersion.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension MeasurementConvertible { 4 | 5 | var partsPerMillion: Measurement { 6 | return measurement(as: UnitDispersion.partsPerMillion) 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Sources/SwiftMeasurement/Units/UnitDuration.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension MeasurementConvertible { 4 | 5 | var seconds: Measurement { 6 | return measurement(as: UnitDuration.seconds) 7 | } 8 | 9 | var minutes: Measurement { 10 | return measurement(as: UnitDuration.minutes) 11 | } 12 | 13 | var hours: Measurement { 14 | return measurement(as: UnitDuration.hours) 15 | } 16 | 17 | var milliseconds: Measurement { 18 | return measurement(as: UnitDuration.milliseconds) 19 | } 20 | 21 | var microseconds: Measurement { 22 | return measurement(as: UnitDuration.microseconds) 23 | } 24 | 25 | var nanoseconds: Measurement { 26 | return measurement(as: UnitDuration.nanoseconds) 27 | } 28 | 29 | var picoseconds: Measurement { 30 | return measurement(as: UnitDuration.picoseconds) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Sources/SwiftMeasurement/Units/UnitElectricCharge.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension MeasurementConvertible { 4 | 5 | var coulombs: Measurement { 6 | return measurement(as: UnitElectricCharge.coulombs) 7 | } 8 | 9 | var megaampereHours: Measurement { 10 | return measurement(as: UnitElectricCharge.megaampereHours) 11 | } 12 | 13 | var kiloampereHours: Measurement { 14 | return measurement(as: UnitElectricCharge.kiloampereHours) 15 | } 16 | 17 | var ampereHours: Measurement { 18 | return measurement(as: UnitElectricCharge.ampereHours) 19 | } 20 | 21 | var milliampereHours: Measurement { 22 | return measurement(as: UnitElectricCharge.milliampereHours) 23 | } 24 | 25 | var microampereHours: Measurement { 26 | return measurement(as: UnitElectricCharge.microampereHours) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Sources/SwiftMeasurement/Units/UnitElectricCurrent.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension MeasurementConvertible { 4 | 5 | var megaamperes: Measurement { 6 | return measurement(as: UnitElectricCurrent.megaamperes) 7 | } 8 | 9 | var kiloamperes: Measurement { 10 | return measurement(as: UnitElectricCurrent.kiloamperes) 11 | } 12 | 13 | var amperes: Measurement { 14 | return measurement(as: UnitElectricCurrent.amperes) 15 | } 16 | 17 | var milliamperes: Measurement { 18 | return measurement(as: UnitElectricCurrent.milliamperes) 19 | } 20 | 21 | var microamperes: Measurement { 22 | return measurement(as: UnitElectricCurrent.microamperes) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Sources/SwiftMeasurement/Units/UnitElectricPotentialDifference.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension MeasurementConvertible { 4 | 5 | var megavolts: Measurement { 6 | return measurement(as: UnitElectricPotentialDifference.megavolts) 7 | } 8 | 9 | var kilovolts: Measurement { 10 | return measurement(as: UnitElectricPotentialDifference.kilovolts) 11 | } 12 | 13 | var volts: Measurement { 14 | return measurement(as: UnitElectricPotentialDifference.volts) 15 | } 16 | 17 | var millivolts: Measurement { 18 | return measurement(as: UnitElectricPotentialDifference.millivolts) 19 | } 20 | 21 | var microvolts: Measurement { 22 | return measurement(as: UnitElectricPotentialDifference.microvolts) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Sources/SwiftMeasurement/Units/UnitElectricResistance.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension MeasurementConvertible { 4 | 5 | var megaohms: Measurement { 6 | return measurement(as: UnitElectricResistance.megaohms) 7 | } 8 | 9 | var kiloohms: Measurement { 10 | return measurement(as: UnitElectricResistance.kiloohms) 11 | } 12 | 13 | var ohms: Measurement { 14 | return measurement(as: UnitElectricResistance.ohms) 15 | } 16 | 17 | var milliohms: Measurement { 18 | return measurement(as: UnitElectricResistance.milliohms) 19 | } 20 | 21 | var microohms: Measurement { 22 | return measurement(as: UnitElectricResistance.microohms) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Sources/SwiftMeasurement/Units/UnitEnergy.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension MeasurementConvertible { 4 | 5 | var kilojoules: Measurement { 6 | return measurement(as: UnitEnergy.kilojoules) 7 | } 8 | 9 | var joules: Measurement { 10 | return measurement(as: UnitEnergy.joules) 11 | } 12 | 13 | var kilocalories: Measurement { 14 | return measurement(as: UnitEnergy.kilocalories) 15 | } 16 | 17 | var calories: Measurement { 18 | return measurement(as: UnitEnergy.calories) 19 | } 20 | 21 | var kilowattHours: Measurement { 22 | return measurement(as: UnitEnergy.kilowattHours) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Sources/SwiftMeasurement/Units/UnitFrequency.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension MeasurementConvertible { 4 | 5 | var terahertz: Measurement { 6 | return measurement(as: UnitFrequency.terahertz) 7 | } 8 | 9 | var gigahertz: Measurement { 10 | return measurement(as: UnitFrequency.gigahertz) 11 | } 12 | 13 | var megahertz: Measurement { 14 | return measurement(as: UnitFrequency.megahertz) 15 | } 16 | 17 | var kilohertz: Measurement { 18 | return measurement(as: UnitFrequency.kilohertz) 19 | } 20 | 21 | var hertz: Measurement { 22 | return measurement(as: UnitFrequency.hertz) 23 | } 24 | 25 | var millihertz: Measurement { 26 | return measurement(as: UnitFrequency.millihertz) 27 | } 28 | 29 | var microhertz: Measurement { 30 | return measurement(as: UnitFrequency.microhertz) 31 | } 32 | 33 | var nanohertz: Measurement { 34 | return measurement(as: UnitFrequency.nanohertz) 35 | } 36 | 37 | var framesPerSecond: Measurement { 38 | return measurement(as: UnitFrequency.framesPerSecond) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Sources/SwiftMeasurement/Units/UnitFuelEfficiency.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension MeasurementConvertible { 4 | 5 | var litersPer100Kilometers: Measurement { 6 | return measurement(as: UnitFuelEfficiency.litersPer100Kilometers) 7 | } 8 | 9 | var milesPerImperialGallon: Measurement { 10 | return measurement(as: UnitFuelEfficiency.milesPerImperialGallon) 11 | } 12 | 13 | var milesPerGallon: Measurement { 14 | return measurement(as: UnitFuelEfficiency.milesPerGallon) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Sources/SwiftMeasurement/Units/UnitIlluminance.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension MeasurementConvertible { 4 | 5 | var lux: Measurement { 6 | return measurement(as: UnitIlluminance.lux) 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Sources/SwiftMeasurement/Units/UnitInformationStorage.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension MeasurementConvertible { 4 | 5 | var bytes: Measurement { 6 | return measurement(as: UnitInformationStorage.bytes) 7 | } 8 | 9 | var bits: Measurement { 10 | return measurement(as: UnitInformationStorage.bits) 11 | } 12 | 13 | var nibbles: Measurement { 14 | return measurement(as: UnitInformationStorage.nibbles) 15 | } 16 | 17 | var yottabytes: Measurement { 18 | return measurement(as: UnitInformationStorage.yottabytes) 19 | } 20 | 21 | var zettabytes: Measurement { 22 | return measurement(as: UnitInformationStorage.zettabytes) 23 | } 24 | 25 | var exabytes: Measurement { 26 | return measurement(as: UnitInformationStorage.exabytes) 27 | } 28 | 29 | var petabytes: Measurement { 30 | return measurement(as: UnitInformationStorage.petabytes) 31 | } 32 | 33 | var terabytes: Measurement { 34 | return measurement(as: UnitInformationStorage.terabytes) 35 | } 36 | 37 | var gigabytes: Measurement { 38 | return measurement(as: UnitInformationStorage.gigabytes) 39 | } 40 | 41 | var megabytes: Measurement { 42 | return measurement(as: UnitInformationStorage.megabytes) 43 | } 44 | 45 | var kilobytes: Measurement { 46 | return measurement(as: UnitInformationStorage.kilobytes) 47 | } 48 | 49 | var yottabits: Measurement { 50 | return measurement(as: UnitInformationStorage.yottabits) 51 | } 52 | 53 | var zettabits: Measurement { 54 | return measurement(as: UnitInformationStorage.zettabits) 55 | } 56 | 57 | var exabits: Measurement { 58 | return measurement(as: UnitInformationStorage.exabits) 59 | } 60 | 61 | var petabits: Measurement { 62 | return measurement(as: UnitInformationStorage.petabits) 63 | } 64 | 65 | var terabits: Measurement { 66 | return measurement(as: UnitInformationStorage.terabits) 67 | } 68 | 69 | var gigabits: Measurement { 70 | return measurement(as: UnitInformationStorage.gigabits) 71 | } 72 | 73 | var megabits: Measurement { 74 | return measurement(as: UnitInformationStorage.megabits) 75 | } 76 | 77 | var kilobits: Measurement { 78 | return measurement(as: UnitInformationStorage.kilobits) 79 | } 80 | 81 | var yobibytes: Measurement { 82 | return measurement(as: UnitInformationStorage.yobibytes) 83 | } 84 | 85 | var zebibytes: Measurement { 86 | return measurement(as: UnitInformationStorage.zebibytes) 87 | } 88 | 89 | var exbibytes: Measurement { 90 | return measurement(as: UnitInformationStorage.exbibytes) 91 | } 92 | 93 | var pebibytes: Measurement { 94 | return measurement(as: UnitInformationStorage.pebibytes) 95 | } 96 | 97 | var tebibytes: Measurement { 98 | return measurement(as: UnitInformationStorage.tebibytes) 99 | } 100 | 101 | var gibibytes: Measurement { 102 | return measurement(as: UnitInformationStorage.gibibytes) 103 | } 104 | 105 | var mebibytes: Measurement { 106 | return measurement(as: UnitInformationStorage.mebibytes) 107 | } 108 | 109 | var kibibytes: Measurement { 110 | return measurement(as: UnitInformationStorage.kibibytes) 111 | } 112 | 113 | var yobibits: Measurement { 114 | return measurement(as: UnitInformationStorage.yobibits) 115 | } 116 | 117 | var zebibits: Measurement { 118 | return measurement(as: UnitInformationStorage.zebibits) 119 | } 120 | 121 | var exbibits: Measurement { 122 | return measurement(as: UnitInformationStorage.exbibits) 123 | } 124 | 125 | var pebibits: Measurement { 126 | return measurement(as: UnitInformationStorage.pebibits) 127 | } 128 | 129 | var tebibits: Measurement { 130 | return measurement(as: UnitInformationStorage.tebibits) 131 | } 132 | 133 | var gibibits: Measurement { 134 | return measurement(as: UnitInformationStorage.gibibits) 135 | } 136 | 137 | var mebibits: Measurement { 138 | return measurement(as: UnitInformationStorage.mebibits) 139 | } 140 | 141 | var kibibits: Measurement { 142 | return measurement(as: UnitInformationStorage.kibibits) 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /Sources/SwiftMeasurement/Units/UnitLength.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension MeasurementConvertible { 4 | 5 | var megameters: Measurement { 6 | return measurement(as: UnitLength.megameters) 7 | } 8 | 9 | var kilometers: Measurement { 10 | return measurement(as: UnitLength.kilometers) 11 | } 12 | 13 | var hectometers: Measurement { 14 | return measurement(as: UnitLength.hectometers) 15 | } 16 | 17 | var decameters: Measurement { 18 | return measurement(as: UnitLength.decameters) 19 | } 20 | 21 | var meters: Measurement { 22 | return measurement(as: UnitLength.meters) 23 | } 24 | 25 | var decimeters: Measurement { 26 | return measurement(as: UnitLength.decimeters) 27 | } 28 | 29 | var centimeters: Measurement { 30 | return measurement(as: UnitLength.centimeters) 31 | } 32 | 33 | var millimeters: Measurement { 34 | return measurement(as: UnitLength.millimeters) 35 | } 36 | 37 | var micrometers: Measurement { 38 | return measurement(as: UnitLength.micrometers) 39 | } 40 | 41 | var nanometers: Measurement { 42 | return measurement(as: UnitLength.nanometers) 43 | } 44 | 45 | var picometers: Measurement { 46 | return measurement(as: UnitLength.picometers) 47 | } 48 | 49 | var inches: Measurement { 50 | return measurement(as: UnitLength.inches) 51 | } 52 | 53 | var feet: Measurement { 54 | return measurement(as: UnitLength.feet) 55 | } 56 | 57 | var yards: Measurement { 58 | return measurement(as: UnitLength.yards) 59 | } 60 | 61 | var miles: Measurement { 62 | return measurement(as: UnitLength.miles) 63 | } 64 | 65 | var scandinavianMiles: Measurement { 66 | return measurement(as: UnitLength.scandinavianMiles) 67 | } 68 | 69 | var lightyears: Measurement { 70 | return measurement(as: UnitLength.lightyears) 71 | } 72 | 73 | var nauticalMiles: Measurement { 74 | return measurement(as: UnitLength.nauticalMiles) 75 | } 76 | 77 | var fathoms: Measurement { 78 | return measurement(as: UnitLength.fathoms) 79 | } 80 | 81 | var furlongs: Measurement { 82 | return measurement(as: UnitLength.furlongs) 83 | } 84 | 85 | var astronomicalUnits: Measurement { 86 | return measurement(as: UnitLength.astronomicalUnits) 87 | } 88 | 89 | var parsecs: Measurement { 90 | return measurement(as: UnitLength.parsecs) 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /Sources/SwiftMeasurement/Units/UnitMass.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension MeasurementConvertible { 4 | 5 | var kilograms: Measurement { 6 | return measurement(as: UnitMass.kilograms) 7 | } 8 | 9 | var grams: Measurement { 10 | return measurement(as: UnitMass.grams) 11 | } 12 | 13 | var decigrams: Measurement { 14 | return measurement(as: UnitMass.decigrams) 15 | } 16 | 17 | var centigrams: Measurement { 18 | return measurement(as: UnitMass.centigrams) 19 | } 20 | 21 | var milligrams: Measurement { 22 | return measurement(as: UnitMass.milligrams) 23 | } 24 | 25 | var micrograms: Measurement { 26 | return measurement(as: UnitMass.micrograms) 27 | } 28 | 29 | var nanograms: Measurement { 30 | return measurement(as: UnitMass.nanograms) 31 | } 32 | 33 | var picograms: Measurement { 34 | return measurement(as: UnitMass.picograms) 35 | } 36 | 37 | var ounces: Measurement { 38 | return measurement(as: UnitMass.ounces) 39 | } 40 | 41 | var pounds: Measurement { 42 | return measurement(as: UnitMass.pounds) 43 | } 44 | 45 | var stones: Measurement { 46 | return measurement(as: UnitMass.stones) 47 | } 48 | 49 | var metricTons: Measurement { 50 | return measurement(as: UnitMass.metricTons) 51 | } 52 | 53 | var shortTons: Measurement { 54 | return measurement(as: UnitMass.shortTons) 55 | } 56 | 57 | var carats: Measurement { 58 | return measurement(as: UnitMass.carats) 59 | } 60 | 61 | var ouncesTroy: Measurement { 62 | return measurement(as: UnitMass.ouncesTroy) 63 | } 64 | 65 | var slugs: Measurement { 66 | return measurement(as: UnitMass.slugs) 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Sources/SwiftMeasurement/Units/UnitPower.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension MeasurementConvertible { 4 | 5 | var terawatts: Measurement { 6 | return measurement(as: UnitPower.terawatts) 7 | } 8 | 9 | var gigawatts: Measurement { 10 | return measurement(as: UnitPower.gigawatts) 11 | } 12 | 13 | var megawatts: Measurement { 14 | return measurement(as: UnitPower.megawatts) 15 | } 16 | 17 | var kilowatts: Measurement { 18 | return measurement(as: UnitPower.kilowatts) 19 | } 20 | 21 | var watts: Measurement { 22 | return measurement(as: UnitPower.watts) 23 | } 24 | 25 | var milliwatts: Measurement { 26 | return measurement(as: UnitPower.milliwatts) 27 | } 28 | 29 | var microwatts: Measurement { 30 | return measurement(as: UnitPower.microwatts) 31 | } 32 | 33 | var nanowatts: Measurement { 34 | return measurement(as: UnitPower.nanowatts) 35 | } 36 | 37 | var picowatts: Measurement { 38 | return measurement(as: UnitPower.picowatts) 39 | } 40 | 41 | var femtowatts: Measurement { 42 | return measurement(as: UnitPower.femtowatts) 43 | } 44 | 45 | var horsepower: Measurement { 46 | return measurement(as: UnitPower.horsepower) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Sources/SwiftMeasurement/Units/UnitPressure.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension MeasurementConvertible { 4 | 5 | var newtonsPerMetersSquared: Measurement { 6 | return measurement(as: UnitPressure.newtonsPerMetersSquared) 7 | } 8 | 9 | var gigapascals: Measurement { 10 | return measurement(as: UnitPressure.gigapascals) 11 | } 12 | 13 | var megapascals: Measurement { 14 | return measurement(as: UnitPressure.megapascals) 15 | } 16 | 17 | var kilopascals: Measurement { 18 | return measurement(as: UnitPressure.kilopascals) 19 | } 20 | 21 | var hectopascals: Measurement { 22 | return measurement(as: UnitPressure.hectopascals) 23 | } 24 | 25 | var inchesOfMercury: Measurement { 26 | return measurement(as: UnitPressure.inchesOfMercury) 27 | } 28 | 29 | var bars: Measurement { 30 | return measurement(as: UnitPressure.bars) 31 | } 32 | 33 | var millibars: Measurement { 34 | return measurement(as: UnitPressure.millibars) 35 | } 36 | 37 | var millimetersOfMercury: Measurement { 38 | return measurement(as: UnitPressure.millimetersOfMercury) 39 | } 40 | 41 | var poundsForcePerSquareInch: Measurement { 42 | return measurement(as: UnitPressure.poundsForcePerSquareInch) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Sources/SwiftMeasurement/Units/UnitSpeed.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension MeasurementConvertible { 4 | 5 | var metersPerSecond: Measurement { 6 | return measurement(as: UnitSpeed.metersPerSecond) 7 | } 8 | 9 | var kilometersPerHour: Measurement { 10 | return measurement(as: UnitSpeed.kilometersPerHour) 11 | } 12 | 13 | var milesPerHour: Measurement { 14 | return measurement(as: UnitSpeed.milesPerHour) 15 | } 16 | 17 | var knots: Measurement { 18 | return measurement(as: UnitSpeed.knots) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Sources/SwiftMeasurement/Units/UnitTemperature.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension MeasurementConvertible { 4 | 5 | var kelvin: Measurement { 6 | return measurement(as: UnitTemperature.kelvin) 7 | } 8 | 9 | var celsius: Measurement { 10 | return measurement(as: UnitTemperature.celsius) 11 | } 12 | 13 | var fahrenheit: Measurement { 14 | return measurement(as: UnitTemperature.fahrenheit) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Sources/SwiftMeasurement/Units/UnitVolume.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension MeasurementConvertible { 4 | 5 | var megaliters: Measurement { 6 | return measurement(as: UnitVolume.megaliters) 7 | } 8 | 9 | var kiloliters: Measurement { 10 | return measurement(as: UnitVolume.kiloliters) 11 | } 12 | 13 | var liters: Measurement { 14 | return measurement(as: UnitVolume.liters) 15 | } 16 | 17 | var deciliters: Measurement { 18 | return measurement(as: UnitVolume.deciliters) 19 | } 20 | 21 | var centiliters: Measurement { 22 | return measurement(as: UnitVolume.centiliters) 23 | } 24 | 25 | var milliliters: Measurement { 26 | return measurement(as: UnitVolume.milliliters) 27 | } 28 | 29 | var cubicKilometers: Measurement { 30 | return measurement(as: UnitVolume.cubicKilometers) 31 | } 32 | 33 | var cubicMeters: Measurement { 34 | return measurement(as: UnitVolume.cubicMeters) 35 | } 36 | 37 | var cubicDecimeters: Measurement { 38 | return measurement(as: UnitVolume.cubicDecimeters) 39 | } 40 | 41 | var cubicCentimeters: Measurement { 42 | return measurement(as: UnitVolume.cubicCentimeters) 43 | } 44 | 45 | var cubicMillimeters: Measurement { 46 | return measurement(as: UnitVolume.cubicMillimeters) 47 | } 48 | 49 | var cubicInches: Measurement { 50 | return measurement(as: UnitVolume.cubicInches) 51 | } 52 | 53 | var cubicFeet: Measurement { 54 | return measurement(as: UnitVolume.cubicFeet) 55 | } 56 | 57 | var cubicYards: Measurement { 58 | return measurement(as: UnitVolume.cubicYards) 59 | } 60 | 61 | var cubicMiles: Measurement { 62 | return measurement(as: UnitVolume.cubicMiles) 63 | } 64 | 65 | var acreFeet: Measurement { 66 | return measurement(as: UnitVolume.acreFeet) 67 | } 68 | 69 | var bushels: Measurement { 70 | return measurement(as: UnitVolume.bushels) 71 | } 72 | 73 | var teaspoons: Measurement { 74 | return measurement(as: UnitVolume.teaspoons) 75 | } 76 | 77 | var tablespoons: Measurement { 78 | return measurement(as: UnitVolume.tablespoons) 79 | } 80 | 81 | var fluidOunces: Measurement { 82 | return measurement(as: UnitVolume.fluidOunces) 83 | } 84 | 85 | var cups: Measurement { 86 | return measurement(as: UnitVolume.cups) 87 | } 88 | 89 | var pints: Measurement { 90 | return measurement(as: UnitVolume.pints) 91 | } 92 | 93 | var quarts: Measurement { 94 | return measurement(as: UnitVolume.quarts) 95 | } 96 | 97 | var gallons: Measurement { 98 | return measurement(as: UnitVolume.gallons) 99 | } 100 | 101 | var imperialTeaspoons: Measurement { 102 | return measurement(as: UnitVolume.imperialTeaspoons) 103 | } 104 | 105 | var imperialTablespoons: Measurement { 106 | return measurement(as: UnitVolume.imperialTablespoons) 107 | } 108 | 109 | var imperialFluidOunces: Measurement { 110 | return measurement(as: UnitVolume.imperialFluidOunces) 111 | } 112 | 113 | var imperialPints: Measurement { 114 | return measurement(as: UnitVolume.imperialPints) 115 | } 116 | 117 | var imperialQuarts: Measurement { 118 | return measurement(as: UnitVolume.imperialQuarts) 119 | } 120 | 121 | var imperialGallons: Measurement { 122 | return measurement(as: UnitVolume.imperialGallons) 123 | } 124 | 125 | var metricCups: Measurement { 126 | return measurement(as: UnitVolume.metricCups) 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /Tests/SwiftMeasurementTests/DimensionalSystemTests.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Testing 3 | @testable import SwiftMeasurement 4 | 5 | @Suite("Dimensional System") 6 | struct DimensionalSystemTests { 7 | 8 | @Suite("DimensionalExponents") 9 | struct DimensionalExponentsTests { 10 | 11 | @Test("Initialization") 12 | func initialization() { 13 | let length = DimensionalExponents(length: 1) 14 | #expect(length.length == 1) 15 | #expect(length.time == 0) 16 | #expect(length.mass == 0) 17 | 18 | let velocity = DimensionalExponents(length: 1, time: -1) 19 | #expect(velocity.length == 1) 20 | #expect(velocity.time == -1) 21 | #expect(velocity.mass == 0) 22 | 23 | let energy = DimensionalExponents(length: 2, time: -2, mass: 1) 24 | #expect(energy.length == 2) 25 | #expect(energy.time == -2) 26 | #expect(energy.mass == 1) 27 | } 28 | 29 | @Test("Addition") 30 | func addition() { 31 | let length = DimensionalExponents(length: 1) 32 | let time = DimensionalExponents(time: 1) 33 | 34 | let result = length + time 35 | #expect(result.length == 1) 36 | #expect(result.time == 1) 37 | #expect(result.mass == 0) 38 | } 39 | 40 | @Test("Subtraction") 41 | func subtraction() { 42 | let energy = DimensionalExponents(length: 2, time: -2, mass: 1) 43 | let mass = DimensionalExponents(mass: 1) 44 | 45 | let result = energy - mass 46 | #expect(result.length == 2) 47 | #expect(result.time == -2) 48 | #expect(result.mass == 0) 49 | } 50 | 51 | @Test("Multiplication") 52 | func multiplication() { 53 | let length = DimensionalExponents(length: 1) 54 | let result = length * 2 55 | 56 | #expect(result.length == 2) 57 | #expect(result.time == 0) 58 | #expect(result.mass == 0) 59 | } 60 | 61 | @Test("Dimensionless Check") 62 | func isDimensionless() { 63 | let dimensionless = DimensionalExponents() 64 | #expect(dimensionless.isDimensionless) 65 | 66 | let length = DimensionalExponents(length: 1) 67 | #expect(!length.isDimensionless) 68 | } 69 | 70 | @Test("String Representation") 71 | func description() { 72 | let length = DimensionalExponents(length: 1) 73 | #expect(length.description == "L^1") 74 | 75 | let velocity = DimensionalExponents(length: 1, time: -1) 76 | #expect(velocity.description == "L^1·T^-1") 77 | 78 | let dimensionless = DimensionalExponents() 79 | #expect(dimensionless.description == "dimensionless") 80 | } 81 | } 82 | 83 | @Suite("DimensionalUnit") 84 | struct DimensionalUnitTests { 85 | 86 | @Test("Unit Type Dimensional Exponents") 87 | func unitDimensions() { 88 | // Length 89 | #expect(UnitLength.dimensions == DimensionalExponents(length: 1)) 90 | 91 | // Area 92 | #expect(UnitArea.dimensions == DimensionalExponents(length: 2)) 93 | 94 | // Speed 95 | #expect(UnitSpeed.dimensions == DimensionalExponents(length: 1, time: -1)) 96 | 97 | // Energy 98 | #expect(UnitEnergy.dimensions == DimensionalExponents(length: 2, time: -2, mass: 1)) 99 | } 100 | } 101 | 102 | @Suite("DimensionalMeasurement") 103 | struct DimensionalMeasurementTests { 104 | 105 | @Test("Initialization") 106 | func initialization() { 107 | let measurement = DimensionalMeasurement(value: 10.0, dimensions: DimensionalExponents(length: 1)) 108 | #expect(measurement.value == 10.0) 109 | #expect(measurement.dimensions == DimensionalExponents(length: 1)) 110 | 111 | let lengthMeasurement = Measurement(value: 20.0, unit: UnitLength.meters) 112 | let dimensionalMeasurement = DimensionalMeasurement(lengthMeasurement) 113 | #expect(dimensionalMeasurement.value == 20.0) 114 | #expect(dimensionalMeasurement.dimensions == UnitLength.dimensions) 115 | } 116 | 117 | @Test("Multiplication") 118 | func multiplication() { 119 | let length = DimensionalMeasurement(value: 10.0, dimensions: DimensionalExponents(length: 1)) 120 | let width = DimensionalMeasurement(value: 5.0, dimensions: DimensionalExponents(length: 1)) 121 | 122 | let area = length * width 123 | #expect(area.value == 50.0) 124 | #expect(area.dimensions == DimensionalExponents(length: 2)) 125 | } 126 | 127 | @Test("Division") 128 | func division() { 129 | let distance = DimensionalMeasurement(value: 100.0, dimensions: DimensionalExponents(length: 1)) 130 | let time = DimensionalMeasurement(value: 10.0, dimensions: DimensionalExponents(time: 1)) 131 | 132 | let speed = distance / time 133 | #expect(speed.value == 10.0) 134 | #expect(speed.dimensions == DimensionalExponents(length: 1, time: -1)) 135 | } 136 | 137 | @Test("Power Operation") 138 | func power() { 139 | let length = DimensionalMeasurement(value: 10.0, dimensions: DimensionalExponents(length: 1)) 140 | 141 | let area = length.power(2) 142 | #expect(area.value == 100.0) 143 | #expect(area.dimensions == DimensionalExponents(length: 2)) 144 | 145 | let volume = length.power(3) 146 | #expect(volume.value == 1000.0) 147 | #expect(volume.dimensions == DimensionalExponents(length: 3)) 148 | } 149 | 150 | @Test("Square Root") 151 | func squareRoot() { 152 | let area = DimensionalMeasurement(value: 100.0, dimensions: DimensionalExponents(length: 2)) 153 | 154 | let length = area.squareRoot() 155 | #expect(length != nil) 156 | #expect(length?.value == 10.0) 157 | #expect(length?.dimensions == DimensionalExponents(length: 1)) 158 | 159 | // Test invalid square root (non-even exponents) 160 | let velocity = DimensionalMeasurement(value: 10.0, dimensions: DimensionalExponents(length: 1, time: -1)) 161 | #expect(velocity.squareRoot() == nil) 162 | } 163 | 164 | @Test("Type Conversion") 165 | func conversion() { 166 | let dimensionalLength = DimensionalMeasurement(value: 10.0, dimensions: DimensionalExponents(length: 1)) 167 | 168 | // Convert to Length 169 | let length = dimensionalLength.convert(to: UnitLength.self) 170 | #expect(length != nil) 171 | #expect(length?.value == 10.0) 172 | #expect(length?.unit == UnitLength.meters) 173 | 174 | // Try to convert to incompatible unit 175 | #expect(dimensionalLength.convert(to: UnitMass.self) == nil) 176 | } 177 | 178 | @Test("Convenience Accessors") 179 | func convenienceAccessors() { 180 | let dimensionalLength = DimensionalMeasurement(value: 10.0, dimensions: DimensionalExponents(length: 1)) 181 | 182 | // Test asLength 183 | #expect(dimensionalLength.asLength != nil) 184 | #expect(dimensionalLength.asLength?.value == 10.0) 185 | #expect(dimensionalLength.asLength?.unit == UnitLength.meters) 186 | 187 | // Test asArea (should be nil) 188 | #expect(dimensionalLength.asArea == nil) 189 | 190 | // Create area measurement 191 | let dimensionalArea = DimensionalMeasurement(value: 100.0, dimensions: DimensionalExponents(length: 2)) 192 | 193 | // Test asArea 194 | #expect(dimensionalArea.asArea != nil) 195 | #expect(dimensionalArea.asArea?.value == 100.0) 196 | #expect(dimensionalArea.asArea?.unit == UnitArea.squareMeters) 197 | } 198 | 199 | @Test("Dimensionless Quantity Creation") 200 | func dimensionlessQuantity() { 201 | let half = DimensionalMeasurement.dimensionless(0.5) 202 | 203 | #expect(half.value == 0.5) 204 | #expect(half.dimensions.isDimensionless) 205 | } 206 | } 207 | 208 | @Suite("Integration") 209 | struct IntegrationTests { 210 | 211 | @Test("Operator Overloads with Foundation Measurements") 212 | func operatorOverloadsWithFoundationMeasurements() { 213 | let speed = Measurement(value: 60.0, unit: UnitSpeed.kilometersPerHour) 214 | let time = Measurement(value: 2.5, unit: UnitDuration.hours) 215 | 216 | // Test multiplication 217 | let distance = speed * time 218 | 219 | #expect(distance.dimensions == UnitLength.dimensions) 220 | 221 | // Check value (60 km/h * 2.5 h = 150 km) 222 | // Since we're working with base units, we need to check the equivalent in meters 223 | let expectedMeters = 150_000.0 // 150 km in meters 224 | 225 | // Use a larger tolerance to account for floating point precision issues 226 | #expect(abs(distance.value - expectedMeters) < 0.15) 227 | 228 | // Convert time to DimensionalMeasurement for division 229 | let timeDimensional = DimensionalMeasurement(time) 230 | 231 | // Test division - distance is already DimensionalMeasurement 232 | let calculatedSpeed = distance / timeDimensional 233 | 234 | #expect(calculatedSpeed.dimensions == UnitSpeed.dimensions) 235 | 236 | // Convert to base units for comparison 237 | let speedInBaseUnits = speed.converted(to: .metersPerSecond).value 238 | #expect(abs(calculatedSpeed.value - speedInBaseUnits) < 0.15) 239 | } 240 | 241 | @Test("Physics Calculations with Dimensional Analysis") 242 | func physicsCalculations() { 243 | // Kinetic energy = 0.5 * m * v² 244 | let mass = Measurement(value: 2.0, unit: UnitMass.kilograms) 245 | let velocity = Measurement(value: 10.0, unit: UnitSpeed.metersPerSecond) 246 | 247 | let half = DimensionalMeasurement.dimensionless(0.5) 248 | let velocitySquared = DimensionalMeasurement(velocity).power(2) 249 | 250 | // Calculate kinetic energy 251 | let kineticEnergy = half * DimensionalMeasurement(mass) * velocitySquared 252 | 253 | // Check dimensions 254 | #expect(kineticEnergy.dimensions == UnitEnergy.dimensions) 255 | 256 | // Check value (0.5 * 2.0 kg * (10 m/s)² = 100 J) 257 | let energyInJoules = kineticEnergy.asEnergy?.converted(to: .joules) 258 | #expect(energyInJoules != nil) 259 | #expect(abs(energyInJoules!.value - 100.0) < 0.1) 260 | } 261 | } 262 | 263 | @Suite("Protocol Conformance") 264 | struct ProtocolConformanceTests { 265 | 266 | @Test("Equatable Implementation") 267 | func equatable() { 268 | // Create two equal measurements 269 | let length1 = DimensionalMeasurement(value: 10.0, dimensions: DimensionalExponents(length: 1)) 270 | let length2 = DimensionalMeasurement(value: 10.0, dimensions: DimensionalExponents(length: 1)) 271 | 272 | // Test equality 273 | #expect(length1 == length2) 274 | 275 | // Create different measurements 276 | let length3 = DimensionalMeasurement(value: 20.0, dimensions: DimensionalExponents(length: 1)) 277 | #expect(length1 != length3) 278 | 279 | // Test different dimensions 280 | let time = DimensionalMeasurement(value: 10.0, dimensions: DimensionalExponents(time: 1)) 281 | #expect(length1 != time) 282 | } 283 | 284 | @Test("Hashable Implementation") 285 | func hashable() { 286 | // Create measurement 287 | let length = DimensionalMeasurement(value: 10.0, dimensions: DimensionalExponents(length: 1)) 288 | 289 | // Use as dictionary key 290 | var dict: [DimensionalMeasurement: String] = [:] 291 | dict[length] = "Length measurement" 292 | 293 | // Retrieve value 294 | #expect(dict[length] == "Length measurement") 295 | } 296 | 297 | @Test("Comparable Implementation") 298 | func comparable() { 299 | // Create measurements 300 | let length1 = DimensionalMeasurement(value: 10.0, dimensions: DimensionalExponents(length: 1)) 301 | let length2 = DimensionalMeasurement(value: 20.0, dimensions: DimensionalExponents(length: 1)) 302 | 303 | // Test comparison 304 | #expect(length1 < length2) 305 | #expect(length2 > length1) 306 | 307 | // Sort array 308 | let unsorted = [length2, length1] 309 | let sorted = unsorted.sorted() 310 | #expect(sorted == [length1, length2]) 311 | } 312 | } 313 | } 314 | -------------------------------------------------------------------------------- /Tests/SwiftMeasurementTests/Measurement+ExtensionsTests.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Testing 3 | @testable import SwiftMeasurement 4 | 5 | @Suite("Measurement Initializers Tests") 6 | struct MeasurementInitializersTests { 7 | 8 | @Test("Initialize with Int value") 9 | func testIntInitializer() { 10 | let lengthFromInt = Measurement(value: 5, unit: UnitLength.meters) 11 | #expect(lengthFromInt.value == 5.0) 12 | #expect(lengthFromInt.unit == UnitLength.meters) 13 | 14 | let massFromInt = Measurement(value: 10, unit: UnitMass.kilograms) 15 | #expect(massFromInt.value == 10.0) 16 | #expect(massFromInt.unit == UnitMass.kilograms) 17 | } 18 | 19 | @Test("Initialize with Float value") 20 | func testFloatInitializer() { 21 | let lengthFromFloat = Measurement(value: Float(3.14), unit: UnitLength.centimeters) 22 | #expect(lengthFromFloat.value == 3.140000104904175) // Float precision 23 | #expect(lengthFromFloat.unit == UnitLength.centimeters) 24 | 25 | let massFromFloat = Measurement(value: Float(2.5), unit: UnitMass.grams) 26 | #expect(massFromFloat.value == 2.5) 27 | #expect(massFromFloat.unit == UnitMass.grams) 28 | } 29 | 30 | @Test("Initialize with large Int values") 31 | func testLargeIntInitializer() { 32 | let bigNumber = 1_000_000 33 | let distance = Measurement(value: bigNumber, unit: UnitLength.kilometers) 34 | #expect(distance.value == 1_000_000.0) 35 | #expect(distance.unit == UnitLength.kilometers) 36 | } 37 | 38 | @Test("Initialize with negative values") 39 | func testNegativeValueInitializers() { 40 | let negativeInt = Measurement(value: -5, unit: UnitLength.meters) 41 | #expect(negativeInt.value == -5.0) 42 | 43 | let negativeFloat = Measurement(value: Float(-3.14), unit: UnitMass.grams) 44 | #expect(negativeFloat.value < 0) 45 | #expect(negativeFloat.value == Double(Float(-3.14))) 46 | } 47 | } 48 | 49 | @Suite("Measurement Literals Tests") 50 | struct MeasurementLiteralsTests { 51 | 52 | @Test("Float literals default to base units") 53 | func testFloatLiterals() { 54 | let distance: Measurement = 3.5 // Should default to meters 55 | #expect(distance.value == 3.5) 56 | #expect(distance.unit == UnitLength.meters) 57 | } 58 | 59 | @Test("Integer literals default to base units") 60 | func testIntegerLiterals() { 61 | let weight: Measurement = 10 // Should default to kilograms 62 | #expect(weight.value == 10.0) 63 | #expect(weight.unit == UnitMass.kilograms) 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Tests/SwiftMeasurementTests/SwiftMeasurementTests.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Testing 3 | @testable import SwiftMeasurement 4 | 5 | // MARK: - Basic Conversion Tests 6 | 7 | @Suite("Double Measurement Conversion Tests") 8 | struct DoubleMeasurementTests { 9 | 10 | @Test("Basic measurement conversions with Double") 11 | func testBasicConversions() async throws { 12 | let a: Double = 3 13 | let b: Double = 4 14 | 15 | #expect(a.kilometers == Measurement(value: a, unit: .kilometers)) 16 | #expect(b.seconds == Measurement(value: b, unit: .seconds)) 17 | } 18 | 19 | @Test("Addition with Double") 20 | func testAddition() async throws { 21 | let a: Double = 3 22 | let b: Double = 4 23 | let c: Double = 7 24 | 25 | #expect(c.grams == a.grams + b.grams) 26 | } 27 | 28 | @Test("Subtraction with Double") 29 | func testSubtraction() async throws { 30 | let a: Double = 3 31 | let b: Double = 4 32 | let c: Double = 7 33 | 34 | #expect(a.acres == c.acres - b.acres) 35 | } 36 | 37 | @Test("Multiplication with Double") 38 | func testMultiplication() async throws { 39 | let c: Double = 7 40 | 41 | #expect(c.liters * 8 == Measurement(value: 56, unit: UnitVolume.liters)) 42 | } 43 | 44 | @Test("Division with Double") 45 | func testDivision() async throws { 46 | let c: Double = 7 47 | 48 | #expect(c.metersPerSecond / 7 == Measurement(value: 1, unit: UnitSpeed.metersPerSecond)) 49 | } 50 | } 51 | 52 | @Suite("Float Measurement Conversion Tests") 53 | struct FloatMeasurementTests { 54 | 55 | @Test("Basic measurement conversions with Float") 56 | func testBasicConversions() async throws { 57 | let a: Float = 3 58 | let b: Float = 4 59 | 60 | #expect(a.kilometers == Measurement(value: a, unit: .kilometers)) 61 | #expect(b.seconds == Measurement(value: b, unit: .seconds)) 62 | } 63 | 64 | @Test("Addition with Float") 65 | func testAddition() async throws { 66 | let a: Float = 3 67 | let b: Float = 4 68 | let c: Float = 7 69 | 70 | #expect(c.grams == a.grams + b.grams) 71 | } 72 | 73 | @Test("Subtraction with Float") 74 | func testSubtraction() async throws { 75 | let a: Float = 3 76 | let b: Float = 4 77 | let c: Float = 7 78 | 79 | #expect(a.acres == c.acres - b.acres) 80 | } 81 | 82 | @Test("Multiplication with Float") 83 | func testMultiplication() async throws { 84 | let c: Float = 7 85 | 86 | #expect(c.liters * 8 == Measurement(value: 56, unit: UnitVolume.liters)) 87 | } 88 | 89 | @Test("Division with Float") 90 | func testDivision() async throws { 91 | let c: Float = 7 92 | 93 | #expect(c.metersPerSecond / 7 == Measurement(value: 1, unit: UnitSpeed.metersPerSecond)) 94 | } 95 | } 96 | 97 | @Suite("Int Measurement Conversion Tests") 98 | struct IntMeasurementTests { 99 | 100 | @Test("Basic measurement conversions with Int") 101 | func testBasicConversions() async throws { 102 | let a: Int = 3 103 | let b: Int = 4 104 | 105 | #expect(a.kilometers == Measurement(value: a, unit: .kilometers)) 106 | #expect(b.seconds == Measurement(value: b, unit: .seconds)) 107 | } 108 | 109 | @Test("Addition with Int") 110 | func testAddition() async throws { 111 | let a: Int = 3 112 | let b: Int = 4 113 | let c: Int = 7 114 | 115 | #expect(c.grams == a.grams + b.grams) 116 | } 117 | 118 | @Test("Subtraction with Int") 119 | func testSubtraction() async throws { 120 | let a: Int = 3 121 | let b: Int = 4 122 | let c: Int = 7 123 | 124 | #expect(a.acres == c.acres - b.acres) 125 | } 126 | 127 | @Test("Multiplication with Int") 128 | func testMultiplication() async throws { 129 | let c: Int = 7 130 | 131 | #expect(c.liters * 8 == Measurement(value: 56, unit: UnitVolume.liters)) 132 | } 133 | 134 | @Test("Division with Int") 135 | func testDivision() async throws { 136 | let c: Int = 7 137 | 138 | #expect(c.metersPerSecond / 7 == Measurement(value: 1, unit: UnitSpeed.metersPerSecond)) 139 | } 140 | } 141 | 142 | // MARK: - Advanced Tests 143 | 144 | @Suite("Mixed Type Operations") 145 | struct MixedTypeMeasurementTests { 146 | 147 | @Test("Mixed type arithmetic operations") 148 | func testMixedTypeArithmetic() async throws { 149 | let a: Double = 3 150 | let b: Float = 4 151 | let c: Int = 7 152 | 153 | // Addition across types 154 | #expect(a.meters + b.meters == Measurement(value: 7, unit: UnitLength.meters)) 155 | #expect(b.liters + c.liters == Measurement(value: 11, unit: UnitVolume.liters)) 156 | #expect(c.seconds + a.seconds == Measurement(value: 10, unit: UnitDuration.seconds)) 157 | } 158 | 159 | @Test("Temperature conversion across types") 160 | func testTemperatureConversion() async throws { 161 | let doubleTemp = 32.0.fahrenheit 162 | let floatTemp: Float = 0 163 | let intTemp: Int = 0 164 | 165 | // Use a small epsilon for floating-point comparisons 166 | let epsilon = 0.0001 167 | 168 | #expect(abs(doubleTemp.value - floatTemp.celsius.converted(to: .fahrenheit).value) < epsilon) 169 | #expect(abs(doubleTemp.value - intTemp.celsius.converted(to: .fahrenheit).value) < epsilon) 170 | } 171 | } 172 | 173 | @Suite("Type Inference Tests") 174 | struct TypeInferenceTests { 175 | 176 | @Test("Type inference for measurement creation") 177 | func testMeasurementTypeInference() async throws { 178 | // These should all compile and work without explicit type annotations 179 | let length1 = 10.meters 180 | let length2 = Float(5).kilometers 181 | let length3 = Int(2).miles 182 | 183 | let time1 = 60.seconds 184 | let time2 = Float(1.5).hours 185 | let time3 = Int(24).hours 186 | 187 | #expect(length1.unit == UnitLength.meters) 188 | #expect(length2.unit == UnitLength.kilometers) 189 | #expect(length3.unit == UnitLength.miles) 190 | 191 | #expect(time1.unit == UnitDuration.seconds) 192 | #expect(time2.unit == UnitDuration.hours) 193 | #expect(time3.unit == UnitDuration.hours) 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /Tests/SwiftMeasurementTests/Units/UnitAccelerationTests.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Testing 3 | @testable import SwiftMeasurement 4 | 5 | @Test("All acceleration units properties are properly mapped") 6 | func testAccelerationUnits() { 7 | let value = 1 8 | 9 | #expect(value.metersPerSecondSquared == Measurement(value: value, unit: .metersPerSecondSquared)) 10 | #expect(value.gravity == Measurement(value: value, unit: .gravity)) 11 | } 12 | -------------------------------------------------------------------------------- /Tests/SwiftMeasurementTests/Units/UnitAngleTests.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Testing 3 | @testable import SwiftMeasurement 4 | 5 | @Test("All angle units properties are properly mapped") 6 | func testAngleUnits() { 7 | let value = 1 8 | 9 | #expect(value.degrees == Measurement(value: value, unit: .degrees)) 10 | #expect(value.arcMinutes == Measurement(value: value, unit: .arcMinutes)) 11 | #expect(value.arcSeconds == Measurement(value: value, unit: .arcSeconds)) 12 | #expect(value.radians == Measurement(value: value, unit: .radians)) 13 | #expect(value.gradians == Measurement(value: value, unit: .gradians)) 14 | #expect(value.revolutions == Measurement(value: value, unit: .revolutions)) 15 | } 16 | -------------------------------------------------------------------------------- /Tests/SwiftMeasurementTests/Units/UnitAreaTests.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Testing 3 | @testable import SwiftMeasurement 4 | 5 | @Test("All area units properties are properly mapped") 6 | func testAreaUnits() { 7 | let value = 1 8 | 9 | #expect(value.squareMegameters == Measurement(value: value, unit: .squareMegameters)) 10 | #expect(value.squareKilometers == Measurement(value: value, unit: .squareKilometers)) 11 | #expect(value.squareMeters == Measurement(value: value, unit: .squareMeters)) 12 | #expect(value.squareCentimeters == Measurement(value: value, unit: .squareCentimeters)) 13 | #expect(value.squareMillimeters == Measurement(value: value, unit: .squareMillimeters)) 14 | #expect(value.squareMicrometers == Measurement(value: value, unit: .squareMicrometers)) 15 | #expect(value.squareNanometers == Measurement(value: value, unit: .squareNanometers)) 16 | #expect(value.squareInches == Measurement(value: value, unit: .squareInches)) 17 | #expect(value.squareFeet == Measurement(value: value, unit: .squareFeet)) 18 | #expect(value.squareYards == Measurement(value: value, unit: .squareYards)) 19 | #expect(value.squareMiles == Measurement(value: value, unit: .squareMiles)) 20 | #expect(value.acres == Measurement(value: value, unit: .acres)) 21 | #expect(value.ares == Measurement(value: value, unit: .ares)) 22 | #expect(value.hectares == Measurement(value: value, unit: .hectares)) 23 | } 24 | -------------------------------------------------------------------------------- /Tests/SwiftMeasurementTests/Units/UnitConcentrationMassTests.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Testing 3 | @testable import SwiftMeasurement 4 | 5 | @Test("All concentrationmass units properties are properly mapped") 6 | func testConcentrationMassUnits() { 7 | let value = 1 8 | 9 | #expect(value.gramsPerLiter == Measurement(value: value, unit: .gramsPerLiter)) 10 | #expect(value.milligramsPerDeciliter == Measurement(value: value, unit: .milligramsPerDeciliter)) 11 | } 12 | -------------------------------------------------------------------------------- /Tests/SwiftMeasurementTests/Units/UnitDispersionTests.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Testing 3 | @testable import SwiftMeasurement 4 | 5 | @Test("All dispersion units properties are properly mapped") 6 | func testDispersionUnits() { 7 | let value = 1 8 | 9 | #expect(value.partsPerMillion == Measurement(value: value, unit: .partsPerMillion)) 10 | } 11 | -------------------------------------------------------------------------------- /Tests/SwiftMeasurementTests/Units/UnitDurationTests.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Testing 3 | @testable import SwiftMeasurement 4 | 5 | @Test("All duration units properties are properly mapped") 6 | func testDurationUnits() { 7 | let value = 1 8 | 9 | #expect(value.seconds == Measurement(value: value, unit: .seconds)) 10 | #expect(value.minutes == Measurement(value: value, unit: .minutes)) 11 | #expect(value.hours == Measurement(value: value, unit: .hours)) 12 | #expect(value.milliseconds == Measurement(value: value, unit: .milliseconds)) 13 | #expect(value.microseconds == Measurement(value: value, unit: .microseconds)) 14 | #expect(value.nanoseconds == Measurement(value: value, unit: .nanoseconds)) 15 | #expect(value.picoseconds == Measurement(value: value, unit: .picoseconds)) 16 | } 17 | -------------------------------------------------------------------------------- /Tests/SwiftMeasurementTests/Units/UnitElectricChargeTests.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Testing 3 | @testable import SwiftMeasurement 4 | 5 | @Test("All electriccharge units properties are properly mapped") 6 | func testElectricChargeUnits() { 7 | let value = 1 8 | 9 | #expect(value.coulombs == Measurement(value: value, unit: .coulombs)) 10 | #expect(value.megaampereHours == Measurement(value: value, unit: .megaampereHours)) 11 | #expect(value.kiloampereHours == Measurement(value: value, unit: .kiloampereHours)) 12 | #expect(value.ampereHours == Measurement(value: value, unit: .ampereHours)) 13 | #expect(value.milliampereHours == Measurement(value: value, unit: .milliampereHours)) 14 | #expect(value.microampereHours == Measurement(value: value, unit: .microampereHours)) 15 | } 16 | -------------------------------------------------------------------------------- /Tests/SwiftMeasurementTests/Units/UnitElectricCurrentTests.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Testing 3 | @testable import SwiftMeasurement 4 | 5 | @Test("All electriccurrent units properties are properly mapped") 6 | func testElectricCurrentUnits() { 7 | let value = 1 8 | 9 | #expect(value.megaamperes == Measurement(value: value, unit: .megaamperes)) 10 | #expect(value.kiloamperes == Measurement(value: value, unit: .kiloamperes)) 11 | #expect(value.amperes == Measurement(value: value, unit: .amperes)) 12 | #expect(value.milliamperes == Measurement(value: value, unit: .milliamperes)) 13 | #expect(value.microamperes == Measurement(value: value, unit: .microamperes)) 14 | } 15 | -------------------------------------------------------------------------------- /Tests/SwiftMeasurementTests/Units/UnitElectricPotentialDifferenceTests.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Testing 3 | @testable import SwiftMeasurement 4 | 5 | @Test("All electricpotentialdifference units properties are properly mapped") 6 | func testElectricPotentialDifferenceUnits() { 7 | let value = 1 8 | 9 | #expect(value.megavolts == Measurement(value: value, unit: .megavolts)) 10 | #expect(value.kilovolts == Measurement(value: value, unit: .kilovolts)) 11 | #expect(value.volts == Measurement(value: value, unit: .volts)) 12 | #expect(value.millivolts == Measurement(value: value, unit: .millivolts)) 13 | #expect(value.microvolts == Measurement(value: value, unit: .microvolts)) 14 | } 15 | -------------------------------------------------------------------------------- /Tests/SwiftMeasurementTests/Units/UnitElectricResistanceTests.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Testing 3 | @testable import SwiftMeasurement 4 | 5 | @Test("All electricresistance units properties are properly mapped") 6 | func testElectricResistanceUnits() { 7 | let value = 1 8 | 9 | #expect(value.megaohms == Measurement(value: value, unit: .megaohms)) 10 | #expect(value.kiloohms == Measurement(value: value, unit: .kiloohms)) 11 | #expect(value.ohms == Measurement(value: value, unit: .ohms)) 12 | #expect(value.milliohms == Measurement(value: value, unit: .milliohms)) 13 | #expect(value.microohms == Measurement(value: value, unit: .microohms)) 14 | } 15 | -------------------------------------------------------------------------------- /Tests/SwiftMeasurementTests/Units/UnitEnergyTests.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Testing 3 | @testable import SwiftMeasurement 4 | 5 | @Test("All energy units properties are properly mapped") 6 | func testEnergyUnits() { 7 | let value = 1 8 | 9 | #expect(value.kilojoules == Measurement(value: value, unit: .kilojoules)) 10 | #expect(value.joules == Measurement(value: value, unit: .joules)) 11 | #expect(value.kilocalories == Measurement(value: value, unit: .kilocalories)) 12 | #expect(value.calories == Measurement(value: value, unit: .calories)) 13 | #expect(value.kilowattHours == Measurement(value: value, unit: .kilowattHours)) 14 | } 15 | -------------------------------------------------------------------------------- /Tests/SwiftMeasurementTests/Units/UnitFrequencyTests.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Testing 3 | @testable import SwiftMeasurement 4 | 5 | @Test("All frequency units properties are properly mapped") 6 | func testFrequencyUnits() { 7 | let value = 1 8 | 9 | #expect(value.terahertz == Measurement(value: value, unit: .terahertz)) 10 | #expect(value.gigahertz == Measurement(value: value, unit: .gigahertz)) 11 | #expect(value.megahertz == Measurement(value: value, unit: .megahertz)) 12 | #expect(value.kilohertz == Measurement(value: value, unit: .kilohertz)) 13 | #expect(value.hertz == Measurement(value: value, unit: .hertz)) 14 | #expect(value.millihertz == Measurement(value: value, unit: .millihertz)) 15 | #expect(value.microhertz == Measurement(value: value, unit: .microhertz)) 16 | #expect(value.nanohertz == Measurement(value: value, unit: .nanohertz)) 17 | #expect(value.framesPerSecond == Measurement(value: value, unit: .framesPerSecond)) 18 | } 19 | -------------------------------------------------------------------------------- /Tests/SwiftMeasurementTests/Units/UnitFuelEfficiencyTests.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Testing 3 | @testable import SwiftMeasurement 4 | 5 | @Test("All fuelefficiency units properties are properly mapped") 6 | func testFuelEfficiencyUnits() { 7 | let value = 1 8 | 9 | #expect(value.litersPer100Kilometers == Measurement(value: value, unit: .litersPer100Kilometers)) 10 | #expect(value.milesPerImperialGallon == Measurement(value: value, unit: .milesPerImperialGallon)) 11 | #expect(value.milesPerGallon == Measurement(value: value, unit: .milesPerGallon)) 12 | } 13 | -------------------------------------------------------------------------------- /Tests/SwiftMeasurementTests/Units/UnitIlluminanceTests.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Testing 3 | @testable import SwiftMeasurement 4 | 5 | @Test("All illuminance units properties are properly mapped") 6 | func testIlluminanceUnits() { 7 | let value = 1 8 | 9 | #expect(value.lux == Measurement(value: value, unit: .lux)) 10 | } 11 | -------------------------------------------------------------------------------- /Tests/SwiftMeasurementTests/Units/UnitInformationStorageTests.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Testing 3 | @testable import SwiftMeasurement 4 | 5 | @Test("All informationstorage units properties are properly mapped") 6 | func testInformationStorageUnits() { 7 | let value = 1 8 | 9 | #expect(value.bytes == Measurement(value: value, unit: .bytes)) 10 | #expect(value.bits == Measurement(value: value, unit: .bits)) 11 | #expect(value.nibbles == Measurement(value: value, unit: .nibbles)) 12 | #expect(value.yottabytes == Measurement(value: value, unit: .yottabytes)) 13 | #expect(value.zettabytes == Measurement(value: value, unit: .zettabytes)) 14 | #expect(value.exabytes == Measurement(value: value, unit: .exabytes)) 15 | #expect(value.petabytes == Measurement(value: value, unit: .petabytes)) 16 | #expect(value.terabytes == Measurement(value: value, unit: .terabytes)) 17 | #expect(value.gigabytes == Measurement(value: value, unit: .gigabytes)) 18 | #expect(value.megabytes == Measurement(value: value, unit: .megabytes)) 19 | #expect(value.kilobytes == Measurement(value: value, unit: .kilobytes)) 20 | #expect(value.yottabits == Measurement(value: value, unit: .yottabits)) 21 | #expect(value.zettabits == Measurement(value: value, unit: .zettabits)) 22 | #expect(value.exabits == Measurement(value: value, unit: .exabits)) 23 | #expect(value.petabits == Measurement(value: value, unit: .petabits)) 24 | #expect(value.terabits == Measurement(value: value, unit: .terabits)) 25 | #expect(value.gigabits == Measurement(value: value, unit: .gigabits)) 26 | #expect(value.megabits == Measurement(value: value, unit: .megabits)) 27 | #expect(value.kilobits == Measurement(value: value, unit: .kilobits)) 28 | #expect(value.yobibytes == Measurement(value: value, unit: .yobibytes)) 29 | #expect(value.zebibytes == Measurement(value: value, unit: .zebibytes)) 30 | #expect(value.exbibytes == Measurement(value: value, unit: .exbibytes)) 31 | #expect(value.pebibytes == Measurement(value: value, unit: .pebibytes)) 32 | #expect(value.tebibytes == Measurement(value: value, unit: .tebibytes)) 33 | #expect(value.gibibytes == Measurement(value: value, unit: .gibibytes)) 34 | #expect(value.mebibytes == Measurement(value: value, unit: .mebibytes)) 35 | #expect(value.kibibytes == Measurement(value: value, unit: .kibibytes)) 36 | #expect(value.yobibits == Measurement(value: value, unit: .yobibits)) 37 | #expect(value.zebibits == Measurement(value: value, unit: .zebibits)) 38 | #expect(value.exbibits == Measurement(value: value, unit: .exbibits)) 39 | #expect(value.pebibits == Measurement(value: value, unit: .pebibits)) 40 | #expect(value.tebibits == Measurement(value: value, unit: .tebibits)) 41 | #expect(value.gibibits == Measurement(value: value, unit: .gibibits)) 42 | #expect(value.mebibits == Measurement(value: value, unit: .mebibits)) 43 | #expect(value.kibibits == Measurement(value: value, unit: .kibibits)) 44 | } 45 | -------------------------------------------------------------------------------- /Tests/SwiftMeasurementTests/Units/UnitLengthTests.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Testing 3 | @testable import SwiftMeasurement 4 | 5 | @Test("All length units properties are properly mapped") 6 | func testLengthUnits() { 7 | let value = 1 8 | 9 | #expect(value.megameters == Measurement(value: value, unit: .megameters)) 10 | #expect(value.kilometers == Measurement(value: value, unit: .kilometers)) 11 | #expect(value.hectometers == Measurement(value: value, unit: .hectometers)) 12 | #expect(value.decameters == Measurement(value: value, unit: .decameters)) 13 | #expect(value.meters == Measurement(value: value, unit: .meters)) 14 | #expect(value.decimeters == Measurement(value: value, unit: .decimeters)) 15 | #expect(value.centimeters == Measurement(value: value, unit: .centimeters)) 16 | #expect(value.millimeters == Measurement(value: value, unit: .millimeters)) 17 | #expect(value.micrometers == Measurement(value: value, unit: .micrometers)) 18 | #expect(value.nanometers == Measurement(value: value, unit: .nanometers)) 19 | #expect(value.picometers == Measurement(value: value, unit: .picometers)) 20 | #expect(value.inches == Measurement(value: value, unit: .inches)) 21 | #expect(value.feet == Measurement(value: value, unit: .feet)) 22 | #expect(value.yards == Measurement(value: value, unit: .yards)) 23 | #expect(value.miles == Measurement(value: value, unit: .miles)) 24 | #expect(value.scandinavianMiles == Measurement(value: value, unit: .scandinavianMiles)) 25 | #expect(value.lightyears == Measurement(value: value, unit: .lightyears)) 26 | #expect(value.nauticalMiles == Measurement(value: value, unit: .nauticalMiles)) 27 | #expect(value.fathoms == Measurement(value: value, unit: .fathoms)) 28 | #expect(value.furlongs == Measurement(value: value, unit: .furlongs)) 29 | #expect(value.astronomicalUnits == Measurement(value: value, unit: .astronomicalUnits)) 30 | #expect(value.parsecs == Measurement(value: value, unit: .parsecs)) 31 | } 32 | -------------------------------------------------------------------------------- /Tests/SwiftMeasurementTests/Units/UnitMassTests.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Testing 3 | @testable import SwiftMeasurement 4 | 5 | @Test("All mass units properties are properly mapped") 6 | func testMassUnits() { 7 | let value = 1 8 | 9 | #expect(value.kilograms == Measurement(value: value, unit: .kilograms)) 10 | #expect(value.grams == Measurement(value: value, unit: .grams)) 11 | #expect(value.decigrams == Measurement(value: value, unit: .decigrams)) 12 | #expect(value.centigrams == Measurement(value: value, unit: .centigrams)) 13 | #expect(value.milligrams == Measurement(value: value, unit: .milligrams)) 14 | #expect(value.micrograms == Measurement(value: value, unit: .micrograms)) 15 | #expect(value.nanograms == Measurement(value: value, unit: .nanograms)) 16 | #expect(value.picograms == Measurement(value: value, unit: .picograms)) 17 | #expect(value.ounces == Measurement(value: value, unit: .ounces)) 18 | #expect(value.pounds == Measurement(value: value, unit: .pounds)) 19 | #expect(value.stones == Measurement(value: value, unit: .stones)) 20 | #expect(value.metricTons == Measurement(value: value, unit: .metricTons)) 21 | #expect(value.shortTons == Measurement(value: value, unit: .shortTons)) 22 | #expect(value.carats == Measurement(value: value, unit: .carats)) 23 | #expect(value.ouncesTroy == Measurement(value: value, unit: .ouncesTroy)) 24 | #expect(value.slugs == Measurement(value: value, unit: .slugs)) 25 | } 26 | -------------------------------------------------------------------------------- /Tests/SwiftMeasurementTests/Units/UnitPowerTests.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Testing 3 | @testable import SwiftMeasurement 4 | 5 | @Test("All power units properties are properly mapped") 6 | func testPowerUnits() { 7 | let value = 1 8 | 9 | #expect(value.terawatts == Measurement(value: value, unit: .terawatts)) 10 | #expect(value.gigawatts == Measurement(value: value, unit: .gigawatts)) 11 | #expect(value.megawatts == Measurement(value: value, unit: .megawatts)) 12 | #expect(value.kilowatts == Measurement(value: value, unit: .kilowatts)) 13 | #expect(value.watts == Measurement(value: value, unit: .watts)) 14 | #expect(value.milliwatts == Measurement(value: value, unit: .milliwatts)) 15 | #expect(value.microwatts == Measurement(value: value, unit: .microwatts)) 16 | #expect(value.nanowatts == Measurement(value: value, unit: .nanowatts)) 17 | #expect(value.picowatts == Measurement(value: value, unit: .picowatts)) 18 | #expect(value.femtowatts == Measurement(value: value, unit: .femtowatts)) 19 | #expect(value.horsepower == Measurement(value: value, unit: .horsepower)) 20 | } 21 | -------------------------------------------------------------------------------- /Tests/SwiftMeasurementTests/Units/UnitPressureTests.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Testing 3 | @testable import SwiftMeasurement 4 | 5 | @Test("All pressure units properties are properly mapped") 6 | func testPressureUnits() { 7 | let value = 1 8 | 9 | #expect(value.newtonsPerMetersSquared == Measurement(value: value, unit: .newtonsPerMetersSquared)) 10 | #expect(value.gigapascals == Measurement(value: value, unit: .gigapascals)) 11 | #expect(value.megapascals == Measurement(value: value, unit: .megapascals)) 12 | #expect(value.kilopascals == Measurement(value: value, unit: .kilopascals)) 13 | #expect(value.hectopascals == Measurement(value: value, unit: .hectopascals)) 14 | #expect(value.inchesOfMercury == Measurement(value: value, unit: .inchesOfMercury)) 15 | #expect(value.bars == Measurement(value: value, unit: .bars)) 16 | #expect(value.millibars == Measurement(value: value, unit: .millibars)) 17 | #expect(value.millimetersOfMercury == Measurement(value: value, unit: .millimetersOfMercury)) 18 | #expect(value.poundsForcePerSquareInch == Measurement(value: value, unit: .poundsForcePerSquareInch)) 19 | } 20 | -------------------------------------------------------------------------------- /Tests/SwiftMeasurementTests/Units/UnitSpeedTests.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Testing 3 | @testable import SwiftMeasurement 4 | 5 | @Test("All speed units properties are properly mapped") 6 | func testSpeedUnits() { 7 | let value = 1 8 | 9 | #expect(value.metersPerSecond == Measurement(value: value, unit: .metersPerSecond)) 10 | #expect(value.kilometersPerHour == Measurement(value: value, unit: .kilometersPerHour)) 11 | #expect(value.milesPerHour == Measurement(value: value, unit: .milesPerHour)) 12 | #expect(value.knots == Measurement(value: value, unit: .knots)) 13 | } 14 | -------------------------------------------------------------------------------- /Tests/SwiftMeasurementTests/Units/UnitTemperatureTests.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Testing 3 | @testable import SwiftMeasurement 4 | 5 | @Test("All temperature units properties are properly mapped") 6 | func testTemperatureUnits() { 7 | let value = 1 8 | 9 | #expect(value.kelvin == Measurement(value: value, unit: .kelvin)) 10 | #expect(value.celsius == Measurement(value: value, unit: .celsius)) 11 | #expect(value.fahrenheit == Measurement(value: value, unit: .fahrenheit)) 12 | } 13 | -------------------------------------------------------------------------------- /Tests/SwiftMeasurementTests/Units/UnitVolumeTests.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Testing 3 | @testable import SwiftMeasurement 4 | 5 | @Test("All volume units properties are properly mapped") 6 | func testVolumeUnits() { 7 | let value = 1 8 | 9 | #expect(value.megaliters == Measurement(value: value, unit: .megaliters)) 10 | #expect(value.kiloliters == Measurement(value: value, unit: .kiloliters)) 11 | #expect(value.liters == Measurement(value: value, unit: .liters)) 12 | #expect(value.deciliters == Measurement(value: value, unit: .deciliters)) 13 | #expect(value.centiliters == Measurement(value: value, unit: .centiliters)) 14 | #expect(value.milliliters == Measurement(value: value, unit: .milliliters)) 15 | #expect(value.cubicKilometers == Measurement(value: value, unit: .cubicKilometers)) 16 | #expect(value.cubicMeters == Measurement(value: value, unit: .cubicMeters)) 17 | #expect(value.cubicDecimeters == Measurement(value: value, unit: .cubicDecimeters)) 18 | #expect(value.cubicCentimeters == Measurement(value: value, unit: .cubicCentimeters)) 19 | #expect(value.cubicMillimeters == Measurement(value: value, unit: .cubicMillimeters)) 20 | #expect(value.cubicInches == Measurement(value: value, unit: .cubicInches)) 21 | #expect(value.cubicFeet == Measurement(value: value, unit: .cubicFeet)) 22 | #expect(value.cubicYards == Measurement(value: value, unit: .cubicYards)) 23 | #expect(value.cubicMiles == Measurement(value: value, unit: .cubicMiles)) 24 | #expect(value.acreFeet == Measurement(value: value, unit: .acreFeet)) 25 | #expect(value.bushels == Measurement(value: value, unit: .bushels)) 26 | #expect(value.teaspoons == Measurement(value: value, unit: .teaspoons)) 27 | #expect(value.tablespoons == Measurement(value: value, unit: .tablespoons)) 28 | #expect(value.fluidOunces == Measurement(value: value, unit: .fluidOunces)) 29 | #expect(value.cups == Measurement(value: value, unit: .cups)) 30 | #expect(value.pints == Measurement(value: value, unit: .pints)) 31 | #expect(value.quarts == Measurement(value: value, unit: .quarts)) 32 | #expect(value.gallons == Measurement(value: value, unit: .gallons)) 33 | #expect(value.imperialTeaspoons == Measurement(value: value, unit: .imperialTeaspoons)) 34 | #expect(value.imperialTablespoons == Measurement(value: value, unit: .imperialTablespoons)) 35 | #expect(value.imperialFluidOunces == Measurement(value: value, unit: .imperialFluidOunces)) 36 | #expect(value.imperialPints == Measurement(value: value, unit: .imperialPints)) 37 | #expect(value.imperialQuarts == Measurement(value: value, unit: .imperialQuarts)) 38 | #expect(value.imperialGallons == Measurement(value: value, unit: .imperialGallons)) 39 | #expect(value.metricCups == Measurement(value: value, unit: .metricCups)) 40 | } 41 | --------------------------------------------------------------------------------