Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 14 additions & 14 deletions Sources/MultiArray/ArrayData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -32,12 +32,12 @@ public protocol ArrayData {
// references (i.e. machine types)
extension ArrayData where Buffer == UnsafeMutablePointer<Self> {
@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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -146,12 +146,12 @@ extension Box: ArrayData {
public typealias Buffer = UnsafeMutablePointer<Element>

@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)
}

Expand Down Expand Up @@ -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
Expand Down
59 changes: 51 additions & 8 deletions Sources/MultiArray/MultiArray.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,23 @@ public struct MultiArray<Element> where Element: Generic, Element.RawRepresentat
/// produce each value.
@inlinable
public init(count: Int, with generator: (Int) throws -> Element) rethrows {
Comment thread
tmcdonell marked this conversation as resolved.
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(unsafeUninitializedCapacity: count) { buffer in
for i in 0 ..< count {
let value = try generator(i)
buffer.initializeElement(at: i, to: value)
}
}
}

/// Create a new MultiArray by applying the given function to each index to
/// produce each value.
@inlinable
public init<E: Error>(count: Int, with generator: (Int) throws(E) -> Element) throws(E) {
try self.init(unsafeUninitializedCapacity: count) { buffer throws(E) in
for i in 0 ..< count {
let value = try generator(i)
buffer.initializeElement(at: i, to: value)
}
}
}

Expand Down Expand Up @@ -66,6 +78,37 @@ public struct MultiArray<Element> 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<E: Error>(
unsafeUninitializedCapacity count: Int,
initializingWith: (inout UninitializedMultiArrayData<Element>) throws(E) -> Void
) throws(E) {
precondition(count >= 0)
self.arrayData = .init(unsafeUninitializedCapacity: count)
var buffer = UninitializedMultiArrayData<Element>(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 UninitializedMultiArrayData<Element> 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 initializeElement(at index: Int, to value: consuming Element) {
Element.RawRepresentation.initialize(self.storage, at: index, to: value.rawRepresentation)
}
}

// TODO: It would be better if this is generic over the underlying storage
Expand All @@ -79,12 +122,12 @@ internal final class MultiArrayData<A: ArrayData> {
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) {
Expand All @@ -106,7 +149,7 @@ internal final class MultiArrayData<A: ArrayData> {
}

deinit {
A.deinitialise(self.storage, count: self.count)
A.deinitialize(self.storage, count: self.count)
self.context.deallocate()
}
}