* Add UnitInterval type * Add test coverage for UnitInterval * Add support for sampling * Add integration tests for sampling
126 lines
4.1 KiB
Swift
126 lines
4.1 KiB
Swift
/// A value constrained to the range 0.0 to 1.0, inclusive.
|
|
///
|
|
/// `UnitInterval` represents a normalized value that is guaranteed to be within
|
|
/// the unit interval [0, 1]. This type is commonly used for representing
|
|
/// priorities in sampling request model preferences.
|
|
///
|
|
/// The type provides safe initialization that returns `nil` for values outside
|
|
/// the valid range, ensuring that all instances contain valid unit interval values.
|
|
///
|
|
/// - Example:
|
|
/// ```swift
|
|
/// let zero: UnitInterval = 0 // 0.0
|
|
/// let half = UnitInterval(0.5)! // 0.5
|
|
/// let one: UnitInterval = 1.0 // 1.0
|
|
/// let invalid = UnitInterval(1.5) // nil
|
|
/// ```
|
|
public struct UnitInterval: Hashable, Sendable {
|
|
private let value: Double
|
|
|
|
/// Creates a unit interval value from a `Double`.
|
|
///
|
|
/// - Parameter value: A double value that must be in the range 0.0...1.0
|
|
/// - Returns: A `UnitInterval` instance if the value is valid, `nil` otherwise
|
|
///
|
|
/// - Example:
|
|
/// ```swift
|
|
/// let valid = UnitInterval(0.75) // Optional(0.75)
|
|
/// let invalid = UnitInterval(-0.1) // nil
|
|
/// let boundary = UnitInterval(1.0) // Optional(1.0)
|
|
/// ```
|
|
public init?(_ value: Double) {
|
|
guard (0...1).contains(value) else { return nil }
|
|
self.value = value
|
|
}
|
|
|
|
/// The underlying double value.
|
|
///
|
|
/// This property provides access to the raw double value that is guaranteed
|
|
/// to be within the range [0, 1].
|
|
///
|
|
/// - Returns: The double value between 0.0 and 1.0, inclusive
|
|
public var doubleValue: Double { value }
|
|
}
|
|
|
|
// MARK: - Comparable
|
|
|
|
extension UnitInterval: Comparable {
|
|
public static func < (lhs: UnitInterval, rhs: UnitInterval) -> Bool {
|
|
lhs.value < rhs.value
|
|
}
|
|
}
|
|
|
|
// MARK: - CustomStringConvertible
|
|
|
|
extension UnitInterval: CustomStringConvertible {
|
|
public var description: String { "\(value)" }
|
|
}
|
|
|
|
// MARK: - Codable
|
|
|
|
extension UnitInterval: Codable {
|
|
public init(from decoder: Decoder) throws {
|
|
let container = try decoder.singleValueContainer()
|
|
let doubleValue = try container.decode(Double.self)
|
|
guard let interval = UnitInterval(doubleValue) else {
|
|
throw DecodingError.dataCorrupted(
|
|
DecodingError.Context(
|
|
codingPath: decoder.codingPath,
|
|
debugDescription: "Value \(doubleValue) is not in range 0...1")
|
|
)
|
|
}
|
|
self = interval
|
|
}
|
|
|
|
public func encode(to encoder: Encoder) throws {
|
|
var container = encoder.singleValueContainer()
|
|
try container.encode(value)
|
|
}
|
|
}
|
|
|
|
// MARK: - ExpressibleByFloatLiteral
|
|
|
|
extension UnitInterval: ExpressibleByFloatLiteral {
|
|
/// Creates a unit interval from a floating-point literal.
|
|
///
|
|
/// This initializer allows you to create `UnitInterval` instances using
|
|
/// floating-point literals. The literal value must be in the range [0, 1]
|
|
/// or a runtime error will occur.
|
|
///
|
|
/// - Parameter value: A floating-point literal between 0.0 and 1.0
|
|
///
|
|
/// - Warning: This initializer will crash if the literal is outside the valid range.
|
|
/// Use the failable initializer `init(_:)` for runtime validation.
|
|
///
|
|
/// - Example:
|
|
/// ```swift
|
|
/// let quarter: UnitInterval = 0.25
|
|
/// let half: UnitInterval = 0.5
|
|
/// ```
|
|
public init(floatLiteral value: Double) {
|
|
self.init(value)!
|
|
}
|
|
}
|
|
|
|
// MARK: - ExpressibleByIntegerLiteral
|
|
|
|
extension UnitInterval: ExpressibleByIntegerLiteral {
|
|
/// Creates a unit interval from an integer literal.
|
|
///
|
|
/// This initializer allows you to create `UnitInterval` instances using
|
|
/// integer literals. Only the values 0 and 1 are valid.
|
|
///
|
|
/// - Parameter value: An integer literal, either 0 or 1
|
|
///
|
|
/// - Warning: This initializer will crash if the literal is outside the valid range.
|
|
/// Use the failable initializer `init(_:)` for runtime validation.
|
|
///
|
|
/// - Example:
|
|
/// ```swift
|
|
/// let zero: UnitInterval = 0
|
|
/// let one: UnitInterval = 1
|
|
/// ```
|
|
public init(integerLiteral value: Int) {
|
|
self.init(Double(value))!
|
|
}
|
|
}
|