Coverage Report

Created: 2025-11-24 06:11

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.95M
#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
398M
#define LINEAR_PROBES 9
73
#endif
74
75
/* This must be >= 1 */
76
15.2M
#define PERTURB_SHIFT 5
77
78
static setentry *
79
set_lookkey(PySetObject *so, PyObject *key, Py_hash_t hash)
80
256M
{
81
256M
    setentry *table;
82
256M
    setentry *entry;
83
256M
    size_t perturb = hash;
84
256M
    size_t mask = so->mask;
85
256M
    size_t i = (size_t)hash & mask; /* Unsigned for defined overflow behavior */
86
256M
    int probes;
87
256M
    int cmp;
88
89
256M
    int frozenset = PyFrozenSet_CheckExact(so);
90
91
271M
    while (1) {
92
271M
        entry = &so->table[i];
93
271M
        probes = (i + LINEAR_PROBES <= mask) ? LINEAR_PROBES: 0;
94
322M
        do {
95
322M
            if (entry->hash == 0 && entry->key == NULL)
96
142M
                return entry;
97
180M
            if (entry->hash == hash) {
98
114M
                PyObject *startkey = entry->key;
99
114M
                assert(startkey != dummy);
100
114M
                if (startkey == key)
101
114M
                    return entry;
102
19.1k
                if (PyUnicode_CheckExact(startkey)
103
19.1k
                    && PyUnicode_CheckExact(key)
104
6.92k
                    && unicode_eq(startkey, key))
105
6.92k
                    return entry;
106
12.2k
                table = so->table;
107
12.2k
                if (frozenset) {
108
0
                    cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
109
0
                    if (cmp < 0)
110
0
                        return NULL;
111
12.2k
                } else {
112
                    // incref startkey because it can be removed from the set by the compare
113
12.2k
                    Py_INCREF(startkey);
114
12.2k
                    cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
115
12.2k
                    Py_DECREF(startkey);
116
12.2k
                    if (cmp < 0)
117
0
                        return NULL;
118
12.2k
                    if (table != so->table || entry->key != startkey)
119
0
                        return set_lookkey(so, key, hash);
120
12.2k
                }
121
12.2k
                if (cmp > 0)
122
12.2k
                    return entry;
123
0
                mask = so->mask;
124
0
            }
125
65.8M
            entry++;
126
65.8M
        } while (probes--);
127
14.7M
        perturb >>= PERTURB_SHIFT;
128
14.7M
        i = (i * 5 + 1 + perturb) & mask;
129
14.7M
    }
130
256M
}
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
6.01M
{
137
6.01M
    setentry *table;
138
6.01M
    setentry *freeslot;
139
6.01M
    setentry *entry;
140
6.01M
    size_t perturb;
141
6.01M
    size_t mask;
142
6.01M
    size_t i;                       /* Unsigned for defined overflow behavior */
143
6.01M
    int probes;
144
6.01M
    int cmp;
145
146
6.01M
  restart:
147
148
6.01M
    mask = so->mask;
149
6.01M
    i = (size_t)hash & mask;
150
6.01M
    freeslot = NULL;
151
6.01M
    perturb = hash;
152
153
6.47M
    while (1) {
154
6.47M
        entry = &so->table[i];
155
6.47M
        probes = (i + LINEAR_PROBES <= mask) ? LINEAR_PROBES: 0;
156
7.99M
        do {
157
7.99M
            if (entry->hash == 0 && entry->key == NULL)
158
1.64M
                goto found_unused_or_dummy;
159
6.35M
            if (entry->hash == hash) {
160
4.36M
                PyObject *startkey = entry->key;
161
4.36M
                assert(startkey != dummy);
162
4.36M
                if (startkey == key)
163
34.3k
                    goto found_active;
164
4.33M
                if (PyUnicode_CheckExact(startkey)
165
4.33M
                    && PyUnicode_CheckExact(key)
166
448k
                    && unicode_eq(startkey, key))
167
448k
                    goto found_active;
168
3.88M
                table = so->table;
169
3.88M
                Py_INCREF(startkey);
170
3.88M
                cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
171
3.88M
                Py_DECREF(startkey);
172
3.88M
                if (cmp > 0)
173
3.88M
                    goto found_active;
174
239
                if (cmp < 0)
175
0
                    goto comparison_error;
176
239
                if (table != so->table || entry->key != startkey)
177
0
                    goto restart;
178
239
                mask = so->mask;
179
239
            }
180
1.98M
            else if (entry->hash == -1) {
181
0
                assert (entry->key == dummy);
182
0
                freeslot = entry;
183
0
            }
184
1.98M
            entry++;
185
1.98M
        } while (probes--);
186
463k
        perturb >>= PERTURB_SHIFT;
187
463k
        i = (i * 5 + 1 + perturb) & mask;
188
463k
    }
189
190
1.64M
  found_unused_or_dummy:
191
1.64M
    if (freeslot == NULL)
192
1.64M
        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.64M
  found_unused:
199
1.64M
    so->fill++;
200
1.64M
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, so->used + 1);
201
1.64M
    entry->key = key;
