cpython/Modules/itertoolsmodule.c

#include "Python.h"
#include "pycore_call.h"              // _PyObject_CallNoArgs()
#include "pycore_ceval.h"             // _PyEval_GetBuiltin()
#include "pycore_critical_section.h"  // Py_BEGIN_CRITICAL_SECTION()
#include "pycore_long.h"              // _PyLong_GetZero()
#include "pycore_moduleobject.h"      // _PyModule_GetState()
#include "pycore_typeobject.h"        // _PyType_GetModuleState()
#include "pycore_object.h"            // _PyObject_GC_TRACK()
#include "pycore_tuple.h"             // _PyTuple_ITEMS()

#include <stddef.h>                   // offsetof()

/* Itertools module written and maintained
   by Raymond D. Hettinger <[email protected]>
*/

itertools_state;

static inline itertools_state *
get_module_state(PyObject *mod)
{}

static inline itertools_state *
get_module_state_by_cls(PyTypeObject *cls)
{}

static struct PyModuleDef itertoolsmodule;

static inline itertools_state *
find_state_by_type(PyTypeObject *tp)
{}

/*[clinic input]
module itertools
class itertools.groupby "groupbyobject *" "clinic_state()->groupby_type"
class itertools._grouper "_grouperobject *" "clinic_state()->_grouper_type"
class itertools.teedataobject "teedataobject *" "clinic_state()->teedataobject_type"
class itertools._tee "teeobject *" "clinic_state()->tee_type"
class itertools.batched "batchedobject *" "clinic_state()->batched_type"
class itertools.cycle "cycleobject *" "clinic_state()->cycle_type"
class itertools.dropwhile "dropwhileobject *" "clinic_state()->dropwhile_type"
class itertools.takewhile "takewhileobject *" "clinic_state()->takewhile_type"
class itertools.starmap "starmapobject *" "clinic_state()->starmap_type"
class itertools.chain "chainobject *" "clinic_state()->chain_type"
class itertools.combinations "combinationsobject *" "clinic_state()->combinations_type"
class itertools.combinations_with_replacement "cwr_object *" "clinic_state()->cwr_type"
class itertools.permutations "permutationsobject *" "clinic_state()->permutations_type"
class itertools.accumulate "accumulateobject *" "clinic_state()->accumulate_type"
class itertools.compress "compressobject *" "clinic_state()->compress_type"
class itertools.filterfalse "filterfalseobject *" "clinic_state()->filterfalse_type"
class itertools.count "countobject *" "clinic_state()->count_type"
class itertools.pairwise "pairwiseobject *" "clinic_state()->pairwise_type"
[clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=aa48fe4de9d4080f]*/

#define clinic_state
#define clinic_state_by_cls
#include "clinic/itertoolsmodule.c.h"
#undef clinic_state_by_cls
#undef clinic_state


/* batched object ************************************************************/

batchedobject;

/*[clinic input]
@classmethod
itertools.batched.__new__ as batched_new
    iterable: object
    n: Py_ssize_t
    *
    strict: bool = False

Batch data into tuples of length n. The last batch may be shorter than n.

Loops over the input iterable and accumulates data into tuples
up to size n.  The input is consumed lazily, just enough to
fill a batch.  The result is yielded as soon as a batch is full
or when the input iterable is exhausted.

    >>> for batch in batched('ABCDEFG', 3):
    ...     print(batch)
    ...
    ('A', 'B', 'C')
    ('D', 'E', 'F')
    ('G',)

If "strict" is True, raises a ValueError if the final batch is shorter
than n.

[clinic start generated code]*/

static PyObject *
batched_new_impl(PyTypeObject *type, PyObject *iterable, Py_ssize_t n,
                 int strict)
/*[clinic end generated code: output=c6de11b061529d3e input=7814b47e222f5467]*/
{}

static void
batched_dealloc(batchedobject *bo)
{}

