From 52959bf2935b2fd8910b242bc755188e2fc9a035 Mon Sep 17 00:00:00 2001 From: Karoy Lorentey Date: Sun, 9 Oct 2022 18:57:20 -0700 Subject: [PATCH] [BitCollections] Move shared utilities to _CollectionsUtilities --- .../BitArray/BitArray+Copy.swift | 2 + .../BitArray+CustomStringConvertible.swift | 2 +- .../BitSet/BitSet+Initializers.swift | 6 +- .../BitSet/BitSet._UnsafeHandle.swift | 16 ++-- .../BitCollections/Shared/UInt+Tricks.swift | 81 ++----------------- ...UnsafeMutableBufferPointer+Utilities.swift | 36 --------- Sources/BitCollections/Shared/_Word.swift | 10 ++- ...ixedWidthInteger+roundUpToPowerOfTwo.swift | 21 +++++ .../Integer rank.swift} | 79 ++++++++++++------ .../UInt+first and last set bit.swift | 25 ++++++ .../Integer tricks/UInt+reversed.swift | 27 +++++++ .../UnsafeBufferPointer+Extras.swift} | 11 +-- .../UnsafeMutableBufferPointer+Extras.swift | 1 - .../UnsafeMutableBufferPointer+SE-0370.swift | 38 +++++++++ .../UnsafeMutablePointer+SE-0370.swift | 34 ++++++++ 15 files changed, 227 insertions(+), 162 deletions(-) delete mode 100644 Sources/BitCollections/Shared/UnsafeMutableBufferPointer+Utilities.swift create mode 100644 Sources/_CollectionsUtilities/Integer tricks/FixedWidthInteger+roundUpToPowerOfTwo.swift rename Sources/_CollectionsUtilities/{Integer tricks.swift => Integer tricks/Integer rank.swift} (64%) create mode 100644 Sources/_CollectionsUtilities/Integer tricks/UInt+first and last set bit.swift create mode 100644 Sources/_CollectionsUtilities/Integer tricks/UInt+reversed.swift rename Sources/{BitCollections/Shared/UnsafeBufferPointer+Utilities.swift => _CollectionsUtilities/UnsafeBufferPointer+Extras.swift} (68%) create mode 100644 Sources/_CollectionsUtilities/UnsafeMutablePointer+SE-0370.swift diff --git a/Sources/BitCollections/BitArray/BitArray+Copy.swift b/Sources/BitCollections/BitArray/BitArray+Copy.swift index e592e5e65..1f339c333 100644 --- a/Sources/BitCollections/BitArray/BitArray+Copy.swift +++ b/Sources/BitCollections/BitArray/BitArray+Copy.swift @@ -9,6 +9,8 @@ // //===----------------------------------------------------------------------===// +import _CollectionsUtilities + extension BitArray { internal mutating func _copy( from range: Range, diff --git a/Sources/BitCollections/BitArray/BitArray+CustomStringConvertible.swift b/Sources/BitCollections/BitArray/BitArray+CustomStringConvertible.swift index 9485c8f66..91357755e 100644 --- a/Sources/BitCollections/BitArray/BitArray+CustomStringConvertible.swift +++ b/Sources/BitCollections/BitArray/BitArray+CustomStringConvertible.swift @@ -23,7 +23,7 @@ extension BitArray: CustomStringConvertible { let b1: UInt8 = 49 // ASCII 1 var i = 0 for v in self { - target._initialize(at: i, to: v ? b1 : b0) + target.initializeElement(at: i, to: v ? b1 : b0) i &+= 1 } return i diff --git a/Sources/BitCollections/BitSet/BitSet+Initializers.swift b/Sources/BitCollections/BitSet/BitSet+Initializers.swift index bec2715db..3c23994b9 100644 --- a/Sources/BitCollections/BitSet/BitSet+Initializers.swift +++ b/Sources/BitCollections/BitSet/BitSet+Initializers.swift @@ -172,16 +172,16 @@ extension BitSet { _storage = Array(unsafeUninitializedCapacity: capacity) { buffer, count in let sharedCount = Swift.min(w1.count, w2.count) for w in 0 ..< sharedCount { - buffer._initialize(at: w, to: function(w1[w], w2[w])) + buffer.initializeElement(at: w, to: function(w1[w], w2[w])) } if includingTail { if w1.count < w2.count { for w in w1.count ..< w2.count { - buffer._initialize(at: w, to: function(_Word.empty, w2[w])) + buffer.initializeElement(at: w, to: function(_Word.empty, w2[w])) } } else { for w in w2.count ..< w1.count { - buffer._initialize(at: w, to: function(w1[w], _Word.empty)) + buffer.initializeElement(at: w, to: function(w1[w], _Word.empty)) } } } diff --git a/Sources/BitCollections/BitSet/BitSet._UnsafeHandle.swift b/Sources/BitCollections/BitSet/BitSet._UnsafeHandle.swift index ff00540a5..a314d58e3 100644 --- a/Sources/BitCollections/BitSet/BitSet._UnsafeHandle.swift +++ b/Sources/BitCollections/BitSet/BitSet._UnsafeHandle.swift @@ -9,6 +9,8 @@ // //===----------------------------------------------------------------------===// +import _CollectionsUtilities + extension BitSet { /// An unsafe-unowned bitset view over `UInt` storage, providing bit set /// primitives. @@ -273,7 +275,7 @@ extension BitSet._UnsafeHandle: BidirectionalCollection { internal var startIndex: Index { let word = _words.firstIndex { !$0.isEmpty } guard let word = word else { return endIndex } - return Index(word: word, bit: _words[word].firstMember) + return Index(word: word, bit: _words[word].firstMember!) } @inlinable @@ -299,7 +301,7 @@ extension BitSet._UnsafeHandle: BidirectionalCollection { } w = _words[word] } - return Index(word: word, bit: w.firstMember) + return Index(word: word, bit: w.firstMember!) } @usableFromInline @@ -318,7 +320,7 @@ extension BitSet._UnsafeHandle: BidirectionalCollection { precondition(word >= 0, "Can't advance below startIndex") w = _words[word] } - return Index(word: word, bit: w.lastMember) + return Index(word: word, bit: w.lastMember!) } @usableFromInline @@ -501,9 +503,7 @@ extension BitSet._UnsafeHandle { _mutableWords[l.word].formIntersection(_Word(upTo: l.bit).complement()) if u.word < wordCount { _mutableWords[u.word].formIntersection(_Word(upTo: u.bit)) - _mutableWords[(u.word + 1)...] - ._rebased() - .assign(repeating: .empty) + _mutableWords[(u.word + 1)...].update(repeating: .empty) } } @@ -542,9 +542,7 @@ extension BitSet._UnsafeHandle { } _mutableWords[l.word].subtract(_Word(upTo: l.bit).complement()) - _mutableWords[(l.word + 1) ..< u.word] - ._rebased() - .assign(repeating: .empty) + _mutableWords[(l.word + 1) ..< u.word].update(repeating: .empty) if u.word < wordCount { _mutableWords[u.word].subtract(_Word(upTo: u.bit)) } diff --git a/Sources/BitCollections/Shared/UInt+Tricks.swift b/Sources/BitCollections/Shared/UInt+Tricks.swift index 0b535c6f8..5ef5fc722 100644 --- a/Sources/BitCollections/Shared/UInt+Tricks.swift +++ b/Sources/BitCollections/Shared/UInt+Tricks.swift @@ -9,36 +9,9 @@ // //===----------------------------------------------------------------------===// -extension UInt { - @inlinable @inline(__always) - internal var _nonzeroBitCount: UInt { - Self(truncatingIfNeeded: nonzeroBitCount) - } - - internal var _reversed: UInt { - // https://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel - var shift: UInt = UInt(UInt.bitWidth) - var mask: UInt = ~0; - var result = self - while true { - shift &>>= 1 - guard shift > 0 else { break } - mask ^= mask &<< shift - result = ((result &>> shift) & mask) | ((result &<< shift) & ~mask) - } - return result - } - - @inlinable @inline(__always) - internal var _lastSetBit: UInt { - UInt(truncatingIfNeeded: self.trailingZeroBitCount) - } - - @inlinable @inline(__always) - internal var _firstSetBit: UInt { - UInt(truncatingIfNeeded: UInt.bitWidth &- 1 &- self.leadingZeroBitCount) - } +import _CollectionsUtilities +extension UInt { /// Returns the position of the `n`th set bit in `self`. /// /// - Parameter n: The to retrieve. This value is @@ -48,52 +21,14 @@ extension UInt { /// - Returns: If this integer contains enough set bits to satisfy the /// request, then this function returns the position of the bit found. /// Otherwise it returns nil. - internal func _nthSetBit(_ n: inout UInt) -> UInt? { - // FIXME: Use bit deposit instruction when available (PDEP on Intel). - assert(UInt.bitWidth == 64 || UInt.bitWidth == 32, "Unsupported UInt bitWidth") - - var shift: UInt = 0 - - let c = self._nonzeroBitCount + internal func _rank(ofBit n: inout UInt) -> UInt? { + let c = self.nonzeroBitCount guard n < c else { - n &-= c + n &-= UInt(bitPattern: c) return nil } - - if UInt.bitWidth == 64 { - let c32 = (self & 0xFFFFFFFF)._nonzeroBitCount - if n >= c32 { - shift &+= 32 - n &-= c32 - } - } - let c16 = ((self &>> shift) & 0xFFFF)._nonzeroBitCount - if n >= c16 { - shift &+= 16 - n &-= c16 - } - let c8 = ((self &>> shift) & 0xFF)._nonzeroBitCount - if n >= c8 { - shift &+= 8 - n &-= c8 - } - let c4 = ((self &>> shift) & 0xF)._nonzeroBitCount - if n >= c4 { - shift &+= 4 - n &-= c4 - } - let c2 = ((self &>> shift) & 0x3)._nonzeroBitCount - if n >= c2 { - shift &+= 2 - n &-= c2 - } - let c1 = (self &>> shift) & 0x1 - if n >= c1 { - shift &+= 1 - n &-= c1 - } - precondition(n == 0 && (self &>> shift) & 0x1 == 1) - return shift + let m = Int(bitPattern: n) + n = 0 + return _bit(ranked: m)! } } - diff --git a/Sources/BitCollections/Shared/UnsafeMutableBufferPointer+Utilities.swift b/Sources/BitCollections/Shared/UnsafeMutableBufferPointer+Utilities.swift deleted file mode 100644 index d8fe84a52..000000000 --- a/Sources/BitCollections/Shared/UnsafeMutableBufferPointer+Utilities.swift +++ /dev/null @@ -1,36 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// This source file is part of the Swift Collections open source project -// -// Copyright (c) 2021-2022 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// -//===----------------------------------------------------------------------===// - -extension Collection { - @inlinable - @inline(__always) - internal func _rebased() -> UnsafeMutableBufferPointer - where Self == UnsafeMutableBufferPointer.SubSequence { - .init(rebasing: self) - } -} - -extension UnsafeMutableBufferPointer { - @inlinable - @inline(__always) - internal func _assign(from source: Self) { - assert(source.count == self.count) - if count > 0 { - baseAddress!.assign(from: source.baseAddress!, count: count) - } - } - - @inlinable - @inline(__always) - internal func _initialize(at index: Int, to value: Element) { - (baseAddress.unsafelyUnwrapped + index).initialize(to: value) - } -} diff --git a/Sources/BitCollections/Shared/_Word.swift b/Sources/BitCollections/Shared/_Word.swift index 09278da4f..b686e6774 100644 --- a/Sources/BitCollections/Shared/_Word.swift +++ b/Sources/BitCollections/Shared/_Word.swift @@ -9,6 +9,8 @@ // //===----------------------------------------------------------------------===// +import _CollectionsUtilities + @usableFromInline @frozen internal struct _Word { @@ -52,12 +54,12 @@ extension _Word { /// then this function returns the member found. Otherwise it returns nil. @inline(never) internal func nthElement(_ n: inout UInt) -> UInt? { - value._nthSetBit(&n) + value._rank(ofBit: &n) } @inline(never) internal func nthElementFromEnd(_ n: inout UInt) -> UInt? { - guard let i = value._reversed._nthSetBit(&n) else { return nil } + guard let i = value._reversed._rank(ofBit: &n) else { return nil } return UInt(UInt.bitWidth) &- 1 &- i } } @@ -102,13 +104,13 @@ extension _Word { @inlinable @inline(__always) - internal var firstMember: UInt { + internal var firstMember: UInt? { value._lastSetBit } @inlinable @inline(__always) - internal var lastMember: UInt { + internal var lastMember: UInt? { value._firstSetBit } diff --git a/Sources/_CollectionsUtilities/Integer tricks/FixedWidthInteger+roundUpToPowerOfTwo.swift b/Sources/_CollectionsUtilities/Integer tricks/FixedWidthInteger+roundUpToPowerOfTwo.swift new file mode 100644 index 000000000..518e257eb --- /dev/null +++ b/Sources/_CollectionsUtilities/Integer tricks/FixedWidthInteger+roundUpToPowerOfTwo.swift @@ -0,0 +1,21 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift Collections open source project +// +// Copyright (c) 2022 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// +//===----------------------------------------------------------------------===// + +extension FixedWidthInteger { + /// Round up `self` to the nearest power of two, assuming it's representable. + /// Returns 0 if `self` isn't positive. + @inlinable + public func _roundUpToPowerOfTwo() -> Self { + guard self > 0 else { return 0 } + let l = Self.bitWidth - (self &- 1).leadingZeroBitCount + return 1 << l + } +} diff --git a/Sources/_CollectionsUtilities/Integer tricks.swift b/Sources/_CollectionsUtilities/Integer tricks/Integer rank.swift similarity index 64% rename from Sources/_CollectionsUtilities/Integer tricks.swift rename to Sources/_CollectionsUtilities/Integer tricks/Integer rank.swift index f081a87c9..bd8e638fd 100644 --- a/Sources/_CollectionsUtilities/Integer tricks.swift +++ b/Sources/_CollectionsUtilities/Integer tricks/Integer rank.swift @@ -9,18 +9,8 @@ // //===----------------------------------------------------------------------===// -extension FixedWidthInteger { - /// Round up `self` to the nearest power of two, assuming it's representable. - /// Returns 0 if `self` isn't positive. - @inlinable - public func _roundUpToPowerOfTwo() -> Self { - guard self > 0 else { return 0 } - let l = Self.bitWidth - (self &- 1).leadingZeroBitCount - return 1 << l - } -} -extension UInt32 { +extension FixedWidthInteger { @inlinable @inline(__always) internal var _nonzeroBitCount: Self { Self(truncatingIfNeeded: nonzeroBitCount) @@ -32,14 +22,64 @@ extension UInt32 { let mask: Self = (1 &<< bit) &- 1 return (self & mask).nonzeroBitCount } +} + +extension UInt { + @_effects(releasenone) + public func _bit(ranked n: Int) -> UInt? { + // FIXME: Use bit deposit instruction when available (PDEP on Intel). + assert(UInt.bitWidth == 64 || UInt.bitWidth == 32, + "Unsupported UInt bitWidth") + + var shift: Self = 0 + var n = Self(truncatingIfNeeded: n) + + if Self.bitWidth == 64 { + let c32 = (self & 0xFFFFFFFF)._nonzeroBitCount + if n >= c32 { + shift &+= 32 + n &-= c32 + } + } + let c16 = ((self &>> shift) & 0xFFFF)._nonzeroBitCount + if n >= c16 { + shift &+= 16 + n &-= c16 + } + let c8 = ((self &>> shift) & 0xFF)._nonzeroBitCount + if n >= c8 { + shift &+= 8 + n &-= c8 + } + let c4 = ((self &>> shift) & 0xF)._nonzeroBitCount + if n >= c4 { + shift &+= 4 + n &-= c4 + } + let c2 = ((self &>> shift) & 0x3)._nonzeroBitCount + if n >= c2 { + shift &+= 2 + n &-= c2 + } + let c1 = (self &>> shift) & 0x1 + if n >= c1 { + shift &+= 1 + n &-= c1 + } + guard n == 0 && (self &>> shift) & 0x1 == 1 else { return nil } + return shift + } +} +extension UInt32 { // Returns the position of the `n`th set bit in `self`, i.e., the bit with // rank `n`. @_effects(releasenone) public func _bit(ranked n: Int) -> UInt? { + // FIXME: Use bit deposit instruction when available (PDEP on Intel). assert(n >= 0 && n < Self.bitWidth) var shift: Self = 0 - var n: Self = UInt32(truncatingIfNeeded: n) + var n = Self(truncatingIfNeeded: n) let c16 = (self & 0xFFFF)._nonzeroBitCount if n >= c16 { shift = 16 @@ -71,25 +111,14 @@ extension UInt32 { } extension UInt16 { - @inlinable @inline(__always) - internal var _nonzeroBitCount: Self { - Self(truncatingIfNeeded: nonzeroBitCount) - } - - @inlinable @inline(__always) - public func _rank(ofBit bit: UInt) -> Int { - assert(bit < Self.bitWidth) - let mask: Self = (1 &<< bit) &- 1 - return (self & mask).nonzeroBitCount - } - // Returns the position of the `n`th set bit in `self`, i.e., the bit with // rank `n`. @_effects(releasenone) public func _bit(ranked n: Int) -> UInt? { + // FIXME: Use bit deposit instruction when available (PDEP on Intel). assert(n >= 0 && n < Self.bitWidth) var shift: Self = 0 - var n: Self = UInt16(truncatingIfNeeded: n) + var n = Self(truncatingIfNeeded: n) let c8 = ((self &>> shift) & 0xFF)._nonzeroBitCount if n >= c8 { shift &+= 8 diff --git a/Sources/_CollectionsUtilities/Integer tricks/UInt+first and last set bit.swift b/Sources/_CollectionsUtilities/Integer tricks/UInt+first and last set bit.swift new file mode 100644 index 000000000..4a0be877b --- /dev/null +++ b/Sources/_CollectionsUtilities/Integer tricks/UInt+first and last set bit.swift @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift Collections open source project +// +// Copyright (c) 2022 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// +//===----------------------------------------------------------------------===// + +extension UInt { + @inlinable @inline(__always) + public var _firstSetBit: UInt? { + guard self != 0 else { return nil } + let v = UInt.bitWidth &- 1 &- self.leadingZeroBitCount + return UInt(truncatingIfNeeded: v) + } + + @inlinable @inline(__always) + public var _lastSetBit: UInt? { + guard self != 0 else { return nil } + return UInt(truncatingIfNeeded: self.trailingZeroBitCount) + } +} diff --git a/Sources/_CollectionsUtilities/Integer tricks/UInt+reversed.swift b/Sources/_CollectionsUtilities/Integer tricks/UInt+reversed.swift new file mode 100644 index 000000000..4d48c5014 --- /dev/null +++ b/Sources/_CollectionsUtilities/Integer tricks/UInt+reversed.swift @@ -0,0 +1,27 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift Collections open source project +// +// Copyright (c) 2022 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// +//===----------------------------------------------------------------------===// + +extension UInt { + @inlinable + public var _reversed: UInt { + // https://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel + var shift: UInt = UInt(UInt.bitWidth) + var mask: UInt = ~0; + var result = self + while true { + shift &>>= 1 + guard shift > 0 else { break } + mask ^= mask &<< shift + result = ((result &>> shift) & mask) | ((result &<< shift) & ~mask) + } + return result + } +} diff --git a/Sources/BitCollections/Shared/UnsafeBufferPointer+Utilities.swift b/Sources/_CollectionsUtilities/UnsafeBufferPointer+Extras.swift similarity index 68% rename from Sources/BitCollections/Shared/UnsafeBufferPointer+Utilities.swift rename to Sources/_CollectionsUtilities/UnsafeBufferPointer+Extras.swift index 417f14ebf..f65d2aba0 100644 --- a/Sources/BitCollections/Shared/UnsafeBufferPointer+Utilities.swift +++ b/Sources/_CollectionsUtilities/UnsafeBufferPointer+Extras.swift @@ -9,19 +9,10 @@ // //===----------------------------------------------------------------------===// -extension Collection { - @inlinable - @inline(__always) - internal func _rebased() -> UnsafeBufferPointer - where Self == UnsafeBufferPointer.SubSequence { - .init(rebasing: self) - } -} - extension UnsafeBufferPointer { @inlinable @inline(__always) - internal func _ptr(at index: Int) -> UnsafePointer { + public func _ptr(at index: Int) -> UnsafePointer { assert(index >= 0 && index < count) return baseAddress.unsafelyUnwrapped + index } diff --git a/Sources/_CollectionsUtilities/UnsafeMutableBufferPointer+Extras.swift b/Sources/_CollectionsUtilities/UnsafeMutableBufferPointer+Extras.swift index f79bcd036..8a85e59bc 100644 --- a/Sources/_CollectionsUtilities/UnsafeMutableBufferPointer+Extras.swift +++ b/Sources/_CollectionsUtilities/UnsafeMutableBufferPointer+Extras.swift @@ -135,4 +135,3 @@ extension Slice { target.moveInitializeAll(fromContentsOf: source) } } - diff --git a/Sources/_CollectionsUtilities/UnsafeMutableBufferPointer+SE-0370.swift b/Sources/_CollectionsUtilities/UnsafeMutableBufferPointer+SE-0370.swift index e76f0af1d..213b6214a 100644 --- a/Sources/_CollectionsUtilities/UnsafeMutableBufferPointer+SE-0370.swift +++ b/Sources/_CollectionsUtilities/UnsafeMutableBufferPointer+SE-0370.swift @@ -366,3 +366,41 @@ extension Slice { base.baseAddress.unsafelyUnwrapped.advanced(by: index).initialize(to: value) } } + +#if swift(<5.8) +extension UnsafeMutableBufferPointer { + /// Updates every element of this buffer's initialized memory. + /// + /// The buffer’s memory must be initialized or its `Element` type + /// must be a trivial type. + /// + /// - Note: All buffer elements must already be initialized. + /// + /// - Parameters: + /// - repeatedValue: The value used when updating this pointer's memory. + @_alwaysEmitIntoClient + public func update(repeating repeatedValue: Element) { + guard let dstBase = baseAddress else { return } + dstBase.update(repeating: repeatedValue, count: count) + } +} +#endif + +#if swift(<5.8) +extension Slice { + /// Updates every element of this buffer slice's initialized memory. + /// + /// The buffer slice’s memory must be initialized or its `Element` + /// must be a trivial type. + /// + /// - Note: All buffer elements must already be initialized. + /// + /// - Parameters: + /// - repeatedValue: The value used when updating this pointer's memory. + @_alwaysEmitIntoClient + public func update(repeating repeatedValue: Element) + where Base == UnsafeMutableBufferPointer { + Base(rebasing: self).update(repeating: repeatedValue) + } +} +#endif diff --git a/Sources/_CollectionsUtilities/UnsafeMutablePointer+SE-0370.swift b/Sources/_CollectionsUtilities/UnsafeMutablePointer+SE-0370.swift new file mode 100644 index 000000000..6f32ffe73 --- /dev/null +++ b/Sources/_CollectionsUtilities/UnsafeMutablePointer+SE-0370.swift @@ -0,0 +1,34 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift Collections open source project +// +// Copyright (c) 2022 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// +//===----------------------------------------------------------------------===// + +#if swift(<5.8) +extension UnsafeMutablePointer { + /// Update this pointer's initialized memory with the specified number of + /// consecutive copies of the given value. + /// + /// The region of memory starting at this pointer and covering `count` + /// instances of the pointer's `Pointee` type must be initialized or + /// `Pointee` must be a trivial type. After calling + /// `update(repeating:count:)`, the region is initialized. + /// + /// - Parameters: + /// - repeatedValue: The value used when updating this pointer's memory. + /// - count: The number of consecutive elements to update. + /// `count` must not be negative. + @_alwaysEmitIntoClient + public func update(repeating repeatedValue: Pointee, count: Int) { + assert(count >= 0, "UnsafeMutablePointer.update(repeating:count:) with negative count") + for i in 0 ..< count { + self[i] = repeatedValue + } + } +} +#endif