Coverage Report

Created: 2025-11-30 06:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython/Objects/setobject.c
Line
Count
Source
1
2
/* set object implementation
3
4
   Written and maintained by Raymond D. Hettinger <python@rcn.com>
5
   Derived from Objects/dictobject.c.
6
7
   The basic lookup function used by all operations.
8
   This is based on Algorithm D from Knuth Vol. 3, Sec. 6.4.
9
10
   The initial probe index is computed as hash mod the table size.
11
   Subsequent probe indices are computed as explained in Objects/dictobject.c.
12
13
   To improve cache locality, each probe inspects a series of consecutive
14
   nearby entries before moving on to probes elsewhere in memory.  This leaves
15
   us with a hybrid of linear probing and randomized probing.  The linear probing
16
   reduces the cost of hash collisions because consecutive memory accesses
17
   tend to be much cheaper than scattered probes.  After LINEAR_PROBES steps,
18
   we then use more of the upper bits from the hash value and apply a simple
19
   linear congruential random number generator.  This helps break-up long
20
   chains of collisions.
21
22
   All arithmetic on hash should ignore overflow.
23
24
   Unlike the dictionary implementation, the lookkey function can return
25
   NULL if the rich comparison returns an error.
26
27
   Use cases for sets differ considerably from dictionaries where looked-up
28
   keys are more likely to be present.  In contrast, sets are primarily
29
   about membership testing where the presence of an element is not known in
30
   advance.  Accordingly, the set implementation needs to optimize for both
31
   the found and not-found case.
32
*/
33
34
#include "Python.h"
35
#include "pycore_ceval.h"               // _PyEval_GetBuiltin()
36
#include "pycore_critical_section.h"    // Py_BEGIN_CRITICAL_SECTION, Py_END_CRITICAL_SECTION
37
#include "pycore_dict.h"                // _PyDict_Contains_KnownHash()
38
#include "pycore_modsupport.h"          // _PyArg_NoKwnames()
39
#include "pycore_object.h"              // _PyObject_GC_UNTRACK()
40
#include "pycore_pyatomic_ft_wrappers.h"  // FT_ATOMIC_LOAD_SSIZE_RELAXED()
41
#include "pycore_pyerrors.h"            // _PyErr_SetKeyError()
42
#include "pycore_setobject.h"           // _PySet_NextEntry() definition
43
#include "pycore_weakref.h"             // FT_CLEAR_WEAKREFS()
44
45
#include "stringlib/eq.h"               // unicode_eq()
46
#include <stddef.h>                     // offsetof()
47
#include "clinic/setobject.c.h"
48
49
/*[clinic input]
50
class set "PySetObject *" "&PySet_Type"
51
class frozenset "PySetObject *" "&PyFrozenSet_Type"
52
[clinic start generated code]*/
53
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=97ad1d3e9f117079]*/
54
55
/*[python input]
56
class setobject_converter(self_converter):
57
    type = "PySetObject *"
58
[python start generated code]*/
59
/*[python end generated code: output=da39a3ee5e6b4b0d input=33a44506d4d57793]*/
60
61
/* Object used as dummy key to fill deleted entries */
62
static PyObject _dummy_struct;
63
64
4.86M
#define dummy (&_dummy_struct)
65
66
67
/* ======================================================================== */
68
/* ======= Begin logic for probing the hash table ========================= */
69
70
/* Set this to zero to turn-off linear probing */
71
#ifndef LINEAR_PROBES
72
412M
#define LINEAR_PROBES 9
73
#endif
74
75
/* This must be >= 1 */
76
13.4M
#define PERTURB_SHIFT 5
77
78
static setentry *
79
set_lookkey(PySetObject *so, PyObject *key, Py_hash_t hash)
80
254M
{
81
254M
    setentry *table;
82
254M
    setentry *entry;
83
254M
    size_t perturb = hash;
84
254M
    size_t mask = so->mask;
85
254M
    size_t i = (size_t)hash & mask; /* Unsigned for defined overflow behavior */
86
254M
    int probes;
87
254M
    int cmp;
88
89
254M
    int frozenset = PyFrozenSet_CheckExact(so);
90
91
268M
    while (1) {
92
268M
        entry = &so->table[i];
93
268M
        probes = (i + LINEAR_PROBES <= mask) ? LINEAR_PROBES: 0;
94
342M
        do {
95
342M
            if (entry->hash == 0 && entry->key == NULL)
96
146M
                return entry;
97
195M
            if (entry->hash == hash) {
98
108M
                PyObject *startkey = entry->key;
99
108M
                assert(startkey != dummy);
100
108M
                if (startkey == key)
101
108M
                    return entry;
102
23.8k
                if (PyUnicode_CheckExact(startkey)
103
23.8k
                    && PyUnicode_CheckExact(key)
104
6.94k
                    && unicode_eq(startkey, key))
105
6.94k
                    return entry;
106
16.9k
                table = so->table;
107
16.9k
                if (frozenset) {
108
0
                    cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
109
0
                    if (cmp < 0)
110
0
                        return NULL;
111
16.9k
                } else {
112
                    // incref startkey because it can be removed from the set by the compare
113
16.9k
                    Py_INCREF(startkey);
114
16.9k
                    cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
115
16.9k
                    Py_DECREF(startkey);
116
16.9k
                    if (cmp < 0)
117
0
                        return NULL;
118
16.9k
                    if (table != so->table || entry->key != startkey)
119
0
                        return set_lookkey(so, key, hash);
120
16.9k
                }
121
16.9k
                if (cmp > 0)
122
16.9k
                    return entry;
123
0
                mask = so->mask;
124
0
            }
125
87.7M
            entry++;
126
87.7M
        } while (probes--);
127
13.3M
        perturb >>= PERTURB_SHIFT;
128
13.3M
        i = (i * 5 + 1 + perturb) & mask;
129
13.3M
    }
130
254M
}
131
132
static int set_table_resize(PySetObject *, Py_ssize_t);
133
134
static int
135
set_add_entry_takeref(PySetObject *so, PyObject *key, Py_hash_t hash)
136
7.11M
{
137
7.11M
    setentry *table;
138
7.11M
    setentry *freeslot;
139
7.11M
    setentry *entry;
140
7.11M
    size_t perturb;
141
7.11M
    size_t mask;
142
7.11M
    size_t i;                       /* Unsigned for defined overflow behavior */
143
7.11M
    int probes;
144
7.11M
    int cmp;
145
146
7.11M
  restart:
147
148
7.11M
    mask = so->mask;
149
7.11M
    i = (size_t)hash & mask;
150
7.11M
    freeslot = NULL;
151
7.11M
    perturb = hash;
152
153
7.21M
    while (1) {
154
7.21M
        entry = &so->table[i];
155
7.21M
        probes = (i + LINEAR_PROBES <= mask) ? LINEAR_PROBES: 0;
156
8.94M
        do {
157
8.94M
            if (entry->hash == 0 && entry->key == NULL)
158
1.69M
                goto found_unused_or_dummy;
159
7.25M
            if (entry->hash == hash) {
160
5.42M
                PyObject *startkey = entry->key;
161
5.42M
                assert(startkey != dummy);
162
5.42M
                if (startkey == key)
163
36.3k
                    goto found_active;
164
5.39M
                if (PyUnicode_CheckExact(startkey)
165
5.39M
                    && PyUnicode_CheckExact(key)
166
525k
                    && unicode_eq(startkey, key))
167
525k
                    goto found_active;
168
4.86M
                table = so->table;
169
4.86M
                Py_INCREF(startkey);
170
4.86M
                cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
171
4.86M
                Py_DECREF(startkey);
172
4.86M
                if (cmp > 0)
173
4.86M
                    goto found_active;
174
213
                if (cmp < 0)
175
0
                    goto comparison_error;
176
213
                if (table != so->table || entry->key != startkey)
177
0
                    goto restart;
178
213
                mask = so->mask;
179
213
            }
180
1.82M
            else if (entry->hash == -1) {
181
0
                assert (entry->key == dummy);
182
0
                freeslot = entry;
183
0
            }
184
1.82M
            entry++;
185
1.82M
        } while (probes--);
186
96.5k
        perturb >>= PERTURB_SHIFT;
187
96.5k
        i = (i * 5 + 1 + perturb) & mask;
188
96.5k
    }
189
190
1.69M
  found_unused_or_dummy:
191
1.69M
    if (freeslot == NULL)
192
1.69M
        goto found_unused;
193
0
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, so->used + 1);
194
0
    freeslot->key = key;
195
0
    freeslot->hash = hash;
196
0
    return 0;
197
198
1.69M
  found_unused:
199
1.69M
    so->fill++;
200
1.69M
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, so->used + 1);
201
1.69M
    entry->key = key;
202
1.69M
    entry->hash = hash;
203
1.69M
    if ((size_t)so->fill*5 < mask*3)
204
1.67M
        return 0;
205
18.7k
    return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4);
206
207
5.42M
  found_active:
208
5.42M
    Py_DECREF(key);
209
5.42M
    return 0;
210
211
0
  comparison_error:
212
0
    Py_DECREF(key);
213
0
    return -1;
214
1.69M
}
215
216
static int
217
set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
218
7.11M
{
219
7.11M
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
220
221
7.11M
    return set_add_entry_takeref(so, Py_NewRef(key), hash);
222
7.11M
}
223
224
static void
225
set_unhashable_type(PyObject *key)
226
0
{
227
0
    PyObject *exc = PyErr_GetRaisedException();
228
0
    assert(exc != NULL);
229
0
    if (!Py_IS_TYPE(exc, (PyTypeObject*)PyExc_TypeError)) {
230
0
        PyErr_SetRaisedException(exc);
231
0
        return;
232
0
    }
233
234
0
    PyErr_Format(PyExc_TypeError,
235
0
                 "cannot use '%T' as a set element (%S)",
236
0
                 key, exc);
237
0
    Py_DECREF(exc);
238
0
}
239
240
int
241
_PySet_AddTakeRef(PySetObject *so, PyObject *key)
242
3.50k
{
243
3.50k
    Py_hash_t hash = _PyObject_HashFast(key);
244
3.50k
    if (hash == -1) {
245
0
        set_unhashable_type(key);
246
0
        Py_DECREF(key);
247
0
        return -1;
248
0
    }
249
    // We don't pre-increment here, the caller holds a strong
250
    // reference to the object which we are stealing.
251
3.50k
    return set_add_entry_takeref(so, key, hash);
252
3.50k
}
253
254
/*
255
Internal routine used by set_table_resize() to insert an item which is
256
known to be absent from the set.  Besides the performance benefit,
257
there is also safety benefit since using set_add_entry() risks making
258
a callback in the middle of a set_table_resize(), see issue 1456209.
259
The caller is responsible for updating the key's reference count and
260
the setobject's fill and used fields.
261
*/
262
static void
263
set_insert_clean(setentry *table, size_t mask, PyObject *key, Py_hash_t hash)
264
851k
{
265
851k
    setentry *entry;
266
851k
    size_t perturb = hash;
267
851k
    size_t i = (size_t)hash & mask;
268
851k
    size_t j;
269
270
854k
    while (1) {
271
854k
        entry = &table[i];
272
854k
        if (entry->key == NULL)
273
790k
            goto found_null;
274
63.6k
        if (i + LINEAR_PROBES <= mask) {
275
71.5k
            for (j = 0; j < LINEAR_PROBES; j++) {
276
71.5k
                entry++;
277
71.5k
                if (entry->key == NULL)
278
61.4k
                    goto found_null;
279
71.5k
            }
280
61.4k
        }
281
2.22k
        perturb >>= PERTURB_SHIFT;
282
2.22k
        i = (i * 5 + 1 + perturb) & mask;
283
2.22k
    }
284
851k
  found_null:
285
851k
    entry->key = key;
286
851k
    entry->hash = hash;
287
851k
}
288
289
/* ======== End logic for probing the hash table ========================== */
290
/* ======================================================================== */
291
292
/*
293
Restructure the table by allocating a new table and reinserting all
294
keys again.  When entries have been deleted, the new table may
295
actually be smaller than the old one.
296
*/
297
static int
298
set_table_resize(PySetObject *so, Py_ssize_t minused)
299
26.0k
{
300
26.0k
    setentry *oldtable, *newtable, *entry;
301
26.0k
    Py_ssize_t oldmask = so->mask;
302
26.0k
    size_t newmask;
303
26.0k
    int is_oldtable_malloced;
304
26.0k
    setentry small_copy[PySet_MINSIZE];
305
306
26.0k
    assert(minused >= 0);
307
308
    /* Find the smallest table size > minused. */
309
    /* XXX speed-up with intrinsics */
310
26.0k
    size_t newsize = PySet_MINSIZE;
311
91.7k
    while (newsize <= (size_t)minused) {
312
65.7k
        newsize <<= 1; // The largest possible value is PY_SSIZE_T_MAX + 1.
313
65.7k
    }
314
315
    /* Get space for a new table. */
316
26.0k
    oldtable = so->table;
317
26.0k
    assert(oldtable != NULL);
318
26.0k
    is_oldtable_malloced = oldtable != so->smalltable;
319
320
26.0k
    if (newsize == PySet_MINSIZE) {
321
        /* A large table is shrinking, or we can't get any smaller. */
322
0
        newtable = so->smalltable;
323
0
        if (newtable == oldtable) {
324
0
            if (so->fill == so->used) {
325
                /* No dummies, so no point doing anything. */
326
0
                return 0;
327
0
            }
328
            /* We're not going to resize it, but rebuild the
329
               table anyway to purge old dummy entries.
330
               Subtle:  This is *necessary* if fill==size,
331
               as set_lookkey needs at least one virgin slot to
332
               terminate failing searches.  If fill < size, it's
333
               merely desirable, as dummies slow searches. */
334
0
            assert(so->fill > so->used);
335
0
            memcpy(small_copy, oldtable, sizeof(small_copy));
336
0
            oldtable = small_copy;
337
0
        }
338
0
    }
339
26.0k
    else {
340
26.0k
        newtable = PyMem_NEW(setentry, newsize);
341
26.0k
        if (newtable == NULL) {
342
0
            PyErr_NoMemory();
343
0
            return -1;
344
0
        }
345
26.0k
    }
346
347
    /* Make the set empty, using the new table. */
348
26.0k
    assert(newtable != oldtable);
349
26.0k
    memset(newtable, 0, sizeof(setentry) * newsize);
350
26.0k
    so->mask = newsize - 1;
351
26.0k
    so->table = newtable;
352
353
    /* Copy the data over; this is refcount-neutral for active entries;
354
       dummy entries aren't copied over, of course */
355
26.0k
    newmask = (size_t)so->mask;
356
26.0k
    if (so->fill == so->used) {
357
1.47M
        for (entry = oldtable; entry <= oldtable + oldmask; entry++) {
358
1.44M
            if (entry->key != NULL) {
359
842k
                set_insert_clean(newtable, newmask, entry->key, entry->hash);
360
842k
            }
361
1.44M
        }
362
26.0k
    } else {
363
0
        so->fill = so->used;
364
0
        for (entry = oldtable; entry <= oldtable + oldmask; entry++) {
365
0
            if (entry->key != NULL && entry->key != dummy) {
366
0
                set_insert_clean(newtable, newmask, entry->key, entry->hash);
367
0
            }
368
0
        }
369
0
    }
370
371
26.0k
    if (is_oldtable_malloced)
372
6.14k
        PyMem_Free(oldtable);
373
26.0k
    return 0;
374
26.0k
}
375
376
static int
377
set_contains_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
378
254M
{
379
254M
    setentry *entry;
380
381
254M
    entry = set_lookkey(so, key, hash);
382
254M
    if (entry != NULL)
383
254M
        return entry->key != NULL;
384
0
    return -1;
385
254M
}
386
387
85.7k
#define DISCARD_NOTFOUND 0
388
1.60k
#define DISCARD_FOUND 1
389
390
static int
391
set_discard_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
392
87.3k
{
393
87.3k
    setentry *entry;
394
87.3k
    PyObject *old_key;
395
396
87.3k
    entry = set_lookkey(so, key, hash);
397
87.3k
    if (entry == NULL)
398
0
        return -1;
399
87.3k
    if (entry->key == NULL)
400
85.7k
        return DISCARD_NOTFOUND;
401
1.60k
    old_key = entry->key;
402
1.60k
    entry->key = dummy;
403
1.60k
    entry->hash = -1;
404
1.60k
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, so->used - 1);
405
1.60k
    Py_DECREF(old_key);