202
1.64M
    entry->hash = hash;
203
1.64M
    if ((size_t)so->fill*5 < mask*3)
204
1.62M
        return 0;
205
19.3k
    return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4);
206
207
4.36M
  found_active:
208
4.36M
    Py_DECREF(key);
209
4.36M
    return 0;
210
211
0
  comparison_error:
212
0
    Py_DECREF(key);
213
0
    return -1;
214
1.64M
}
215
216
static int
217
set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
218
6.00M
{
219
6.00M
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
220
221
6.00M
    return set_add_entry_takeref(so, Py_NewRef(key), hash);
222
6.00M
}
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
781k
{
265
781k
    setentry *entry;
266
781k
    size_t perturb = hash;
267
781k
    size_t i = (size_t)hash & mask;
268
781k
    size_t j;
269
270
784k
    while (1) {
271
784k
        entry = &table[i];
272
784k
        if (entry->key == NULL)
273
725k
            goto found_null;
274
58.7k
        if (i + LINEAR_PROBES <= mask) {
275
65.3k
            for (j = 0; j < LINEAR_PROBES; j++) {
276
65.3k
                entry++;
277
65.3k
                if (entry->key == NULL)
278
55.6k
                    goto found_null;
279
65.3k
            }
280
55.6k
        }
281
3.07k
        perturb >>= PERTURB_SHIFT;
282
3.07k
        i = (i * 5 + 1 + perturb) & mask;
283
3.07k
    }
284
781k
  found_null:
285
781k
    entry->key = key;
286
781k
    entry->hash = hash;
287
781k
}
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.7k
{
300
26.7k
    setentry *oldtable, *newtable, *entry;
301
26.7k
    Py_ssize_t oldmask = so->mask;
302
26.7k
    size_t newmask;
303
26.7k
    int is_oldtable_malloced;
304
26.7k
    setentry small_copy[PySet_MINSIZE];
305
306
26.7k
    assert(minused >= 0);
307
308
    /* Find the smallest table size > minused. */
309
    /* XXX speed-up with intrinsics */
310
26.7k
    size_t newsize = PySet_MINSIZE;
311
93.6k
    while (newsize <= (size_t)minused) {
312
66.9k
        newsize <<= 1; // The largest possible value is PY_SSIZE_T_MAX + 1.
313
66.9k
    }
314
315
    /* Get space for a new table. */
316
26.7k
    oldtable = so->table;
317
26.7k
    assert(oldtable != NULL);
318
26.7k
    is_oldtable_malloced = oldtable != so->smalltable;
319
320
26.7k
    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.7k
    else {
340
26.7k
        newtable = PyMem_NEW(setentry, newsize);
341
26.7k
        if (newtable == NULL) {
342
0
            PyErr_NoMemory();
343
0
            return -1;
344
0
        }
345
26.7k
    }
346
347
    /* Make the set empty, using the new table. */
348
26.7k
    assert(newtable != oldtable);
349
26.7k
    memset(newtable, 0, sizeof(setentry) * newsize);
350
26.7k
    so->mask = newsize - 1;
351
26.7k
    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.7k
    newmask = (size_t)so->mask;
356
26.7k
    if (so->fill == so->used) {
357
1.35M
        for (entry = oldtable; entry <= oldtable + oldmask; entry++) {
358
1.32M
            if (entry->key != NULL) {
359
771k
                set_insert_clean(newtable, newmask, entry->key, entry->hash);
360
771k
            }
361
1.32M
        }
362
26.7k
    } 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.7k
    if (is_oldtable_malloced)
372
6.19k
        PyMem_Free(oldtable);
373
26.7k
    return 0;
374
26.7k
}
375
376
static int
377
set_contains_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
378
256M
{
379
256M
    setentry *entry;
380
381
256M
    entry = set_lookkey(so, key, hash);
382
256M
    if (entry != NULL)
383
256M
        return entry->key != NULL;
384
0
    return -1;
385
256M
}
386
387
86.4k
#define DISCARD_NOTFOUND 0
388
1.62k
#define DISCARD_FOUND 1
389
390
static int
391
set_discard_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
392
88.1k
{
393
88.1k
    setentry *entry;
394
88.1k
    PyObject *old_key;
395
396
88.1k
    entry = set_lookkey(so, key, hash);
397
88.1k
    if (entry == NULL)
398
0
        return -1;
399
88.1k
    if (entry->key == NULL)
400
86.4k
        return DISCARD_NOTFOUND;
401
1.62k
    old_key = entry->key;
402
1.62k
    entry->key = dummy;
403
1.62k
    entry->hash = -1;
404
1.62k
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, so->used - 1);
405
1.62k
    Py_DECREF(old_key);
