Skip to content

Commit

Permalink
Merge pull request apple#353 from lorentey/disable-bitwise-ops-on-bit…
Browse files Browse the repository at this point in the history
…array

[BitArray] Disable bitwise operators for now
  • Loading branch information
lorentey authored Jan 30, 2024
2 parents 7c9df00 + 8dd4e59 commit 04aab35
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 12 deletions.
34 changes: 33 additions & 1 deletion Sources/BitCollections/BitArray/BitArray+BitwiseOperations.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,40 @@
//
// This source file is part of the Swift Collections open source project
//
// Copyright (c) 2021-2023 Apple Inc. and the Swift project authors
// Copyright (c) 2021 - 2024 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 false
// FIXME: Bitwise operators disabled for now. I have two concerns:
// 1. We need to support bitwise operations over slices of bit arrays, not just
// whole arrays.
// 2. We need to put in-place mutations as the primary operation, and they
// need to avoid copy-on-write copies unless absolutely necessary.
//
// It seems unlikely that the operator syntax will survive these points.
// We have five (5!) separate cases:
//
// foo |= bar
// foo[i ..< j] |= bar
// foo |= bar[u ..< v]
// foo[i ..< j] |= bar[u ..< v]
// foo[i ..< j] |= foo[k ..< l]
//
// The last one where the array is ORed with itself is particularly problematic
// -- like memcpy, these operations can easily support overlapping inputs, but
// it doesn't seem likely we can implement that with this nice slicing syntax,
// unless we are okay with forcing a CoW copy. (Which we aren't.)
//
// Even ignoring that, I would not like to end up with four overloads for each
// operator, especially not for such niche operations. So we'll entirely disable
// these for now, to prevent any shipping API from interfering with an eventual
// redesign. (This is an active area of experimentation, as it will potentially
// also affect our non-copyable container design.)

extension BitArray {
/// Stores the result of performing a bitwise OR operation on two
/// equal-sized bit arrays in the left-hand-side variable.
Expand Down Expand Up @@ -105,7 +132,9 @@ extension BitArray {
result ^= right
return result
}
}

extension BitArray {
/// Returns the complement of the given bit array.
///
/// - Parameter value: A bit array.
Expand All @@ -117,7 +146,10 @@ extension BitArray {
result.toggleAll()
return result
}
}
#endif

extension BitArray {
public mutating func toggleAll() {
_update { handle in
let w = handle._mutableWords
Expand Down
22 changes: 13 additions & 9 deletions Sources/BitCollections/BitCollections.docc/Extensions/BitArray.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,16 @@
- ``replaceSubrange(_:with:)-2i7lu``
- ``replaceSubrange(_:with:)-b5ou``

### Bitwise Operators

- ``&(_:_:)``
- ``_(_:_:)-1rhw``
- ``_(_:_:)-56s54``
- ``~(_:)``
- ``&=(_:_:)``
- ``_=(_:_:)-69yf0``
- ``_=(_:_:)-icef``
### Bitwise Operations

- ``toggleAll()``
- ``toggleAll(in:)-3duwn``
- ``toggleAll(in:)-5hfhl``

<!--- ``&(_:_:)``-->
<!--- ``_(_:_:)-1rhw``-->
<!--- ``_(_:_:)-56s54``-->
<!--- ``~(_:)``-->
<!--- ``&=(_:_:)``-->
<!--- ``_=(_:_:)-69yf0``-->
<!--- ``_=(_:_:)-icef``-->
40 changes: 38 additions & 2 deletions Tests/BitCollectionsTests/BitArrayTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//
// This source file is part of the Swift Collections open source project
//
// Copyright (c) 2021 Apple Inc. and the Swift project authors
// Copyright (c) 2021 - 2024 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
Expand Down Expand Up @@ -822,6 +822,7 @@ final class BitArrayTests: CollectionTestCase {
}
}

#if false // FIXME: Bitwise operations disabled for now
func test_bitwiseOr() {
withSome("count", in: 0 ..< 512, maxSamples: 100) { count in
withEvery("i", in: 0 ..< 10) { i in
Expand Down Expand Up @@ -887,7 +888,42 @@ final class BitArrayTests: CollectionTestCase {
}
}
}

#endif

func test_toggleAll() {
withSome("count", in: 0 ..< 512, maxSamples: 100) { count in
withEvery("i", in: 0 ..< 10) { i in
let a = randomBoolArray(count: count)

var b = BitArray(a)
b.toggleAll()

let expected = a.map { !$0 }

expectEqualElements(b, expected)
}
}
}

func test_toggleAll_range() {
withSome("count", in: 0 ..< 512, maxSamples: 50) { count in
let a = randomBoolArray(count: count)

withSomeRanges("range", in: 0 ..< count, maxSamples: 100) { range in
withEvery("shared", in: [false, true]) { shared in
var expected = a
for i in range { expected[i].toggle() }

var b = BitArray(a)
withHiddenCopies(if: shared, of: &b) { b in
b.toggleAll(in: range)
expectEqualElements(b, expected)
}
}
}
}
}

func test_truncateOrExtend() {
withSome("oldCount", in: 0 ..< 512, maxSamples: 50) { oldCount in
withSome("newCount", in: 0 ... 1024, maxSamples: 30) { newCount in
Expand Down

0 comments on commit 04aab35

Please sign in to comment.