static int
batched_traverse(batchedobject *bo, visitproc visit, void *arg)
{}

static PyObject *
batched_next(batchedobject *bo)
{}

static PyType_Slot batched_slots[] =;

static PyType_Spec batched_spec =;


/* pairwise object ***********************************************************/

pairwiseobject;

/*[clinic input]
@classmethod
itertools.pairwise.__new__ as pairwise_new
    iterable: object
    /
Return an iterator of overlapping pairs taken from the input iterator.

    s -> (s0,s1), (s1,s2), (s2, s3), ...

[clinic start generated code]*/

static PyObject *
pairwise_new_impl(PyTypeObject *type, PyObject *iterable)
/*[clinic end generated code: output=9f0267062d384456 input=6e7c3cddb431a8d6]*/
{}

static void
pairwise_dealloc(pairwiseobject *po)
{}

static int
pairwise_traverse(pairwiseobject *po, visitproc visit, void *arg)
{}

static PyObject *
pairwise_next(pairwiseobject *po)
{}

static PyType_Slot pairwise_slots[] =;

static PyType_Spec pairwise_spec =;


/* groupby object ************************************************************/

groupbyobject;

static PyObject *_grouper_create(groupbyobject *, PyObject *);

/*[clinic input]
@classmethod
itertools.groupby.__new__

    iterable as it: object
        Elements to divide into groups according to the key function.
    key as keyfunc: object = None
        A function for computing the group category for each element.
        If the key function is not specified or is None, the element itself
        is used for grouping.

make an iterator that returns consecutive keys and groups from the iterable
[clinic start generated code]*/

static PyObject *
itertools_groupby_impl(PyTypeObject *type, PyObject *it, PyObject *keyfunc)
/*[clinic end generated code: output=cbb1ae3a90fd4141 input=6b3d123e87ff65a1]*/
{}

static void
groupby_dealloc(groupbyobject *gbo)
{}

static int
groupby_traverse(groupbyobject *gbo, visitproc visit, void *arg)
{}

Py_LOCAL_INLINE(int)
groupby_step(groupbyobject *gbo)
{}

static PyObject *
groupby_next(groupbyobject *gbo)
{}

static PyType_Slot groupby_slots[] =;

static PyType_Spec groupby_spec =;

/* _grouper object (internal) ************************************************/

_grouperobject;

/*[clinic input]
@classmethod
itertools._grouper.__new__

    parent: object(subclass_of='clinic_state_by_cls()->groupby_type')
    tgtkey: object
    /
[clinic start generated code]*/

static PyObject *
itertools__grouper_impl(PyTypeObject *type, PyObject *parent,
                        PyObject *tgtkey)
/*[clinic end generated code: output=462efb1cdebb5914 input=afe05eb477118f12]*/
{}

static PyObject *
_grouper_create(groupbyobject *parent, PyObject *tgtkey)
{}

static void
_grouper_dealloc(_grouperobject *igo)
{}

static int
_grouper_traverse(_grouperobject *igo, visitproc visit, void *arg)
{}

static PyObject *
_grouper_next(_grouperobject *igo)
{}

static PyType_Slot _grouper_slots[] =;

static PyType_Spec _grouper_spec =;


/* tee object and with supporting function and objects ***********************/

/* The teedataobject pre-allocates space for LINKCELLS number of objects.
   To help the object fit neatly inside cache lines (space for 16 to 32
   pointers), the value should be a multiple of 16 minus  space for
   the other structure members including PyHEAD overhead.  The larger the
   value, the less memory overhead per object and the less time spent
   allocating/deallocating new links.  The smaller the number, the less
   wasted space and the more rapid freeing of older data.
*/
#define LINKCELLS

teedataobject;

teeobject;

static PyObject *
teedataobject_newinternal(itertools_state *state, PyObject *it)
{}

static PyObject *
teedataobject_jumplink(itertools_state *state, teedataobject *tdo)
{}