406
1.62k
    return DISCARD_FOUND;
407
88.1k
}
408
409
static int
410
set_add_key(PySetObject *so, PyObject *key)
411
5.96M
{
412
5.96M
    Py_hash_t hash = _PyObject_HashFast(key);
413
5.96M
    if (hash == -1) {
414
0
        set_unhashable_type(key);
415
0
        return -1;
416
0
    }
417
5.96M
    return set_add_entry(so, key, hash);
418
5.96M
}
419
420
static int
421
set_contains_key(PySetObject *so, PyObject *key)
422
256M
{
423
256M
    Py_hash_t hash = _PyObject_HashFast(key);
424
256M
    if (hash == -1) {
425
0
        set_unhashable_type(key);
426
0
        return -1;
427
0
    }
428
256M
    return set_contains_entry(so, key, hash);
429
256M
}
430
431
static int
432
set_discard_key(PySetObject *so, PyObject *key)
433
88.1k
{
434
88.1k
    Py_hash_t hash = _PyObject_HashFast(key);
435
88.1k
    if (hash == -1) {
436
0
        set_unhashable_type(key);
437
0
        return -1;
438
0
    }
439
88.1k
    return set_discard_entry(so, key, hash);
440
88.1k
}
441
442
static void
443
set_empty_to_minsize(PySetObject *so)
444
4.68k
{
445
4.68k
    memset(so->smalltable, 0, sizeof(so->smalltable));
446
4.68k
    so->fill = 0;
447
4.68k
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, 0);
448
4.68k
    so->mask = PySet_MINSIZE - 1;
449
4.68k
    so->table = so->smalltable;
450
4.68k
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->hash, -1);
451
4.68k
}
452
453
static int
454
set_clear_internal(PyObject *self)
455
8.97k
{
456
8.97k
    PySetObject *so = _PySet_CAST(self);
457
8.97k
    setentry *entry;
458
8.97k
    setentry *table = so->table;
459
8.97k
    Py_ssize_t fill = so->fill;
460
8.97k
    Py_ssize_t used = so->used;
461
8.97k
    int table_is_malloced = table != so->smalltable;
462
8.97k
    setentry small_copy[PySet_MINSIZE];
463
464
8.97k
    assert (PyAnySet_Check(so));
465
8.97k
    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
8.97k
    if (table_is_malloced)
474
1.37k
        set_empty_to_minsize(so);
475
476
7.60k
    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.31k
        memcpy(small_copy, table, sizeof(small_copy));
482
3.31k
        table = small_copy;
483
3.31k
        set_empty_to_minsize(so);
484
3.31k
    }
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.44M
    for (entry = table; used > 0; entry++) {
492
1.43M
        if (entry->key && entry->key != dummy) {
493
372k
            used--;
494
372k
            Py_DECREF(entry->key);
495
372k
        }
496
1.43M
    }
497
498
8.97k
    if (table_is_malloced)
499
1.37k
        PyMem_Free(table);
500
8.97k
    return 0;
