Post

Replies

Boosts

Views

Activity

Use FormatStyle to print formatted values from a Vector structure
I'm trying to use FormatStyle from Foundation to format numbers when printing a vector structure. See code below. import Foundation struct Vector<T> { var values: [T] subscript(item: Int) -> T { get { values[item] } set { values[item] = newValue } } } extension Vector: CustomStringConvertible { var description: String { var desc = "( " desc += values.map { "\($0)" }.joined(separator: " ") desc += " )" return desc } } extension Vector { func formatted<F: FormatStyle>(_ style: F) -> String where F.FormatInput == T, F.FormatOutput == String { var desc = "( " desc += values.map { style.format($0) }.joined(separator: " ") desc += " )" return desc } } In the example below, the vector contains a mix of integer and float literals. The result is a vector with a type of Vector<Double>. Since the values of the vector are inferred as Double then I expect the print output to display as decimal numbers. However, the .number formatted output seems to ignore the vector type and print the values as a mix of integers and decimals. This is fixed by explicitly providing a format style with a fraction length. So why is the .formatted(.number) method ignoring the vector type T which is Double in this example? let vec = Vector(values: [-2, 5.5, 100, 19, 4, 8.37]) print(vec) print(vec.formatted(.number)) print(vec.formatted(.number.precision(.fractionLength(1...)))) ( -2.0 5.5 100.0 19.0 4.0 8.37 ) // correct output that uses all Double types ( -2 5.5 100 19 4 8.37 ) // wrong output that uses Int and Double types ( -2.0 5.5 100.0 19.0 4.0 8.37 ) // correct output that uses all Double types
1
0
112
1d
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
444
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
817
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.9k
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
806
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.3k
Jun ’20