406
1.60k
    return DISCARD_FOUND;
407
87.3k
}
408
409
static int
410
set_add_key(PySetObject *so, PyObject *key)
411
7.06M
{
412
7.06M
    Py_hash_t hash = _PyObject_HashFast(key);
413
7.06M
    if (hash == -1) {
414
0
        set_unhashable_type(key);
415
0
        return -1;
416
0
    }
417
7.06M
    return set_add_entry(so, key, hash);
418
7.06M
}
419
420
static int
421
set_contains_key(PySetObject *so, PyObject *key)
422
254M
{
423
254M
    Py_hash_t hash = _PyObject_HashFast(key);
424
254M
    if (hash == -1) {
425
0
        set_unhashable_type(key);
426
0
        return -1;
427
0
    }
428
254M
    return set_contains_entry(so, key, hash);
429
254M
}
430
431
static int
432
set_discard_key(PySetObject *so, PyObject *key)
433
87.3k
{
434
87.3k
    Py_hash_t hash = _PyObject_HashFast(key);
435
87.3k
    if (hash == -1) {
436
0
        set_unhashable_type(key);
437
0
        return -1;
438
0
    }
439
87.3k
    return set_discard_entry(so, key, hash);
440
87.3k
}
441
442
static void
443
set_empty_to_minsize(PySetObject *so)
444
4.92k
{
445
4.92k
    memset(so->smalltable, 0, sizeof(so->smalltable));
446
4.92k
    so->fill = 0;
447
4.92k
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, 0);
448
4.92k
    so->mask = PySet_MINSIZE - 1;
449
4.92k
    so->table = so->smalltable;
450
4.92k
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->hash, -1);
451
4.92k
}
452
453
static int
454
set_clear_internal(PyObject *self)
455
9.55k
{
456
9.55k
    PySetObject *so = _PySet_CAST(self);
457
9.55k
    setentry *entry;
458
9.55k
    setentry *table = so->table;
459
9.55k
    Py_ssize_t fill = so->fill;
460
9.55k
    Py_ssize_t used = so->used;
461
9.55k
    int table_is_malloced = table != so->smalltable;
462
9.55k
    setentry small_copy[PySet_MINSIZE];
463
464
9.55k
    assert (PyAnySet_Check(so));
465
9.55k
    assert(table != NULL);
466
467
    /* This is delicate.  During the process of clearing the set,
468
     * decrefs can cause the set to mutate.  To avoid fatal confusion
469
     * (voice of experience), we have to make the set empty before
470
     * clearing the slots, and never refer to anything via so->ref while
471
     * clearing.
472
     */
473
9.55k
    if (table_is_malloced)
474
1.57k
        set_empty_to_minsize(so);
475
476
7.98k
    else if (fill > 0) {
477
        /* It's a small table with something that needs to be cleared.
478
         * Afraid the only safe way is to copy the set entries into
479
         * another small table first.
480
         */
481
3.34k
        memcpy(small_copy, table, sizeof(small_copy));
482
3.34k
        table = small_copy;
483
3.34k
        set_empty_to_minsize(so);
484
3.34k
    }
485
    /* else it's a small table that's already empty */
486
487
    /* Now we can finally clear things.  If C had refcounts, we could
488
     * assert that the refcount on table is 1 now, i.e. that this function
489
     * has unique access to it, so decref side-effects can't alter it.
490
     */
491
1.27M
    for (entry = table; used > 0; entry++) {
492
1.26M
        if (entry->key && entry->key != dummy) {
493
332k
            used--;
494
332k
            Py_DECREF(entry->key);
495
332k
        }
496
1.26M
    }
497
498
9.55k
    if (table_is_malloced)
499
1.57k
        PyMem_Free(table);
500
9.55k
    return 0;
501
9.55k
}
502
503
/*
504
 * Iterate over a set table.  Use like so:
505
 *
506
 *     Py_ssize_t pos;
507
 *     setentry *entry;
508
 *     pos = 0;   # important!  pos should not otherwise be changed by you
509
 *     while (set_next(yourset, &pos, &entry)) {
510
 *              Refer to borrowed reference in entry->key.
511
 *     }
512
 *
513
 * CAUTION:  In general, it isn't safe to use set_next in a loop that
514
 * mutates the table.
515
 */
516
static int
517
set_next(PySetObject *so, Py_ssize_t *pos_ptr, setentry **entry_ptr)
518
3.73M
{
519
3.73M
    Py_ssize_t i;
520
3.73M
    Py_ssize_t mask;
521
3.73M
    setentry *entry;
522
523
3.73M
    assert (PyAnySet_Check(so));
524
3.73M
    i = *pos_ptr;
525
3.73M
    assert(i >= 0);
526
3.73M
    mask = so->mask;
527
3.73M
    entry = &so->table[i];
528
17.1M
    while (i <= mask && (entry->key == NULL || entry->key == dummy)) {
529
13.3M
        i++;
530
13.3M
        entry++;
531
13.3M
    }
532
3.73M
    *pos_ptr = i+1;
533
3.73M
    if (i > mask)
534
1.13M
        return 0;
535
3.73M
    assert(entry != NULL);
536
2.59M
    *entry_ptr = entry;
537
2.59M
    return 1;
538
3.73M
}
539
540
static void
541
set_dealloc(PyObject *self)
542
1.65M
{
543
1.65M
    PySetObject *so = _PySet_CAST(self);
544
1.65M
    setentry *entry;
545
1.65M
    Py_ssize_t used = so->used;
546
547
    /* bpo-31095: UnTrack is needed before calling any callbacks */
548
1.65M
    PyObject_GC_UnTrack(so);
549
1.65M
    FT_CLEAR_WEAKREFS(self, so->weakreflist);
550
551
5.99M
    for (entry = so->table; used > 0; entry++) {
552
4.34M
        if (entry->key && entry->key != dummy) {
553
1.42M
                used--;
554
1.42M
                Py_DECREF(entry->key);
555
1.42M
        }
556
4.34M
    }
557
1.65M
    if (so->table != so->smalltable)
558
17.5k
        PyMem_Free(so->table);
559
1.65M
    Py_TYPE(so)->tp_free(so);
560
1.65M
}
561
562
static PyObject *
563
set_repr_lock_held(PySetObject *so)
564
0
{
565
0
    PyObject *result=NULL, *keys, *listrepr, *tmp;
566
0
    int status = Py_ReprEnter((PyObject*)so);
567
568
0
    if (status != 0) {
569
0
        if (status < 0)
570
0
            return NULL;
571
0
        return PyUnicode_FromFormat("%s(...)", Py_TYPE(so)->tp_name);
572
0
    }
573
574
    /* shortcut for the empty set */
575
0
    if (!so->used) {
576
0
        Py_ReprLeave((PyObject*)so);
577
0
        return PyUnicode_FromFormat("%s()", Py_TYPE(so)->tp_name);
578
0
    }
579
580
    // gh-129967: avoid PySequence_List because it might re-lock the object
581
    // lock or the GIL and allow something to clear the set from underneath us.
582
0
    keys = PyList_New(so->used);
583
0
    if (keys == NULL) {
584
0
        goto done;
585
0
    }
586
587
0
    Py_ssize_t pos = 0, idx = 0;
588
0
    setentry *entry;
589
0
    while (set_next(so, &pos, &entry)) {
590
0
        PyList_SET_ITEM(keys, idx++, Py_NewRef(entry->key));
591
0
    }
592
593
    /* repr(keys)[1:-1] */
594
0
    listrepr = PyObject_Repr(keys);
595
0
    Py_DECREF(keys);
596
0
    if (listrepr == NULL)
597
0
        goto done;
598
0
    tmp = PyUnicode_Substring(listrepr, 1, PyUnicode_GET_LENGTH(listrepr)-1);
599
0
    Py_DECREF(listrepr);
600
0
    if (tmp == NULL)
601
0
        goto done;
602
0
    listrepr = tmp;
603
604
0
    if (!PySet_CheckExact(so))
605
0
        result = PyUnicode_FromFormat("%s({%U})",
606
0
                                      Py_TYPE(so)->tp_name,
607
0
                                      listrepr);
608
0
    else
609
0
        result = PyUnicode_FromFormat("{%U}", listrepr);
610
0
    Py_DECREF(listrepr);
611
0
done:
612
0
    Py_ReprLeave((PyObject*)so);
613
0
    return result;
614
0
}
615
616
static PyObject *
617
set_repr(PyObject *self)
618
0
{
619
0
    PySetObject *so = _PySet_CAST(self);
620
0
    PyObject *result;
621
0
    Py_BEGIN_CRITICAL_SECTION(so);
622
0
    result = set_repr_lock_held(so);
623
0
    Py_END_CRITICAL_SECTION();
624
0
    return result;
625
0
}
626
627
static Py_ssize_t
628
set_len(PyObject *self)
629
288k
{
630
288k
    PySetObject *so = _PySet_CAST(self);
631
288k
    return FT_ATOMIC_LOAD_SSIZE_RELAXED(so->used);
632
288k
}
633
634
static int
635
set_merge_lock_held(PySetObject *so, PyObject *otherset)
636
130k
{
637
130k
    PySetObject *other;
638
130k
    PyObject *key;
639
130k
    Py_ssize_t i;
640
130k
    setentry *so_entry;
641
130k
    setentry *other_entry;
642
643
130k
    assert (PyAnySet_Check(so));
644
130k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
645
130k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(otherset);
646
647
130k
    other = _PySet_CAST(otherset);
648
130k
    if (other == so || other->used == 0)
649
        /* a.update(a) or a.update(set()); nothing to do */
650
74.7k
        return 0;
651
    /* Do one big resize at the start, rather than
652
     * incrementally resizing as we insert new keys.  Expect
653
     * that there will be no (or few) overlapping keys.
654
     */
655
55.6k
    if ((so->fill + other->used)*5 >= so->mask*3) {
656
7.25k
        if (set_table_resize(so, (so->used + other->used)*2) != 0)
657
0
            return -1;
658
7.25k
    }
659
55.6k
    so_entry = so->table;
660
55.6k
    other_entry = other->table;
661
662
    /* If our table is empty, and both tables have the same size, and
663
       there are no dummies to eliminate, then just copy the pointers. */
664
55.6k
    if (so->fill == 0 && so->mask == other->mask && other->fill == other->used) {
665
400k
        for (i = 0; i <= other->mask; i++, so_entry++, other_entry++) {
666
362k
            key = other_entry->key;
667
362k
            if (key != NULL) {
668
90.9k
                assert(so_entry->key == NULL);
669
90.9k
                so_entry->key = Py_NewRef(key);
670
90.9k
                so_entry->hash = other_entry->hash;
671
90.9k
            }
672
362k
        }
673
38.0k
        so->fill = other->fill;
674
38.0k
        FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, other->used);
675
38.0k
        return 0;
676
38.0k
    }
677
678
    /* If our table is empty, we can use set_insert_clean() */
679
17.6k
    if (so->fill == 0) {
680
1.14k
        setentry *newtable = so->table;
681
1.14k
        size_t newmask = (size_t)so->mask;
682
1.14k
        so->fill = other->used;
683
1.14k
        FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, other->used);
684
44.1k
        for (i = other->mask + 1; i > 0 ; i--, other_entry++) {
685
42.9k
            key = other_entry->key;
686
42.9k
            if (key != NULL && key != dummy) {
687
9.12k
                set_insert_clean(newtable, newmask, Py_NewRef(key),
688
9.12k
                                 other_entry->hash);
689
9.12k
            }
690
42.9k
        }
691
1.14k
        return 0;
692
1.14k
    }
693
694
    /* We can't assure there are no duplicates, so do normal insertions */
695
181k
    for (i = 0; i <= other->mask; i++) {
696
164k
        other_entry = &other->table[i];
697
164k
        key = other_entry->key;
698
164k
        if (key != NULL && key != dummy) {
699
47.1k
            if (set_add_entry(so, key, other_entry->hash))
700
0
                return -1;
701
47.1k
        }
702
164k
    }
703
16.4k
    return 0;