static PyObject *
teedataobject_getitem(teedataobject *tdo, int i)
{}

static int
teedataobject_traverse(teedataobject *tdo, visitproc visit, void * arg)
{}

static void
teedataobject_safe_decref(PyObject *obj)
{}

static int
teedataobject_clear(teedataobject *tdo)
{}

static void
teedataobject_dealloc(teedataobject *tdo)
{}

/*[clinic input]
@classmethod
itertools.teedataobject.__new__
    iterable as it: object
    values: object(subclass_of='&PyList_Type')
    next: object
    /
Data container common to multiple tee objects.
[clinic start generated code]*/

static PyObject *
itertools_teedataobject_impl(PyTypeObject *type, PyObject *it,
                             PyObject *values, PyObject *next)
/*[clinic end generated code: output=3343ceb07e08df5e input=be60f2fabd2b72ba]*/
{}

static PyType_Slot teedataobject_slots[] =;

static PyType_Spec teedataobject_spec =;


static PyObject *
tee_next(teeobject *to)
{}

static int
tee_traverse(teeobject *to, visitproc visit, void *arg)
{}

static PyObject *
tee_copy(teeobject *to, PyObject *Py_UNUSED(ignored))
{}

PyDoc_STRVAR(teecopy_doc, "Returns an independent iterator.");

static PyObject *
tee_fromiterable(itertools_state *state, PyObject *iterable)
{}

/*[clinic input]
@classmethod
itertools._tee.__new__
    iterable: object
    /
Iterator wrapped to make it copyable.
[clinic start generated code]*/

static PyObject *
itertools__tee_impl(PyTypeObject *type, PyObject *iterable)
/*[clinic end generated code: output=b02d3fd26c810c3f input=adc0779d2afe37a2]*/
{}

static int
tee_clear(teeobject *to)
{}

static void
tee_dealloc(teeobject *to)
{}

static PyMethodDef tee_methods[] =;

static PyMemberDef tee_members[] =;

static PyType_Slot tee_slots[] =;

static PyType_Spec tee_spec =;

/*[clinic input]
itertools.tee
    iterable: object
    n: Py_ssize_t = 2
    /
Returns a tuple of n independent iterators.
[clinic start generated code]*/

static PyObject *
itertools_tee_impl(PyObject *module, PyObject *iterable, Py_ssize_t n)
/*[clinic end generated code: output=1c64519cd859c2f0 input=c99a1472c425d66d]*/
{}


/* cycle object **************************************************************/

cycleobject;

/*[clinic input]
@classmethod
itertools.cycle.__new__
    iterable: object
    /
Return elements from the iterable until it is exhausted. Then repeat the sequence indefinitely.
[clinic start generated code]*/

static PyObject *
itertools_cycle_impl(PyTypeObject *type, PyObject *iterable)
/*[clinic end generated code: output=f60e5ec17a45b35c input=9d1d84bcf66e908b]*/
{}

static void
cycle_dealloc(cycleobject *lz)
{}

static int
cycle_traverse(cycleobject *lz, visitproc visit, void *arg)
{}

static PyObject *
cycle_next(cycleobject *lz)
{}

static PyType_Slot cycle_slots[] =;

static PyType_Spec cycle_spec =;


/* dropwhile object **********************************************************/

dropwhileobject;

/*[clinic input]
@classmethod
itertools.dropwhile.__new__
    predicate as func: object
    iterable as seq: object
    /
Drop items from the iterable while predicate(item) is true.

Afterwards, return every element until the iterable is exhausted.
[clinic start generated code]*/

static PyObject *
itertools_dropwhile_impl(PyTypeObject *type, PyObject *func, PyObject *seq)
/*[clinic end generated code: output=92f9d0d89af149e4 input=d39737147c9f0a26]*/
{}

static void
dropwhile_dealloc(dropwhileobject *lz)
{}

static int
dropwhile_traverse(dropwhileobject *lz, visitproc visit, void *arg)
{}

