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@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
> rm...@latencyzero.com
> 
> 
> _______________________________________________
> swift-users mailing list
> swift-users@swift.org
> https://lists.swift.org/mailman/listinfo/swift-users

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

Reply via email to