Open vade opened 1 year ago
@vade I apologize for very late response. (I didn't notice your message...) First, thank you for your willing to contribute to Matft! My implementation is following rule, (but not decide strictly)
Accelerate
framework, such like vDSP_**
or cblas_**
, put codes regarding to Accelerate
into Sources/Matft/library/*.swift
. I use the vDSP_vneg(D)
(known as negative operation) as the example following this explanation. So, because i want to use vDSP_vneg(D)
function, put codes into Sources/Matft/library/vDSP.swift
.vDSP
function, I split codes in vDSP.swift
into 3 blocks.typealias
of vDSP
to pass the vDSP_vneg
and vDSP_vnegD
. The naming rule is vDSP_**_func
. As you can know, there are two functions for float and double respectively in Accelerate
framework . And also, Matft uses float and double into the core (StoredType
). internal typealias vDSP_convert_func<T, U> = (UnsafePointer<T>, vDSP_Stride, UnsafeMutablePointer<U>, vDSP_Stride, vDSP_Length) -> Void
Note: vDSP_vneg
's arguments are same as some conversion functions (e.g. vDSP_vdpsp
) when i use two generic types (T
and U
)
typealias
. The naming rule is wrap_vDSP_**
. In this code, I implement the type conversion mainly such like Int
into vDSP_Stride
. I don't know if the inline decorator is valid or not ; )/// Wrapper of vDSP conversion function
/// - Parameters:
/// - srcptr: A source pointer
/// - srcStride: A source stride
/// - dstptr: A destination pointer
/// - dstStride: A destination stride
/// - size: A size to be copied
/// - vDSP_func: The vDSP conversion function
@inline(__always)
internal func wrap_vDSP_convert<T, U>(_ size: Int, _ srcptr: UnsafePointer<T>, _ srcStride: Int, _ dstptr: UnsafeMutablePointer<U>, _ dstStride: Int, _ vDSP_func: vDSP_convert_func<T, U>){
vDSP_func(srcptr, vDSP_Stride(srcStride), dstptr, vDSP_Stride(dstStride), vDSP_Length(size))
}
vDSP_vneg
. The naming rule is **_by_vDSP
. /// Pre operation mfarray by vDSP
/// - Parameters:
/// - mfarray: An input mfarray
/// - vDSP_func: vDSP_convert_func
/// - Returns: Pre operated mfarray
internal func preop_by_vDSP<T: MfStorable>(_ mfarray: MfArray, _ vDSP_func: vDSP_convert_func<T, T>) -> MfArray{
//return mfarray must be either row or column major
var mfarray = mfarray
//print(mfarray)
mfarray = check_contiguous(mfarray)
//print(mfarray)
//print(mfarray.strides)
let newdata = MfData(size: mfarray.storedSize, mftype: mfarray.mftype)
newdata.withUnsafeMutableStartPointer(datatype: T.self){
dstptrT in
mfarray.withUnsafeMutableStartPointer(datatype: T.self){
[unowned mfarray] in
wrap_vDSP_convert(mfarray.storedSize, $0, 1, dstptrT, 1, vDSP_func)
//vDSP_func($0.baseAddress!, vDSP_Stride(1), dstptrT, vDSP_Stride(1), vDSP_Length(mfarray.storedSize))
}
}
let newstructure = MfStructure(shape: mfarray.shape, strides: mfarray.strides)
return MfArray(mfdata: newdata, mfstructure: newstructure)
}
**_by_vDSP
in the Matft public function which the users can use in Sources/Matft/function/**/@@.swift
. The public function is in Sources/Matft/function/static
or Sources/Matft/function/method
. Because Matft stores float or double as StoredType
, I change the argument of the **_by_vDSP
./**
Element-wise negativity
- parameters:
- mfarray: mfarray
*/
public static func neg(_ mfarray: MfArray) -> MfArray{
switch mfarray.storedType{
case .Float:
return preop_by_vDSP(mfarray, vDSP_vneg)
case .Double:
return preop_by_vDSP(mfarray, vDSP_vnegD)
}
}
Hi there
Ive got a few minor implementations of some numpy / scipy functions on vectors in vDSP along with associated XCTests that I think would make good contributions to Matft.
I'm curious how to best / properly implement these into Matft, as it seems like having a single home for them makes sense, and your code seems very well organized.
I'm not entirely sure of the code structure / best place to implement the logic in a generic way that leverages Matfts existing code base.
Do you have any suggestions?
numpy.allclose()
as an extension to Arrayscipy.spatial.distance.cosine
and
scipy.ndimage.gaussian_filter_1d
as array extensions allowing one to cache the computed gaussian kernel.Note I only really implement the default padding of reflect so far.