File: Time.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (153 lines) | stat: -rw-r--r-- 4,648 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// Taken from swift-collections-benchmark

import Foundation
import ArgumentParser

public struct Time {
  public let seconds: TimeInterval
  
  public init(_ seconds: TimeInterval) {
    precondition(!seconds.isNaN)
    self.seconds = seconds
  }
}

extension Time {
  public static let second = Time(1)
  public static let millisecond = Time(1e-3)
  public static let microsecond = Time(1e-6)
  public static let nanosecond = Time(1e-9)
  public static let picosecond = Time(1e-12)
  public static let femtosecond = Time(1e-15)
  public static let attosecond = Time(1e-18)
  public static let zero = Time(0)
}

extension Time {
  public static func since(_ start: Tick) -> Time {
    Tick.now.elapsedTime(since: start)
  }
}

extension Time: RawRepresentable {
  public var rawValue: TimeInterval { seconds }
  
  public init(rawValue: TimeInterval) {
    self.seconds = rawValue
  }
}

extension Time: Equatable {
  public static func == (left: Self, right: Self) -> Bool {
    return left.seconds == right.seconds
  }
}

extension Time: Hashable {
  public func hash(into hasher: inout Hasher) {
    hasher.combine(seconds)
  }
}

extension Time: Comparable {
  public static func < (left: Self, right: Self) -> Bool {
    return left.seconds < right.seconds
  }
}

extension Time {
  public static func - (left: Self, right: Self) -> Self {
    return Time(left.seconds - right.seconds)
  }
  
  public func abs() -> Time {
    Time(Swift.abs(self.seconds))
  }
}

extension Time: CustomStringConvertible {
  public var description: String {
    if self.seconds == 0 { return "0" }
    if self.abs() < .attosecond { return String(format: "%.3gas", seconds * 1e18) }
    if self.abs() < .picosecond { return String(format: "%.3gfs", seconds * 1e15) }
    if self.abs() < .nanosecond  { return String(format: "%.3gps", seconds * 1e12) }
    if self.abs() < .microsecond { return String(format: "%.3gns", seconds * 1e9) }
    if self.abs() < .millisecond { return String(format: "%.3gµs", seconds * 1e6) }
    if self.abs() < .second      { return String(format: "%.3gms", seconds * 1e3) }
    if self.seconds < 1000 { return String(format: "%.3gs", seconds) }
    return String(format: "%gs", seconds.rounded())
  }
  
  public var typesetDescription: String {
    let spc = "\u{200A}"
    if self.seconds == 0 { return "0\(spc)s" }
    if self.abs() < .femtosecond { return String(format: "%.3g\(spc)as", seconds * 1e18) }
    if self.abs() < .picosecond { return String(format: "%.3g\(spc)fs", seconds * 1e15) }
    if self.abs() < .nanosecond  { return String(format: "%.3g\(spc)ps", seconds * 1e12) }
    if self.abs() < .microsecond { return String(format: "%.3g\(spc)ns", seconds * 1e9) }
    if self.abs() < .millisecond { return String(format: "%.3g\(spc)µs", seconds * 1e6) }
    if self.abs() < .second      { return String(format: "%.3g\(spc)ms", seconds * 1e3) }
    if self.seconds < 1000 { return String(format: "%.3g\(spc)s", seconds) }
    return String(format: "%g\(spc)s", seconds.rounded())
  }
}

extension Time: Codable {
  public init(from decoder: Decoder) throws {
    self.seconds = try TimeInterval(from: decoder)
  }
  
  public func encode(to encoder: Encoder) throws {
    try self.seconds.encode(to: encoder)
  }
}

extension Time: ExpressibleByArgument {
  public init?(argument: String) {
    self.init(argument)
  }
}

extension Time {
  private static let _scaleFromSuffix: [String: Time] = [
    "": .second,
    "s": .second,
    "ms": .millisecond,
    "µs": .microsecond,
    "us": .microsecond,
    "ns": .nanosecond,
    "ps": .picosecond,
    "fs": .femtosecond,
    "as": .attosecond,
  ]
  
  private static let _floatingPointCharacterSet = CharacterSet(charactersIn: "+-0123456789.e")
  
  public init?(_ description: String) {
    var description = description.trimmingCharacters(in: .whitespacesAndNewlines)
    description = description.lowercased()
    if let i = description.rangeOfCharacter(from: Time._floatingPointCharacterSet.inverted) {
      let number = description.prefix(upTo: i.lowerBound)
      let suffix = description.suffix(from: i.lowerBound)
      guard let value = Double(number) else { return nil }
      guard let scale = Time._scaleFromSuffix[String(suffix)] else { return nil }
      self = Time(value * scale.seconds)
    }
    else {
      guard let value = Double(description) else { return nil }
      self = Time(value)
    }
  }
}

extension Time {
  public func amortized(over size: Size) -> Time {
    return Time(seconds / TimeInterval(size.rawValue))
  }
}

extension Time {
  internal func _orIfZero(_ time: Time) -> Time {
    self > .zero ? self : time
  }
}