Post

Replies

Boosts

Views

Activity

Integer arithmetic with Accelerate
Almost all the functions in Accelerate are for single precision (Float) and double precision (Double) operations. However, I stumbled upon three integer arithmetic functions which operate on Int32 values. Are there any more functions in Accelerate that operate on integer values? If not, then why aren't there more functions that work with integers?
1
0
243
Oct ’24
Data storage for a Matrix struct when working with Accelerate
I have a Matrix structure as defined below for working with 2D numerical data in Accelerate. The underlying numerical data in this Matrix struct is stored as an Array. struct Matrix<T> { let rows: Int let columns: Int var data: [T] init(rows: Int, columns: Int, fill: T) { self.rows = rows self.columns = columns self.data = Array(repeating: fill, count: rows * columns) } init(rows: Int, columns: Int, source: (inout UnsafeMutableBufferPointer<T>) -> Void) { self.rows = rows self.columns = columns self.data = Array(unsafeUninitializedCapacity: rows * columns) { buffer, initializedCount in source(&buffer) initializedCount = rows * columns } } subscript(row: Int, column: Int) -> T { get { return self.data[(row * self.columns) + column] } set { self.data[(row * self.columns) + column] = newValue } } } Multiplication is implemented by the functions shown below. import Accelerate infix operator .* func .* (lhs: Matrix<Double>, rhs: Matrix<Double>) -> Matrix<Double> { precondition(lhs.rows == rhs.rows && lhs.columns == rhs.columns, "Matrices must have same dimensions") let result = Matrix<Double>(rows: lhs.rows, columns: rhs.columns) { buffer in vDSP.multiply(lhs.data, rhs.data, result: &buffer) } return result } func * (lhs: Matrix<Double>, rhs: Matrix<Double>) -> Matrix<Double> { precondition(lhs.columns == rhs.rows, "Number of columns in left matrix must equal number of rows in right matrix") var a = lhs.data var b = rhs.data let m = lhs.rows // number of rows in matrices A and C let n = rhs.columns // number of columns in matrices B and C let k = lhs.columns // number of columns in matrix A; number of rows in matrix B let alpha = 1.0 let beta = 0.0 // matrix multiplication where C ← αAB + βC let c = Matrix<Double>(rows: lhs.rows, columns: rhs.columns) { buffer in cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, m, n, k, alpha, &a, k, &b, n, beta, buffer.baseAddress, n) } return c } I can also define a Matrix structure where the underlying data is an UnsafeMutableBufferPointer. The buffer is handled by the MatrixData class. struct Matrix<T> { let rows: Int let columns: Int var data: MatrixData<T> init(rows: Int, columns: Int, fill: T) { self.rows = rows self.columns = columns self.data = MatrixData(count: rows * columns, fill: fill) } init(rows: Int, columns: Int) { self.rows = rows self.columns = columns self.data = MatrixData(count: rows * columns) } subscript(row: Int, column: Int) -> T { get { return self.data.buffer[(row * self.columns) + column] } set { self.data.buffer[(row * self.columns) + column] = newValue } } } class MatrixData<T> { var buffer: UnsafeMutableBufferPointer<T> var baseAddress: UnsafeMutablePointer<T> { get { self.buffer.baseAddress! } } init(count: Int, fill: T) { let start = UnsafeMutablePointer<T>.allocate(capacity: count) self.buffer = UnsafeMutableBufferPointer(start: start, count: count) self.buffer.initialize(repeating: fill) } init(count: Int) { let start = UnsafeMutablePointer<T>.allocate(capacity: count) self.buffer = UnsafeMutableBufferPointer(start: start, count: count) } deinit { self.buffer.deinitialize() self.buffer.deallocate() } } Multiplication for this approach is implemented by the functions shown here. import Accelerate infix operator .* func .* (lhs: Matrix<Double>, rhs: Matrix<Double>) -> Matrix<Double> { precondition(lhs.rows == rhs.rows && lhs.columns == rhs.columns, "Matrices must have same dimensions") let result = Matrix<Double>(rows: lhs.rows, columns: lhs.columns) vDSP.multiply(lhs.data.buffer, rhs.data.buffer, result: &result.data.buffer) return result } func * (lhs: Matrix<Double>, rhs: Matrix<Double>) -> Matrix<Double> { precondition(lhs.columns == rhs.rows, "Number of columns in left matrix must equal number of rows in right matrix") let a = lhs.data.baseAddress let b = rhs.data.baseAddress let m = lhs.rows // number of rows in matrices A and C let n = rhs.columns // number of columns in matrices B and C let k = lhs.columns // number of columns in matrix A; number of rows in matrix B let alpha = 1.0 let beta = 0.0 // matrix multiplication where C ← αAB + βC let c = Matrix<Double>(rows: lhs.rows, columns: rhs.columns) cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, m, n, k, alpha, a, k, b, n, beta, c.data.baseAddress, n) return c } Both of these approaches give me similar performance. The only difference that I have noticed is the matrix buffer approach allows for reference semantics. For example, the code below uses half the memory with the matrix buffer approach compared to the matrix array approach. This is because b acts as a reference to a using the matrix buffer approach; otherwise, the matrix array approach makes a full copy of a. let n = 10_000 let a = Matrix<Double>(rows: n, columns: n, fill: 0) var b = a b[0, 0] = 99 b[0, 1] = 22 Other than reference semantics, are there any reasons to use one of these approaches over the other?
3
0
590
Jun ’24
Default window size does not work for macOS 13 app using SwiftUI
I'm using Xcode 14.1 and created a new macOS 13 project. Before I build/run the project, I added a .defaultSize to the window group. But when I run the project for the first time, the window size does not adhere to the default size. Is there something else needed to define a default window size? Here is the ContentView.swift file: import SwiftUI struct ContentView: View {     var body: some View {         VStack {             Image(systemName: "globe")                 .imageScale(.large)                 .foregroundColor(.accentColor)             Text("Hello, world!")         }         .padding()     } } Here is the ExampleApp.swift file: import SwiftUI @main struct WindowDefaultSizeApp: App {     var body: some Scene {         WindowGroup {             ContentView()         }         .defaultSize(width: 300, height: 200)     } }
2
0
1.7k
Dec ’22
Resize window containing NavigationSplitView
The macOS code shown below uses SwiftUI to create a two column NavigationSplitView. The detail views are different sizes but the window does not change size when the detail view changes. How can I adjust the window size based on the detail view? import SwiftUI struct AppleView: View { var body: some View { Text("Apple View 🍎").font(.title) .frame(width: 500, height: 300) .background(.purple) } } struct KiwiView: View { var body: some View { Text("Kiwi View 🥝").font(.title) .frame(width: 400, height: 500) .background(.green) } } enum Fruit: String, CaseIterable { case apple = "Apple" case kiwi = "Kiwi" } struct DetailView: View { @Binding var selectedItem: Fruit var body: some View { switch selectedItem { case .apple: AppleView() case .kiwi: KiwiView() } } } struct ContentView: View { @State private var selectedFruit: Fruit = .apple var body: some View { NavigationSplitView { List(Fruit.allCases, id: \.self, selection: $selectedFruit) { fruit in Text(fruit.rawValue) } } detail: { DetailView(selectedItem: $selectedFruit) } } }
0
0
755
Dec ’22
Set width of sidebar in macOS using SwiftUI
I'm using a NavigationView to display a SidebarView and DetailView in the window of a Mac app: import SwiftUI private let fruits = ["🍎 Apple", "🥥 Coconut", "🥭 Mango", "🥝 Kiwi"] struct SidebarView: View { &#9;&#9;@Binding var selectedFruit: String? &#9;&#9;var body: some View { &#9;&#9;&#9;&#9;List(fruits, id: \.self, selection: $selectedFruit) { fruit in &#9;&#9;&#9;&#9;&#9;&#9;Text("\(fruit)") &#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;.listStyle(SidebarListStyle()) &#9;&#9;&#9;&#9;.frame(minWidth: 180, idealWidth: 200, maxWidth: 300) &#9;&#9;} } struct DetailView: View { &#9;&#9;@Binding var fruit: String? &#9;&#9;var body: some View { &#9;&#9;&#9;&#9;Text("\(fruit ?? "Default Fruit")") &#9;&#9;&#9;&#9;&#9;&#9;.font(.headline) &#9;&#9;&#9;&#9;&#9;&#9;.frame(maxWidth: .infinity, maxHeight: .infinity) &#9;&#9;} } struct ContentView: View { &#9;&#9;@State private var selectedFruit: String? &#9;&#9;var body: some View { &#9;&#9;&#9;&#9;NavigationView { &#9;&#9;&#9;&#9;&#9;&#9;SidebarView(selectedFruit: $selectedFruit) &#9;&#9;&#9;&#9;&#9;&#9;DetailView(fruit: $selectedFruit) &#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;.frame(width: 500, height: 400) &#9;&#9;} } struct ContentView_Previews: PreviewProvider { &#9;&#9;static var previews: some View { &#9;&#9;&#9;&#9;ContentView() &#9;&#9;} } The width of the SidebarView can be adjusted by dragging the center divider left or right in the window. I would like to have an initial width of 200 defined for the sidebar along with a minimum width of 180 and a max width of 300. I attempted this by setting the frame of the List which does indeed set the max width but the sidebar can still be completely collapsed. Also, the initial width of the sidebar seems to be defined by minWidth not idealWidth.
5
0
4.1k
Jun ’20