static PyObject *
dropwhile_next(dropwhileobject *lz)
{}

static PyType_Slot dropwhile_slots[] =;

static PyType_Spec dropwhile_spec =;


/* takewhile object **********************************************************/

takewhileobject;

/*[clinic input]
@classmethod
itertools.takewhile.__new__
    predicate as func: object
    iterable as seq: object
    /
Return successive entries from an iterable as long as the predicate evaluates to true for each entry.
[clinic start generated code]*/

static PyObject *
itertools_takewhile_impl(PyTypeObject *type, PyObject *func, PyObject *seq)
/*[clinic end generated code: output=bb179ea7864e2ef6 input=ba5255f7519aa119]*/
{}

static void
takewhile_dealloc(takewhileobject *lz)
{}

static int
takewhile_traverse(takewhileobject *lz, visitproc visit, void *arg)
{}

static PyObject *
takewhile_next(takewhileobject *lz)
{}

static PyType_Slot takewhile_slots[] =;

static PyType_Spec takewhile_spec =;


/* islice object *************************************************************/

isliceobject;

static PyObject *
islice_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{}

static void
islice_dealloc(isliceobject *lz)
{}

static int
islice_traverse(isliceobject *lz, visitproc visit, void *arg)
{}

static PyObject *
islice_next(isliceobject *lz)
{}

PyDoc_STRVAR(islice_doc,
"islice(iterable, stop) --> islice object\n\
islice(iterable, start, stop[, step]) --> islice object\n\
\n\
Return an iterator whose next() method returns selected values from an\n\
iterable.  If start is specified, will skip all preceding elements;\n\
otherwise, start defaults to zero.  Step defaults to one.  If\n\
specified as another value, step determines how many values are\n\
skipped between successive calls.  Works like a slice() on a list\n\
but returns an iterator.");

static PyType_Slot islice_slots[] =;

static PyType_Spec islice_spec =;


/* starmap object ************************************************************/

starmapobject;

/*[clinic input]
@classmethod
itertools.starmap.__new__
    function as func: object
    iterable as seq: object
    /
Return an iterator whose values are returned from the function evaluated with an argument tuple taken from the given sequence.
[clinic start generated code]*/

static PyObject *
itertools_starmap_impl(PyTypeObject *type, PyObject *func, PyObject *seq)
/*[clinic end generated code: output=79eeb81d452c6e8d input=844766df6a0d4dad]*/
{}

static void
starmap_dealloc(starmapobject *lz)
{}

static int
starmap_traverse(starmapobject *lz, visitproc visit, void *arg)
{}

static PyObject *
starmap_next(starmapobject *lz)
{}

static PyType_Slot starmap_slots[] =;

static PyType_Spec starmap_spec =;


/* chain object **************************************************************/

chainobject;

static PyObject *
chain_new_internal(PyTypeObject *type, PyObject *source)
{}

static PyObject *
chain_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{}

/*[clinic input]
@classmethod
itertools.chain.from_iterable
    iterable as arg: object
    /
Alternative chain() constructor taking a single iterable argument that evaluates lazily.
[clinic start generated code]*/

static PyObject *
itertools_chain_from_iterable(PyTypeObject *type, PyObject *arg)
/*[clinic end generated code: output=667ae7a7f7b68654 input=72c39e3a2ca3be85]*/
{}

static void
chain_dealloc(chainobject *lz)
{}

static int
chain_traverse(chainobject *lz, visitproc visit, void *arg)
{}

static PyObject *
chain_next(chainobject *lz)
{}

PyDoc_STRVAR(chain_doc,
"chain(*iterables)\n\
--\n\
\n\
Return a chain object whose .__next__() method returns elements from the\n\
first iterable until it is exhausted, then elements from the next\n\
iterable, until all of the iterables are exhausted.");

static PyMethodDef chain_methods[] =;