501
8.97k
}
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.84M
{
519
3.84M
    Py_ssize_t i;
520
3.84M
    Py_ssize_t mask;
521
3.84M
    setentry *entry;
522
523
3.84M
    assert (PyAnySet_Check(so));
524
3.84M
    i = *pos_ptr;
525
3.84M
    assert(i >= 0);
526
3.84M
    mask = so->mask;
527
3.84M
    entry = &so->table[i];
528
17.9M
    while (i <= mask && (entry->key == NULL || entry->key == dummy)) {
529
14.0M
        i++;
530
14.0M
        entry++;
531
14.0M
    }
532
3.84M
    *pos_ptr = i+1;
533
3.84M
    if (i > mask)
534
1.20M
        return 0;
535
3.84M
    assert(entry != NULL);
536
2.64M
    *entry_ptr = entry;
537
2.64M
    return 1;
538
3.84M
}
539
540
static void
541
set_dealloc(PyObject *self)
542
1.78M
{
543
1.78M
    PySetObject *so = _PySet_CAST(self);
544
1.78M
    setentry *entry;
545
1.78M
    Py_ssize_t used = so->used;
546
547
    /* bpo-31095: UnTrack is needed before calling any callbacks */
548
1.78M
    PyObject_GC_UnTrack(so);
549
1.78M
    FT_CLEAR_WEAKREFS(self, so->weakreflist);
550
551
6.33M
    for (entry = so->table; used > 0; entry++) {
552
4.55M
        if (entry->key && entry->key != dummy) {
553
1.33M
                used--;
554
1.33M
                Py_DECREF(entry->key);
555
1.33M
        }
556
4.55M
    }
557
1.78M
    if (so->table != so->smalltable)
558
18.3k
        PyMem_Free(so->table);
559
1.78M
    Py_TYPE(so)->tp_free(so);
560
1.78M
}
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
303k
{
630
303k
    PySetObject *so = _PySet_CAST(self);
631
303k
    return FT_ATOMIC_LOAD_SSIZE_RELAXED(so->used);
632
303k
}
633
634
static int
635
set_merge_lock_held(PySetObject *so, PyObject *otherset)
636
131k
{
637
131k
    PySetObject *other;
638
131k
    PyObject *key;
639
131k
    Py_ssize_t i;
640
131k
    setentry *so_entry;
641
131k
    setentry *other_entry;
642
643
131k
    assert (PyAnySet_Check(so));
644
131k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
645
131k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(otherset);
646
647
131k
    other = _PySet_CAST(otherset);
648
131k
    if (other == so || other->used == 0)
649
        /* a.update(a) or a.update(set()); nothing to do */
650
75.6k
        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.32k
        if (set_table_resize(so, (so->used + other->used)*2) != 0)
657
0
            return -1;
658
7.32k
    }
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
401k
        for (i = 0; i <= other->mask; i++, so_entry++, other_entry++) {
666
363k
            key = other_entry->key;
667
363k
            if (key != NULL) {
668
91.3k
                assert(so_entry->key == NULL);
669
91.3k
                so_entry->key = Py_NewRef(key);
670
91.3k
                so_entry->hash = other_entry->hash;
671
91.3k
            }
672
363k
        }
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.16k
        setentry *newtable = so->table;
681
1.16k
        size_t newmask = (size_t)so->mask;
682
1.16k
        so->fill = other->used;
683
1.16k
        FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, other->used);
684
44.8k
        for (i = other->mask + 1; i > 0 ; i--, other_entry++) {
685
43.7k
            key = other_entry->key;
686
43.7k
            if (key != NULL && key != dummy) {
687
9.29k
                set_insert_clean(newtable, newmask, Py_NewRef(key),
688
9.29k
                                 other_entry->hash);
689
9.29k
            }
690
43.7k
        }
691
1.16k
        return 0;
692
1.16k
    }
693
694
    /* We can't assure there are no duplicates, so do normal insertions */
