blob: 95bad99c7defa4f97260547e14ffcfc3019de198 [file] [log] [blame]
// 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