static PyType_Slot chain_slots[] =;

static PyType_Spec chain_spec =;


/* product object ************************************************************/

productobject;

static PyObject *
product_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{}

static void
product_dealloc(productobject *lz)
{}

static PyObject *
product_sizeof(productobject *lz, void *unused)
{}

PyDoc_STRVAR(sizeof_doc, "Returns size in memory, in bytes.");

static int
product_traverse(productobject *lz, visitproc visit, void *arg)
{}

static PyObject *
product_next(productobject *lz)
{}

static PyMethodDef product_methods[] =;

PyDoc_STRVAR(product_doc,
"product(*iterables, repeat=1)\n\
--\n\
\n\
Cartesian product of input iterables.  Equivalent to nested for-loops.\n\n\
For example, product(A, B) returns the same as:  ((x,y) for x in A for y in B).\n\
The leftmost iterators are in the outermost for-loop, so the output tuples\n\
cycle in a manner similar to an odometer (with the rightmost element changing\n\
on every iteration).\n\n\
To compute the product of an iterable with itself, specify the number\n\
of repetitions with the optional repeat keyword argument. For example,\n\
product(A, repeat=4) means the same as product(A, A, A, A).\n\n\
product('ab', range(3)) --> ('a',0) ('a',1) ('a',2) ('b',0) ('b',1) ('b',2)\n\
product((0,1), (0,1), (0,1)) --> (0,0,0) (0,0,1) (0,1,0) (0,1,1) (1,0,0) ...");

static PyType_Slot product_slots[] =;

static PyType_Spec product_spec =;


/* combinations object *******************************************************/

combinationsobject;


/*[clinic input]
@classmethod
itertools.combinations.__new__
    iterable: object
    r: Py_ssize_t
Return successive r-length combinations of elements in the iterable.

combinations(range(4), 3) --> (0,1,2), (0,1,3), (0,2,3), (1,2,3)
[clinic start generated code]*/

static PyObject *
itertools_combinations_impl(PyTypeObject *type, PyObject *iterable,
                            Py_ssize_t r)
/*[clinic end generated code: output=87a689b39c40039c input=06bede09e3da20f8]*/
{}

static void
combinations_dealloc(combinationsobject *co)
{}

static PyObject *
combinations_sizeof(combinationsobject *co, void *unused)
{}

static int
combinations_traverse(combinationsobject *co, visitproc visit, void *arg)
{}

static PyObject *
combinations_next(combinationsobject *co)
{}

static PyMethodDef combinations_methods[] =;

static PyType_Slot combinations_slots[] =;

static PyType_Spec combinations_spec =;


/* combinations with replacement object **************************************/

/* Equivalent to:

        def combinations_with_replacement(iterable, r):
            "combinations_with_replacement('ABC', 2) --> AA AB AC BB BC CC"
            # number items returned:  (n+r-1)! / r! / (n-1)!
            pool = tuple(iterable)
            n = len(pool)
            indices = [0] * r
            yield tuple(pool[i] for i in indices)
            while 1:
                for i in reversed(range(r)):
                    if indices[i] != n - 1:
                        break
                else:
                    return
                indices[i:] = [indices[i] + 1] * (r - i)
                yield tuple(pool[i] for i in indices)

        def combinations_with_replacement2(iterable, r):
            'Alternate version that filters from product()'
            pool = tuple(iterable)
            n = len(pool)
            for indices in product(range(n), repeat=r):
                if sorted(indices) == list(indices):
                    yield tuple(pool[i] for i in indices)
*/
cwrobject;

/*[clinic input]
@classmethod
itertools.combinations_with_replacement.__new__
    iterable: object
    r: Py_ssize_t
Return successive r-length combinations of elements in the iterable allowing individual elements to have successive repeats.

combinations_with_replacement('ABC', 2) --> ('A','A'), ('A','B'), ('A','C'), ('B','B'), ('B','C'), ('C','C')
[clinic start generated code]*/