695
181k
    for (i = 0; i <= other->mask; i++) {
696
165k
        other_entry = &other->table[i];
697
165k
        key = other_entry->key;
698
165k
        if (key != NULL && key != dummy) {
699
47.3k
            if (set_add_entry(so, key, other_entry->hash))
700
0
                return -1;
701
47.3k
        }
702
165k
    }
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
568
    while (entry->key == NULL || entry->key==dummy) {
730
332
        entry++;
731
332
        if (entry > limit)
732
0
            entry = so->table;
733
332
    }
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.18M
{
745
1.18M
    PySetObject *so = _PySet_CAST(self);
746
1.18M
    Py_ssize_t pos = 0;
747
1.18M
    setentry *entry;
748
749
3.73M
    while (set_next(so, &pos, &entry))
750
2.55M
        Py_VISIT(entry->key);
751
1.18M
    return 0;
752
1.18M
}
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.14k
{
762
4.14k
    return ((h ^ 89869747UL) ^ (h << 16)) * 3644798167UL;
763
4.14k
}
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
204
{
778
204
    PySetObject *so = _PySet_CAST(self);
779
204
    Py_uhash_t hash = 0;
780
204
    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.28k
    for (entry = so->table; entry <= &so->table[so->mask]; entry++)
793
4.08k
        hash ^= _shuffle_bits(entry->hash);
794
795
    /* Remove the effect of an odd number of NULL entries */
796
204
    if ((so->mask + 1 - so->fill) & 1)
797
69
        hash ^= _shuffle_bits(0);
798
799
    /* Remove the effect of an odd number of dummy entries */
800
204
    if ((so->fill - so->used) & 1)
801
0
        hash ^= _shuffle_bits(-1);
802
803
    /* Factor in the number of active entries */
804
204
    hash ^= ((Py_uhash_t)PySet_GET_SIZE(self) + 1) * 1927868237UL;
805
806
    /* Disperse patterns arising in nested frozensets */
807
204
    hash ^= (hash >> 11) ^ (hash >> 25);
808
204
    hash = hash * 69069U + 907133923UL;
809
810
    /* -1 is reserved as an error code */
811
204
    if (hash == (Py_uhash_t)-1)
812
0
        hash = 590923713UL;
813
814
204
    return (Py_hash_t)hash;
815
204
}
816
817
static Py_hash_t
818
frozenset_hash(PyObject *self)
819
340
{
820
340
    PySetObject *so = _PySet_CAST(self);
821
340
    Py_uhash_t hash;
822
823
340
    if (FT_ATOMIC_LOAD_SSIZE_RELAXED(so->hash) != -1) {
824
136
        return FT_ATOMIC_LOAD_SSIZE_RELAXED(so->hash);
825
136
    }
826
827
204
    hash = frozenset_hash_impl(self);
828
204
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->hash, hash);
829
204
    return hash;
