Last active
November 10, 2018 17:16
-
-
Save tcldr/f25a1a147b07774ae5bc5be01c5e157b to your computer and use it in GitHub Desktop.
Range based clamping for `FloatingPoint` types.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// FloatingPoint extension | |
extension FloatingPoint { | |
func clamped<T: ClampableRangeExpression>(to range: T) -> Self where T.Bound == Self { | |
return range.clamping(self) | |
} | |
} | |
// RangeExpression extension | |
protocol ClampableRangeExpression: RangeExpression where Bound: FloatingPoint { | |
func clamping(_ value: Bound) -> Bound | |
} | |
// Conformance for various Range Types | |
extension PartialRangeFrom: ClampableRangeExpression where Bound: FloatingPoint { | |
func clamping(_ value: Bound) -> Bound { | |
return contains(value) ? value : lowerBound | |
} | |
} | |
extension PartialRangeThrough: ClampableRangeExpression where Bound: FloatingPoint { | |
func clamping(_ value: Bound) -> Bound { | |
return contains(value) ? value : upperBound | |
} | |
} | |
extension ClosedRange: ClampableRangeExpression where Bound: FloatingPoint { | |
func clamping(_ value: Bound) -> Bound { | |
return (lowerBound...).clamping((...upperBound).clamping(value)) | |
} | |
} | |
extension Range: ClampableRangeExpression where Bound: FloatingPoint { | |
func clamping(_ value: Bound) -> Bound { | |
guard !isEmpty else { return .nan } | |
return (lowerBound...).clamping((..<upperBound).clamping(value)) | |
} | |
} | |
extension PartialRangeUpTo: ClampableRangeExpression where Bound: FloatingPoint { | |
func clamping(_ value: Bound) -> Bound { | |
return (...upperBound.nextDown).clamping(value) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment