[swift-users] Extending Arrays of specific type, and specialization

Hooman Mehr hooman at mac.com
Mon Nov 21 20:29:24 CST 2016


This is not possible in Swift 3.0. Swift 4.0 will improve things with conditional conformances.

For now, the best solution is using global functions instead of extending types or protocols.

For example you can do this now:

extension Array where Element: FloatingPoint {
    
    func sum() -> Element {
        guard count > 0 else { return 0 }
        switch self[0] {
        case is Double:
            var result = Double()
            vDSP_sveD(unsafeBitCast(self, to: Array<Double>.self), 1, &result, vDSP_Length(count))
            print("vDSP")
            return unsafeBitCast(result, to: Element.self)
        case is Float:
            var result = Float()
            vDSP_sve(unsafeBitCast(self, to: Array<Float>.self), 1, &result, vDSP_Length(count))
            print("vDSP")
            return unsafeBitCast(result, to: Element.self)
        default:
            print("default")
            return reduce(0, +)
        }
    }
}

But this is not very efficient, especially if it is defined in another module, which limits optimizations.

Instead, a family of overloaded global functions gives you the most coverage and best performance, at the expense of repetition and boilerplate code:

func sum<S: Sequence>(_ sequence: S) -> S.Iterator.Element where S.Iterator.Element: Integer {
    var result: S.Iterator.Element = 0
    for element in sequence { result += element }
    return result
}

func sum<S: Sequence>(_ sequence: S) -> S.Iterator.Element where S.Iterator.Element: FloatingPoint {
    var result: S.Iterator.Element = 0
    for element in sequence { result += element }
    return result
}

func sum(_ array: Array<Double>) -> Double {
    var result = Double()
    vDSP_sveD(array, 1, &result, vDSP_Length(array.count))
    return result
}

func sum(_ array: ContiguousArray<Double>) -> Double {
    var result = Double()
    array.withUnsafeBufferPointer { vDSP_sveD($0.baseAddress!, 1, &result, vDSP_Length(array.count)) }
    return result
}

func sum(_ array: ArraySlice<Double>) -> Double {
    var result = Double()
    array.withUnsafeBufferPointer { vDSP_sveD($0.baseAddress!, 1, &result, vDSP_Length(array.count)) }
    return result
}

func sum(_ array: Array<Float>) -> Float {
    var result = Float()
    vDSP_sve(array, 1, &result, vDSP_Length(array.count))
    return result
}

func sum(_ array: ContiguousArray<Float>) -> Float {
    var result = Float()
    array.withUnsafeBufferPointer { vDSP_sve($0.baseAddress!, 1, &result, vDSP_Length(array.count)) }
    return result
}

func sum(_ array: ArraySlice<Float>) -> Float {
    var result = Float()
    array.withUnsafeBufferPointer { vDSP_sve($0.baseAddress!, 1, &result, vDSP_Length(array.count)) }
    return result
}

The above code covers summing any integer or floating point sequence of numbers, while being accelerated for Float and Double array types (Array, ContiguousArray and ArraySlice)


> On Nov 21, 2016, at 4:32 PM, Rick Mann via swift-users <swift-users at swift.org> wrote:
> 
> My googling is not turning up an answer that works in Xcode 8.1. I'd like to do this:
> 
> 
> import Accelerate
> 
> extension
> Array
> 	where Element == Double
> {
> 	func
> 	sum()
> 		-> Double
> 	{
> 		var result: Double = 0.0
> 		vDSP_sveD(self, 1, &result, vDSP_Length(self.count))
> 		return result
> 	}
> }
> 
> But I get "same-type requirement makes generic parameter 'Element' non-generic."
> 
> Also, will there ever be any way to specialize something like
> 
> 	let numbers: [Double] = ...
> 	let sum = numbers.reduce(0.0, +)
> 
> Into a call to vDSP_sveD()? Would it require compiler optimizations for Accelerate?
> 
> Thanks!
> 
> -- 
> Rick Mann
> rmann at latencyzero.com
> 
> 
> _______________________________________________
> swift-users mailing list
> swift-users at swift.org
> https://lists.swift.org/mailman/listinfo/swift-users

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20161121/7197535c/attachment.html>


More information about the swift-users mailing list