-
Notifications
You must be signed in to change notification settings - Fork 10.4k
/
Copy path0026-rdar21382194.swift
114 lines (93 loc) · 2.84 KB
/
0026-rdar21382194.swift
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
// RUN: not %target-swift-frontend %s -typecheck
/// Abstraction of numeric types that approximate real numbers
protocol ApproximateReal {
init() // zero
func * (Self,Self) -> Self
func + (Self,Self) -> Self
func / (Self,Self) -> Self
func - (Self,Self) -> Self
prefix func + (Self) -> Self
prefix func - (Self) -> Self
}
extension Double : ApproximateReal {}
extension Float : ApproximateReal {}
// Abstraction of a mathematical vector
protocol Vector {
init()
associatedtype Element : ApproximateReal
func dotProduct(Self) -> Element
// Extras
var count: Int {get}
subscript(Int) -> Element {get set}
associatedtype Tail
}
struct EmptyVector<T: ApproximateReal> : Vector {
init() {}
typealias Element = T
func dotProduct(other: EmptyVector) -> Element {
return Element() // zero
}
var count: Int { return 0 }
subscript(i: Int) -> Element {
get { fatalError("subscript out-of-range") }
set { fatalError("subscript out-of-range") }
}
}
struct Vector<Tail: Vector> : Vector {
typealias Element = Tail.Element
init(head: Element, tail: Tail) {
self.head = head
self.tail = tail
}
init() {
self.head = Element()
self.tail = Tail()
}
/*
init(scalar: Element) {
self.head = Element()
self.tail = Tail()
}
*/
func dotProduct(other: Vector) -> Element {
return head * other.head + tail.dotProduct(other.tail)
}
var count: Int { return tail.count + 1 }
var head: Element
var tail: Tail
subscript(i: Int) -> Element {
get { return i == 0 ? head : tail[i - 1] }
set { if i == 0 { head = newValue } else { tail[i - 1] = newValue } }
}
}
extension Vector where Tail == EmptyVector<Element> {
init(_ scalar: Element) {
self.init()
self[0] = scalar
}
}
//===--- A nice operator for composing vectors ----------------------------===//
//===--- there's probably a more appropriate symbol -----------------------===//
infix operator ⋮ {
associativity right
precedence 1
}
func ⋮ <T: ApproximateReal> (lhs: T, rhs: T) -> Vector<Vector<EmptyVector<T> > > {
return Vector(head: lhs, tail: Vector(head: rhs, tail: EmptyVector()))
}
func ⋮ <T: ApproximateReal, U where U.Element == T> (lhs: T, rhs: Vector<U>) -> Vector<Vector<U> > {
return Vector(head: lhs, tail: rhs)
}
extension Vector : CustomDebugStringConvertible {
var debugDescription: String {
if count == 1 {
return "Vector(\(String(reflecting: head)))"
}
return "\(String(reflecting: head)) ⋮ " + (count == 2 ? String(reflecting: self[1]) : String(reflecting: tail))
}
}
//===--- Test -------------------------------------------------------------===//
print(Vector(head: 3.0, tail: EmptyVector()))
print(3.0 ⋮ 4.0 ⋮ 5.0)
print( (3.0 ⋮ 4.0 ⋮ 5.0).dotProduct(6.0 ⋮ 7.0 ⋮ 8.0) ) // 86.0
// print( (3.0 ⋮ 4.0 ⋮ 5.0).dotProduct(6.0 ⋮ 7.0) ) // Won't compile