FloatingPoint.swift 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
  1. //
  2. // FloatingPoint.swift
  3. // LoopKit
  4. //
  5. // Created by Michael Pangburn on 7/30/20.
  6. // Copyright © 2020 LoopKit Authors. All rights reserved.
  7. //
  8. extension Double {
  9. public func matchingOrTruncatedValue(from supportedValues: [Double], withinDecimalPlaces precision: Int) -> Double {
  10. let nearestSupportedValue = roundedToNearest(of: supportedValues)
  11. return abs(nearestSupportedValue - self) <= pow(10.0, Double(-precision))
  12. ? nearestSupportedValue
  13. : truncating(toOneOf: supportedValues)
  14. }
  15. }
  16. extension FloatingPoint {
  17. /// Precondition: - `supportedValues` is sorted in ascending order.
  18. public func roundedToNearest(of supportedValues: [Self]) -> Self {
  19. guard !supportedValues.isEmpty else {
  20. return self
  21. }
  22. let splitPoint = supportedValues.partitioningIndex(where: { $0 > self })
  23. switch splitPoint {
  24. case supportedValues.startIndex:
  25. return supportedValues.first!
  26. case supportedValues.endIndex:
  27. return supportedValues.last!
  28. default:
  29. let (lesser, greater) = (supportedValues[splitPoint - 1], supportedValues[splitPoint])
  30. return (self - lesser) <= (greater - self) ? lesser : greater
  31. }
  32. }
  33. /// Precondition: - `supportedValues` is sorted in ascending order.
  34. public func truncating(toOneOf supportedValues: [Self]) -> Self {
  35. guard !supportedValues.isEmpty else {
  36. return self
  37. }
  38. let splitPoint = supportedValues.partitioningIndex(where: { $0 > self })
  39. return splitPoint == supportedValues.startIndex
  40. ? supportedValues.first!
  41. : supportedValues[splitPoint - 1]
  42. }
  43. }