704
16.4k
}
705
706
/*[clinic input]
707
@critical_section
708
set.pop
709
    so: setobject
710
711
Remove and return an arbitrary set element.
712
713
Raises KeyError if the set is empty.
714
[clinic start generated code]*/
715
716
static PyObject *
717
set_pop_impl(PySetObject *so)
718
/*[clinic end generated code: output=4d65180f1271871b input=9296c84921125060]*/
719
236
{
720
    /* Make sure the search finger is in bounds */
721
236
    setentry *entry = so->table + (so->finger & so->mask);
722
236
    setentry *limit = so->table + so->mask;
723
236
    PyObject *key;
724
725
236
    if (so->used == 0) {
726
0
        PyErr_SetString(PyExc_KeyError, "pop from an empty set");
727
0
        return NULL;
728
0
    }
729
519
    while (entry->key == NULL || entry->key==dummy) {
730
283
        entry++;
731
283
        if (entry > limit)
732
0
            entry = so->table;
733
283
    }
734
236
    key = entry->key;
735
236
    entry->key = dummy;
736
236
    entry->hash = -1;
737
236
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, so->used - 1);
738
236
    so->finger = entry - so->table + 1;   /* next place to start */
739
236
    return key;
740
236
}
741
742
static int
743
set_traverse(PyObject *self, visitproc visit, void *arg)
744
1.11M
{
745
1.11M
    PySetObject *so = _PySet_CAST(self);
746
1.11M
    Py_ssize_t pos = 0;
747
1.11M
    setentry *entry;
748
749
3.63M
    while (set_next(so, &pos, &entry))
750
2.51M
        Py_VISIT(entry->key);
751
1.11M
    return 0;
752
1.11M
}
753
754
/* Work to increase the bit dispersion for closely spaced hash values.
755
   This is important because some use cases have many combinations of a
756
   small number of elements with nearby hashes so that many distinct
757
   combinations collapse to only a handful of distinct hash values. */
758
759
static Py_uhash_t
760
_shuffle_bits(Py_uhash_t h)
761
4.17k
{
762
4.17k
    return ((h ^ 89869747UL) ^ (h << 16)) * 3644798167UL;
763
4.17k
}
764
765
/* Most of the constants in this hash algorithm are randomly chosen
766
   large primes with "interesting bit patterns" and that passed tests
767
   for good collision statistics on a variety of problematic datasets
768
   including powersets and graph structures (such as David Eppstein's
769
   graph recipes in Lib/test/test_set.py).
770
771
   This hash algorithm can be used on either a frozenset or a set.
772
   When it is used on a set, it computes the hash value of the equivalent
773
   frozenset without creating a new frozenset object. */
774
775
static Py_hash_t
776
frozenset_hash_impl(PyObject *self)
777
207
{
778
207
    PySetObject *so = _PySet_CAST(self);
779
207
    Py_uhash_t hash = 0;
780
207
    setentry *entry;
781
782
    /* Xor-in shuffled bits from every entry's hash field because xor is
783
       commutative and a frozenset hash should be independent of order.
784
785
       For speed, include null entries and dummy entries and then
786
       subtract out their effect afterwards so that the final hash
787
       depends only on active entries.  This allows the code to be
788
       vectorized by the compiler and it saves the unpredictable
789
       branches that would arise when trying to exclude null and dummy
790
       entries on every iteration. */
791
792
4.31k
    for (entry = so->table; entry <= &so->table[so->mask]; entry++)
793
4.10k
        hash ^= _shuffle_bits(entry->hash);
794
795
    /* Remove the effect of an odd number of NULL entries */
796
207
    if ((so->mask + 1 - so->fill) & 1)
797
72
        hash ^= _shuffle_bits(0);
798
799
    /* Remove the effect of an odd number of dummy entries */
800
207
    if ((so->fill - so->used) & 1)
801
0
        hash ^= _shuffle_bits(-1);
802
803
    /* Factor in the number of active entries */
804
207
    hash ^= ((Py_uhash_t)PySet_GET_SIZE(self) + 1) * 1927868237UL;
805
806
    /* Disperse patterns arising in nested frozensets */
807
207
    hash ^= (hash >> 11) ^ (hash >> 25);
808
207
    hash = hash * 69069U + 907133923UL;
809
810
    /* -1 is reserved as an error code */
811
207
    if (hash == (Py_uhash_t)-1)
812
0
        hash = 590923713UL;
813
814
207
    return (Py_hash_t)hash;
815
207
}
816
817
static Py_hash_t
818
frozenset_hash(PyObject *self)
819
345
{
820
345
    PySetObject *so = _PySet_CAST(self);
821
345
    Py_uhash_t hash;
822
823
345
    if (FT_ATOMIC_LOAD_SSIZE_RELAXED(so->hash) != -1) {
824
138
        return FT_ATOMIC_LOAD_SSIZE_RELAXED(so->hash);
825
138
    }
826
827
207
    hash = frozenset_hash_impl(self);
828
207
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->hash, hash);
829
207
    return hash;
830
345
}
831
832
/***** Set iterator type ***********************************************/
833
834
typedef struct {
835
    PyObject_HEAD
836
    PySetObject *si_set; /* Set to NULL when iterator is exhausted */
837
    Py_ssize_t si_used;
838
    Py_ssize_t si_pos;
839
    Py_ssize_t len;
840
} setiterobject;
841
842
static void
843
setiter_dealloc(PyObject *self)
844
269k
{
845
269k
    setiterobject *si = (setiterobject*)self;
846
    /* bpo-31095: UnTrack is needed before calling any callbacks */
847
269k
    _PyObject_GC_UNTRACK(si);
848
269k
    Py_XDECREF(si->si_set);
849
269k
    PyObject_GC_Del(si);
850
269k
}
851
852
static int
853
setiter_traverse(PyObject *self, visitproc visit, void *arg)
854
100
{
855
100
    setiterobject *si = (setiterobject*)self;
856
100
    Py_VISIT(si->si_set);
857
100
    return 0;
858
100
}
859
860
static PyObject *
861
setiter_len(PyObject *op, PyObject *Py_UNUSED(ignored))
862
10
{
863
10
    setiterobject *si = (setiterobject*)op;
864
10
    Py_ssize_t len = 0;
865
10
    if (si->si_set != NULL && si->si_used == si->si_set->used)
866
10
        len = si->len;
867
10
    return PyLong_FromSsize_t(len);
868
10
}
869
870
PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
871
872
static PyObject *
873
setiter_reduce(PyObject *op, PyObject *Py_UNUSED(ignored))
874
0
{
875
0
    setiterobject *si = (setiterobject*)op;
876
877
    /* copy the iterator state */
878
0
    setiterobject tmp = *si;
879
0
    Py_XINCREF(tmp.si_set);
880
881
    /* iterate the temporary into a list */
882
0
    PyObject *list = PySequence_List((PyObject*)&tmp);
883
0
    Py_XDECREF(tmp.si_set);
884
0
    if (list == NULL) {
885
0
        return NULL;
886
0
    }
887
0
    return Py_BuildValue("N(N)", _PyEval_GetBuiltin(&_Py_ID(iter)), list);
888
0
}
889
890
PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
891
892
static PyMethodDef setiter_methods[] = {
893
    {"__length_hint__", setiter_len, METH_NOARGS, length_hint_doc},
894
    {"__reduce__", setiter_reduce, METH_NOARGS, reduce_doc},
895
    {NULL,              NULL}           /* sentinel */
896
};
897
898
static PyObject *setiter_iternext(PyObject *self)
899
720k
{
900
720k
    setiterobject *si = (setiterobject*)self;
901
720k
    PyObject *key = NULL;
902
720k
    Py_ssize_t i, mask;
903
720k
    setentry *entry;
904
720k
    PySetObject *so = si->si_set;
905
906
720k
    if (so == NULL)
907
0
        return NULL;
908
720k
    assert (PyAnySet_Check(so));
909
910
720k
    Py_ssize_t so_used = FT_ATOMIC_LOAD_SSIZE(so->used);
911
720k
    Py_ssize_t si_used = FT_ATOMIC_LOAD_SSIZE(si->si_used);
912
720k
    if (si_used != so_used) {
913
0
        PyErr_SetString(PyExc_RuntimeError,
914
0
                        "Set changed size during iteration");
915
0
        si->si_used = -1; /* Make this state sticky */
916
0
        return NULL;
917
0
    }
918
919
720k
    Py_BEGIN_CRITICAL_SECTION(so);
920
720k
    i = si->si_pos;
921
720k
    assert(i>=0);
922
720k
    entry = so->table;
923
720k
    mask = so->mask;
924
3.64M
    while (i <= mask && (entry[i].key == NULL || entry[i].key == dummy)) {
925
2.92M
        i++;
926
2.92M
    }
927
720k
    if (i <= mask) {
928
450k
        key = Py_NewRef(entry[i].key);
929
450k
    }
930
720k
    Py_END_CRITICAL_SECTION();
931
720k
    si->si_pos = i+1;
932
720k
    if (key == NULL) {
933
269k
        si->si_set = NULL;
934
269k
        Py_DECREF(so);
935
269k
        return NULL;
936
269k
    }
937
450k
    si->len--;
938
450k
    return key;
939
720k
}
940
941
PyTypeObject PySetIter_Type = {
942
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
943
    "set_iterator",                             /* tp_name */
944
    sizeof(setiterobject),                      /* tp_basicsize */
945
    0,                                          /* tp_itemsize */
946
    /* methods */
947
    setiter_dealloc,                            /* tp_dealloc */
948
    0,                                          /* tp_vectorcall_offset */
949
    0,                                          /* tp_getattr */
950
    0,                                          /* tp_setattr */
951
    0,                                          /* tp_as_async */
952
    0,                                          /* tp_repr */
953
    0,                                          /* tp_as_number */
954
    0,                                          /* tp_as_sequence */
955
    0,                                          /* tp_as_mapping */
956
    0,                                          /* tp_hash */
957
    0,                                          /* tp_call */
958
    0,                                          /* tp_str */
959
    PyObject_GenericGetAttr,                    /* tp_getattro */
960
    0,                                          /* tp_setattro */
961
    0,                                          /* tp_as_buffer */
962
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,    /* tp_flags */
963
    0,                                          /* tp_doc */
964
    setiter_traverse,                           /* tp_traverse */
965
    0,                                          /* tp_clear */
966
    0,                                          /* tp_richcompare */
967
    0,                                          /* tp_weaklistoffset */
968
    PyObject_SelfIter,                          /* tp_iter */
969
    setiter_iternext,                           /* tp_iternext */
970
    setiter_methods,                            /* tp_methods */
971
    0,
972
};
973
974
static PyObject *
975
set_iter(PyObject *so)
976
269k
{
977
269k
    Py_ssize_t size = set_len(so);
978
269k
    setiterobject *si = PyObject_GC_New(setiterobject, &PySetIter_Type);
979
269k
    if (si == NULL)
980
0
        return NULL;
981
269k
    si->si_set = (PySetObject*)Py_NewRef(so);
982
269k
    si->si_used = size;
983
269k
    si->si_pos = 0;
984
269k
    si->len = size;
985
269k
    _PyObject_GC_TRACK(si);
986
269k
    return (PyObject *)si;
987
269k
}
988
989
static int
990
set_update_dict_lock_held(PySetObject *so, PyObject *other)
991
180
{
992
180
    assert(PyDict_CheckExact(other));
993
994
180
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
995
180
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(other);
996
997
    /* Do one big resize at the start, rather than
998
    * incrementally resizing as we insert new keys.  Expect
999
    * that there will be no (or few) overlapping keys.
1000
    */
1001
180
    Py_ssize_t dictsize = PyDict_GET_SIZE(other);
1002
180
    if ((so->fill + dictsize)*5 >= so->mask*3) {
1003
4
        if (set_table_resize(so, (so->used + dictsize)*2) != 0) {
1004
0
            return -1;
1005
0
        }
1006
4
    }
1007
1008
180
    Py_ssize_t pos = 0;
1009
180
    PyObject *key;
1010
180
    PyObject *value;
1011
180
    Py_hash_t hash;
1012
344
    while (_PyDict_Next(other, &pos, &key, &value, &hash)) {
1013
164
        if (set_add_entry(so, key, hash)) {
1014
0
            return -1;
1015
0
        }
1016
164
    }
1017
180
    return 0;
1018
180
}
1019
1020
static int
1021
set_update_iterable_lock_held(PySetObject *so, PyObject *other)
1022
14.9k
{
1023
14.9k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
1024
1025
14.9k
    PyObject *it = PyObject_GetIter(other);
1026
14.9k
    if (it == NULL) {
1027
0
        return -1;
1028
0
    }
1029
1030
14.9k
    PyObject *key;
1031
76.6k
    while ((key = PyIter_Next(it)) != NULL) {
1032
61.7k
        if (set_add_key(so, key)) {
1033
0
            Py_DECREF(it);
1034
0
            Py_DECREF(key);
1035
0
            return -1;
1036
0
        }
1037
61.7k
        Py_DECREF(key);
1038
61.7k
    }
1039
14.9k
    Py_DECREF(it);
1040
14.9k
    if (PyErr_Occurred())
1041
0
        return -1;
1042
14.9k
    return 0;
1043
14.9k
}
1044
1045
static int
1046
set_update_lock_held(PySetObject *so, PyObject *other)
1047
0
{
1048
0
    if (PyAnySet_Check(other)) {
1049
0
        return set_merge_lock_held(so, other);
1050
0
    }
1051
0
    else if (PyDict_CheckExact(other)) {
1052
0
        return set_update_dict_lock_held(so, other);
1053
0
    }
1054
0
    return set_update_iterable_lock_held(so, other);
1055
0
}
1056
1057
// set_update for a `so` that is only visible to the current thread
1058
static int
1059
set_update_local(PySetObject *so, PyObject *other)
1060
72.8k
{
1061
72.8k
    assert(Py_REFCNT(so) == 1);
1062
72.8k
    if (PyAnySet_Check(other)) {
1063
57.6k
        int rv;
1064
57.6k
        Py_BEGIN_CRITICAL_SECTION(other);
1065
57.6k
        rv = set_merge_lock_held(so, other);
1066
57.6k
        Py_END_CRITICAL_SECTION();
1067
57.6k
        return rv;
1068
57.6k
    }
1069
15.1k
    else if (PyDict_CheckExact(other)) {
1070
180
        int rv;
1071
180
        Py_BEGIN_CRITICAL_SECTION(other);
1072
180
        rv = set_update_dict_lock_held(so, other);
1073
180
        Py_END_CRITICAL_SECTION();
1074
180
        return rv;
1075
180
    }
1076
14.9k
    return set_update_iterable_lock_held(so, other);
1077
72.8k
}
1078
1079
static int
1080
set_update_internal(PySetObject *so, PyObject *other)
1081
70.1k
{
1082
70.1k
    if (PyAnySet_Check(other)) {
1083
70.1k
        if (Py_Is((PyObject *)so, other)) {
1084
0
            return 0;
1085
0
        }
1086
70.1k
        int rv;
1087
70.1k
        Py_BEGIN_CRITICAL_SECTION2(so, other);
1088
70.1k
        rv = set_merge_lock_held(so, other);
1089
70.1k
        Py_END_CRITICAL_SECTION2();
1090
70.1k
        return rv;
1091
70.1k
    }
1092
0
    else if (PyDict_CheckExact(other)) {
1093
0
        int rv;
1094
0
        Py_BEGIN_CRITICAL_SECTION2(so, other);
1095
0
        rv = set_update_dict_lock_held(so, other);
1096
0
        Py_END_CRITICAL_SECTION2();
1097
0
        return rv;
1098
0
    }
1099
0
    else {
1100
0
        int rv;
1101
0
        Py_BEGIN_CRITICAL_SECTION(so);
1102
0
        rv = set_update_iterable_lock_held(so, other);
1103
0
        Py_END_CRITICAL_SECTION();
1104
0
        return rv;
1105
0
    }
1106
70.1k
}
1107
1108
/*[clinic input]
1109
set.update
1110
    so: setobject
1111
    *others: array
1112
1113
Update the set, adding elements from all others.
1114
[clinic start generated code]*/
1115
1116
static PyObject *
1117
set_update_impl(PySetObject *so, PyObject * const *others,
1118
                Py_ssize_t others_length)
