Skip to content

Instantly share code, notes, and snippets.

@dagronf
Created July 5, 2020 20:07
Show Gist options
  • Save dagronf/69f96c1fa55a10a14cfd6a42a7a801d3 to your computer and use it in GitHub Desktop.
Save dagronf/69f96c1fa55a10a14cfd6a42a7a801d3 to your computer and use it in GitHub Desktop.
Swift extensions for floating point and integer range clamping (swift, clamp)
//
// Clamp.swift
//
// Created by Darren Ford on 6/7/20.
// Copyright © 2020 Darren Ford. All rights reserved.
//
import Foundation
public extension ExpressibleByIntegerLiteral where Self: FloatingPoint {
// Regular range x..<y
@inlinable func clamped(to range: Range<Self>) -> Self {
let upper = range.upperBound.nextDown
return min(max(self, range.lowerBound), upper)
}
@inlinable mutating func clamping(to range: Range<Self>) {
self = self.clamped(to: range)
}
// Range up to ..<y
@inlinable func clamped(to range: PartialRangeUpTo<Self>) -> Self {
return min(self, range.upperBound.nextDown)
}
@inlinable mutating func clamping(to range: PartialRangeUpTo<Self>) {
self = self.clamped(to: range)
}
}
public extension ExpressibleByIntegerLiteral where Self: Strideable {
// Regular range x..<y
@inlinable func clamped(to range: Range<Self>) -> Self {
let upper = range.upperBound.advanced(by: -1)
return min(max(self, range.lowerBound), upper)
}
@inlinable mutating func clamping(to range: Range<Self>) {
self = self.clamped(to: range)
}
// Range up to ..<y
@inlinable func clamped(to range: PartialRangeUpTo<Self>) -> Self {
return min(self, range.upperBound.advanced(by: -1))
}
@inlinable mutating func clamping(to range: PartialRangeUpTo<Self>) {
self = self.clamped(to: range)
}
}
public extension ExpressibleByIntegerLiteral where Self: Comparable {
// Closed range x...y
@inlinable func clamped(to range: ClosedRange<Self>) -> Self {
return min(max(self, range.lowerBound), range.upperBound)
}
@inlinable mutating func clamping(to range: ClosedRange<Self>) {
self = self.clamped(to: range)
}
// Partial range through ...y
@inlinable func clamped(to range: PartialRangeThrough<Self>) -> Self {
return min(range.upperBound, self)
}
@inlinable mutating func clamping(to range: PartialRangeThrough<Self>) {
self = self.clamped(to: range)
}
// Partial range from x...
@inlinable func clamped(to range: PartialRangeFrom<Self>) -> Self {
return max(range.lowerBound, self)
}
@inlinable mutating func clamping(to range: PartialRangeFrom<Self>) {
self = self.clamped(to: range)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment