Handling dimensional numbers with physical units in Swift made easy.

Overview

Dimensional arithmetics in Swift

This package provides an easy and natural way of dealing with physical sizes. Performing complex arithmetics or unit conversion is as easy as using floating point values. Check out the code below, to get a glimpse on what is possible with this package.

let area = 2.4[.m] * 5.86[.inch] // Area of a rectangle 2.4 m x 5.86 ″
let force = 52.36[.lb] * SI.g // Force exceeded by a mass of 52.36 ℔ under gravity

let pressure = force / area // Calculate the pressure
let min_boundary = 2 * sqrt(SI.π * area) // Calculate the minimal boundary of the area

print(pressure.convert(to: .Pa)) // Prints "651.9938206417452 Pa"
print(min_boundary.convert(to: .mm)) // Prints "2118.7329427128902 mm"

TLDR

  • Install this package like any other Swift package using the Swift package manager.
  • Construct an SI number using SI(_ value: Double, _ unit: SI.Unit) or the subscript notation
    let a1 = SI(2.5, .m / .s ** 2) // Creates an SI number of 2.5 m/s²
    let a2 = 2.5[.m / .s ** 2] // Also 2.5 m/s² 
  • Perform any calculations you would do with a double, SI will take care of the rest.
  • To convert an SI number to a desired unit use convert(to: SI.Unit)
  • Define custom units by natural calculation e.g.
    let N = .kg * .m / .s ** 2 // Creates the unit N (1 N = 1 kg·m/s²)
    let lb = SI.Unit("", 0.45359237 * kg) // Creates the unit lb with the name "℔" and 1 ℔ = 0.45359237 kg
  • You can use physical constants provided under SI

Basic usage

Every SI number consists of a value and a unit. When performing arithmetic operations, the unit of a number is considered to ensure physical accuracy and proper conversion. Adding e.g. 1 m to 500 mm will return 1.5 m, while an addition with 1 s will result in an error since the physical dimensions of the units mismatch.

Construction

To construct an SInumber you have three options:

  1. Using the SI initializer
    let myLength = SI(2.5, SI.Unit.m) // 2.5 meters
    let myVelocity = SI(2.5, .m / .s) // 2.5 meters per second
    let myScalar = SI(2.5) // 2.5 (scalar value)
  2. Using the subscript shortcut. With this you can create an SI on the fly subscripting of a Double
    let myLength = 2.5[SI.Unit.m] // 2.5 meters
    let myVelocity = 2.5[.m / .s] // 2.5 meters per second
    let myScalar = 2.5[] // 2.5 (empty subscript for scalar value)

Initialization

You can use SI like a Double without the struggle of keeping track of unit conversions. Here are some examples

let l1 = 2[.m] // 2 meters
let l2 = 500[.mm] // 500 millimeters = 0.5 meters

l1 + l2 // 2.5m (2.5[.m])
l1 - l2 // 1.5m (1.5[.m])
l1 * l2 // 1m² (1[.m ** 2])
l1 / l2 // 4 (4[])
2 * l1 // 4m (4[.m])
l1 ** 2 // 4m² (4[.m ** 2])
pow(l1, 2) // 4m² (4[.m ** 2])
sqrt(l1 * l2) // 1m (1[.m])

Caution Be careful when adding two SI numbers with mismatching physical dimensions e.g. 1[.m] + 2[.s] since this will result in a precondition failure.

Conversion

To convert an SI number to a desired unit use convert() or convertToSI() to convert to an SI unit.

let myLength = 2.5[.inch].convertToSI() // 0.063 m
let myTime = 24[.hour].convert(to: .day) // 1.0 day

Caution Be careful when converting an SI number to a unit with mismatching physical dimensions e.g. 1[.m].convert(to: .s) since this will result in a precondition failure.

To typecast an SI to an Int or Double just use the initializer.

let double = Double(2[.m] / 2[.mm]) // 1000.0
let int = Double(2[.mm] / 2[.m]) // 1000

Caution Be careful when typecasting an SI with a non-scalar physical dimensions e.g. Double(1.2[.m]) since this will result in a precondition failure.

Custom Units

If you find your unit missing in the library of SI.Unit, you can easily create one.

Creating units on the fly

SI.Unit supports multiplication, division and exponentiation so creating a new unit in place is really easy.

let N = .kg * .m / .s ** 2 // Newton
let lb = 0.45359237 * .kg // Pound

Prefixes

To add a prefix to a unit (e.g. N → kN, m → μ), you can use the inbuilt methods.

let μm = μ(.m) // Micrometer: 1 μm = 10⁻⁶ m
let kN = k(.N) // Kilonewton: 1 kN = 10³ N

Define a named unit

To define a named SI.Unit you must use the initializer. You can create a new SI.Unit based of an existing one or one created on the fly. The name is used in the customDebugString.

Tip Add your named units as an extension of SI.Unit to make them easily available.

extension SI.Unit {
   public static let N = Self("N", kg * m / (s ** 2)) // Force in Newton
}
let Hz = SI.Unit("Hz", .scalar / .s) // Frequency in Hertz

Unit dimension

An SI.Unit consists of a dimension and a multiplicator. The dimension is a dictionary of type [SI.Unit.Base : Int] where the key stands for the respective Base dimension and the value for its power. For example

SI.Unit("m/s", .m / .s).dimension = [SI.Unit.Base.m: 1, SI.Unit.Base.s: -1]

The multiplicator is used to convert the unit to the SI system.

All standard base units are provided in the SI package. To define a new base unit (e.g. €, happiness,...) extend of SI.Unit.Base and use the default initializer and provide the standard symbol. Then define the standard unit of the new dimension providing the new dimension, the multiplicator and a name.

extension SI.Unit.Base{
   public static let currency = Self(name: "")
}
extension SI.Unit {
   public static let euro = Self("", 1, [Base.currency: 1])
}

Contribution

You have found a bug 🐞 or have a question 🤔 ? Just send me a message or create an issue, and I will try to get back to you as soon as possible.

You want to develop this package further? Just create a merge request or send me a message. Please add exhaustive test to your new functionality in order to keep this package as stable and reliable as possible. Also, please make sure to document your code to make it legible for other devs. If you have any questions just write me. Thank you very much for your contribution! ✌️

You might also like...
Easy way to detect iOS device properties, OS versions and work with screen sizes. Powered by Swift.
Easy way to detect iOS device properties, OS versions and work with screen sizes. Powered by Swift.

Easy way to detect device environment: Device model and version Screen resolution Interface orientation iOS version Battery state Environment Helps to

Testable Combine Publishers - An easy, declarative way to unit test Combine Publishers in Swift
Testable Combine Publishers - An easy, declarative way to unit test Combine Publishers in Swift

Testable Combine Publishers An easy, declarative way to unit test Combine Publishers in Swift About Combine Publishers are notoriously verbose to unit

SwiftRegressor - A linear regression tool that’s flexible and easy to use

SwiftRegressor - A linear regression tool that’s flexible and easy to use

Easy CBOR encoding and decoding for iOS, macOS, tvOS and watchOS.

CBORCoding CBORCoding is a lightweight framework containing a coder pair for encoding and decoding Codable conforming types to and from CBOR document

An application focused on managing men's haircuts. It has never been so easy to keep the cut on time
An application focused on managing men's haircuts. It has never been so easy to keep the cut on time

An application focused on managing men's haircuts. It has never been so easy to keep the cut on time

BCSwiftTor - Opinionated pure Swift controller for Tor, including full support for Swift 5.5 and Swift Concurrency

BCSwiftTor Opinionated pure Swift controller for Tor, including full support for

Swift Markdown is a Swift package for parsing, building, editing, and analyzing Markdown documents.

Swift Markdown is a Swift package for parsing, building, editing, and analyzing Markdown documents.

Cross-Platform, Protocol-Oriented Programming base library to complement the Swift Standard Library. (Pure Swift, Supports Linux)

SwiftFoundation Cross-Platform, Protocol-Oriented Programming base library to complement the Swift Standard Library. Goals Provide a cross-platform in

Swift - ✏️Swift 공부 저장소✏️

Swift 스위프트의 기초 1. Swift의 기본 2. 변수와 상수 [3. 데이터 타입 기본] [4. 데이터 타입 고급] 5. 연산자 6. 흐름 제어 7. 함수 8. 옵셔널 객체지향 프로그래밍과 스위프트 9. 구조체와 클래스 10. 프로퍼티와 메서드 11. 인스턴스 생

Releases(v0.3.0)
Owner
Niklas Nickel
Niklas Nickel
Showcase new features after an app update similar to Pages, Numbers and Keynote.

WhatsNew Description WhatsNew automatically displays a short description of the new features when users update your app. This is similar to what happe

Patrick Balestra 1.5k Jan 4, 2023
[iOS] Animated analog flip numbers like airport/train-station displays (SwiftUI)

A SwiftUI FlipNumberView A small universal (iOS + macOS) app displaying the current time with a flip animation. This is still WIP and doesn't support

M Emrich 6 Dec 6, 2022
A Codable Undefinable type for handling JSON undefined values.

Undefinable Overview The purpose of this type is represent the JSON undefined state in Swift structs and classes. The Undefinable enum is a generic wi

David Monagle 3 Dec 18, 2022
Swift Date() made easy

Swift-Date-Extensions Swift Date() made easy! // Will return the wekkday in a st

Ricky Stone 0 Dec 28, 2021
An OpenAI DALLE2 App - Made with SwiftUI

DALLE2-Swift An OpenAI DALLE2 App - Made with SwiftUI Video Demo https://twitter.com/1998design/status/1582612175021277190?s=61&t=U6jwceFUGJlOkNKAIBbL

MING 9 Dec 20, 2022
Swift-DocC is a documentation compiler for Swift frameworks and packages aimed at making it easy to write and publish great developer documentation.

Swift-DocC is a documentation compiler for Swift frameworks and packages aimed at making it easy to write and publish great developer docum

Apple 833 Jan 3, 2023
Sovran-Swift: Small, efficient, easy. State Management for Swift

Sovran-Swift: Small, efficient, easy. State Management for Swift

Segment 5 Jan 3, 2023
🗃 Powerful and easy to use Swift Query Builder for Vapor 3.

⚠️ This lib is DEPRECATED ⚠️ please use SwifQL with Bridges Quick Intro struct PublicUser: Codable { var name: String var petName: String

iMike 145 Sep 10, 2022
RandomKit is a Swift framework that makes random data generation simple and easy.

RandomKit is a Swift framework that makes random data generation simple and easy. Build Status Installation Compatibility Swift Package Manager CocoaP

Nikolai Vazquez 1.5k Dec 29, 2022
CocoAttributedStringBuilder: Elegant and Easy AttributedStringBuilder in Swift

CocoAttributedStringBuilder: Elegant and Easy AttributedStringBuilder in Swift Features Requirements Installation SampleProjects Usage Contributors Li

Kiarash Vosough 10 Sep 5, 2022