1119
/*[clinic end generated code: output=017c781c992d5c23 input=ed5d78885b076636]*/
1120
0
{
1121
0
    Py_ssize_t i;
1122
1123
0
    for (i = 0; i < others_length; i++) {
1124
0
        PyObject *other = others[i];
1125
0
        if (set_update_internal(so, other))
1126
0
            return NULL;
1127
0
    }
1128
0
    Py_RETURN_NONE;
1129
0
}
1130
1131
/* XXX Todo:
1132
   If aligned memory allocations become available, make the
1133
   set object 64 byte aligned so that most of the fields
1134
   can be retrieved or updated in a single cache line.
1135
*/
1136
1137
static PyObject *
1138
make_new_set(PyTypeObject *type, PyObject *iterable)
1139
1.65M
{
1140
1.65M
    assert(PyType_Check(type));
1141
1.65M
    PySetObject *so;
1142
1143
1.65M
    so = (PySetObject *)type->tp_alloc(type, 0);
1144
1.65M
    if (so == NULL)
1145
0
        return NULL;
1146
1147
1.65M
    so->fill = 0;
1148
1.65M
    so->used = 0;
1149
1.65M
    so->mask = PySet_MINSIZE - 1;
1150
1.65M
    so->table = so->smalltable;
1151
1.65M
    so->hash = -1;
1152
1.65M
    so->finger = 0;
1153
1.65M
    so->weakreflist = NULL;
1154
1155
1.65M
    if (iterable != NULL) {
1156
72.7k
        if (set_update_local(so, iterable)) {
1157
0
            Py_DECREF(so);
1158
0
            return NULL;
1159
0
        }
1160
72.7k
    }
1161
1162
1.65M
    return (PyObject *)so;
1163
1.65M
}
1164
1165
static PyObject *
1166
make_new_set_basetype(PyTypeObject *type, PyObject *iterable)
1167
2.64k
{
1168
2.64k
    if (type != &PySet_Type && type != &PyFrozenSet_Type) {
1169
0
        if (PyType_IsSubtype(type, &PySet_Type))
1170
0
            type = &PySet_Type;
1171
0
        else
1172
0
            type = &PyFrozenSet_Type;
1173
0
    }
1174
2.64k
    return make_new_set(type, iterable);
1175
2.64k
}
1176
1177
static PyObject *
1178
make_new_frozenset(PyTypeObject *type, PyObject *iterable)
1179
331
{
1180
331
    if (type != &PyFrozenSet_Type) {
1181
0
        return make_new_set(type, iterable);
1182
0
    }
1183
1184
331
    if (iterable != NULL && PyFrozenSet_CheckExact(iterable)) {
1185
        /* frozenset(f) is idempotent */
1186
0
        return Py_NewRef(iterable);
1187
0
    }
1188
331
    return make_new_set(type, iterable);
1189
331
}
1190
1191
static PyObject *
1192
frozenset_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1193
0
{
1194
0
    PyObject *iterable = NULL;
1195
1196
0
    if ((type == &PyFrozenSet_Type ||
1197
0
         type->tp_init == PyFrozenSet_Type.tp_init) &&
1198
0
        !_PyArg_NoKeywords("frozenset", kwds)) {
1199
0
        return NULL;
1200
0
    }
1201
1202
0
    if (!PyArg_UnpackTuple(args, type->tp_name, 0, 1, &iterable)) {
1203
0
        return NULL;
1204
0
    }
1205
1206
0
    return make_new_frozenset(type, iterable);
1207
0
}
1208
1209
static PyObject *
1210
frozenset_vectorcall(PyObject *type, PyObject * const*args,
1211
                     size_t nargsf, PyObject *kwnames)
1212
331
{
1213
331
    if (!_PyArg_NoKwnames("frozenset", kwnames)) {
1214
0
        return NULL;
1215
0
    }
1216
1217
331
    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
1218
331
    if (!_PyArg_CheckPositional("frozenset", nargs, 0, 1)) {
1219
0
        return NULL;
1220
0
    }
1221
1222
331
    PyObject *iterable = (nargs ? args[0] : NULL);
1223
331
    return make_new_frozenset(_PyType_CAST(type), iterable);
1224
331
}
1225
1226
static PyObject *
1227
set_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1228
0
{
1229
0
    return make_new_set(type, NULL);
1230
0
}
1231
1232
/* set_swap_bodies() switches the contents of any two sets by moving their
1233
   internal data pointers and, if needed, copying the internal smalltables.
1234
   Semantically equivalent to:
1235
1236
     t=set(a); a.clear(); a.update(b); b.clear(); b.update(t); del t
1237
1238
   The function always succeeds and it leaves both objects in a stable state.
1239
   Useful for operations that update in-place (by allowing an intermediate
1240
   result to be swapped into one of the original inputs).
1241
*/
1242
1243
static void
1244
set_swap_bodies(PySetObject *a, PySetObject *b)
1245
0
{
1246
0
    Py_ssize_t t;
1247
0
    setentry *u;
1248
0
    setentry tab[PySet_MINSIZE];
1249
0
    Py_hash_t h;
1250
1251
0
    t = a->fill;     a->fill   = b->fill;        b->fill  = t;
1252
0
    t = a->used;
1253
0
    FT_ATOMIC_STORE_SSIZE_RELAXED(a->used, b->used);
1254
0
    FT_ATOMIC_STORE_SSIZE_RELAXED(b->used, t);
1255
0
    t = a->mask;     a->mask   = b->mask;        b->mask  = t;
1256
1257
0
    u = a->table;
1258
0
    if (a->table == a->smalltable)
1259
0
        u = b->smalltable;
1260
0
    a->table  = b->table;
1261
0
    if (b->table == b->smalltable)
1262
0
        a->table = a->smalltable;
1263
0
    b->table = u;
1264
1265
0
    if (a->table == a->smalltable || b->table == b->smalltable) {
1266
0
        memcpy(tab, a->smalltable, sizeof(tab));
1267
0
        memcpy(a->smalltable, b->smalltable, sizeof(tab));
1268
0
        memcpy(b->smalltable, tab, sizeof(tab));
1269
0
    }
1270
1271
0
    if (PyType_IsSubtype(Py_TYPE(a), &PyFrozenSet_Type)  &&
1272
0
        PyType_IsSubtype(Py_TYPE(b), &PyFrozenSet_Type)) {
1273
0
        h = FT_ATOMIC_LOAD_SSIZE_RELAXED(a->hash);
1274
0
        FT_ATOMIC_STORE_SSIZE_RELAXED(a->hash, FT_ATOMIC_LOAD_SSIZE_RELAXED(b->hash));
1275
0
        FT_ATOMIC_STORE_SSIZE_RELAXED(b->hash, h);
1276
0
    } else {
1277
0
        FT_ATOMIC_STORE_SSIZE_RELAXED(a->hash, -1);
1278
0
        FT_ATOMIC_STORE_SSIZE_RELAXED(b->hash, -1);
1279
0
    }
1280
0
}
1281
1282
/*[clinic input]
1283
@critical_section
1284
set.copy
1285
    so: setobject
1286
1287
Return a shallow copy of a set.
1288
[clinic start generated code]*/
1289
1290
static PyObject *
1291
set_copy_impl(PySetObject *so)
1292
/*[clinic end generated code: output=c9223a1e1cc6b041 input=c169a4fbb8209257]*/
1293
2.46k
{
1294
2.46k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
1295
2.46k
    PyObject *copy = make_new_set_basetype(Py_TYPE(so), NULL);
1296
2.46k
    if (copy == NULL) {
1297
0
        return NULL;
1298
0
    }
1299
2.46k
    if (set_merge_lock_held((PySetObject *)copy, (PyObject *)so) < 0) {
1300
0
        Py_DECREF(copy);
1301
0
        return NULL;
1302
0
    }
1303
2.46k
    return copy;
1304
2.46k
}
1305
1306
/*[clinic input]
1307
@critical_section
1308
frozenset.copy
1309
    so: setobject
1310
1311
Return a shallow copy of a set.
1312
[clinic start generated code]*/
1313
1314
static PyObject *
1315
frozenset_copy_impl(PySetObject *so)
1316
/*[clinic end generated code: output=b356263526af9e70 input=fbf5bef131268dd7]*/
1317
0
{
1318
0
    if (PyFrozenSet_CheckExact(so)) {
1319
0
        return Py_NewRef(so);
1320
0
    }
1321
0
    return set_copy_impl(so);
1322
0
}
1323
1324
/*[clinic input]
1325
@critical_section
1326
set.clear
1327
    so: setobject
1328
1329
Remove all elements from this set.
1330
[clinic start generated code]*/
1331
1332
static PyObject *
1333
set_clear_impl(PySetObject *so)
1334
/*[clinic end generated code: output=4e71d5a83904161a input=c6f831b366111950]*/
1335
9.55k
{
1336
9.55k
    set_clear_internal((PyObject*)so);
1337
9.55k
    Py_RETURN_NONE;
1338
9.55k
}
1339
1340
/*[clinic input]
1341
set.union
1342
    so: setobject
1343
    *others: array
1344
1345
Return a new set with elements from the set and all others.
1346
[clinic start generated code]*/
1347
1348
static PyObject *
1349
set_union_impl(PySetObject *so, PyObject * const *others,
1350
               Py_ssize_t others_length)
1351
/*[clinic end generated code: output=b1bfa3d74065f27e input=55a2e81db6347a4f]*/
1352
2
{
1353
2
    PySetObject *result;
1354
2
    PyObject *other;
1355
2
    Py_ssize_t i;
1356
1357
2
    result = (PySetObject *)set_copy((PyObject *)so, NULL);
1358
2
    if (result == NULL)
1359
0
        return NULL;
1360
1361
4
    for (i = 0; i < others_length; i++) {
1362
2
        other = others[i];
1363
2
        if ((PyObject *)so == other)
1364
0
            continue;
1365
2
        if (set_update_local(result, other)) {
1366
0
            Py_DECREF(result);
1367
0
            return NULL;
1368
0
        }
1369
2
    }
1370
2
    return (PyObject *)result;
1371
2
}
1372
1373
static PyObject *
1374
set_or(PyObject *self, PyObject *other)
1375
64
{
1376
64
    PySetObject *result;
1377
1378
64
    if (!PyAnySet_Check(self) || !PyAnySet_Check(other))
1379
0
        Py_RETURN_NOTIMPLEMENTED;
1380
1381
64
    result = (PySetObject *)set_copy(self, NULL);
1382
64
    if (result == NULL) {
1383
0
        return NULL;
1384
0
    }
1385
64
    if (Py_Is(self, other)) {
1386
0
        return (PyObject *)result;
1387
0
    }
1388
64
    if (set_update_local(result, other)) {
1389
0
        Py_DECREF(result);
1390
0
        return NULL;
1391
0
    }
1392
64
    return (PyObject *)result;
1393
64
}
1394
1395
static PyObject *
1396
set_ior(PyObject *self, PyObject *other)
1397
70.1k
{
1398
70.1k
    if (!PyAnySet_Check(other))
1399
0
        Py_RETURN_NOTIMPLEMENTED;
1400
70.1k
    PySetObject *so = _PySet_CAST(self);
1401
1402
70.1k
    if (set_update_internal(so, other)) {
1403
0
        return NULL;
1404
0
    }
1405
70.1k
    return Py_NewRef(so);
1406
70.1k
}
1407
1408
static PyObject *
1409
set_intersection(PySetObject *so, PyObject *other)
1410
180
{
1411
180
    PySetObject *result;
1412
180
    PyObject *key, *it, *tmp;
1413
180
    Py_hash_t hash;
1414
180
    int rv;
1415
1416
180
    if ((PyObject *)so == other)
1417
0
        return set_copy_impl(so);
1418
1419
180
    result = (PySetObject *)make_new_set_basetype(Py_TYPE(so), NULL);
1420
180
    if (result == NULL)
1421
0
        return NULL;
1422
1423
180
    if (PyAnySet_Check(other)) {
1424
180
        Py_ssize_t pos = 0;
1425
180
        setentry *entry;
1426
1427
180
        if (PySet_GET_SIZE(other) > PySet_GET_SIZE(so)) {
1428
144
            tmp = (PyObject *)so;
1429
144
            so = (PySetObject *)other;
1430
144
            other = tmp;
1431
144
        }
1432
1433
252
        while (set_next((PySetObject *)other, &pos, &entry)) {
1434
72
            key = entry->key;
1435
72
            hash = entry->hash;
1436
72
            Py_INCREF(key);
1437
72
            rv = set_contains_entry(so, key, hash);
1438
72
            if (rv < 0) {
1439
0
                Py_DECREF(result);
1440
0
                Py_DECREF(key);
1441
0
                return NULL;
1442
0
            }
1443
72
            if (rv) {
1444
0
                if (set_add_entry(result, key, hash)) {
1445
0
                    Py_DECREF(result);
1446
0
                    Py_DECREF(key);
1447
0
                    return NULL;
1448
0
                }
1449
0
            }
1450
72
            Py_DECREF(key);
1451
72
        }
1452
180
        return (PyObject *)result;
1453
180
    }
1454
1455
0
    it = PyObject_GetIter(other);
1456
0
    if (it == NULL) {
1457
0
        Py_DECREF(result);
1458
0
        return NULL;
1459
0
    }
1460
1461
0
    while ((key = PyIter_Next(it)) != NULL) {
1462
0
        hash = PyObject_Hash(key);
1463
0
        if (hash == -1)
1464
0
            goto error;
1465
0
        rv = set_contains_entry(so, key, hash);
1466
0
        if (rv < 0)
1467
0
            goto error;
1468
0
        if (rv) {
1469
0
            if (set_add_entry(result, key, hash))
1470
0
                goto error;
1471
0
            if (PySet_GET_SIZE(result) >= PySet_GET_SIZE(so)) {
1472
0
                Py_DECREF(key);
1473
0
                break;
1474
0
            }
1475
0
        }
1476
0
        Py_DECREF(key);
1477
0
    }
1478
0
    Py_DECREF(it);
1479
0
    if (PyErr_Occurred()) {
1480
0
        Py_DECREF(result);
1481
0
        return NULL;
1482
0
    }
1483
0
    return (PyObject *)result;
1484
0
  error:
1485
0
    Py_DECREF(it);
1486
0
    Py_DECREF(result);
1487
0
    Py_DECREF(key);
1488
0
    return NULL;
1489
0
}
1490
1491
/*[clinic input]
1492
set.intersection as set_intersection_multi
1493
    so: setobject
1494
    *others: array
1495
1496
Return a new set with elements common to the set and all others.
1497
[clinic start generated code]*/
1498
1499
static PyObject *
1500
set_intersection_multi_impl(PySetObject *so, PyObject * const *others,
1501
                            Py_ssize_t others_length)