830
340
}
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
285k
{
845
285k
    setiterobject *si = (setiterobject*)self;
846
    /* bpo-31095: UnTrack is needed before calling any callbacks */
847
285k
    _PyObject_GC_UNTRACK(si);
848
285k
    Py_XDECREF(si->si_set);
849
285k
    PyObject_GC_Del(si);
850
285k
}
851
852
static int
853
setiter_traverse(PyObject *self, visitproc visit, void *arg)
854
120
{
855
120
    setiterobject *si = (setiterobject*)self;
856
120
    Py_VISIT(si->si_set);
857
120
    return 0;
858
120
}
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
825k
{
900
825k
    setiterobject *si = (setiterobject*)self;
901
825k
    PyObject *key = NULL;
902
825k
    Py_ssize_t i, mask;
903
825k
    setentry *entry;
904
825k
    PySetObject *so = si->si_set;
905
906
825k
    if (so == NULL)
907
0
        return NULL;
908
825k
    assert (PyAnySet_Check(so));
909
910
825k
    Py_ssize_t so_used = FT_ATOMIC_LOAD_SSIZE(so->used);
911
825k
    Py_ssize_t si_used = FT_ATOMIC_LOAD_SSIZE(si->si_used);
912
825k
    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
825k
    Py_BEGIN_CRITICAL_SECTION(so);
920
825k
    i = si->si_pos;
921
825k
    assert(i>=0);
922
825k
    entry = so->table;
923
825k
    mask = so->mask;
924
4.06M
    while (i <= mask && (entry[i].key == NULL || entry[i].key == dummy)) {
925
3.23M
        i++;
926
3.23M
    }
927
825k
    if (i <= mask) {
928
539k
        key = Py_NewRef(entry[i].key);
929
539k
    }
930
825k
    Py_END_CRITICAL_SECTION();
931
825k
    si->si_pos = i+1;
932
825k
    if (key == NULL) {
933
285k
        si->si_set = NULL;
934
285k
        Py_DECREF(so);
935
285k
        return NULL;
936
285k
    }
937
539k
    si->len--;
938
539k
    return key;
939
825k
}
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
285k
{
977
285k
    Py_ssize_t size = set_len(so);
978
285k
    setiterobject *si = PyObject_GC_New(setiterobject, &PySetIter_Type);
979
285k
    if (si == NULL)
980
0
        return NULL;
981
285k
    si->si_set = (PySetObject*)Py_NewRef(so);
982
285k
    si->si_used = size;
983
285k
    si->si_pos = 0;
984
285k
    si->len = size;
985
285k
    _PyObject_GC_TRACK(si);
986
285k
    return (PyObject *)si;
987
285k
}
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.6k
{
1023
14.6k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
1024
1025
14.6k
    PyObject *it = PyObject_GetIter(other);
1026
14.6k
    if (it == NULL) {
1027
0
        return -1;
1028
0
    }
1029
1030
14.6k
    PyObject *key;
1031
75.5k
    while ((key = PyIter_Next(it)) != NULL) {
1032
60.9k
        if (set_add_key(so, key)) {
1033
0
            Py_DECREF(it);
1034
0
            Py_DECREF(key);
1035
0
            return -1;
1036
0
        }
1037
60.9k
        Py_DECREF(key);
1038
60.9k
    }
1039
14.6k
    Py_DECREF(it);
1040
14.6k
    if (PyErr_Occurred())
1041
0
        return -1;
1042
14.6k
    return 0;
1043
14.6k
}
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
73.0k
{
1061
73.0k
    assert(Py_REFCNT(so) == 1);
1062
73.0k
    if (PyAnySet_Check(other)) {
1063
58.1k
        int rv;
1064
58.1k
        Py_BEGIN_CRITICAL_SECTION(other);
1065
58.1k
        rv = set_merge_lock_held(so, other);
1066
58.1k
        Py_END_CRITICAL_SECTION();
1067
58.1k
        return rv;
1068
58.1k
    }
1069
14.8k
    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.6k
    return set_update_iterable_lock_held(so, other);
1077
73.0k
}
1078
1079
static int
1080
set_update_internal(PySetObject *so, PyObject *other)
1081
70.7k
{
1082
70.7k
    if (PyAnySet_Check(other)) {
1083
70.7k
        if (Py_Is((PyObject *)so, other)) {
1084
0
            return 0;
1085
0
        }
1086
70.7k
        int rv;
1087
70.7k
        Py_BEGIN_CRITICAL_SECTION2(so, other);
1088
70.7k
        rv = set_merge_lock_held(so, other);
1089
70.7k
        Py_END_CRITICAL_SECTION2();
1090
70.7k
        return rv;
1091
70.7k
    }
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.7k
}
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.78M
{
1140
1.78M
    assert(PyType_Check(type));
1141
1.78M
    PySetObject *so;
1142
1143
1.78M
    so = (PySetObject *)type->tp_alloc(type, 0);
1144
1.78M
    if (so == NULL)
1145
0
        return NULL;
1146
1147
1.78M
    so->fill = 0;
1148
1.78M
    so->used = 0;
1149
1.78M
    so->mask = PySet_MINSIZE - 1;
1150
1.78M
    so->table = so->smalltable;
1151
1.78M
    so->hash = -1;
1152
1.78M
    so->finger = 0;
1153
1.78M
    so->weakreflist = NULL;
1154
1155
1.78M
    if (iterable != NULL) {
1156
72.9k
        if (set_update_local(so, iterable)) {
1157
0
            Py_DECREF(so);
1158
0
            return NULL;
1159
0
        }
1160
72.9k
    }
1161
1162
1.78M
    return (PyObject *)so;
1163
1.78M
}
1164
1165
static PyObject *
1166
make_new_set_basetype(PyTypeObject *type, PyObject *iterable)
1167
2.57k
{
1168
2.57k
    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.57k
    return make_new_set(type, iterable);
1175
2.57k
}
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.39k
{
1294
2.39k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
1295
2.39k
    PyObject *copy = make_new_set_basetype(Py_TYPE(so), NULL);
1296
2.39k
    if (copy == NULL) {
1297
0
        return NULL;
1298
0
    }
1299
2.39k
    if (set_merge_lock_held((PySetObject *)copy, (PyObject *)so) < 0) {
1300
0
        Py_DECREF(copy);
1301
0
        return NULL;
1302
0
    }
1303
2.39k
    return copy;
1304
2.39k
}
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
8.97k
{
1336
8.97k
    set_clear_internal((PyObject*)so);
1337
8.97k
    Py_RETURN_NONE;
1338
8.97k
}
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.7k
{
1398
70.7k
    if (!PyAnySet_Check(other))
1399
0
        Py_RETURN_NOTIMPLEMENTED;
1400
70.7k
    PySetObject *so = _PySet_CAST(self);
1401
1402
70.7k
    if (set_update_internal(so, other)) {
1403
0
        return NULL;
1404
0
    }
1405
70.7k
    return Py_NewRef(so);
1406
70.7k
}
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
27.5k
{
1612
27.5k
    PyObject *key, *it, *tmp;
1613
27.5k
    int rv;
1614
1615
27.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
27.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
27.5k
    it = PyObject_GetIter(other);
1647
27.5k
    if (it == NULL)
1648
0
        return NULL;
1649
1650
3.20M
    while ((key = PyIter_Next(it)) != NULL) {
1651
3.19M
        rv = set_contains_key(so, key);
1652
3.19M
        Py_DECREF(key);
1653
3.19M
        if (rv < 0) {
1654
0
            Py_DECREF(it);
1655
0
            return NULL;
1656
0
        }
1657
3.19M
        if (rv) {
1658
14.0k
            Py_DECREF(it);
1659
14.0k
            Py_RETURN_FALSE;
1660
14.0k
        }
1661
3.19M
    }
1662
13.5k
    Py_DECREF(it);
1663
13.5k
    if (PyErr_Occurred())
1664
0
        return NULL;
1665
13.5k
    Py_RETURN_TRUE;
1666
13.5k
}
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.71k
{
2133
2.71k
    if (PyAnySet_Check(other)) {
2134
0
        return set_issubset(other, (PyObject *)so);
2135
0
    }
2136
2137
2.71k
    PyObject *key, *it = PyObject_GetIter(other);
2138
2.71k
    if (it == NULL) {
2139
0
        return NULL;
2140
0
    }
2141
15.4k
    while ((key = PyIter_Next(it)) != NULL) {
2142
12.8k
        int rv = set_contains_key(so, key);
2143
12.8k
        Py_DECREF(key);
2144
12.8k
        if (rv < 0) {
2145
0
            Py_DECREF(it);
2146
0
            return NULL;
2147
0
        }
2148
12.8k
        if (!rv) {
2149
26
            Py_DECREF(it);
2150
26
            Py_RETURN_FALSE;
2151
26
        }
2152
12.8k
    }
2153
2.68k
    Py_DECREF(it);
2154
2.68k
    if (PyErr_Occurred()) {
2155
0
        return NULL;
2156
0
    }
2157
2.68k
    Py_RETURN_TRUE;
2158
2.68k
}
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
5.84M
{
2220
5.84M
    if (set_add_key(so, key))
2221
0
        return NULL;
2222
5.84M
    Py_RETURN_NONE;
2223
5.84M
}
2224
2225
static int
2226
set_contains_lock_held(PySetObject *so, PyObject *key)
2227
253M
{
2228
253M
    int rv;
2229
2230
253M
    rv = set_contains_key(so, key);
2231
253M
    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
253M
    return rv;
2242
253M
}
2243
2244
int
2245
_PySet_Contains(PySetObject *so, PyObject *key)
2246
233M
{
2247
233M
    assert(so);
2248
2249
233M
    int rv;
2250
233M
    if (PyFrozenSet_CheckExact(so)) {
2251
172M
        rv = set_contains_lock_held(so, key);
2252
172M
    } else {
2253
60.6M
        Py_BEGIN_CRITICAL_SECTION(so);
2254
60.6M
        rv = set_contains_lock_held(so, key);
2255
60.6M
        Py_END_CRITICAL_SECTION();
2256
60.6M
    }
2257
233M
    return rv;
2258
233M
}
2259
2260
static int
2261
set_contains(PyObject *self, PyObject *key)
2262
599
{
2263
599
    PySetObject *so = _PySet_CAST(self);
2264
599
    return _PySet_Contains(so, key);
2265
599
}
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
20.3M
{
2282
20.3M
    long result;
2283
2284
20.3M
    result = set_contains_lock_held(so, key);
2285
20.3M
    if (result < 0)
2286
0
        return NULL;
2287
20.3M
    return PyBool_FromLong(result);
2288
20.3M
}
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
546
{
2304
546
    long result;
2305
2306
546
    result = set_contains_lock_held(so, key);
2307
546
    if (result < 0)
2308
0
        return NULL;
2309
546
    return PyBool_FromLong(result);
2310
546
}
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.64M
{
2469
1.64M
    assert(PyType_Check(type));
2470
2471
1.64M
    if (!_PyArg_NoKwnames("set", kwnames)) {
2472
0
        return NULL;
2473
0
    }
2474
2475
1.64M
    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
2476
1.64M
    if (!_PyArg_CheckPositional("set", nargs, 0, 1)) {
2477
0
        return NULL;
2478
0
    }
2479
2480
1.64M
    if (nargs) {
2481
14.3k
        return make_new_set(_PyType_CAST(type), args[0]);
2482
14.3k
    }
2483
2484
1.63M
    return make_new_set(_PyType_CAST(type), NULL);
2485
1.64M
}
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
135k
{
2707
135k
    return make_new_set(&PySet_Type, iterable);
2708
135k
}
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
185k
{
2746
185k
    if (!PyAnySet_Check(anyset)) {
2747
0
        PyErr_BadInternalCall();
2748
0
        return -1;
2749
0
    }
2750
185k
    if (PyFrozenSet_CheckExact(anyset)) {
2751
0
        return set_contains_key((PySetObject *)anyset, key);
2752
0
    }
2753
185k
    int rv;
2754
185k
    Py_BEGIN_CRITICAL_SECTION(anyset);
2755
185k
    rv = set_contains_key((PySetObject *)anyset, key);
2756
185k
    Py_END_CRITICAL_SECTION();
2757
185k
    return rv;
2758
185k
}
2759
2760
int
2761
PySet_Discard(PyObject *set, PyObject *key)
2762
88.1k
{
2763
88.1k
    if (!PySet_Check(set)) {
2764
0
        PyErr_BadInternalCall();
2765
0
        return -1;
2766
0
    }
2767
2768
88.1k
    int rv;
2769
88.1k
    Py_BEGIN_CRITICAL_SECTION(set);
2770
88.1k
    rv = set_discard_key((PySetObject *)set, key);
2771
88.1k
    Py_END_CRITICAL_SECTION();
2772
88.1k
    return rv;
2773
88.1k
}
2774
2775
int
2776
PySet_Add(PyObject *anyset, PyObject *key)
2777
58.3k
{
2778
58.3k
    if (PySet_Check(anyset)) {
2779
55.8k
        int rv;
2780
55.8k
        Py_BEGIN_CRITICAL_SECTION(anyset);
2781
55.8k
        rv = set_add_key((PySetObject *)anyset, key);
2782
55.8k
        Py_END_CRITICAL_SECTION();
2783
55.8k
        return rv;
2784
55.8k
    }
2785
2786
2.56k
    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.56k
        return set_add_key((PySetObject *)anyset, key);
2792
2.56k
    }
2793
2794
0
    PyErr_BadInternalCall();
2795
0
    return -1;
2796
2.56k
}
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
473
        return 0;
2809
1.41k
    *key = entry->key;
2810
1.41k
    *hash = entry->hash;
2811
1.41k
    return 1;
2812
1.89k
}
2813
2814
int
2815
_PySet_NextEntryRef(PyObject *set, Py_ssize_t *pos, PyObject **key, Py_hash_t *hash)
2816
104k
{
2817
104k
    setentry *entry;
2818
2819
104k
    if (!PyAnySet_Check(set)) {
2820
0
        PyErr_BadInternalCall();
2821
0
        return -1;
2822
0
    }
2823
104k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(set);
2824
104k
    if (set_next((PySetObject *)set, pos, &entry) == 0)
2825
19.0k
        return 0;
2826
85.3k
    *key = Py_NewRef(entry->key);
2827
85.3k
    *hash = entry->hash;
2828
85.3k
    return 1;
2829
104k
}
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);