From f140cd57e502549ff822d4f4dbe7611fa7e7fc0f Mon Sep 17 00:00:00 2001 From: "Trevor L. McDonell" Date: Thu, 18 Dec 2025 14:20:26 +0100 Subject: [PATCH 1/2] feat: add .init(unsafeUninitialisedCapacity:initialisingWith:) --- Sources/MultiArray/MultiArray.swift | 59 +++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 8 deletions(-) diff --git a/Sources/MultiArray/MultiArray.swift b/Sources/MultiArray/MultiArray.swift index 06aeacb..685acc2 100644 --- a/Sources/MultiArray/MultiArray.swift +++ b/Sources/MultiArray/MultiArray.swift @@ -34,11 +34,23 @@ public struct MultiArray where Element: Generic, Element.RawRepresentat /// produce each value. @inlinable public init(count: Int, with generator: (Int) throws -> Element) rethrows { - precondition(count >= 0) - self.arrayData = .init(unsafeUninitializedCapacity: count) - for i in 0 ..< count { - let value = try generator(i) - Element.RawRepresentation.initialise(self.arrayData.storage, at: i, to: value.rawRepresentation) + try self.init(unsafeUninitialisedCapacity: count) { buffer in + for i in 0 ..< count { + let value = try generator(i) + buffer.initialiseElement(at: i, to: value) + } + } + } + + /// Create a new MultiArray by applying the given function to each index to + /// produce each value. + @inlinable + public init(count: Int, with generator: (Int) throws(E) -> Element) throws(E) { + try self.init(unsafeUninitialisedCapacity: count) { buffer throws(E) in + for i in 0 ..< count { + let value = try generator(i) + buffer.initialiseElement(at: i, to: value) + } } } @@ -66,6 +78,37 @@ public struct MultiArray where Element: Generic, Element.RawRepresentat self.init(Array(elements)) } } + + /// Creates an array with the specified capacity, then calls the given + /// closure with a buffer covering the array's uninitialized memory. + @inlinable + public init( + unsafeUninitialisedCapacity count: Int, + initialisingWith: (inout UninitialisedMultiArrayData) throws(E) -> Void + ) throws(E) { + precondition(count >= 0) + self.arrayData = .init(unsafeUninitialisedCapacity: count) + var buffer = UninitialisedMultiArrayData(arrayData.storage) + try initialisingWith(&buffer) + } +} + +// Wrapper so that we can expose the buffer using the surface Element type, +// rather than the underlying RawRepresentation type. +public struct UninitialisedMultiArrayData where Element: Generic, Element.RawRepresentation: ArrayData { + @usableFromInline + let storage: Element.RawRepresentation.Buffer + + @usableFromInline + init(_ storage: Element.RawRepresentation.Buffer) { + self.storage = storage + } + + /// Initialises the element at the given `index` to the given `value` + @inlinable + public func initialiseElement(at index: Int, to value: consuming Element) { + Element.RawRepresentation.initialise(self.storage, at: index, to: value.rawRepresentation) + } } // TODO: It would be better if this is generic over the underlying storage @@ -79,15 +122,15 @@ internal final class MultiArrayData { let count: Int @usableFromInline - var context: UnsafeMutableRawPointer + let context: UnsafeMutableRawPointer // Storing the internal pointers for speed(?), but we could also recompute // them from the base context. @usableFromInline - var storage: A.Buffer + let storage: A.Buffer @inlinable - init(unsafeUninitializedCapacity count: Int) { + init(unsafeUninitialisedCapacity count: Int) { var context = UnsafeMutableRawPointer.allocate(byteCount: A.rawSize(capacity: count, from: 0), alignment: 16) self.count = count self.context = context From ca3a52c162f0b70f2aef5859f2978b3acc38f187 Mon Sep 17 00:00:00 2001 From: "Trevor L. McDonell" Date: Tue, 6 Jan 2026 15:23:01 +0100 Subject: [PATCH 2/2] fix: americanizzze This switches to the american spelling of initialise, to match the spelling of the existing Array initialiser that this mimics. *sigh* For internal consistency this also changes some (internal) functions to use american spelling as well. Although these are marked as public, that is due to Swift modularity limitations and they are actually internal functions not intended to be used outside this module, so this is not a breaking API change. --- Sources/MultiArray/ArrayData.swift | 28 ++++++++++++++-------------- Sources/MultiArray/MultiArray.swift | 28 ++++++++++++++-------------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/Sources/MultiArray/ArrayData.swift b/Sources/MultiArray/ArrayData.swift index d683d6f..b4686b6 100644 --- a/Sources/MultiArray/ArrayData.swift +++ b/Sources/MultiArray/ArrayData.swift @@ -18,8 +18,8 @@ public protocol ArrayData { associatedtype Buffer - static func initialise(_ arrayData: Buffer, at: Int, to value: Self) - static func deinitialise(_ arrayData: Buffer, count: Int) + static func initialize(_ arrayData: Buffer, at: Int, to value: Self) + static func deinitialize(_ arrayData: Buffer, count: Int) static func read(_ arrayData: Buffer, at index: Int) -> Self static func write(_ arrayData: Buffer, at index: Int, to value: Self) @@ -32,12 +32,12 @@ public protocol ArrayData { // references (i.e. machine types) extension ArrayData where Buffer == UnsafeMutablePointer { @inlinable - public static func initialise(_ arrayData: Self.Buffer, at index: Int, to value: Self) { + public static func initialize(_ arrayData: Self.Buffer, at index: Int, to value: Self) { (arrayData + index).initialize(to: value) } @inlinable - public static func deinitialise(_: Self.Buffer, count _: Int) { /* no-op */ } + public static func deinitialize(_: Self.Buffer, count _: Int) { /* no-op */ } @inlinable // @inline(__always) @@ -113,10 +113,10 @@ extension Unit: ArrayData { public typealias Buffer = Void @inlinable - public static func initialise(_: Self.Buffer, at _: Int, to _: Self) { /* no-op */ } + public static func initialize(_: Self.Buffer, at _: Int, to _: Self) { /* no-op */ } @inlinable - public static func deinitialise(_: Self.Buffer, count _: Int) { /* no-op */ } + public static func deinitialize(_: Self.Buffer, count _: Int) { /* no-op */ } @inlinable // @inline(__always) @@ -146,12 +146,12 @@ extension Box: ArrayData { public typealias Buffer = UnsafeMutablePointer @inlinable - public static func initialise(_ arrayData: Self.Buffer, at index: Int, to value: Self) { + public static func initialize(_ arrayData: Self.Buffer, at index: Int, to value: Self) { (arrayData + index).initialize(to: value.unbox) } @inlinable - public static func deinitialise(_ arrayData: Self.Buffer, count: Int) { + public static func deinitialize(_ arrayData: Self.Buffer, count: Int) { arrayData.deinitialize(count: count) } @@ -192,15 +192,15 @@ extension Product: ArrayData where A: ArrayData, B: ArrayData { public typealias Buffer = (A.Buffer, B.Buffer) @inlinable - public static func initialise(_ arrayData: Self.Buffer, at index: Int, to value: Self) { - A.initialise(arrayData.0, at: index, to: value._0) - B.initialise(arrayData.1, at: index, to: value._1) + public static func initialize(_ arrayData: Self.Buffer, at index: Int, to value: Self) { + A.initialize(arrayData.0, at: index, to: value._0) + B.initialize(arrayData.1, at: index, to: value._1) } @inlinable - public static func deinitialise(_ arrayData: Self.Buffer, count: Int) { - A.deinitialise(arrayData.0, count: count) - B.deinitialise(arrayData.1, count: count) + public static func deinitialize(_ arrayData: Self.Buffer, count: Int) { + A.deinitialize(arrayData.0, count: count) + B.deinitialize(arrayData.1, count: count) } @inlinable diff --git a/Sources/MultiArray/MultiArray.swift b/Sources/MultiArray/MultiArray.swift index 685acc2..ba70dd1 100644 --- a/Sources/MultiArray/MultiArray.swift +++ b/Sources/MultiArray/MultiArray.swift @@ -34,10 +34,10 @@ public struct MultiArray where Element: Generic, Element.RawRepresentat /// produce each value. @inlinable public init(count: Int, with generator: (Int) throws -> Element) rethrows { - try self.init(unsafeUninitialisedCapacity: count) { buffer in + try self.init(unsafeUninitializedCapacity: count) { buffer in for i in 0 ..< count { let value = try generator(i) - buffer.initialiseElement(at: i, to: value) + buffer.initializeElement(at: i, to: value) } } } @@ -46,10 +46,10 @@ public struct MultiArray where Element: Generic, Element.RawRepresentat /// produce each value. @inlinable public init(count: Int, with generator: (Int) throws(E) -> Element) throws(E) { - try self.init(unsafeUninitialisedCapacity: count) { buffer throws(E) in + try self.init(unsafeUninitializedCapacity: count) { buffer throws(E) in for i in 0 ..< count { let value = try generator(i) - buffer.initialiseElement(at: i, to: value) + buffer.initializeElement(at: i, to: value) } } } @@ -83,19 +83,19 @@ public struct MultiArray where Element: Generic, Element.RawRepresentat /// closure with a buffer covering the array's uninitialized memory. @inlinable public init( - unsafeUninitialisedCapacity count: Int, - initialisingWith: (inout UninitialisedMultiArrayData) throws(E) -> Void + unsafeUninitializedCapacity count: Int, + initializingWith: (inout UninitializedMultiArrayData) throws(E) -> Void ) throws(E) { precondition(count >= 0) - self.arrayData = .init(unsafeUninitialisedCapacity: count) - var buffer = UninitialisedMultiArrayData(arrayData.storage) - try initialisingWith(&buffer) + self.arrayData = .init(unsafeUninitializedCapacity: count) + var buffer = UninitializedMultiArrayData(arrayData.storage) + try initializingWith(&buffer) } } // Wrapper so that we can expose the buffer using the surface Element type, // rather than the underlying RawRepresentation type. -public struct UninitialisedMultiArrayData where Element: Generic, Element.RawRepresentation: ArrayData { +public struct UninitializedMultiArrayData where Element: Generic, Element.RawRepresentation: ArrayData { @usableFromInline let storage: Element.RawRepresentation.Buffer @@ -106,8 +106,8 @@ public struct UninitialisedMultiArrayData where Element: Generic, Eleme /// Initialises the element at the given `index` to the given `value` @inlinable - public func initialiseElement(at index: Int, to value: consuming Element) { - Element.RawRepresentation.initialise(self.storage, at: index, to: value.rawRepresentation) + public func initializeElement(at index: Int, to value: consuming Element) { + Element.RawRepresentation.initialize(self.storage, at: index, to: value.rawRepresentation) } } @@ -130,7 +130,7 @@ internal final class MultiArrayData { let storage: A.Buffer @inlinable - init(unsafeUninitialisedCapacity count: Int) { + init(unsafeUninitializedCapacity count: Int) { var context = UnsafeMutableRawPointer.allocate(byteCount: A.rawSize(capacity: count, from: 0), alignment: 16) self.count = count self.context = context @@ -149,7 +149,7 @@ internal final class MultiArrayData { } deinit { - A.deinitialise(self.storage, count: self.count) + A.deinitialize(self.storage, count: self.count) self.context.deallocate() } }