1502
/*[clinic end generated code: output=db9ff9f875132b6b input=36c7b615694cadae]*/
1503
0
{
1504
0
    Py_ssize_t i;
1505
1506
0
    if (others_length == 0) {
1507
0
        return set_copy((PyObject *)so, NULL);
1508
0
    }
1509
1510
0
    PyObject *result = Py_NewRef(so);
1511
0
    for (i = 0; i < others_length; i++) {
1512
0
        PyObject *other = others[i];
1513
0
        PyObject *newresult;
1514
0
        Py_BEGIN_CRITICAL_SECTION2(result, other);
1515
0
        newresult = set_intersection((PySetObject *)result, other);
1516
0
        Py_END_CRITICAL_SECTION2();
1517
0
        if (newresult == NULL) {
1518
0
            Py_DECREF(result);
1519
0
            return NULL;
1520
0
        }
1521
0
        Py_SETREF(result, newresult);
1522
0
    }
1523
0
    return result;
1524
0
}
1525
1526
static PyObject *
1527
set_intersection_update(PySetObject *so, PyObject *other)
1528
0
{
1529
0
    PyObject *tmp;
1530
1531
0
    tmp = set_intersection(so, other);
1532
0
    if (tmp == NULL)
1533
0
        return NULL;
1534
0
    set_swap_bodies(so, (PySetObject *)tmp);
1535
0
    Py_DECREF(tmp);
1536
0
    Py_RETURN_NONE;
1537
0
}
1538
1539
/*[clinic input]
1540
set.intersection_update as set_intersection_update_multi
1541
    so: setobject
1542
    *others: array
1543
1544
Update the set, keeping only elements found in it and all others.
1545
[clinic start generated code]*/
1546
1547
static PyObject *
1548
set_intersection_update_multi_impl(PySetObject *so, PyObject * const *others,
1549
                                   Py_ssize_t others_length)
1550
/*[clinic end generated code: output=d768b5584675b48d input=782e422fc370e4fc]*/
1551
0
{
1552
0
    PyObject *tmp;
1553
1554
0
    tmp = set_intersection_multi_impl(so, others, others_length);
1555
0
    if (tmp == NULL)
1556
0
        return NULL;
1557
0
    Py_BEGIN_CRITICAL_SECTION(so);
1558
0
    set_swap_bodies(so, (PySetObject *)tmp);
1559
0
    Py_END_CRITICAL_SECTION();
1560
0
    Py_DECREF(tmp);
1561
0
    Py_RETURN_NONE;
1562
0
}
1563
1564
static PyObject *
1565
set_and(PyObject *self, PyObject *other)
1566
180
{
1567
180
    if (!PyAnySet_Check(self) || !PyAnySet_Check(other))
1568
0
        Py_RETURN_NOTIMPLEMENTED;
1569
180
    PySetObject *so = _PySet_CAST(self);
1570
1571
180
    PyObject *rv;
1572
180
    Py_BEGIN_CRITICAL_SECTION2(so, other);
1573
180
    rv = set_intersection(so, other);
1574
180
    Py_END_CRITICAL_SECTION2();
1575
1576
180
    return rv;
1577
180
}
1578
1579
static PyObject *
1580
set_iand(PyObject *self, PyObject *other)
1581
0
{
1582
0
    PyObject *result;
1583
1584
0
    if (!PyAnySet_Check(other))
1585
0
        Py_RETURN_NOTIMPLEMENTED;
1586
0
    PySetObject *so = _PySet_CAST(self);
1587
1588
0
    Py_BEGIN_CRITICAL_SECTION2(so, other);
1589
0
    result = set_intersection_update(so, other);
1590
0
    Py_END_CRITICAL_SECTION2();
1591
1592
0
    if (result == NULL)
1593
0
        return NULL;
1594
0
    Py_DECREF(result);
1595
0
    return Py_NewRef(so);
1596
0
}
1597
1598
/*[clinic input]
1599
@critical_section so other
1600
set.isdisjoint
1601
    so: setobject
1602
    other: object
1603
    /
1604
1605
Return True if two sets have a null intersection.
1606
[clinic start generated code]*/
1607
1608
static PyObject *
1609
set_isdisjoint_impl(PySetObject *so, PyObject *other)
1610
/*[clinic end generated code: output=273493f2d57c565e input=32f8dcab5e0fc7d6]*/
1611
34.5k
{
1612
34.5k
    PyObject *key, *it, *tmp;
1613
34.5k
    int rv;
1614
1615
34.5k
    if ((PyObject *)so == other) {
1616
0
        if (PySet_GET_SIZE(so) == 0)
1617
0
            Py_RETURN_TRUE;
1618
0
        else
1619
0
            Py_RETURN_FALSE;
1620
0
    }
1621
1622
34.5k
    if (PyAnySet_CheckExact(other)) {
1623
0
        Py_ssize_t pos = 0;
1624
0
        setentry *entry;
1625
1626
0
        if (PySet_GET_SIZE(other) > PySet_GET_SIZE(so)) {
1627
0
            tmp = (PyObject *)so;
1628
0
            so = (PySetObject *)other;
1629
0
            other = tmp;
1630
0
        }
1631
0
        while (set_next((PySetObject *)other, &pos, &entry)) {
1632
0
            PyObject *key = entry->key;
1633
0
            Py_INCREF(key);
1634
0
            rv = set_contains_entry(so, key, entry->hash);
1635
0
            Py_DECREF(key);
1636
0
            if (rv < 0) {
1637
0
                return NULL;
1638
0
            }
1639
0
            if (rv) {
1640
0
                Py_RETURN_FALSE;
1641
0
            }
1642
0
        }
1643
0
        Py_RETURN_TRUE;
1644
0
    }
1645
1646
34.5k
    it = PyObject_GetIter(other);
1647
34.5k
    if (it == NULL)
1648
0
        return NULL;
1649
1650
3.70M
    while ((key = PyIter_Next(it)) != NULL) {
1651
3.68M
        rv = set_contains_key(so, key);
1652
3.68M
        Py_DECREF(key);
1653
3.68M
        if (rv < 0) {
1654
0
            Py_DECREF(it);
1655
0
            return NULL;
1656
0
        }
1657
3.68M
        if (rv) {
1658
14.2k
            Py_DECREF(it);
1659
14.2k
            Py_RETURN_FALSE;
1660
14.2k
        }
1661
3.68M
    }
1662
20.3k
    Py_DECREF(it);
1663
20.3k
    if (PyErr_Occurred())
1664
0
        return NULL;
1665
20.3k
    Py_RETURN_TRUE;
1666
20.3k
}
1667
1668
static int
1669
set_difference_update_internal(PySetObject *so, PyObject *other)
1670
10
{
1671
10
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
1672
10
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(other);
1673
1674
10
    if ((PyObject *)so == other)
1675
0
        return set_clear_internal((PyObject*)so);
1676
1677
10
    if (PyAnySet_Check(other)) {
1678
10
        setentry *entry;
1679
10
        Py_ssize_t pos = 0;
1680
1681
        /* Optimization:  When the other set is more than 8 times
1682
           larger than the base set, replace the other set with
1683
           intersection of the two sets.
1684
        */
1685
10
        if ((PySet_GET_SIZE(other) >> 3) > PySet_GET_SIZE(so)) {
1686
0
            other = set_intersection(so, other);
1687
0
            if (other == NULL)
1688
0
                return -1;
1689
10
        } else {
1690
10
            Py_INCREF(other);
1691
10
        }
1692
1693
22
        while (set_next((PySetObject *)other, &pos, &entry)) {
1694
12
            PyObject *key = entry->key;
1695
12
            Py_INCREF(key);
1696
12
            if (set_discard_entry(so, key, entry->hash) < 0) {
1697
0
                Py_DECREF(other);
1698
0
                Py_DECREF(key);
1699
0
                return -1;
1700
0
            }
1701
12
            Py_DECREF(key);
1702
12
        }
1703
1704
10
        Py_DECREF(other);
1705
10
    } else {
1706
0
        PyObject *key, *it;
1707
0
        it = PyObject_GetIter(other);
1708
0
        if (it == NULL)
1709
0
            return -1;
1710
1711
0
        while ((key = PyIter_Next(it)) != NULL) {
1712
0
            if (set_discard_key(so, key) < 0) {
1713
0
                Py_DECREF(it);
1714
0
                Py_DECREF(key);
1715
0
                return -1;
1716
0
            }
1717
0
            Py_DECREF(key);
1718
0
        }
1719
0
        Py_DECREF(it);
1720
0
        if (PyErr_Occurred())
1721
0
            return -1;
1722
0
    }
1723
    /* If more than 1/4th are dummies, then resize them away. */
1724
10
    if ((size_t)(so->fill - so->used) <= (size_t)so->mask / 4)
1725
10
        return 0;
1726
0
    return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4);
1727
10
}
1728
1729
/*[clinic input]
1730
set.difference_update
1731
    so: setobject
1732
    *others: array
1733
1734
Update the set, removing elements found in others.
1735
[clinic start generated code]*/
1736
1737
static PyObject *
1738
set_difference_update_impl(PySetObject *so, PyObject * const *others,
1739
                           Py_ssize_t others_length)
1740
/*[clinic end generated code: output=04a22179b322cfe6 input=93ac28ba5b233696]*/
1741
0
{
1742
0
    Py_ssize_t i;
1743
1744
0
    for (i = 0; i < others_length; i++) {
1745
0
        PyObject *other = others[i];
1746
0
        int rv;
1747
0
        Py_BEGIN_CRITICAL_SECTION2(so, other);
1748
0
        rv = set_difference_update_internal(so, other);
1749
0
        Py_END_CRITICAL_SECTION2();
1750
0
        if (rv) {
1751
0
            return NULL;
1752
0
        }
1753
0
    }
1754
0
    Py_RETURN_NONE;
1755
0
}
1756
1757
static PyObject *
1758
set_copy_and_difference(PySetObject *so, PyObject *other)
1759
10
{
1760
10
    PyObject *result;
1761
1762
10
    result = set_copy_impl(so);
1763
10
    if (result == NULL)
1764
0
        return NULL;
1765
10
    if (set_difference_update_internal((PySetObject *) result, other) == 0)
1766
10
        return result;
1767
0
    Py_DECREF(result);
1768
0
    return NULL;
1769
10
}
1770
1771
static PyObject *
1772
set_difference(PySetObject *so, PyObject *other)
1773
12
{
1774
12
    PyObject *result;
1775
12
    PyObject *key;
1776
12
    Py_hash_t hash;
1777
12
    setentry *entry;
1778
12
    Py_ssize_t pos = 0, other_size;
1779
12
    int rv;
1780
1781
12
    if (PyAnySet_Check(other)) {
1782
12
        other_size = PySet_GET_SIZE(other);
1783
12
    }
1784
0
    else if (PyDict_CheckExact(other)) {
1785
0
        other_size = PyDict_GET_SIZE(other);
1786
0
    }
1787
0
    else {
1788
0
        return set_copy_and_difference(so, other);
1789
0
    }
1790
1791
    /* If len(so) much more than len(other), it's more efficient to simply copy
1792
     * so and then iterate other looking for common elements. */
1793
12
    if ((PySet_GET_SIZE(so) >> 2) > other_size) {
1794
10
        return set_copy_and_difference(so, other);
1795
10
    }
1796
1797
2
    result = make_new_set_basetype(Py_TYPE(so), NULL);
1798
2
    if (result == NULL)
1799
0
        return NULL;
1800
1801
2
    if (PyDict_CheckExact(other)) {
1802
0
        while (set_next(so, &pos, &entry)) {
1803
0
            key = entry->key;
1804
0
            hash = entry->hash;
1805
0
            Py_INCREF(key);
1806
0
            rv = _PyDict_Contains_KnownHash(other, key, hash);
1807
0
            if (rv < 0) {
1808
0
                Py_DECREF(result);
1809
0
                Py_DECREF(key);
1810
0
                return NULL;
1811
0
            }
1812
0
            if (!rv) {
1813
0
                if (set_add_entry((PySetObject *)result, key, hash)) {
1814
0
                    Py_DECREF(result);
1815
0
                    Py_DECREF(key);
1816
0
                    return NULL;
1817
0
                }
1818
0
            }
1819
0
            Py_DECREF(key);
1820
0
        }
1821
0
        return result;
1822
0
    }
1823
1824
    /* Iterate over so, checking for common elements in other. */
1825
28
    while (set_next(so, &pos, &entry)) {
1826
26
        key = entry->key;
1827
26
        hash = entry->hash;
1828
26
        Py_INCREF(key);
1829
26
        rv = set_contains_entry((PySetObject *)other, key, hash);
1830
26
        if (rv < 0) {
1831
0
            Py_DECREF(result);
1832
0
            Py_DECREF(key);
1833
0
            return NULL;
1834
0
        }
1835
26
        if (!rv) {
1836
20
            if (set_add_entry((PySetObject *)result, key, hash)) {
1837
0
                Py_DECREF(result);
1838
0
                Py_DECREF(key);
1839
0
                return NULL;
1840
0
            }
1841
20
        }
1842
26
        Py_DECREF(key);
1843
26
    }
1844
2
    return result;
1845
2
}
1846
1847
/*[clinic input]
1848
set.difference as set_difference_multi
1849
    so: setobject
1850
    *others: array
1851
1852
Return a new set with elements in the set that are not in the others.
1853
[clinic start generated code]*/
1854
1855
static PyObject *
1856
set_difference_multi_impl(PySetObject *so, PyObject * const *others,
1857
                          Py_ssize_t others_length)
