Skip to content

Commit

Permalink
move to setutils, changelog
Browse files Browse the repository at this point in the history
  • Loading branch information
metagn committed Oct 18, 2024
1 parent 4e4b24e commit 47537bc
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 28 deletions.
5 changes: 5 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ rounding guarantees (via the

## Standard library additions and changes

[//]: # "Additions:"
- `setutils.symmetricDifference` along with its operator version
`` setutils.`-+-` `` and in-place version `setutils.toggle` have been added
to more efficiently calculate the symmetric difference of bitsets.

[//]: # "Changes:"
- `std/math` The `^` symbol now supports floating-point as exponent in addition to the Natural type.

Expand Down
1 change: 1 addition & 0 deletions compiler/condsyms.nim
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,4 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimHasGenericsOpenSym2")
defineSymbol("nimHasGenericsOpenSym3")
defineSymbol("nimHasJsNoLambdaLifting")
defineSymbol("nimHasXorSet")
28 changes: 28 additions & 0 deletions lib/std/setutils.nim
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,31 @@ func `[]=`*[T](t: var set[T], key: T, val: bool) {.inline.} =
s[a3] = true
assert s == {a2, a3}
if val: t.incl key else: t.excl key

when defined(nimHasXorSet):
func symmetricDifference*[T](x, y: set[T]): set[T] {.magic: "XorSet".} =
## This operator computes the symmetric difference of two sets,
## equivalent to but more efficient than `x + y - x * y` or
## `(x - y) + (y - x)`.
runnableExamples:
assert symmetricDifference({1, 2, 3}, {2, 3, 4}) == {1, 4}
else:
func symmetricDifference*[T](x, y: set[T]): set[T] {.inline.} =
result = x + y - (x * y)

proc `-+-`*[T](x, y: set[T]): set[T] {.inline.} =
## Operator alias for `symmetricDifference`.
runnableExamples:
assert {1, 2, 3} -+- {2, 3, 4} == {1, 4}
result = symmetricDifference(x, y)

proc toggle*[T](x: var set[T], y: set[T]) {.inline.} =
## Toggles the existence of each value of `y` in `x`.
## If any element in `y` is also in `x`, it is excluded from `x`;
## otherwise it is included.
## Equivalent to `x = symmetricDifference(x, y)`.
runnableExamples:
var x = {1, 2, 3}
x.toggle({2, 3, 4})
assert x == {1, 4}
x = symmetricDifference(x, y)
6 changes: 0 additions & 6 deletions lib/system/setops.nim
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,6 @@ func `-`*[T](x, y: set[T]): set[T] {.magic: "MinusSet".} =
runnableExamples:
assert {1, 2, 3} - {2, 3, 4} == {1}

func symmetricDifference*[T](x, y: set[T]): set[T] {.magic: "XorSet".} =
## This operator computes the symmetric difference of two sets,
## equivalent to `x + y - x * y` or `(x - y) + (y - x)`.
runnableExamples:
assert symmetricDifference({1, 2, 3}, {2, 3, 4}) == {1, 4}

func contains*[T](x: set[T], y: T): bool {.magic: "InSet".} =
## One should overload this proc if one wants to overload the `in` operator.
##
Expand Down
22 changes: 0 additions & 22 deletions tests/sets/tsets_various.nim
Original file line number Diff line number Diff line change
Expand Up @@ -281,28 +281,6 @@ template main() =
let foo = proc() = discard
setA.incl(foo)
doAssert setA.contains(foo)

block: # set symmetric difference (xor), https://github.com/nim-lang/RFCs/issues/554
type T = set[range[0..15]]
let x: T = {1, 4, 5, 8, 9}
let y: T = {0, 2..6, 9}
let res = symmetricDifference(x, y)
doAssert res == {0, 1, 2, 3, 6, 8}
doAssert res == (x + y - x * y)
doAssert res == ((x - y) + (y - x))
template toggle[T](a: var set[T], b: set[T]) =
a = symmetricDifference(a, b)
var z = x
doAssert z == {1, 4, 5, 8, 9}
doAssert z == x
z.toggle(y)
doAssert z == res
z.toggle(y)
doAssert z == x
z.toggle({1, 5})
doAssert z == {4, 8, 9}
z.toggle({3, 8})
doAssert z == {3, 4, 9}

static: main()
main()
20 changes: 20 additions & 0 deletions tests/stdlib/tsetutils.nim
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,26 @@ template main =
s[a2] = true
s[a3] = true
doAssert s == {a2, a3}

block: # set symmetric difference (xor), https://github.com/nim-lang/RFCs/issues/554
type T = set[range[0..15]]
let x: T = {1, 4, 5, 8, 9}
let y: T = {0, 2..6, 9}
let res = symmetricDifference(x, y)
doAssert res == {0, 1, 2, 3, 6, 8}
doAssert res == (x + y - x * y)
doAssert res == ((x - y) + (y - x))
var z = x
doAssert z == {1, 4, 5, 8, 9}
doAssert z == x
z.toggle(y)
doAssert z == res
z.toggle(y)
doAssert z == x
z.toggle({1, 5})
doAssert z == {4, 8, 9}
z.toggle({3, 8})
doAssert z == {3, 4, 9}

main()
static: main()

0 comments on commit 47537bc

Please sign in to comment.