static PyObject *
itertools_combinations_with_replacement_impl(PyTypeObject *type,
                                             PyObject *iterable,
                                             Py_ssize_t r)
/*[clinic end generated code: output=48b26856d4e659ca input=1dc58e82a0878fdc]*/
{}

static void
cwr_dealloc(cwrobject *co)
{}

static PyObject *
cwr_sizeof(cwrobject *co, void *unused)
{}

static int
cwr_traverse(cwrobject *co, visitproc visit, void *arg)
{}

static PyObject *
cwr_next(cwrobject *co)
{}

static PyMethodDef cwr_methods[] =;

static PyType_Slot cwr_slots[] =;

static PyType_Spec cwr_spec =;


/* permutations object ********************************************************

def permutations(iterable, r=None):
    # permutations('ABCD', 2) --> AB AC AD BA BC BD CA CB CD DA DB DC
    # permutations(range(3)) --> 012 021 102 120 201 210
    pool = tuple(iterable)
    n = len(pool)
    r = n if r is None else r
    if r > n:
        return
    indices = list(range(n))
    cycles = list(range(n, n-r, -1))
    yield tuple(pool[i] for i in indices[:r])
    while n:
        for i in reversed(range(r)):
            cycles[i] -= 1
            if cycles[i] == 0:
                indices[i:] = indices[i+1:] + indices[i:i+1]
                cycles[i] = n - i
            else:
                j = cycles[i]
                indices[i], indices[-j] = indices[-j], indices[i]
                yield tuple(pool[i] for i in indices[:r])
                break
        else:
            return
*/

permutationsobject;

/*[clinic input]
@classmethod
itertools.permutations.__new__
    iterable: object
    r as robj: object = None
Return successive r-length permutations of elements in the iterable.

permutations(range(3), 2) --> (0,1), (0,2), (1,0), (1,2), (2,0), (2,1)
[clinic start generated code]*/

static PyObject *
itertools_permutations_impl(PyTypeObject *type, PyObject *iterable,
                            PyObject *robj)
/*[clinic end generated code: output=296a72fa76d620ea input=57d0170a4ac0ec7a]*/
{}

static void
permutations_dealloc(permutationsobject *po)
{}

static PyObject *
permutations_sizeof(permutationsobject *po, void *unused)
{}

static int
permutations_traverse(permutationsobject *po, visitproc visit, void *arg)
{}

static PyObject *
permutations_next(permutationsobject *po)
{}

static PyMethodDef permuations_methods[] =;

static PyType_Slot permutations_slots[] =;

static PyType_Spec permutations_spec =;


/* accumulate object ********************************************************/

accumulateobject;

/*[clinic input]
@classmethod
itertools.accumulate.__new__
    iterable: object
    func as binop: object = None
    *
    initial: object = None
Return series of accumulated sums (or other binary function results).
[clinic start generated code]*/

static PyObject *
itertools_accumulate_impl(PyTypeObject *type, PyObject *iterable,
                          PyObject *binop, PyObject *initial)
/*[clinic end generated code: output=66da2650627128f8 input=c4ce20ac59bf7ffd]*/
{}

static void
accumulate_dealloc(accumulateobject *lz)
{}

static int
accumulate_traverse(accumulateobject *lz, visitproc visit, void *arg)
{}

static PyObject *
accumulate_next(accumulateobject *lz)
{}

static PyType_Slot accumulate_slots[] =;

static PyType_Spec accumulate_spec =;


/* compress object ************************************************************/

/* Equivalent to:

    def compress(data, selectors):
        "compress('ABCDEF', [1,0,1,0,1,1]) --> A C E F"
        return (d for d, s in zip(data, selectors) if s)
*/

compressobject;

/*[clinic input]
@classmethod
itertools.compress.__new__
    data as seq1: object
    selectors as seq2: object
Return data elements corresponding to true selector elements.

Forms a shorter iterator from selected data elements using the selectors to
choose the data elements.
[clinic start generated code]*/

static PyObject *
itertools_compress_impl(PyTypeObject *type, PyObject *seq1, PyObject *seq2)
/*[clinic end generated code: output=7e67157212ed09e0 input=79596d7cd20c77e5]*/
{}

static void
compress_dealloc(compressobject *lz)
{}

static int
compress_traverse(compressobject *lz, visitproc visit, void *arg)
{}

static PyObject *
compress_next(compressobject *lz)
{}

static PyType_Slot compress_slots[] =;

static PyType_Spec compress_spec =;


/* filterfalse object ************************************************************/

filterfalseobject;

/*[clinic input]
@classmethod
itertools.filterfalse.__new__
    function as func: object
    iterable as seq: object
    /
Return those items of iterable for which function(item) is false.

If function is None, return the items that are false.
[clinic start generated code]*/

static PyObject *
itertools_filterfalse_impl(PyTypeObject *type, PyObject *func, PyObject *seq)
/*[clinic end generated code: output=55f87eab9fc0484e input=2d684a2c66f99cde]*/
{}

static void
filterfalse_dealloc(filterfalseobject *lz)
{}

static int
filterfalse_traverse(filterfalseobject *lz, visitproc visit, void *arg)
{}

static PyObject *
filterfalse_next(filterfalseobject *lz)
{}

static PyType_Slot filterfalse_slots[] =;

static PyType_Spec filterfalse_spec =;


/* count object ************************************************************/

countobject;

/* Counting logic and invariants:

fast_mode:  when cnt an integer < PY_SSIZE_T_MAX and no step is specified.

    assert(long_cnt == NULL && long_step==PyLong(1));
    Advances with:  cnt += 1
    When count hits PY_SSIZE_T_MAX, switch to slow_mode.

slow_mode:  when cnt == PY_SSIZE_T_MAX, step is not int(1), or cnt is a float.

    assert(cnt == PY_SSIZE_T_MAX && long_cnt != NULL && long_step != NULL);
    All counting is done with python objects (no overflows or underflows).
    Advances with:  long_cnt += long_step
    Step may be zero -- effectively a slow version of repeat(cnt).
    Either long_cnt or long_step may be a float, Fraction, or Decimal.
*/

/*[clinic input]
@classmethod
itertools.count.__new__
    start as long_cnt: object(c_default="NULL") = 0
    step as long_step: object(c_default="NULL") = 1
Return a count object whose .__next__() method returns consecutive values.

Equivalent to:
    def count(firstval=0, step=1):
        x = firstval
        while 1:
            yield x
            x += step
[clinic start generated code]*/

static PyObject *
itertools_count_impl(PyTypeObject *type, PyObject *long_cnt,
                     PyObject *long_step)
/*[clinic end generated code: output=09a9250aebd00b1c input=d7a85eec18bfcd94]*/
{}

static void
count_dealloc(countobject *lz)
{}

static int
count_traverse(countobject *lz, visitproc visit, void *arg)
{}

static PyObject *
count_nextlong(countobject *lz)
{}

static PyObject *
count_next(countobject *lz)
{}

static PyObject *
count_repr(countobject *lz)
{}

static PyType_Slot count_slots[] =;

static PyType_Spec count_spec =;


/* repeat object ************************************************************/

repeatobject;

static PyObject *
repeat_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{}

static void
repeat_dealloc(repeatobject *ro)
{}

static int
repeat_traverse(repeatobject *ro, visitproc visit, void *arg)
{}

static PyObject *
repeat_next(repeatobject *ro)
{}

static PyObject *
repeat_repr(repeatobject *ro)
{}

static PyObject *
repeat_len(repeatobject *ro, PyObject *Py_UNUSED(ignored))
{}

PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");

static PyMethodDef repeat_methods[] =;