1858
/*[clinic end generated code: output=b0d33fb05d5477a7 input=c1eb448d483416ad]*/
1859
0
{
1860
0
    Py_ssize_t i;
1861
0
    PyObject *result, *other;
1862
1863
0
    if (others_length == 0) {
1864
0
        return set_copy((PyObject *)so, NULL);
1865
0
    }
1866
1867
0
    other = others[0];
1868
0
    Py_BEGIN_CRITICAL_SECTION2(so, other);
1869
0
    result = set_difference(so, other);
1870
0
    Py_END_CRITICAL_SECTION2();
1871
0
    if (result == NULL)
1872
0
        return NULL;
1873
1874
0
    for (i = 1; i < others_length; i++) {
1875
0
        other = others[i];
1876
0
        int rv;
1877
0
        Py_BEGIN_CRITICAL_SECTION(other);
1878
0
        rv = set_difference_update_internal((PySetObject *)result, other);
1879
0
        Py_END_CRITICAL_SECTION();
1880
0
        if (rv) {
1881
0
            Py_DECREF(result);
1882
0
            return NULL;
1883
0
        }
1884
0
    }
1885
0
    return result;
1886
0
}
1887
1888
static PyObject *
1889
set_sub(PyObject *self, PyObject *other)
1890
12
{
1891
12
    if (!PyAnySet_Check(self) || !PyAnySet_Check(other))
1892
0
        Py_RETURN_NOTIMPLEMENTED;
1893
12
    PySetObject *so = _PySet_CAST(self);
1894
1895
12
    PyObject *rv;
1896
12
    Py_BEGIN_CRITICAL_SECTION2(so, other);
1897
12
    rv = set_difference(so, other);
1898
12
    Py_END_CRITICAL_SECTION2();
1899
12
    return rv;
1900
12
}
1901
1902
static PyObject *
1903
set_isub(PyObject *self, PyObject *other)
1904
0
{
1905
0
    if (!PyAnySet_Check(other))
1906
0
        Py_RETURN_NOTIMPLEMENTED;
1907
0
    PySetObject *so = _PySet_CAST(self);
1908
1909
0
    int rv;
1910
0
    Py_BEGIN_CRITICAL_SECTION2(so, other);
1911
0
    rv = set_difference_update_internal(so, other);
1912
0
    Py_END_CRITICAL_SECTION2();
1913
0
    if (rv < 0) {
1914
0
        return NULL;
1915
0
    }
1916
0
    return Py_NewRef(so);
1917
0
}
1918
1919
static int
1920
set_symmetric_difference_update_dict(PySetObject *so, PyObject *other)
1921
0
{
1922
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
1923
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(other);
1924
1925
0
    Py_ssize_t pos = 0;
1926
0
    PyObject *key, *value;
1927
0
    Py_hash_t hash;
1928
0
    while (_PyDict_Next(other, &pos, &key, &value, &hash)) {
1929
0
        Py_INCREF(key);
1930
0
        int rv = set_discard_entry(so, key, hash);
1931
0
        if (rv < 0) {
1932
0
            Py_DECREF(key);
1933
0
            return -1;
1934
0
        }
1935
0
        if (rv == DISCARD_NOTFOUND) {
1936
0
            if (set_add_entry(so, key, hash)) {
1937
0
                Py_DECREF(key);
1938
0
                return -1;
1939
0
            }
1940
0
        }
1941
0
        Py_DECREF(key);
1942
0
    }
1943
0
    return 0;
1944
0
}
1945
1946
static int
1947
set_symmetric_difference_update_set(PySetObject *so, PySetObject *other)
1948
0
{
1949
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
1950
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(other);
1951
1952
0
    Py_ssize_t pos = 0;
1953
0
    setentry *entry;
1954
0
    while (set_next(other, &pos, &entry)) {
1955
0
        PyObject *key = Py_NewRef(entry->key);
1956
0
        Py_hash_t hash = entry->hash;
1957
0
        int rv = set_discard_entry(so, key, hash);
1958
0
        if (rv < 0) {
1959
0
            Py_DECREF(key);
1960
0
            return -1;
1961
0
        }
1962
0
        if (rv == DISCARD_NOTFOUND) {
1963
0
            if (set_add_entry(so, key, hash)) {
1964
0
                Py_DECREF(key);
1965
0
                return -1;
1966
0
            }
1967
0
        }
1968
0
        Py_DECREF(key);
1969
0
    }
1970
0
    return 0;
1971
0
}
1972
1973
/*[clinic input]
1974
@permit_long_summary
1975
set.symmetric_difference_update
1976
    so: setobject
1977
    other: object
1978
    /
1979
1980
Update the set, keeping only elements found in either set, but not in both.
1981
[clinic start generated code]*/
1982
1983
static PyObject *
1984
set_symmetric_difference_update_impl(PySetObject *so, PyObject *other)
1985
/*[clinic end generated code: output=79f80b4ee5da66c1 input=86a3dddac9bfb15e]*/
1986
0
{
1987
0
    if (Py_Is((PyObject *)so, other)) {
1988
0
        return set_clear((PyObject *)so, NULL);
1989
0
    }
1990
1991
0
    int rv;
1992
0
    if (PyDict_CheckExact(other)) {
1993
0
        Py_BEGIN_CRITICAL_SECTION2(so, other);
1994
0
        rv = set_symmetric_difference_update_dict(so, other);
1995
0
        Py_END_CRITICAL_SECTION2();
1996
0
    }
1997
0
    else if (PyAnySet_Check(other)) {
1998
0
        Py_BEGIN_CRITICAL_SECTION2(so, other);
1999
0
        rv = set_symmetric_difference_update_set(so, (PySetObject *)other);
2000
0
        Py_END_CRITICAL_SECTION2();
2001
0
    }
2002
0
    else {
2003
0
        PySetObject *otherset = (PySetObject *)make_new_set_basetype(Py_TYPE(so), other);
2004
0
        if (otherset == NULL) {
2005
0
            return NULL;
2006
0
        }
2007
2008
0
        Py_BEGIN_CRITICAL_SECTION(so);
2009
0
        rv = set_symmetric_difference_update_set(so, otherset);
2010
0
        Py_END_CRITICAL_SECTION();
2011
2012
0
        Py_DECREF(otherset);
2013
0
    }
2014
0
    if (rv < 0) {
2015
0
        return NULL;
2016
0
    }
2017
0
    Py_RETURN_NONE;
2018
0
}
2019
2020
/*[clinic input]
2021
@critical_section so other
2022
set.symmetric_difference
2023
    so: setobject
2024
    other: object
2025
    /
2026
2027
Return a new set with elements in either the set or other but not both.
2028
[clinic start generated code]*/
2029
2030
static PyObject *
2031
set_symmetric_difference_impl(PySetObject *so, PyObject *other)
2032
/*[clinic end generated code: output=270ee0b5d42b0797 input=624f6e7bbdf70db1]*/
2033
0
{
2034
0
    PySetObject *result = (PySetObject *)make_new_set_basetype(Py_TYPE(so), NULL);
2035
0
    if (result == NULL) {
2036
0
        return NULL;
2037
0
    }
2038
0
    if (set_update_lock_held(result, other) < 0) {
2039
0
        Py_DECREF(result);
2040
0
        return NULL;
2041
0
    }
2042
0
    if (set_symmetric_difference_update_set(result, so) < 0) {
2043
0
        Py_DECREF(result);
2044
0
        return NULL;
2045
0
    }
2046
0
    return (PyObject *)result;
2047
0
}
2048
2049
static PyObject *
2050
set_xor(PyObject *self, PyObject *other)
2051
0
{
2052
0
    if (!PyAnySet_Check(self) || !PyAnySet_Check(other))
2053
0
        Py_RETURN_NOTIMPLEMENTED;
2054
0
    PySetObject *so = _PySet_CAST(self);
2055
0
    return set_symmetric_difference((PyObject*)so, other);
2056
0
}
2057
2058
static PyObject *
2059
set_ixor(PyObject *self, PyObject *other)
2060
0
{
2061
0
    PyObject *result;
2062
2063
0
    if (!PyAnySet_Check(other))
2064
0
        Py_RETURN_NOTIMPLEMENTED;
2065
0
    PySetObject *so = _PySet_CAST(self);
2066
2067
0
    result = set_symmetric_difference_update((PyObject*)so, other);
2068
0
    if (result == NULL)
2069
0
        return NULL;
2070
0
    Py_DECREF(result);
2071
0
    return Py_NewRef(so);
2072
0
}
2073
2074
/*[clinic input]
2075
@critical_section so other
2076
set.issubset
2077
    so: setobject
2078
    other: object
2079
    /
2080
2081
Report whether another set contains this set.
2082
[clinic start generated code]*/
2083
2084
static PyObject *
2085
set_issubset_impl(PySetObject *so, PyObject *other)
2086
/*[clinic end generated code: output=b2b59d5f314555ce input=f2a4fd0f2537758b]*/
2087
118
{
2088
118
    setentry *entry;
2089
118
    Py_ssize_t pos = 0;
2090
118
    int rv;
2091
2092
118
    if (!PyAnySet_Check(other)) {
2093
0
        PyObject *tmp = set_intersection(so, other);
2094
0
        if (tmp == NULL) {
2095
0
            return NULL;
2096
0
        }
2097
0
        int result = (PySet_GET_SIZE(tmp) == PySet_GET_SIZE(so));
2098
0
        Py_DECREF(tmp);
2099
0
        return PyBool_FromLong(result);
2100
0
    }
2101
118
    if (PySet_GET_SIZE(so) > PySet_GET_SIZE(other))
2102
0
        Py_RETURN_FALSE;
2103
2104
528
    while (set_next(so, &pos, &entry)) {
2105
410
        PyObject *key = entry->key;
2106
410
        Py_INCREF(key);
2107
410
        rv = set_contains_entry((PySetObject *)other, key, entry->hash);
2108
410
        Py_DECREF(key);
2109
410
        if (rv < 0) {
2110
0
            return NULL;
2111
0
        }
2112
410
        if (!rv) {
2113
0
            Py_RETURN_FALSE;
2114
0
        }
2115
410
    }
2116
118
    Py_RETURN_TRUE;
2117
118
}
2118
2119
/*[clinic input]
2120
@critical_section so other
2121
set.issuperset
2122
    so: setobject
2123
    other: object
2124
    /
2125
2126
Report whether this set contains another set.
2127
[clinic start generated code]*/
2128
2129
static PyObject *
2130
set_issuperset_impl(PySetObject *so, PyObject *other)
2131
/*[clinic end generated code: output=ecf00ce552c09461 input=5f2e1f262e6e4ccc]*/
2132
2.55k
{
2133
2.55k
    if (PyAnySet_Check(other)) {
2134
0
        return set_issubset(other, (PyObject *)so);
2135
0
    }
2136
2137
2.55k
    PyObject *key, *it = PyObject_GetIter(other);
2138
2.55k
    if (it == NULL) {
2139
0
        return NULL;
2140
0
    }
2141
14.6k
    while ((key = PyIter_Next(it)) != NULL) {
2142
12.1k
        int rv = set_contains_key(so, key);
2143
12.1k
        Py_DECREF(key);
2144
12.1k
        if (rv < 0) {
2145
0
            Py_DECREF(it);
2146
0
            return NULL;
2147
0
        }
2148
12.1k
        if (!rv) {
2149
26
            Py_DECREF(it);
2150
26
            Py_RETURN_FALSE;
2151
26
        }
2152
12.1k
    }
2153
2.53k
    Py_DECREF(it);
2154
2.53k
    if (PyErr_Occurred()) {
2155
0
        return NULL;
2156
0
    }
2157
2.53k
    Py_RETURN_TRUE;
2158
2.53k
}
2159
2160
static PyObject *
2161
set_richcompare(PyObject *self, PyObject *w, int op)
2162
118
{
2163
118
    PySetObject *v = _PySet_CAST(self);
2164
118
    PyObject *r1;
2165
118
    int r2;
2166
2167
118
    if(!PyAnySet_Check(w))
2168
0
        Py_RETURN_NOTIMPLEMENTED;
2169
2170
118
    switch (op) {
2171
44
    case Py_EQ:
2172
44
        if (PySet_GET_SIZE(v) != PySet_GET_SIZE(w))
2173
0
            Py_RETURN_FALSE;
2174
44
        Py_hash_t v_hash = FT_ATOMIC_LOAD_SSIZE_RELAXED(v->hash);
2175
44
        Py_hash_t w_hash = FT_ATOMIC_LOAD_SSIZE_RELAXED(((PySetObject *)w)->hash);
2176
44
        if (v_hash != -1 && w_hash != -1 && v_hash != w_hash)
2177
0
            Py_RETURN_FALSE;
2178
44
        return set_issubset((PyObject*)v, w);
2179
0
    case Py_NE:
2180
0
        r1 = set_richcompare((PyObject*)v, w, Py_EQ);
2181
0
        if (r1 == NULL)
2182
0
            return NULL;
2183
0
        r2 = PyObject_IsTrue(r1);
2184
0
        Py_DECREF(r1);
2185
0
        if (r2 < 0)
2186
0
            return NULL;
2187
0
        return PyBool_FromLong(!r2);
2188
74
    case Py_LE:
2189
74
        return set_issubset((PyObject*)v, w);
2190
0
    case Py_GE:
2191
0
        return set_issuperset((PyObject*)v, w);
2192
0
    case Py_LT:
2193
0
        if (PySet_GET_SIZE(v) >= PySet_GET_SIZE(w))
2194
0
            Py_RETURN_FALSE;
2195
0
        return set_issubset((PyObject*)v, w);
2196
0
    case Py_GT:
2197
0
        if (PySet_GET_SIZE(v) <= PySet_GET_SIZE(w))
2198
0
            Py_RETURN_FALSE;
2199
0
        return set_issuperset((PyObject*)v, w);
2200
118
    }
2201
118
    Py_RETURN_NOTIMPLEMENTED;
2202
118
}
2203
2204
/*[clinic input]
2205
@critical_section
2206
set.add
2207
    so: setobject
2208
    object as key: object
2209
    /
2210
2211
Add an element to a set.
2212
2213
This has no effect if the element is already present.
2214
[clinic start generated code]*/
2215
2216
static PyObject *
2217
set_add_impl(PySetObject *so, PyObject *key)
2218
/*[clinic end generated code: output=4cc4a937f1425c96 input=03baf62cb0e66514]*/
2219
6.94M
{
2220
6.94M
    if (set_add_key(so, key))
2221
0
        return NULL;
2222
6.94M
    Py_RETURN_NONE;
2223
6.94M
}
2224
2225
static int
2226
set_contains_lock_held(PySetObject *so, PyObject *key)
2227
251M
{
2228
251M
    int rv;
2229
2230
251M
    rv = set_contains_key(so, key);
2231
251M
    if (rv < 0) {
2232
0
        if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError))
2233
0
            return -1;
2234
0
        PyErr_Clear();
2235
0
        Py_hash_t hash;
2236
0
        Py_BEGIN_CRITICAL_SECTION(key);
2237
0
        hash = frozenset_hash_impl(key);
2238
0
        Py_END_CRITICAL_SECTION();
2239
0
        rv = set_contains_entry(so, key, hash);
2240
0
    }
2241
251M
    return rv;
2242
251M
}
2243
2244
int
2245
_PySet_Contains(PySetObject *so, PyObject *key)
2246
229M
{
2247
229M
    assert(so);
2248
2249
229M
    int rv;
2250
229M
    if (PyFrozenSet_CheckExact(so)) {
2251
166M
        rv = set_contains_lock_held(so, key);
2252
166M
    } else {
2253
62.6M
        Py_BEGIN_CRITICAL_SECTION(so);
2254
62.6M
        rv = set_contains_lock_held(so, key);
2255
62.6M
        Py_END_CRITICAL_SECTION();
2256
62.6M
    }
2257
229M
    return rv;
2258
229M
}
2259
2260
static int
2261
set_contains(PyObject *self, PyObject *key)
2262
604
{
2263
604
    PySetObject *so = _PySet_CAST(self);
2264
604
    return _PySet_Contains(so, key);
2265
604
}
2266
2267
/*[clinic input]
2268
@critical_section
2269
@coexist
2270
set.__contains__
2271
    so: setobject
2272
    object as key: object
2273
    /
2274
2275
x.__contains__(y) <==> y in x.
2276
[clinic start generated code]*/
2277
2278
static PyObject *
2279
set___contains___impl(PySetObject *so, PyObject *key)
2280
/*[clinic end generated code: output=b44863d034b3c70e input=4a7d568459617f24]*/
2281
21.4M
{
2282
21.4M
    long result;
2283
2284
21.4M
    result = set_contains_lock_held(so, key);
2285
21.4M
    if (result < 0)
2286
0
        return NULL;
2287
21.4M
    return PyBool_FromLong(result);
2288
21.4M
}
2289
2290
/*[clinic input]
2291
@coexist
2292
frozenset.__contains__
2293
    so: setobject
2294
    object as key: object
2295
    /
2296
2297
x.__contains__(y) <==> y in x.
2298
[clinic start generated code]*/
2299
2300
static PyObject *
2301
frozenset___contains___impl(PySetObject *so, PyObject *key)
2302
/*[clinic end generated code: output=2301ed91bc3a6dd5 input=2f04922a98d8bab7]*/
2303
552
{
2304
552
    long result;
2305
2306
552
    result = set_contains_lock_held(so, key);
2307
552
    if (result < 0)
2308
0
        return NULL;
2309
552
    return PyBool_FromLong(result);
2310
552
}
2311
2312
/*[clinic input]
2313
@critical_section
2314
set.remove
2315
    so: setobject
2316
    object as key: object
2317
    /
2318
2319
Remove an element from a set; it must be a member.
2320
2321
If the element is not a member, raise a KeyError.
2322
[clinic start generated code]*/
2323
2324
static PyObject *
2325
set_remove_impl(PySetObject *so, PyObject *key)
2326
/*[clinic end generated code: output=0b9134a2a2200363 input=893e1cb1df98227a]*/
2327
0
{
2328
0
    int rv;
2329
2330
0
    rv = set_discard_key(so, key);
2331
0
    if (rv < 0) {
2332
0
        if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError))
2333
0
            return NULL;
2334
0
        PyErr_Clear();
2335
0
        Py_hash_t hash;
2336
0
        Py_BEGIN_CRITICAL_SECTION(key);
2337
0
        hash = frozenset_hash_impl(key);
2338
0
        Py_END_CRITICAL_SECTION();
2339
0
        rv = set_discard_entry(so, key, hash);
2340
0
        if (rv < 0)
2341
0
            return NULL;
2342
0
    }
2343
2344
0
    if (rv == DISCARD_NOTFOUND) {
2345
0
        _PyErr_SetKeyError(key);
2346
0
        return NULL;
2347
0
    }
2348
0
    Py_RETURN_NONE;
2349
0
}
2350
2351
/*[clinic input]
2352
@critical_section
2353
set.discard
2354
    so: setobject
2355
    object as key: object
2356
    /
2357
2358
Remove an element from a set if it is a member.
2359
2360
Unlike set.remove(), the discard() method does not raise
2361
an exception when an element is missing from the set.
2362
[clinic start generated code]*/
2363
2364
static PyObject *
2365
set_discard_impl(PySetObject *so, PyObject *key)
2366
/*[clinic end generated code: output=eec3b687bf32759e input=861cb7fb69b4def0]*/
2367
0
{
2368
0
    int rv;
2369
2370
0
    rv = set_discard_key(so, key);
2371
0
    if (rv < 0) {
2372
0
        if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError))
2373
0
            return NULL;
2374
0
        PyErr_Clear();
2375
0
        Py_hash_t hash;
2376
0
        Py_BEGIN_CRITICAL_SECTION(key);
2377
0
        hash = frozenset_hash_impl(key);
2378
0
        Py_END_CRITICAL_SECTION();
2379
0
        rv = set_discard_entry(so, key, hash);
2380
0
        if (rv < 0)
2381
0
            return NULL;
2382
0
    }
2383
0
    Py_RETURN_NONE;
2384
0
}
2385
2386
/*[clinic input]
2387
@critical_section
2388
set.__reduce__
2389
    so: setobject
2390
2391
Return state information for pickling.
2392
[clinic start generated code]*/
2393
2394
static PyObject *
2395
set___reduce___impl(PySetObject *so)
2396
/*[clinic end generated code: output=9af7d0e029df87ee input=59405a4249e82f71]*/
2397
0
{
2398
0
    PyObject *keys=NULL, *args=NULL, *result=NULL, *state=NULL;
2399
2400
0
    keys = PySequence_List((PyObject *)so);
2401
0
    if (keys == NULL)
2402
0
        goto done;
2403
0
    args = PyTuple_Pack(1, keys);
2404
0
    if (args == NULL)
2405
0
        goto done;
2406
0
    state = _PyObject_GetState((PyObject *)so);
2407
0
    if (state == NULL)
2408
0
        goto done;
2409
0
    result = PyTuple_Pack(3, Py_TYPE(so), args, state);
2410
0
done:
2411
0
    Py_XDECREF(args);
2412
0
    Py_XDECREF(keys);
2413
0
    Py_XDECREF(state);
2414
0
    return result;
2415
0
}
2416
2417
/*[clinic input]
2418
@critical_section
2419
set.__sizeof__
2420
    so: setobject
2421
2422
S.__sizeof__() -> size of S in memory, in bytes.
2423
[clinic start generated code]*/
2424
2425
static PyObject *
2426
set___sizeof___impl(PySetObject *so)
2427
/*[clinic end generated code: output=4bfa3df7bd38ed88 input=09e1a09f168eaa23]*/
2428
0
{
2429
0
    size_t res = _PyObject_SIZE(Py_TYPE(so));
2430
0
    if (so->table != so->smalltable) {
2431
0
        res += ((size_t)so->mask + 1) * sizeof(setentry);
2432
0
    }
2433
0
    return PyLong_FromSize_t(res);
2434
0
}
2435
2436
static int
2437
set_init(PyObject *so, PyObject *args, PyObject *kwds)
2438
0
{
2439
0
    PySetObject *self = _PySet_CAST(so);
2440
0
    PyObject *iterable = NULL;
2441
2442
0
    if (!_PyArg_NoKeywords("set", kwds))
2443
0
        return -1;
2444
0
    if (!PyArg_UnpackTuple(args, Py_TYPE(self)->tp_name, 0, 1, &iterable))
2445
0
        return -1;
2446
2447
0
    if (_PyObject_IsUniquelyReferenced((PyObject *)self) && self->fill == 0) {
2448
0
        self->hash = -1;
2449
0
        if (iterable == NULL) {
2450
0
            return 0;
2451
0
        }
2452
0
        return set_update_local(self, iterable);
2453
0
    }
2454
0
    Py_BEGIN_CRITICAL_SECTION(self);
2455
0
    if (self->fill)
2456
0
        set_clear_internal((PyObject*)self);
2457
0
    self->hash = -1;
2458
0
    Py_END_CRITICAL_SECTION();
2459
2460
0
    if (iterable == NULL)
2461
0
        return 0;
2462
0
    return set_update_internal(self, iterable);
2463
0
}
2464
2465
static PyObject*
2466
set_vectorcall(PyObject *type, PyObject * const*args,
2467
               size_t nargsf, PyObject *kwnames)