PyDoc_STRVAR(repeat_doc,
"repeat(object [,times]) -> create an iterator which returns the object\n\
for the specified number of times.  If not specified, returns the object\n\
endlessly.");

static PyType_Slot repeat_slots[] =;

static PyType_Spec repeat_spec =;


/* ziplongest object *********************************************************/

ziplongestobject;

static PyObject *
zip_longest_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{}

static void
zip_longest_dealloc(ziplongestobject *lz)
{}

static int
zip_longest_traverse(ziplongestobject *lz, visitproc visit, void *arg)
{}

static PyObject *
zip_longest_next(ziplongestobject *lz)
{}

PyDoc_STRVAR(zip_longest_doc,
"zip_longest(*iterables, fillvalue=None)\n\
--\n\
\n\
Return a zip_longest object whose .__next__() method returns a tuple where\n\
the i-th element comes from the i-th iterable argument.  The .__next__()\n\
method continues until the longest iterable in the argument sequence\n\
is exhausted and then it raises StopIteration.  When the shorter iterables\n\
are exhausted, the fillvalue is substituted in their place.  The fillvalue\n\
defaults to None or can be specified by a keyword argument.\n\
");

static PyType_Slot ziplongest_slots[] =;

static PyType_Spec ziplongest_spec =;


/* module level code ********************************************************/

PyDoc_STRVAR(module_doc,
"Functional tools for creating and using iterators.\n\
\n\
Infinite iterators:\n\
count(start=0, step=1) --> start, start+step, start+2*step, ...\n\
cycle(p) --> p0, p1, ... plast, p0, p1, ...\n\
repeat(elem [,n]) --> elem, elem, elem, ... endlessly or up to n times\n\
\n\
Iterators terminating on the shortest input sequence:\n\
accumulate(p[, func]) --> p0, p0+p1, p0+p1+p2\n\
batched(p, n) --> [p0, p1, ..., p_n-1], [p_n, p_n+1, ..., p_2n-1], ...\n\
chain(p, q, ...) --> p0, p1, ... plast, q0, q1, ...\n\
chain.from_iterable([p, q, ...]) --> p0, p1, ... plast, q0, q1, ...\n\
compress(data, selectors) --> (d[0] if s[0]), (d[1] if s[1]), ...\n\
dropwhile(predicate, seq) --> seq[n], seq[n+1], starting when predicate fails\n\
groupby(iterable[, keyfunc]) --> sub-iterators grouped by value of keyfunc(v)\n\
filterfalse(predicate, seq) --> elements of seq where predicate(elem) is False\n\
islice(seq, [start,] stop [, step]) --> elements from\n\
       seq[start:stop:step]\n\
pairwise(s) --> (s[0],s[1]), (s[1],s[2]), (s[2], s[3]), ...\n\
starmap(fun, seq) --> fun(*seq[0]), fun(*seq[1]), ...\n\
tee(it, n=2) --> (it1, it2 , ... itn) splits one iterator into n\n\
takewhile(predicate, seq) --> seq[0], seq[1], until predicate fails\n\
zip_longest(p, q, ...) --> (p[0], q[0]), (p[1], q[1]), ...\n\
\n\
Combinatoric generators:\n\
product(p, q, ... [repeat=1]) --> cartesian product\n\
permutations(p[, r])\n\
combinations(p, r)\n\
combinations_with_replacement(p, r)\n\
");

static int
itertoolsmodule_traverse(PyObject *mod, visitproc visit, void *arg)
{}

static int
itertoolsmodule_clear(PyObject *mod)
{}

static void
itertoolsmodule_free(void *mod)
{}

#define ADD_TYPE(module, type, spec)

static int
itertoolsmodule_exec(PyObject *mod)
{}

static struct PyModuleDef_Slot itertoolsmodule_slots[] =;

static PyMethodDef module_methods[] =;


static struct PyModuleDef itertoolsmodule =;

PyMODINIT_FUNC
PyInit_itertools(void)
{}