2468
1.51M
{
2469
1.51M
    assert(PyType_Check(type));
2470
2471
1.51M
    if (!_PyArg_NoKwnames("set", kwnames)) {
2472
0
        return NULL;
2473
0
    }
2474
2475
1.51M
    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
2476
1.51M
    if (!_PyArg_CheckPositional("set", nargs, 0, 1)) {
2477
0
        return NULL;
2478
0
    }
2479
2480
1.51M
    if (nargs) {
2481
14.5k
        return make_new_set(_PyType_CAST(type), args[0]);
2482
14.5k
    }
2483
2484
1.50M
    return make_new_set(_PyType_CAST(type), NULL);
2485
1.51M
}
2486
2487
static PySequenceMethods set_as_sequence = {
2488
    set_len,                            /* sq_length */
2489
    0,                                  /* sq_concat */
2490
    0,                                  /* sq_repeat */
2491
    0,                                  /* sq_item */
2492
    0,                                  /* sq_slice */
2493
    0,                                  /* sq_ass_item */
2494
    0,                                  /* sq_ass_slice */
2495
    set_contains,                       /* sq_contains */
2496
};
2497
2498
/* set object ********************************************************/
2499
2500
static PyMethodDef set_methods[] = {
2501
    SET_ADD_METHODDEF
2502
    SET_CLEAR_METHODDEF
2503
    SET___CONTAINS___METHODDEF
2504
    SET_COPY_METHODDEF
2505
    SET_DISCARD_METHODDEF
2506
    SET_DIFFERENCE_MULTI_METHODDEF
2507
    SET_DIFFERENCE_UPDATE_METHODDEF
2508
    SET_INTERSECTION_MULTI_METHODDEF
2509
    SET_INTERSECTION_UPDATE_MULTI_METHODDEF
2510
    SET_ISDISJOINT_METHODDEF
2511
    SET_ISSUBSET_METHODDEF
2512
    SET_ISSUPERSET_METHODDEF
2513
    SET_POP_METHODDEF
2514
    SET___REDUCE___METHODDEF
2515
    SET_REMOVE_METHODDEF
2516
    SET___SIZEOF___METHODDEF
2517
    SET_SYMMETRIC_DIFFERENCE_METHODDEF
2518
    SET_SYMMETRIC_DIFFERENCE_UPDATE_METHODDEF
2519
    SET_UNION_METHODDEF
2520
    SET_UPDATE_METHODDEF
2521
    {"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
2522
    {NULL,              NULL}   /* sentinel */
2523
};
2524
2525
static PyNumberMethods set_as_number = {
2526
    0,                                  /*nb_add*/
2527
    set_sub,                            /*nb_subtract*/
2528
    0,                                  /*nb_multiply*/
2529
    0,                                  /*nb_remainder*/
2530
    0,                                  /*nb_divmod*/
2531
    0,                                  /*nb_power*/
2532
    0,                                  /*nb_negative*/
2533
    0,                                  /*nb_positive*/
2534
    0,                                  /*nb_absolute*/
2535
    0,                                  /*nb_bool*/
2536
    0,                                  /*nb_invert*/
2537
    0,                                  /*nb_lshift*/
2538
    0,                                  /*nb_rshift*/
2539
    set_and,                            /*nb_and*/
2540
    set_xor,                            /*nb_xor*/
2541
    set_or,                             /*nb_or*/
2542
    0,                                  /*nb_int*/
2543
    0,                                  /*nb_reserved*/
2544
    0,                                  /*nb_float*/
2545
    0,                                  /*nb_inplace_add*/
2546
    set_isub,                           /*nb_inplace_subtract*/
2547
    0,                                  /*nb_inplace_multiply*/
2548
    0,                                  /*nb_inplace_remainder*/
2549
    0,                                  /*nb_inplace_power*/
2550
    0,                                  /*nb_inplace_lshift*/
2551
    0,                                  /*nb_inplace_rshift*/
2552
    set_iand,                           /*nb_inplace_and*/
2553
    set_ixor,                           /*nb_inplace_xor*/
2554
    set_ior,                            /*nb_inplace_or*/
2555
};
2556
2557
PyDoc_STRVAR(set_doc,
2558
"set(iterable=(), /)\n\
2559
--\n\
2560
\n\
2561
Build an unordered collection of unique elements.");
2562
2563
PyTypeObject PySet_Type = {
2564
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
2565
    "set",                              /* tp_name */
2566
    sizeof(PySetObject),                /* tp_basicsize */
2567
    0,                                  /* tp_itemsize */
2568
    /* methods */
2569
    set_dealloc,                        /* tp_dealloc */
2570
    0,                                  /* tp_vectorcall_offset */
2571
    0,                                  /* tp_getattr */
2572
    0,                                  /* tp_setattr */
2573
    0,                                  /* tp_as_async */
2574
    set_repr,                           /* tp_repr */
2575
    &set_as_number,                     /* tp_as_number */
2576
    &set_as_sequence,                   /* tp_as_sequence */
2577
    0,                                  /* tp_as_mapping */
2578
    PyObject_HashNotImplemented,        /* tp_hash */
2579
    0,                                  /* tp_call */
2580
    0,                                  /* tp_str */
2581
    PyObject_GenericGetAttr,            /* tp_getattro */
2582
    0,                                  /* tp_setattro */
2583
    0,                                  /* tp_as_buffer */
2584
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
2585
        Py_TPFLAGS_BASETYPE |
2586
        _Py_TPFLAGS_MATCH_SELF,         /* tp_flags */
2587
    set_doc,                            /* tp_doc */
2588
    set_traverse,                       /* tp_traverse */
2589
    set_clear_internal,                 /* tp_clear */
2590
    set_richcompare,                    /* tp_richcompare */
2591
    offsetof(PySetObject, weakreflist), /* tp_weaklistoffset */
2592
    set_iter,                           /* tp_iter */
2593
    0,                                  /* tp_iternext */
2594
    set_methods,                        /* tp_methods */
2595
    0,                                  /* tp_members */
2596
    0,                                  /* tp_getset */
2597
    0,                                  /* tp_base */
2598
    0,                                  /* tp_dict */
2599
    0,                                  /* tp_descr_get */
2600
    0,                                  /* tp_descr_set */
2601
    0,                                  /* tp_dictoffset */
2602
    set_init,                           /* tp_init */
2603
    PyType_GenericAlloc,                /* tp_alloc */
2604
    set_new,                            /* tp_new */
2605
    PyObject_GC_Del,                    /* tp_free */
2606
    .tp_vectorcall = set_vectorcall,
2607
    .tp_version_tag = _Py_TYPE_VERSION_SET,
2608
};
2609
2610
/* frozenset object ********************************************************/
2611
2612
2613
static PyMethodDef frozenset_methods[] = {
2614
    FROZENSET___CONTAINS___METHODDEF
2615
    FROZENSET_COPY_METHODDEF
2616
    SET_DIFFERENCE_MULTI_METHODDEF
2617
    SET_INTERSECTION_MULTI_METHODDEF
2618
    SET_ISDISJOINT_METHODDEF
2619
    SET_ISSUBSET_METHODDEF
2620
    SET_ISSUPERSET_METHODDEF
2621
    SET___REDUCE___METHODDEF
2622
    SET___SIZEOF___METHODDEF
2623
    SET_SYMMETRIC_DIFFERENCE_METHODDEF
2624
    SET_UNION_METHODDEF
2625
    {"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
2626
    {NULL,              NULL}   /* sentinel */
2627
};
2628
2629
static PyNumberMethods frozenset_as_number = {
2630
    0,                                  /*nb_add*/
2631
    set_sub,                            /*nb_subtract*/
2632
    0,                                  /*nb_multiply*/
2633
    0,                                  /*nb_remainder*/
2634
    0,                                  /*nb_divmod*/
2635
    0,                                  /*nb_power*/
2636
    0,                                  /*nb_negative*/
2637
    0,                                  /*nb_positive*/
2638
    0,                                  /*nb_absolute*/
2639
    0,                                  /*nb_bool*/
2640
    0,                                  /*nb_invert*/
2641
    0,                                  /*nb_lshift*/
2642
    0,                                  /*nb_rshift*/
2643
    set_and,                            /*nb_and*/
2644
    set_xor,                            /*nb_xor*/
2645
    set_or,                             /*nb_or*/
2646
};
2647
2648
PyDoc_STRVAR(frozenset_doc,
2649
"frozenset(iterable=(), /)\n\
2650
--\n\
2651
\n\
2652
Build an immutable unordered collection of unique elements.");
2653
2654
PyTypeObject PyFrozenSet_Type = {
2655
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
2656
    "frozenset",                        /* tp_name */
2657
    sizeof(PySetObject),                /* tp_basicsize */
2658
    0,                                  /* tp_itemsize */
2659
    /* methods */
2660
    set_dealloc,                        /* tp_dealloc */
2661
    0,                                  /* tp_vectorcall_offset */
2662
    0,                                  /* tp_getattr */
2663
    0,                                  /* tp_setattr */
2664
    0,                                  /* tp_as_async */
2665
    set_repr,                           /* tp_repr */
2666
    &frozenset_as_number,               /* tp_as_number */
2667
    &set_as_sequence,                   /* tp_as_sequence */
2668
    0,                                  /* tp_as_mapping */
2669
    frozenset_hash,                     /* tp_hash */
2670
    0,                                  /* tp_call */
2671
    0,                                  /* tp_str */
2672
    PyObject_GenericGetAttr,            /* tp_getattro */
2673
    0,                                  /* tp_setattro */
2674
    0,                                  /* tp_as_buffer */
2675
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
2676
        Py_TPFLAGS_BASETYPE |
2677
        _Py_TPFLAGS_MATCH_SELF,         /* tp_flags */
2678
    frozenset_doc,                      /* tp_doc */
2679
    set_traverse,                       /* tp_traverse */
2680
    set_clear_internal,                 /* tp_clear */
2681
    set_richcompare,                    /* tp_richcompare */
2682
    offsetof(PySetObject, weakreflist), /* tp_weaklistoffset */
2683
    set_iter,                           /* tp_iter */
2684
    0,                                  /* tp_iternext */
2685
    frozenset_methods,                  /* tp_methods */
2686
    0,                                  /* tp_members */
2687
    0,                                  /* tp_getset */
2688
    0,                                  /* tp_base */
2689
    0,                                  /* tp_dict */
2690
    0,                                  /* tp_descr_get */
2691
    0,                                  /* tp_descr_set */
2692
    0,                                  /* tp_dictoffset */
2693
    0,                                  /* tp_init */
2694
    PyType_GenericAlloc,                /* tp_alloc */
2695
    frozenset_new,                      /* tp_new */
2696
    PyObject_GC_Del,                    /* tp_free */
2697
    .tp_vectorcall = frozenset_vectorcall,
2698
    .tp_version_tag = _Py_TYPE_VERSION_FROZEN_SET,
2699
};
2700
2701
2702
/***** C API functions *************************************************/
2703
2704
PyObject *
2705
PySet_New(PyObject *iterable)
2706
134k
{
2707
134k
    return make_new_set(&PySet_Type, iterable);
2708
134k
}
2709
2710
PyObject *
2711
PyFrozenSet_New(PyObject *iterable)
2712
2.96k
{
2713
2.96k
    return make_new_set(&PyFrozenSet_Type, iterable);
2714
2.96k
}
2715
2716
Py_ssize_t
2717
PySet_Size(PyObject *anyset)
2718
136
{
2719
136
    if (!PyAnySet_Check(anyset)) {
2720
0
        PyErr_BadInternalCall();
2721
0
        return -1;
2722
0
    }
2723
136
    return set_len(anyset);
2724
136
}
2725
2726
int
2727
PySet_Clear(PyObject *set)
2728
333
{
2729
333
    if (!PySet_Check(set)) {
2730
0
        PyErr_BadInternalCall();
2731
0
        return -1;
2732
0
    }
2733
333
    (void)set_clear(set, NULL);
2734
333
    return 0;
2735
333
}
2736
2737
void
2738
_PySet_ClearInternal(PySetObject *so)
2739
0
{
2740
0
    (void)set_clear_internal((PyObject*)so);
2741
0
}
2742
2743
int
2744
PySet_Contains(PyObject *anyset, PyObject *key)
2745
184k
{
2746
184k
    if (!PyAnySet_Check(anyset)) {
2747
0
        PyErr_BadInternalCall();
2748
0
        return -1;
2749
0
    }
2750
184k
    if (PyFrozenSet_CheckExact(anyset)) {
2751
0
        return set_contains_key((PySetObject *)anyset, key);
2752
0
    }
2753
184k
    int rv;
2754
184k
    Py_BEGIN_CRITICAL_SECTION(anyset);
2755
184k
    rv = set_contains_key((PySetObject *)anyset, key);
2756
184k
    Py_END_CRITICAL_SECTION();
2757
184k
    return rv;
2758
184k
}
2759
2760
int
2761
PySet_Discard(PyObject *set, PyObject *key)
2762
87.3k
{
2763
87.3k
    if (!PySet_Check(set)) {
2764
0
        PyErr_BadInternalCall();
2765
0
        return -1;
2766
0
    }
2767
2768
87.3k
    int rv;
2769
87.3k
    Py_BEGIN_CRITICAL_SECTION(set);
2770
87.3k
    rv = set_discard_key((PySetObject *)set, key);
2771
87.3k
    Py_END_CRITICAL_SECTION();
2772
87.3k
    return rv;
2773
87.3k
}
2774
2775
int
2776
PySet_Add(PyObject *anyset, PyObject *key)
2777
58.0k
{
2778
58.0k
    if (PySet_Check(anyset)) {
2779
55.4k
        int rv;
2780
55.4k
        Py_BEGIN_CRITICAL_SECTION(anyset);
2781
55.4k
        rv = set_add_key((PySetObject *)anyset, key);
2782
55.4k
        Py_END_CRITICAL_SECTION();
2783
55.4k
        return rv;
2784
55.4k
    }
2785
2786
2.55k
    if (PyFrozenSet_Check(anyset) && _PyObject_IsUniquelyReferenced(anyset)) {
2787
        // We can only change frozensets if they are uniquely referenced. The
2788
        // API limits the usage of `PySet_Add` to "fill in the values of brand
2789
        // new frozensets before they are exposed to other code". In this case,
2790
        // this can be done without a lock.
2791
2.55k
        return set_add_key((PySetObject *)anyset, key);
2792
2.55k
    }
2793
2794
0
    PyErr_BadInternalCall();
2795
0
    return -1;
2796
2.55k
}
2797
2798
int
2799
_PySet_NextEntry(PyObject *set, Py_ssize_t *pos, PyObject **key, Py_hash_t *hash)
2800
1.89k
{
2801
1.89k
    setentry *entry;
2802
2803
1.89k
    if (!PyAnySet_Check(set)) {
2804
0
        PyErr_BadInternalCall();
2805
0
        return -1;
2806
0
    }
2807
1.89k
    if (set_next((PySetObject *)set, pos, &entry) == 0)
2808
475
        return 0;
2809
1.42k
    *key = entry->key;
2810
1.42k
    *hash = entry->hash;
2811
1.42k
    return 1;
2812
1.89k
}
2813
2814
int
2815
_PySet_NextEntryRef(PyObject *set, Py_ssize_t *pos, PyObject **key, Py_hash_t *hash)
2816
99.3k
{
2817
99.3k
    setentry *entry;
2818
2819
99.3k
    if (!PyAnySet_Check(set)) {
2820
0
        PyErr_BadInternalCall();
2821
0
        return -1;
2822
0
    }
2823
99.3k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(set);
2824
99.3k
    if (set_next((PySetObject *)set, pos, &entry) == 0)
2825
19.6k
        return 0;
2826
79.7k
    *key = Py_NewRef(entry->key);
2827
79.7k
    *hash = entry->hash;
2828
79.7k
    return 1;
2829
99.3k
}
2830
2831
PyObject *
2832
PySet_Pop(PyObject *set)
2833
24
{
2834
24
    if (!PySet_Check(set)) {
2835
0
        PyErr_BadInternalCall();
2836
0
        return NULL;
2837
0
    }
2838
24
    return set_pop(set, NULL);
2839
24
}
2840
2841
int
2842
_PySet_Update(PyObject *set, PyObject *iterable)
2843
36
{
2844
36
    if (!PySet_Check(set)) {
2845
0
        PyErr_BadInternalCall();
2846
0
        return -1;
2847
0
    }
2848
36
    return set_update_internal((PySetObject *)set, iterable);
2849
36
}
2850
2851
/* Exported for the gdb plugin's benefit. */
2852
PyObject *_PySet_Dummy = dummy;
2853
2854
/***** Dummy Struct  *************************************************/
2855
2856
static PyObject *
2857
dummy_repr(PyObject *op)
2858
0
{
2859
0
    return PyUnicode_FromString("<dummy key>");
2860
0
}
2861
2862
static void _Py_NO_RETURN
2863
dummy_dealloc(PyObject* ignore)
2864
0
{
2865
0
    Py_FatalError("deallocating <dummy key>");
2866
0
}
2867
2868
static PyTypeObject _PySetDummy_Type = {
2869
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
2870
    "<dummy key> type",
2871
    0,
2872
    0,
2873
    dummy_dealloc,      /*tp_dealloc*/ /*never called*/
2874
    0,                  /*tp_vectorcall_offset*/
2875
    0,                  /*tp_getattr*/
2876
    0,                  /*tp_setattr*/
2877
    0,                  /*tp_as_async*/
2878
    dummy_repr,         /*tp_repr*/
2879
    0,                  /*tp_as_number*/
2880
    0,                  /*tp_as_sequence*/
2881
    0,                  /*tp_as_mapping*/
2882
    0,                  /*tp_hash */
2883
    0,                  /*tp_call */
2884
    0,                  /*tp_str */
2885
    0,                  /*tp_getattro */
2886
    0,                  /*tp_setattro */
2887
    0,                  /*tp_as_buffer */
2888
    Py_TPFLAGS_DEFAULT, /*tp_flags */
2889
};
2890
2891
static PyObject _dummy_struct = _PyObject_HEAD_INIT(&_PySetDummy_Type);