
    3j%                      U d Z ddlmZ ddlmZ ddlmZ ddlZddlm	Z	m
Z
 ddlZddlZddlZddlZddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZ  ej,                  d      Z G d dej0                        Z G d dej0                        Z G d dej0                        Z G d dej0                        Z G d dej0                        ZdZdZdZ dZ!dZ"eee e!e"gZ#dZ$ e%ejL                        dgz   Z'd4dZ(d Z)d5d6d Z*d5d!Z+d" Z,d7d#Z-d$ Z. G d% d&      Z/ G d' d(      Z0 G d) d*      Z1 G d+ d,      Z2 G d- d.      Z3 G d/ d0ejh                        Z5g Z6d1e7d2<   e8d3k(  rddlZ ejr                  e5       yy)8a  
A comprehensive, object model of the Xenakis Sieve. :class:`music21.sieve.Sieve`
objects can be created from high-level string notations, and used to generate line segments
in various representation. Additional functionality is available through associated objects.

The :class:`music21.sieve.Sieve` class permits generation segments in four formats.

>>> a = sieve.Sieve('3@2|7@1')
>>> a.segment()
[1, 2, 5, 8, 11, 14, 15, 17, 20, 22, 23, 26, 29, 32, 35, 36, 38, 41, 43, 44,
 47, 50, 53, 56, 57, 59, 62, 64, 65, 68, 71, 74, 77, 78, 80, 83, 85, 86, 89, 92, 95, 98, 99]

>>> a.segment(segmentFormat='binary')
[0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1,
 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1,
 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1,
 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1]

>>> a.segment(segmentFormat='width')
[1, 3, 3, 3, 3, 1, 2, 3, 2, 1, 3, 3, 3, 3, 1, 2, 3, 2, 1, 3, 3, 3, 3, 1, 2, 3, 2,
 1, 3, 3, 3, 3, 1, 2, 3, 2, 1, 3, 3, 3, 3, 1]

>>> len(a.segment(segmentFormat='unit'))
43

A :class:`music21.sieve.CompressionSegment` can be used to derive a Sieve from a
ny sequence of integers.

>>> a = sieve.CompressionSegment([3, 4, 5, 6, 7, 8, 13, 19])
>>> str(a)
'6@1|7@6|8@5|9@4|10@3|11@8'

The :class:`music21.sieve.PitchSieve` class provides a quick generation of
:class:`music21.pitch.Pitch` lists from Sieves.

>>> a = sieve.PitchSieve('13@3|13@6|13@9', 'c1', 'c10', 'f#4')
>>> pitches = a()
>>> ', '.join([str(p) for p in pitches])
'F#1, A1, C2, G2, B-2, C#3, G#3, B3, D4, A4, C5, E-5, B-5, C#6, E6, B6, D7,
 F7, C8, E-8, F#8, C#9, E9, G9'
    )annotations)literal_eval)IterableN)gcdlcm)common)environment)exceptions21)interval)pitchsievec                      e Zd Zy)UnitExceptionN__name__
__module____qualname__     :/DATA/.local/lib/python3.12/site-packages/music21/sieve.pyr   r   I       r   r   c                      e Zd Zy)ResidualExceptionNr   r   r   r   r   r   M   r   r   r   c                      e Zd Zy)SieveExceptionNr   r   r   r   r   r   Q   r   r   r   c                      e Zd Zy)CompressionSegmentExceptionNr   r   r   r   r   r   U   r   r   r   c                      e Zd Zy)PitchSieveExceptionNr   r   r   r   r   r   Y   r   r   r   {}&|^-@c              #     K   i }d}	 |j                  |d      }|||z   }||v r
||z   }||v r
|||<   n||z  }|||<   || k\  r| |dz   }Fw)a  
    Yields the sequence of prime numbers via the Sieve of Eratosthenes.
    rather than creating a fixed list of a range (z) and crossing out
    multiples of sequential candidates, this algorithm stores primes under
    their next possible candidate, thus allowing the generation of primes
    in sequence without storing a complete range (z).

    Create a dictionary. Each entry in the dictionary is a key:item pair of
    (key) the largest multiple of this prime so far found and (item)
    the prime. The dictionary only has as many entries as found primes.

    If a candidate is not a key in the dictionary, it is not a multiple of
    any already-found prime; it is thus a prime. a new entry is added to the
    dictionary, with the square of the prime as the key. The square of the prime
    is the next possible multiple to be found.

    To use this generator, create an instance and then call the .next() method
    on the instance.

    >>> a = sieve.eratosthenes()
    >>> next(a)
    2
    >>> next(a)
    3

    We can also specify a starting value for the sequence, skipping over
    initial primes smaller than this number:

    >>> a = sieve.eratosthenes(95)
    >>> next(a)
    97
    >>> next(a)
    101
       N   )pop)firstCandidateDqpnextMults        r   eratosthenesr0   p   s     F 	A	A
 EE!TN= 1uHa-#a< a- AhK 1uHAhKN"E) s
   ,AAc                v   t        |       } | dv ry| dz  }|dvryg d}| dk  r| |v ryy|D ]  }| |z  dk(  s y | d	z
  d	}}|d	z  s|d	z  }|d	z   }|d	z  st        d
      D ]U  }t        t        j                  d	| d	z
        ||       }|d	k(  r-t        d	|      D ]  }|| d	z
  k(  r Ft        |d|       }  y y)a  
    Returns True if an integer is likely prime or False if it is likely composite using the
    Rabin Miller primality test.

    See also here: http://www.4dsolutions.net/ocn/numeracy2.html

    >>> sieve.rabinMiller(234)
    False
    >>> sieve.rabinMiller(5)
    True
    >>> sieve.rabinMiller(4)
    False

    >>> sieve.rabinMiller(97 * 2)
    False

    >>> sieve.rabinMiller(6 ** 4 + 1)  # prime
    True

    >>> sieve.rabinMiller(123986234193)  # divisible by 3, runs fast
    False
    )r(      T   )r)      F)r4                           %   )   +   /   5   ;   =   C   G   I   O   S   Y   a   d   r   r)   
   r(   )absrangepowrandomrandint)	nmprimesprimesriyjs	            r   rabinMillerr[      s    . 	AAF{	AA;F 	Cx;u9>  q5!qA!e	aE !e 2Yq!a%(!Q/6q!AAEzAq!A 
   r   c                x   | D ]"  }t        j                  |      rt        d       g }||j                          |d   }|d   }n8t	        t        j                  |             }|j                          |d   }|d   }t        ||dz         D ])  }|| v r|j                  d       |j                  d       + |S )a  
    Treat a sequence of integers as defining contiguous binary integers,
    where provided values are 1's and excluded values are zero.

    For instance, running [3, 10, 12] through this method gives a 1 for
    the first entry (signifying 3), 0s for the next six entries (signifying
    4-9), a 1 (for 10), a 0 (for 11), and a 1 (for 12).

    >>> sieve.discreteBinaryPad([3, 10, 12])
    [1, 0, 0, 0, 0, 0, 0, 1, 0, 1]

    >>> sieve.discreteBinaryPad([3, 4, 5])
    [1, 1, 1]

    znon-integer value foundr   r)   )	r   isNumr   sortlistcopydeepcopyrN   append)seriesfixRangexdiscreteminValmaxVal	seriesAlts          r   discreteBinaryPadrk      s    " ||A 9::  H!"v./	1266A:&;OOAOOA	 '
 Or   c                j   ||j                          |d   }|d   }nt        |       }t        |       }||z
  }g }t        |       dkD  rY| D ]R  }||z
  }t	        j
                  |      rt        |      }|dk7  r|j                  ||z         B|j                  d       T |S |j                  d       |S )a3  
    Given a list of numbers, create a proportional spacing across the unit interval.

    The first entry will always be 0 and the last 1, other entries will be spaced
    according to their distance between these two units.  For instance, for 0, 3, 4
    the middle entry will be 0.75 since 3 is 3/4 of the distance between 0 and 4:

    >>> sieve.unitNormRange([0, 3, 4])
    [0.0, 0.75, 1.0]

    but for [1, 3, 4], it will be 0.666... because 3 is 2/3 of the distance between
    1 and 4

    >>> sieve.unitNormRange([1, 3, 4])
    [0.0, 0.666..., 1.0]

    r   r]   r)   )r_   minmaxlenr   r^   floatrc   )rd   re   minFoundmaxFoundspanunitvaldifs           r   unitNormRangerw     s    $ A;B<v;v;hDD
6{QC.C||C CjqyC$J'A  K 	AKr   c                    | dk  rdgS | dk(  rddgS g }d| dz
  z  }t        | dz
        D ]  }|j                  ||z          |j                  d       |S )a9  
    Given a certain number of parts, return a list unit-interval values
    between 0 and 1, with as many divisions as parts; 0 and 1 are always inclusive.

    >>> sieve.unitNormEqual(3)
    [0.0, 0.5, 1]

    If parts is 0 or 1, then a single entry of [0] is given:

    >>> sieve.unitNormEqual(1)
    [0]
    r)   r   r(   )rN   rc   )partsrt   steprY   s       r   unitNormEqualr{   A  sg     zs
	!1vEAIuqy!AKKD! "Ar   c                    ||k(  rg S ||k  r|}|}n|}|}d}g }|}||k  r!|j                  |       || z  }|dz  }||k  r!|rt        |      S |S )a  
    Given a step size and an a/b min/max range, calculate number of parts
    to fill step through inclusive a,b, then return a unit interval list of values
    necessary to cover region.

    Note that returned values are, by default, normalized within the unit interval.

    >>> sieve.unitNormStep(0.5, 0, 1)
    [0.0, 0.5, 1]

    >>> sieve.unitNormStep(0.5, -1, 1)
    [0.0, 0.25, 0.5, 0.75, 1]

    >>> sieve.unitNormStep(0.5, -1, 1, normalized=False)
    [-1, -0.5, 0.0, 0.5, 1.0]

    >>> post = sieve.unitNormStep(0.25, 0, 20)
    >>> len(post)
    81
    >>> post = sieve.unitNormStep(0.25, 0, 20, normalized=False)
    >>> len(post)
    81

    r   r)   )rc   r{   )	rz   ab
normalizedrh   ri   countvaluesrf   s	            r   unitNormStepr   [  s    2 	Av	1u EFA
v+a	T	
 v+ U##r   c                n    d}|dk(  rd}|S | |k(  rd}|S |dk  r|| z  |z  }|dk(  r	 |S |dz   }|dk  r|S )Nr   r)   '  r   )c1c2gru   s       r   	_meziriacr     sq     	
A	Qw H 
r H %ir6R-CaxH AA	 %i
 Hr   c                  (    e Zd Zd ZddZd ZddZy)PrimeSegmentc                N    g | _         || _        || _        | j                          y)a  
        A generator of prime number segments, given a start value
        and desired length of primes.

        >>> ps = sieve.PrimeSegment(3, 20)
        >>> ps()
        [3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73]
        N)segstartlength
_fillRange)selfr   r   s      r   __init__zPrimeSegment.__init__  s#     
r   Nc                   g }d}|dz  dk(  r||kD  r|dk(  r|dz   }n|dz
  }n|}	 t        |      r"|j                  |       t        |      |k\  r	 |S ||k(  r	 |S ||kD  r|dk(  r|dz   }n|dz
  }n|dk(  r|dz   }n|dz
  }\)z
        scan all number in range and return a list of primes
        provide a max to force stoppage at  certain point before the
        maximum length
        direction determines which way things go.
           r(   r   upr)   )r[   rc   ro   )r   r   r   stop	directionr   _oddBoundaryrR   s           r   _fillRabinMillerzPrimeSegment._fillRabinMiller  s     19>el2D AIAIA1~

1s8v% 
 Dy 
 <$AAAA$AAAA! r   c                   | j                   dk  r| j                  t        | j                         | j                  dd      }|D cg c]  }|  }}t	        |      | j                  k  r5| j                  d| j                  t	        |      z
  dd      }||z   | _        y|| _        y| j                  | j                   | j                  dd      | _        yc c}w )z2
        fill positive and negative range
        r   downNr   )r   r   rM   r   ro   r   )r   segNegrf   segPoss       r   r   zPrimeSegment._fillRange  s     ::>**3tzz?DKKFSF"()&Qqb&F)6{T[[(..q$++F2K9=tE!F?! ,,TZZdDQDH *s   
Cc                ~   | j                   d   | j                   d   g}|dv rt        | j                   |      S |dk(  rt        | j                   |      S |dv r[g }t        t	        | j                         dz
        D ]3  }|j                  | j                   |dz      | j                   |   z
         5 |S | j                   S )z
        assumes that min and max values are derived from found primes
        means that primes will always be at boundaries
        r   r]   binbinaryrt   widwidthr)   )r   rk   rw   rN   ro   rc   )r   segmentFormatzr   rX   s        r   __call__zPrimeSegment.__call__  s    
 XXa[$((2,'--$TXXq11f$ 1--..C3txx=1,-

DHHQUOdhhqk9; .J88Or   )Nr   N)r   r   r   r   r   r   r   r   r   r   r   r     s    #JR$r   r   c                      e Zd ZdZddZd Zd Zd ZddZddZ	d	 Z
dd
ZddZd Zd Zd Zd Zd Zd Zd Zd Zd Zy)Residuala   
    object that represents a modulus and a start point
    each object stores a range of integers (self._z) from which sections are drawn
    this range of integers can be changed whenever the section os drawn

    >>> residual = sieve.Residual(3, 2)
    Nc                    |t        t        d            }|| _        || _        |dvrt	        d      || _        | j                  dk(  r|| _        n|| j                  z  | _        g d| _        d| _        y )NrK   )r   r)   z)negative value must be 0, 1, or a Booleanr   intr   rt   r   r   )	r`   rN   _z_mr   _neg_shift_segmentFormatOptions_segmentFormat)r   rS   shiftnegr   s        r   r   zResidual.__init__  sq     9U3Z Af#$OPP	77a<DK$''/DK%B"#r   c                    || _         y)zJ
        z is the range of integers to use when generating a list
        Nr   r   r   s     r   setZzResidual.setZ%  s     r   c                >    t        t        ||dz               | _        y)zv
        z is the range of integers to use when generating a list
        convenience function that fixes max
        r)   Nr`   rN   r   r   minIntmaxInts      r   	setZRangezResidual.setZRange+      
 uVVaZ01r   c                    |j                         j                         }|| j                  v rt        d|       || _        y )Nzformat not in format options: )striplowerr   r   r   r   fmts     r   setSegmentFormatzResidual.setSegmentFormat2  s?    iik!$,,,#&DSE$JKK!r   c                   || j                   }|| j                  }g }| j                  dk(  r|S || j                  z   | j                  z  }|D ]&  }||| j                  z  k(  s|j	                  |       ( | j
                  r0t        j                  |      }|D ]  }|j                  |        |}n|}|dv rt        ||      S |dk(  rt        ||      S |dv r| j                  gt        |      dz
  z  }|S |dv r|S t        | d      )a  
        get a residual subset of this modulus at this n
        within the integer range provided by z
        format can be 'int' or 'bin', for integer or binary

        >>> a = sieve.Residual(3, 2)
        >>> a.segment(3)
        [2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47, 50, 53, 56, 59,
         62, 65, 68, 71, 74, 77, 80, 83, 86, 89, 92, 95, 98]
        >>> a.segment(3, range(3, 15))
        [5, 8, 11, 14]
        r   r   rt   r   r)   )r   integerz( not a valid sieve segmentFormat string.)r   r   r   r   rc   r   ra   rb   removerk   rw   ro   r   )	r   rR   r   r   subsetvaluecompSetr   r   s	            r   segmentzResidual.segment:  s    9A  //M77a<M_'EEDGGO#e$  99mmA&Gu%  CC--$S!,,f$ a((..77)s3x!|,CJ00J#}o5]$^__r   c                    | j                   S )z
        period is M; obvious, but nice for completeness

        >>> a = sieve.Residual(3, 2)
        >>> a.period()
        3
        )r   r   s    r   periodzResidual.periodi  s     wwr   c                    t        j                   | j                        }t        j                   | j                        }t        j                   | j                        }t	        |||| j
                        S r   )ra   r   r   r   r   r   )r   rS   r   r   s       r   ra   zResidual.copyt  sM    IIdgg		$++&ii		"5#tww//r   c                (    | j                  |||      S )a  
        calls self.segment(); uses _segmentFormat

        >>> a = sieve.Residual(3, 2)
        >>> a()
        [2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47,
         50, 53, 56, 59, 62, 65, 68, 71, 74, 77, 80, 83, 86, 89, 92, 95, 98]
        )r   r   rR   r   r   s       r   r   zResidual.__call__|  s     ||Aq-00r   c                   |dk(  rN| j                   dk7  r| j                   d| j                    d}n| j                   d}| j                  rd| }|S | j                   d| j                    }| j                  rd| }|S )zG
        does not show any logical operator but unary negation
        classicr   z(n+)z(n)r%   r&   )r   r   r   )r   stylerepStrs      r   	representzResidual.represent  s     I{{a GG9C}A6 GG9CyyVH
  y$++/FyyVHr   c                "    | j                         S )z
        str representation using M(n + shift) style notation

        >>> a = sieve.Residual(3, 2)
        >>> str(a)
        '3@2'
        r   r   s    r   __str__zResidual.__str__  s     ~~r   c                    |y| j                   |j                   k(  r3| j                  |j                  k(  r| j                  |j                  k(  ryy)zF
        ==, compare residual classes in terms of m and shift
        r   r)   r   r   r   r   others     r   __eq__zResidual.__eq__  sB     =GGuxxKK5<</II+r   c                \   | j                   |j                   k  ry| j                   |j                   kD  ry| j                   |j                   k(  r_| j                  |j                  k  ry| j                  |j                  kD  ry| j                  |j                  k7  r| j                  dk(  ryyyy)z
        allow comparison based on m and shift; if all equal look at neg

        Still being used internally even though __cmp__ is not used in Python 3
        r]   r)   r   Nr   r   s     r   __cmp__zResidual.__cmp__  s     77UXXWWuxxWW {{U\\)u||+99

*yyA~!  !r   c                .    | j                  |      dk(  ryy)Nr]   TFr   r   s     r   __lt__zResidual.__lt__  s    <<"$r   c                .    | j                  |      dk(  ryy)Nr)   TFr   r   s     r   __gt__zResidual.__gt__  s    <<!#r   c                |    | j                   rd}nd}t        | j                  | j                  || j                        S )z8
        unary neg operators; return neg object
        r   r)   )r   r   r   r   r   )r   r   s     r   __neg__zResidual.__neg__  s2     99CCc477;;r   c                N   |j                   s| j                   rt        d      | j                  | j                  |j                  | j                  |j                        \  }}t        | j                        t        |j                        z  }t        |      }t        ||d|      S )a   
        &, produces an intersection of two Residual classes
        returns a new Residual class
        cannot be done if R under complementation

        >>> a = sieve.Residual(3, 2)
        >>> b = sieve.Residual(5, 1)
        >>> c = a & b
        >>> str(c)
        '15@11'
        z3complemented Residual objects cannot be intersectedr   )	r   r   _cmpIntersectionr   r   setr   r`   r   )r   r   rS   rR   zSetr   s         r   __and__zResidual.__and__  s{     ::#$YZZ$$TWWehhU\\R1477|c%((m+J1a##r   c                     y)z
        ``|``, not sure if this can be implemented
        i.e., a union of two Residual classes can not be expressed as a single
        Residual, that is intersections can always be reduced, whereas unions
        cannot be reduced.
        Nr   r   s     r   __or__zResidual.__or__  s     	r   c                &   t        ||      }||z  }||z  }d}d}	|dk7  r|dk7  r||z  }||z  }n||	fS |dk7  r||z
  |z  dk7  r||	fS |dk7  r||z
  |z  dk(  r||k7  r||k(  r|}	|}|	|fS ||z  |z  }	t        ||      }
||
||z
  z  |z  z   |	z  }|	|fS )z
        compression by intersection
        find m,n such that the intersection of two Residuals can
        be reduced to one Residual. Xenakis p 273.
        r   r)   )r   r   )r   m1m2n1n2dr   r   n3m3r   s              r   r   zResidual._cmpIntersection  s     BK1W1W7rQwbBbBr6M6R1})r6M!V"r'Q!+"(rBBr6Mb1B"b!AR"W*+r1Br6Mr   )r   r   Nr   NNreturnr   r   )r   r   r   __doc__r   r   r   r   r   r   ra   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r     sc    $*2"-`^0
1" 6<$*r   r   c                  >    e Zd ZdZd
dZd
dZd Zd Zd Zd Z	d	 Z
y)CompressionSegmenta  
    Utility to convert from a point sequence to sieve.

    A z range can be supplied to explicitly provide the complete sieve segment,
    both positive and negative values. all values in the z range not in the
    segment are interpreted as negative values. thus, there is an essential
    dependency on the z range and the realized sieve.

    No matter the size of the z range, there is a modulus at which one point
    in the segment can be found. As such, any segment can be reduced to, at a
    minimum, a residual for each point in the segment, each, for the supplied z,
    providing a segment with one point.

    The same segment can then have multiplied logical string representations,
    depending on the provided z.

    >>> a = sieve.CompressionSegment([3, 4, 5, 6, 7, 8, 13, 19])
    >>> str(a)
    '6@1|7@6|8@5|9@4|10@3|11@8'

    >>> b = sieve.CompressionSegment([0, 2, 4, 6, 8])
    >>> str(b)
    '2@0'

    >>> c = sieve.CompressionSegment([0, 2, 4, 5, 7, 9, 11, 12])
    >>> str(c)
    '5@2|5@4|6@5|7@0'
    Nc                   t        t        j                  |            }|j                          g | _        |D ],  }|| j                  vs| j                  j                  |       . t        | j                        dk  rt        d      | j                  |       t        | j                        | _
        	 | j                          y # t        $ r}t        d      |d }~ww xY w)Nr)   z'segment must have more than one elementz*no Residual classes found for this z range)r`   ra   rb   r_   _matchrc   ro   r   _zUpdater   _maxMod_processAssertionError)r   srcr   numassertErrors        r   r   zCompressionSegment.__init__=  s     4==%&
C$++%""3'  t{{q -.WXXa 477|	MMO 	-<	s   6C 	C!CC!c                   |M| j                  | j                  |      st        d      || _        | j                  d   | j                  d   }}y | j                  d   | j                  d   }}t	        t        ||dz               | _        y )Nz-z range must be a superset of desired segmentr   r]   r)   )_subsetr   r   r   r`   rN   )r   r   zMinzMaxs       r   r  zCompressionSegment._zUpdateW  s    =<<Q/1CE E DGTWWR[$D QR$D5q23DGr   c                    | j                   S )z

        >>> a = sieve.CompressionSegment([3, 4, 5, 6, 7, 8])
        >>> b = a()
        >>> str(b[0])
        '1@0'
        )
_residualsr   s    r   r   zCompressionSegment.__call__f  s     r   c                    g }t        | j                        dk(  rt        | j                  d         }|S | j                  D ]  }|j                  t        |              dj	                  |      }|S )Nr)   r   r#   )ro   r  strrc   join)r   resStrresObjs      r   r   zCompressionSegment.__str__p  se    t1$+,F
  //c&k* *XXf%Fr   c                H    d}|D ]  }||v s|dz   } |t        |      k(  ryy)zM
        True if sub is part of set; assumes no redundancies in each
        r   r)   )ro   )r   subthisSet	commonNumrf   s        r   r	  zCompressionSegment._subset{  s7     	AG|%M	  C r   c                   d}|| j                   k  r`t        ||d| j                        } |       }| j                  ||      r||fS | j                  ||      r||fS |dz   }|| j                   k  r`t	        d| j                          )z_
        given a point, and SieveSegment, find a modulus and shift that
        match.
        r)   r   za mod was not found less than )r  r   r   r	  r   )r   rR   partwholerS   objr   s          r   _findzCompressionSegment._find  s    
 $,,1aDGG,C%C||C&Cxc5)CxAA $,, =dll^LMMr   c                   g | _         t        j                  | j                        }d}|r|dz  }|d   }| j                  ||| j                        \  }}|t	        d      || j                   vr8| j                   j                  |       |D ]  }||v s|j                  |        |sn|r| j                   j                          y)a  
        take a copy of match; move through each value of this list as if it
        were n; for each n test each modulo (from 1 to len(z) + 1) to find a
        residual. when found (one will be found), keep it; remove the found
        segments from the match, and repeat.
        r   r)   r   Nz_find() returned a None object)r  ra   r   r  r   rc   r   r_   )r   matchmaxToRunrR   r  r   rf   s          r   r  zCompressionSegment._process  s     		$++&MHaAzz!UDKK8HC{12RSS$//)&&s+AEzQ    	r   r   )r   r   r   r   r   r  r   r   r	  r  r  r   r   r   r   r     s+    :44N&r   r   c                  *   e Zd ZdZd'd(dZd Zd Zd Zd Zd'dZ	d	 Z
d
 Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd)dZd Zd Zd*dZd Zd Zd'dZd Zd'dZd Z d  Z!	 	 	 	 d+	 	 	 d,d!Z"d-d"Z#d.d#Z$	 d/	 	 	 	 	 	 	 	 	 	 	 d0d$Z%d1d%Z&d& Z'y)2Sievez
    Create a sieve segment from a sieve logical string of any complexity.

    >>> a = sieve.Sieve('3@11')
    >>> b = sieve.Sieve('2&4&8|5')
    >>> c = sieve.Sieve('(5|2)&4&8')
    Nc                v   |%t        |t              rt        t        d            }n|t	        j
                  |      r	 || _        d| _        d | _        d| _	        g d| _
        d| _        i | _        d| _        d| _        d| _        d| _        d| _        || _        | j$                  | j'                          y y )	NrK   expr   r   Fr    r]   )
isinstancer  r`   rN   r   
isListLiker   _state_expTyper   r   _nonCompressible_resLib_resId_expTree
_expPeriod_cmpTree
_cmpPeriod_usrStr_load)r   usrStrr   s      r   r   zSieve.__init__  s    9FC0U3Z AY6,,V4/4#%B" %,. <<#JJL $r   c                   t        j                  | j                        r<| j                          | j	                  | j                         | j                          y | j                          | j                          | j                          y r   )r   r%  r/  	_resClear_initLoadSegment_initCompression
_initParser   s    r   r0  zSieve._load  s^    T\\*NN!!$,,/!!# NNOO!!#r   c                   d| _         t        | j                  v s6t        | j                  v s$t        | j                  v st
        | j                  v r	 | j                          n	 | j                          d| _         d}| j                  rd}|S | j                   dk(  rd}|S | j                   dk(  rd}|S # t        $ r
 d| _        Y Jw xY w# t        $ r+ 	 | j                          n# t        $ r
 d| _        Y nw xY wY w xY w)Ncomplexr)   simpler#  zno compression possibler   intersection)r'  NEGr+  LGROUPRGROUPXOR_cmpSegment
IndexErrorr(  r   	TypeError)r   methods     r   r5  zSieve._initCompression  s    "4== T]]*T]]*$--'*  ".%%' (   .F
 	 ]]i'F  ]]h&#F'  *()%*  ..$$&! .,-D)..sH   B2 #C 2CC	C<C#"C<#C63C<5C66C<;C<c                    | j                  d      }| j                  d      }t        | }||k(  r|| _        || _        y|| _        t        | | _        y)zb
        Lazy period initialization, called only when needed from public period() method.
        r"  cmpN)_resPeriodListr   r,  r.  )r   mListExpmListCmplcmExps       r   _initPeriodzSieve._initPeriod/  sU     &&u-&&u-hx$DO$DO$DO!8nDOr   c                    d| _         y)z7
        Set this Sieve to its expanded state.
        r"  N)r&  r   s    r   expandzSieve.expand?  s     r   c                    |7|| j                   k7  r(|| _         | j                  d       | j                          | j                  ryd| _        y)z9
        Set this sieve to its compressed state.
        NrD  )r   r3  r5  r(  r&  r   s     r   compresszSieve.compressE  sE     =Q$''\DGNN5!!!#  DKr   c                    d| j                  d      i}| j                  -| j                  | j                  d         j                  |d<   |S | j                  |d<   |S )zH
        Provides a dictionary data representation for exchange
        logStrr"  r   r   )r   r   r)  
_resKeyStrr   )r   datas     r   _getParameterDatazSieve._getParameterDataU  s`    
 dnnU+
 77?T__Q%78::DI  DIr   c                    || _         y)zu
        Set the z as a list. The z is the range of integers to use when
        generating a sieve segment.
        Nr   r   s     r   r   z
Sieve.setZd  s    
 r   c                >    t        t        ||dz               | _        y)z
        Set the z as a min and max value. The z is the range of
        integers to use when generating a sieve segment.
        r)   Nr   r   s      r   r   zSieve.setZRangek  r   r   c                    |j                         j                         }|| j                  vrt        d|       || _        y )Nzcannot set to format: )r   r   r   r   r   r   s     r   r   zSieve.setSegmentFormatr  s?    iik!d000 #9#!?@@!r   c                    | j                         }dj                  t        t        |d   t        g      }|d   }t        ||      S )z9
        unary neg operators; return neg object.
        r#  rO  r   )rR  r  r;  r<  r=  r   )r   dataSelfr1  r   s       r   r   zSieve.__neg__}  sN     ))+X	
  SMVQr   c           	        | j                         }|j                         }dj                  t        |d   t        t        t        |d   t        g      }t        |d         t        |d         z  }t        |      }t        ||      S )z
        &, produces an intersection of two

        >>> a = sieve.Sieve('3@11')
        >>> b = sieve.Sieve('2&4&8|5')
        >>> c = sieve.Sieve('(5|2)&4&8')
        >>> d = a & b
        >>> str(d)
        '{2@0&4@0&8@0|5@0}&{3@2}'
        r#  rO  r   )rR  r  r<  r=  ANDr   r`   r   r   r   rW  	dataOtherr1  r   r   s          r   r   zSieve.__and__  s     ))+++-	hX
  8C=!C	#$77JVQr   c           	        | j                         }|j                         }dj                  t        |d   t        t        t        |d   t        g      }t        |d         t        |d         z  }t        |      }t        ||      S )z
        ``|``, produces a union

        >>> a = sieve.Sieve('3@11')
        >>> b = sieve.Sieve('2&4&8|5')
        >>> d = a | b
        >>> str(d)
        '{2@0&4@0&8@0|5@0}|{3@2}'
        r#  rO  r   )rR  r  r<  r=  ORr   r`   r   rZ  s          r   r   zSieve.__or__  s     ))+++-	hX
  8C=!C	#$77JVQr   c           	        | j                         }|j                         }dj                  t        |d   t        t        t        |d   t        g      }t        |d         t        |d         z  }t        |      }t        ||      S )z4
        ^, produces exclusive disjunction.
        r#  rO  r   )rR  r  r<  r=  r>  r   r`   r   rZ  s          r   __xor__zSieve.__xor__  s     ))+++-	hX
  8C=!C	#$77JVQr   c                   d}t        j                  |      rt        |      dddS |j                         }|sy|j	                  d      r|j                  dd      }|j	                  d      r|j                  dd      }|j                  t        d      }|j                  t        d      }|d   dk(  rd	}|d	d j                         }nd}|sy	 t        |      }d}t        j                  |      rt        |      }d}n0t        j                  |      r|d   }t        |      d	kD  r|d	   }nd}|||d
S # t        t        t        f$ r Y yw xY w)ai  
        process an arg string for proper Residual creation
        valid syntax for Mod, shift pairs:
        all valid: MsubN, M@N, M,N, M
        if M is given alone, shift is assumed to be 0
        this method assumes that all brackets have been replaced with parentheses
        returns a dictionary of args suitable for creating a Residual class
        r   )rS   rR   r   Nr  ,r&   r#  r%   r)   )rS   r   r   )r   r^   r   r   findreplacer<  r=  r   	NameErrorSyntaxErrorrA  r%  ro   )r   r1  rS   r   argsr   s         r   _parseResidualzSieve._parseResidual  sS    <<V1Q77;;u^^E3/F;;s^^C-F ++ !9CABZ%%'FC	  'D <<D	AEt$QA4y1}Q 	 ;	2 		s   D6 6EEc                   t        j                  |      rt        |      }| d}|j                  d      dk\  r|j	                  dt
              }|j                  d      dk\  r|j	                  dt
              }|j                  d      dk\  r|j	                  dt              }|j                  d      dk\  r|j	                  dt              }|j                  d      dk\  r|j	                  dt              }|j                  d	      dk\  r|j	                  d	t              }|j                  d
      dk\  r|j	                  d
t              }|j                  d      dk\  r|j	                  dt              }|j                  d      dk\  r|j	                  dt              }|j                  d      dk\  r|j	                  dt              }|j	                  dd      }|S )a  
        provide synonyms for logical symbols::

            intersection == and, &, *
            union        == or, |, +
            not          == not, -

        the native format for str representation uses only ``&``, ``|``, ``-``;
        this method converts all other string representations

        all brackets and braces are replaced with parenthesis
        parentheses are only used for the internal representation
        on string representation, braces are restored
        z@0andr   *or+xorr$   not[](r    r#  )
r   r^   r   rb  rc  rY  r]  r;  r<  r=  )r   r1  s     r   _parseLogiczSieve._parseLogic  s     <<[Fxr]F;;u"^^E3/F;;sq ^^C-F;;t!^^D"-F;;sq ^^C,F;;u"^^C,F;;u"^^E3/F;;sq ^^C0F;;sq ^^C0F;;sq ^^C0F;;sq ^^C0FR(r   c                Z    t        |      }t        |      j                  dd      }d| dS )zF
        return string necessary to instantiate a set object.
        rr  r#  zset(r   )r`   reprrc  )r   valLists     r   _setInstantiateStrzSieve._setInstantiateStrC  s2     w-w-''R0gYa  r   c                    d| dS )Nz<R>r   )r   resIds     r   rP  zSieve._resKeyStrK  s    E7!}r   c                
   |dvrt        d      |dk(  r5g }| j                  D ]"  }|| j                  v s|j                  |       $ |S |dk(  r5g }| j                  D ]"  }|| j                  v s|j                  |       $ |S y)z5
        get residual keys based on library.
        )rD  r"  zstate must be 'cmp' or 'exp'rD  r"  N)r   r)  r-  rc   r+  )r   statelibKeyskeys       r   _resKeyszSieve._resKeysN  s     & !?@@E>G||$--'NN3' $ Ne^G||$--'NN3' $ N r   c                    g }| j                  |      D ]5  }| j                  |   j                         }||vs%|j                  |       7 |j	                          |S )z
        For all residual classes, get the period, or the value of M,
        and return these in a list. Remove any redundant values and sort.
        )r  r)  r   rc   r_   )r   r|  mListr~  r.   s        r   rE  zSieve._resPeriodLista  sU    
 =='CS!((*A~Q ( 	

r   c                0   | j                  dj                  |            }|%dj                  |      }d| }t        d|d      t        |d   |d   |d   | j                        }|| j
                  | j                  |      <   | j                  |      S )z
        create a residual object, store in expResidualLib
        return a string id representation
        this uses self._z at initialization.
        r#  zcannot parse zbad residual class notation: (r   rS   r   r   )rg  r  r   r   r   r)  rP  )r   rz  r  resDictjoinedmsgr  s          r   
_resCreatezSieve._resCreaten  s     %%bggfo6?WWV_F!&*C #A#!JKK'#,(8!%.$''3 06T__U+,u%%r   c                `    || j                   | j                  |      <   | j                  |      S r   )r)  rP  )r   rz  r  s      r   
_resAssignzSieve._resAssign  s(    /5T__U+,u%%r   c                    || j                   }t        j                  |      s|t        d|       | j                  |   ||      }| j                  |      S )z
        this is where residuals are converted to set evaluating strings
        z should not be stored; should be a temporary value
        z"z must be a list of integers, not )r   r   r%  r   r)  rw  )r   rz  rR   r   rv  s        r   _resToSetStrzSieve._resToSetStr  s_    
 9A  # #EaU!KLL%$,,u%a+&&w//r   c                ,    | j                   dz   | _         y)z'
        increment the _resId.
        r)   N)r*  r   s    r   _resIdIncrementzSieve._resIdIncrement  s     kkAor   c                ,   t        t        | j                  j                                     }|D ];  }| j	                  |      }|| j
                  vs#|| j                  vs2t        d       t        | j                  j                               | _        y)z
        reset self._resId to the next available number
        may need to re-label some residual classes if gaps develop
        ids should be contiguous integer sequence
        zgap in residual keysN)	rN   ro   r)  keysrP  r-  r+  r   r*  )r   iValsrX   testKeys       r   _resResetIdzSieve._resResetId  sv     c$,,++-./Aooa(Gdmm+t}}0L$%;<< 
 $,,++-.r   c                    |i | _         d| _        y |dk(  r6| j                  |      }|D ]  }| j                   |=  | j                          y |dk(  rt	        d      y )Nr   rD  r"  z1Expanded residual classes should never be cleared)r)  r*  r  r  r   )r   r|  cmpKeysr~  s       r   r3  zSieve._resClear  sf    =DLDKe^mmE*GLL%  e^ !TUU r   c                f   g | _         t        || j                        }| j                  |j                  | _         |       }|D ]G  }| j                   j                  | j	                  | j
                  |             | j                          I t        j                  | j                         | _         y)z=
        load from a segments
        reload _resId.
        N)	r+  r   r   rc   r  r*  r  r]  r  )r   usrDatasegObjunionr  s        r   r4  zSieve._initLoadSegment  s     #GTWW577?iiDGFMM  f!EF  "  .r   c                   i | _         d| _        g | _        | j                  t	        j
                  | j                              }d}	 |t        |      k(  rn||   }|dk(  rd}n||dz
     }|t        |      dz
  k(  rd}n||dz      }|t        v r"| j                  j                  |       |dz   }n|t        k(  r|d}t        d| d      |t        k(  r||t        v rd}t        d| d      |t        k(  rX|V|t        k(  rM|)|t        t        t        t         fvrd	}t        d
| d      | j                  j                  |       |dz  }n |t"        j$                  v s	|t        k(  rg }t	        j                  |      }	d}
||	|
z      t        k(  r|j                  t               |
dz   }
	 |	|
z   t        |      k(  rn1||	|
z      }|t        v s	|t        k(  rn|j                  |       |
dz   }
C| j                  j                  | j'                  | j                  dj)                  |                   | j+                          ||
z   }n|dz   }| j                   st        d      dj)                  | j                        | _        y)zV
        process usrStr string into proper argument dictionaries for Residual
        r   r)   Nz(negation cannot be used without operandsz"badly formed logical string (a): (r   z,negation cannot be used as a binary operatorz"badly formed logical string (b): (z6negation must be of a group and isolated by delimitersz"badly formed logical string (c): (r#  zno residual classes defined)r)  r*  r+  rs  ra   rb   r/  ro   BOUNDSrc   r;  r   RESIDUALr<  rY  r]  r>  stringdigitsr  r  r  )r   r   rO  rX   charcharPreviouscharNextr  r  subStartsubLensubChars               r   r6  zSieve._initParse  s   
 !!$--"=>CK!9DAv#%a!e}CK!O#!!a%= v~$$T*E !1@$'I#a%PQQ#+"."h.D$'I#a%PQQ #+*&( !,(b#0FFRC(+McURS)TUU$$T*Q
 &$#+99Q<(V+,3MM#&#aZF 6)c&k9$X%67G&(GsNg.!'!  $$T__T[["''&/%RS$$&JEO R || !>??.r   c                v   g | _         t        j                  | j                        }|j                  t              }d}|D ]  }|dk(  r	|j                  t
              }t        |      dk(  r| j                  |d      }nPt        t        |      dz
        D ]6  }|dk(  r| j                  ||      }n|}| j                  ||dz         }||z  }8 | j                   j                  | j                  | j                  |             | j                           t        j                  | j                         | _         y)z9
        an unbound sieve, intersection Residual
        r   r#  r)   N)r-  ra   r+  splitr]  rY  ro   r)  rN   rc   r  r*  r  r  )	r   rO  orListr:  orGroupandListrX   r}   r~   s	            r   r   zSieve._cmpIntersection!  s
    4==)b!G"}mmC(G7|q #||GAJ7s7|a/0AAv LL4(WQU^4A#$q5L 1 MM  l!KL  ") * .r   c                d   g | _         | j                  d      }|st        d      t        || j                        } |       D ]G  }| j                   j                  | j                  | j                  |             | j                          I t        j                  | j                         | _         y)z<
        a bound sieve, uss a newly created segment
        r"  z/empty segment; segment compression not possibleN)r-  r   r@  r   r   rc   r  r*  r  r]  r  )r   r   r  r  s       r   r?  zSieve._cmpSegmentA  s    
 ll5!NOO#C1hFMM  f!EF  "  .r   c           	        || j                   }|| j                  }|| j                  }|dk(  r t        j                  | j                        }n'|dk(  r t        j                  | j
                        }nd}| j                  |      }t        ddd|      }| j                   |             }|j                  d|dz         }|D ]%  }	|j                  |	| j                  |	||            }' |j                  t        d      }|j                  t        d	      }	 t        |d
dt        iii       }
t#        |
      }
|
j%                          |dv rt'        |
|      S |dk(  rt)        |
|      S |dv r=g }t+        t-        |
      dz
        D ]  }|j/                  |
|dz      |
|   z
         ! |S |
S # t        $ r}t!        d| d	      |d}~ww xY w)a  
        Return a sieve segment in various formats.

        >>> a = sieve.Sieve('3@11')
        >>> a.segment('exp')
        [2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47,
         50, 53, 56, 59, 62, 65, 68, 71, 74, 77, 80, 83, 86, 89, 92, 95, 98]

        >>> c = sieve.Sieve('(5|2)&4&8')
        >>> c.segment('cmp', segmentFormat='wid')
        [8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8]
        Nr"  rD  r#  r)   r   r%   rq  r   __builtins__r   zbadly formed logical string (r   rt   r   )r&  r   r   ra   r+  r-  r  r   rw  rc  r  r<  r=  evalr   re  r   r`   r_   rk   rw   rN   ro   rc   )r   r|  rR   r   r   evalStrr  r  setStrr~  r   ser   rX   s                 r   r   zSieve.segmentT  s   & =KKE9A  //ME>ii.Ge^ii.GG}}U# !Q1%((2//#v|4Cooc4+<+<S!Q+GHG  //&#.//&#.		 w% >CC 3i
--$S!,,f$ a((..C3s8a<(

CAJQ/1 )JJ#  	 /y:	s   F, ,	G
5GG
c                    | j                   }| j                  dk(  r| j                          |dk(  r| j                  S |dk(  r| j                  S t	        d      )aE  
        Return the period of the sieve.

        >>> a = sieve.Sieve('3@11')
        >>> a.period()
        3
        >>> b = sieve.Sieve('2&4&8|5')
        >>> b.period()
        40
        >>> c = sieve.Sieve('(5|2)&4&8')
        >>> c.period()
        40

        * Changed in v9: state is taken from the object.
        r]   r"  rD  zState must be exp or cmp)r&  r,  rI  r.  
ValueError)r   r|  s     r   r   zSieve.period  sS    ( ??b E>??"e^??"788r   c                >    | j                  | j                  |||      S r   )r   r&  r   s       r   r   zSieve.__call__  s    ||DKKA}==r   c           
        g }|}d}|dk  r|}	||z   }
|dv r2| j                  | j                  |t        t        |	|
            |      }n1| j                  | j                  |t        t        |	|
            d      }||dd z   }||z   }|dz   }t	        |      |k\  rn|dk  r|d| }t	        |      |k7  rt        d      |dk(  rt        |t        |d   |d	   dz               S |d
v rt        |t        |d   |d	   dz               S |S )z
        Collect sieve segment points for the provided length and format.

        >>> a = sieve.Sieve('3@11')
        >>> a.collect(10, 100, 10, 'int')
        [102, 105, 108, 111, 114, 117, 120, 123, 126, 129]
        r   r   r   r   Nr)   z/desired length of sieve segment cannot be foundrt   r]   r   )r   r&  r`   rN   ro   r   rw   rk   )r   rR   zMinimumr   r   zStepfoundr.   zExtendCountr
  r  segmentPartialr   s                r   collectzSieve.collect  s@   * U"Du9D  00!%dkk1.25t3D.E}"V "&dkk1.25t3D.Eu"N N1--EE	A'!+L5zV## U"( GVns8v !RSS F" eCFCGaK&@AA//$S%AB!*DEEJr   c                F   || j                   }|dk(  r t        j                  | j                        }n'|dk(  r t        j                  | j                        }nd}| j	                  |      }|D ]0  }|j                  || j                  |   j                  |            }2 |S )z
        style of None is use for users; adds | to single residuals
        style abs (absolute) does not add | tos single residual class
        r"  rD  r#  )r&  ra   r+  r-  r  rc  r)  r   )r   r|  r   r  r  r~  s         r   r   zSieve.represent  s    
 =KKEE>))DMM*Ce^))DMM*CC }}U#C++c4<<#4#>#>u#EFC 
r   c                "    | j                         S r   r   r   s    r   r   zSieve.__str__  s    ~~r   r   )r1  zstr | list[str]r   zlist[int] | None)r   	list[int])r   N)Nr   NN)r|  z*t.Literal['cmp'] | t.Literal['exp'] | Noner   r  r   r   )rK   )rR   r   r  r   r   r   r   r  r  r   r   r  )NN)(r   r   r   r   r   r0  r5  rI  rK  rM  rR  r   r   r   r   r   r   r_  rg  rs  rw  rP  r  rE  r  r  r  r  r  r3  r4  r6  r   r?  r   r   r   r  r   r   r   r   r   r   r     s%   8	$>-   2"  6 6 .;z+\!&&"&0&/V /$V/v/@/* 9=

K5K 
KZ9>> 99 9 	9
 9 9 
9v* r   r   c                  >    e Zd ZdZ	 	 	 	 d	 	 	 	 	 	 	 ddZd ZddZy)	
PitchSieveat  
    Quick utility generator of :class:`music21.pitch.Pitch` lists
    from :class:`music21.sieve.Sieve` objects.

    >>> ps = sieve.PitchSieve('6@0', 'c4', 'c8')
    >>> [str(p) for p in ps()]
    ['C4', 'F#4', 'C5', 'F#5', 'C6', 'F#6', 'C7', 'F#7', 'C8']

    >>> a = sieve.PitchSieve('4@7')
    >>> [str(p) for p in a()]
    ['E-3', 'G3', 'B3', 'E-4', 'G4', 'B4']
    Nc                   || _         t        | j                         | _        |t        j                  |      | _        nt        j                  d      | _        |t        j                  |      | _        nt        j                  d      | _        |t        j                  |      | _        n$t        j                  | j
                        | _        |t        |      | _        y || _        y )Nc3c5)sieveStringr   sieveObjectr   Pitch
pitchLower
pitchUpperpitchOriginra   rb   rp   eld)r   r  r  r  r  r  s         r   r   zPitchSieve.__init__(  s     ' #((8(8"9!#kk*5DO#kk$/DO!#kk*5DO#kk$/DO"${{;7D#}}T__=D?SzDHDHr   c           	        | j                   j                  }| j                  j                  }t        t	        t        |      t        |dz                     }| j                  j                  }| j                  dk(  rI| j                  ||      }g }|D ].  }t        j                         }||_        |j                  |       0 |S t        | j                  ||d      }	t        t	        t        |	                  }| j                  ||d      }
g }t	        t        |
            D ]:  }|
|   dk(  st        j                         }|	|   |_        |j                  |       < |S )ag  
        Return a sieve segment as a list of :class:`music21.pitch.Pitch` objects,
        mapped to the range between pitchLower and pitchUpper.

        >>> a = sieve.PitchSieve('4@7&5@4')
        >>> a()
        [<music21.pitch.Pitch G4>]

        >>> a = sieve.PitchSieve('13@3|13@6|13@9', 'c1', 'c10')
        >>> ', '.join([str(p) for p in a()])
        'E-1, F#1, A1, E2, G2, B-2, F3, G#3, B3, F#4, A4, C5, G5, B-5, C#6, G#6, B6,
         D7, A7, C8, E-8, B-8, C#9, E9, B9'

        >>> a = sieve.PitchSieve('3@0', 'c4', 'c5', 'c4', 0.5)
        >>> a.eld
        0.5

        The following is a microtonal pitch sieve; presently these are not
        displayed; true values are
        [0, 1.5, 3.0, 4.5, 6.0, 7.5, 9.0, 10.5, 12.0]

        >>> pitches = a()
        >>> ', '.join([str(p) for p in pitches])
        'C4, C#~4, E-4, E~4, F#4, G~4, A4, B`4, C5'

        True values: [0.5, 2.0, 3.5, 5.0, 6.5, 8.0, 9.5, 11.0]

        >>> a = sieve.PitchSieve('3@0', 'c4', 'c5', 'c#4', 0.5)
        >>> pitches = a()
        >>> ', '.join([str(p) for p in pitches])
        'C~4, D4, E`4, F4, F#~4, G#4, A~4, B4'
        r)   F)r   r   )r  psr  r`   rN   r   r  r  r  r   r  rc   r   ro   )r   minPSmaxPSr   rR   sieveSegIntegerssieveSegpsNumr.   rv  binSegrX   s               r   r   zPitchSieve.__call__H  s0   D """"s5z3uqy>23 88q=#//15H)KKM" *&  #488UEeLG U3w<()A%%aE2FH3v;'!9>A"1:ADOOA&	 (
 r   c                J   | j                   j                         }|dk  rt        t        |dz               }nd}| j                  d|d      }g }t	        |      D ]8  \  }}t        j                  || j                  z        }|j                  |       : |st        d      |S )ax  
        Return a list of Interval objects that defines the complete structure
        of this :class:`music21.sieve.Sieve`.

        >>> a = sieve.PitchSieve('3@0')
        >>> a.getIntervalSequence()
        [<music21.interval.Interval m3>]

        >>> a = sieve.PitchSieve('3@0|7@0')
        >>> a.sieveObject.segment()
        [0, 3, 6, 7, 9, 12, 14, 15, 18, 21, 24, 27, 28, 30, 33, 35, 36, 39, 42, 45, 48, 49,
         51, 54, 56, 57, 60, 63, 66, 69, 70, 72, 75, 77, 78, 81, 84, 87, 90, 91, 93, 96, 98, 99]
        >>> a.sieveObject.period()
        21
        >>> a.getIntervalSequence()
        [<music21.interval.Interval m3>, <music21.interval.Interval m3>,
         <music21.interval.Interval m2>, <music21.interval.Interval M2>,
         <music21.interval.Interval m3>, <music21.interval.Interval M2>,
         <music21.interval.Interval m2>, <music21.interval.Interval m3>,
         <music21.interval.Interval m3>]

        This is the PitchSieve for a major scale:

        >>> b = sieve.PitchSieve('(-3@2 & 4) | (-3@1 & 4@1) | (3@2 & 4@2) | (-3 & 4@3)')
        >>> b.getIntervalSequence()
        [<music21.interval.Interval M2>,
         <music21.interval.Interval M2>,
         <music21.interval.Interval m2>,
         <music21.interval.Interval M2>,
         <music21.interval.Interval M2>,
         <music21.interval.Interval M2>,
         <music21.interval.Interval m2>]
        iɚ;r)   Nr   r   )r   zinterval segment has no values)
r  r   r`   rN   	enumerater   Intervalr  rc   r   )r   r.   r   widthSegmentspostrX   r   intervalObjs           r   getIntervalSequencezPitchSieve.getIntervalSequence  s    P ##% y=U1q5\"AA ((AU(C(*!-0HAu"++EDHH,<=KKK$ 1
 %&FGGr   )NNNr)   )r  
str | Noner  r  r  r  r  zint | float)r   zlist[interval.Interval])r   r   r   r   r   r   r  r   r   r   r  r    sL     )-(,)-"#% & '	
  @>@=r   r  c                  B    e Zd Zd Zd Zd Zd Zd Zd Zd Z	d Z
d	 Zy
)Testc                (    | j                  dd       y )NT)assertEqualr   s    r   	testDummyzTest.testDummy  s    t$r   c                f    d}|D ]  }|t        |      dz   z  } |dt        |      dz
   }|dz  }|S )Nro  z, r   r(   rp  )r  ro   )r   listInoutr.   s       r   pitchOutzTest.pitchOut  sE    A3q6D= C !CHqL!s

r   c                t    t        d      }g d}|D ]$  \  }}}}t        ||      }t        ||      }||z  }& y )Nr2   ))r2   r3   r(   r4   )r   r3   r)   r2   )r4   r   r2   r(   )r   )	r   r}   testArgsr   r   r   r   r~   rX   s	            r   testIntersectionzTest.testIntersection  sC    QK?&NBBR AR AAA 'r   c           	     f    g d}|D ](  }t        |      } |dt        t        d                  }* y )N)z-5 | 4 & 4sub3 & 6 | 4 & 4z2 or 4 and 4 & 6 or 4 & 4r2   )r(   r   r3      )r)   r3   r6      r8   r      )r   r`   rN   )r   r  argtestObjdummys        r   testSieveParsezTest.testSieveParse  s2     CCjGAtE"I/E r   c                r    t        ddd      }t        d      }|j                  |j                  f} |       }y )Nz-5 | 4 & 4sub3 & 6b3zf#4)r  r  r  )r   unused_testObjr  r  s       r   testSievePitchzTest.testSievePitch  s9    #$8$F12""G$6$66	r   c                f    g d}|D ](  }t        |      }t        t        |            } |       }* y )N))r2   r3      )	r   r3   r           r  $   *   )r   r3   r7   )r(   r2   r   r4   r  	   rL   r6      r8   r9      r:   r     r;   r<   )r   r(   r   r4   r5   r  r6   r  r  r  r8   r9      r:   r  )
r)   r(   r2   r   r4   r3   r5   r  r  rL   )iir   r(   r)   )r   r   r  )r   rf  r  r  sObjr  s         r   testTimePointzTest.testTimePoint  s3     C$S)CS?DFE r   c                   t        t        d            }d}t        ||      }| j                  t	        |      d       d}t        ||      }| j                  t	        |      d       d}t        ||      }| j                  t	        |      d       d}t        ||      }| j                  t	        |      d	       d
}t        ||      }| j                  t	        |      d       y )NrK   z"3@2 & 4@1 | 2@0 & 3@1 | 3@3 | -4@2z3@2&4@1|2@0&3@1|3@0|-4@2z5-(3@2 & -4@1 & -(12@3 | 12@8) | (-2@0 & 3@1 | (3@3)))z)-{3@2&-4@1&-{12@3|12@8}|{-2@0&3@1|{3@0}}}z[(8@0 | 8@1 | 8@7) & (5@1 | 5@3)] |   [(8@0 | 8@1 | 8@2) & 5@0] | [8@3 & (5@0 | 5@1 | 5@2 | 5@3 | 5@4)] | [8@4 & (5@0 | 5@1 | 5@2 | 5@3 | 5@4)] | [(8@5 | 8@6) & (5@2 | 5@3 | 5@4)] | (8@1 & 5@2) | (8@6 & 5@1)z{{8@0|8@1|8@7}&{5@1|5@3}}|{{8@0|8@1|8@2}&5@0}|{8@3&{5@0|5@1|5@2|5@3|5@4}}|{8@4&{5@0|5@1|5@2|5@3|5@4}}|{{8@5|8@6}&{5@2|5@3|5@4}}|{8@1&5@2}|{8@6&5@1}z4(-3@2 & 4) | (-3@1 & 4@1) | (3@2 & 4@2) | (-3 & 4@3)z*{-3@2&4@0}|{-3@1&4@1}|{3@2&4@2}|{-3@0&4@3}zV(-(13@3 | 13@5 | 13@7 | 13@9) & 11@2) | (-(11@4 | 11@8) & 13@9) | (13@0 | 13@1 | 13@6)zB{-{13@3|13@5|13@7|13@9}&11@2}|{-{11@4|11@8}&13@9}|{13@0|13@1|13@6})r`   rN   r   r  r  )r   r   r1  r}   s       r   	testSievezTest.testSieve  s    s5&!Q!;<H&!Q!LMR &!QI	J H&!Q!MN)&!Q]	_r   c                    ddl m} |j                  ddd      }| j                  | j	                   |             d       |j                  dddd      }| j                  | j	                   |             d	       y )
Nr   r   z3@0|7@0r   c6z\[C2, E-2, F#2, G2, A2, C3, D3, E-3, F#3, A3, C4, E-4, E4, F#4, A4, B4, C5, E-5, F#5, A5, C6]r(   r  z5[C2, D2, F#2, C3, E3, F#3, C4, F#4, C5, F#5, G#5, C6]music21r   r  r  r  r   r   s1s      r   testPitchSieveAzTest.testPitchSieveA3  su    !it4rt,B	C it;rt,P	Rr   c                    ddl m} |j                  dddd      }| j                  | j	                   |             d       |j                  d	ddd      }| j                  | j	                   |             d
       y )Nr   r  z1@0r   r  g      ?r  a  [C2, C~2, C#2, C#~2, D2, D~2, E-2, E`2, E2, E~2, F2, F~2, F#2, F#~2, G2, G~2, G#2, G#~2, A2, A~2, B-2, B`2, B2, B~2, C3, C~3, C#3, C#~3, D3, D~3, E-3, E`3, E3, E~3, F3, F~3, F#3, F#~3, G3, G~3, G#3, G#~3, A3, A~3, B-3, B`3, B3, B~3, C4, C~4, C#4, C#~4, D4, D~4, E-4, E`4, E4, E~4, F4, F~4, F#4, F#~4, G4, G~4, G#4, G#~4, A4, A~4, B-4, B`4, B4, B~4, C5, C~5, C#5, C#~5, D5, D~5, E-5, E`5, E5, E~5, F5, F~5, F#5, F#~5, G5, G~5, G#5, G#~5, A5, A~5, B-5, B`5, B5, B~5, C6]z3@0z[C2, C#~2, E-2, E~2, F#2, G~2, A2, B`2, C3, C#~3, E-3, E~3, F#3, G~3, A3, B`3, C4, C#~4, E-4, E~4, F#4, G~4, A4, B`4, C5, C#~5, E-5, E~5, F#5, G~5, A5, B`5, C6]r  r  s      r   testPitchSieveBzTest.testPitchSieveB?  s}    ! eT4S9rt,Z	[ eT4S9rt,-	.r   N)r   r   r   r  r  r  r  r  r  r  r
  r  r   r   r   r  r    s2    %0_B
R.r   r  z
list[type]
_DOC_ORDER__main__)r(   r   )rd   zIterable[int]r   r  )r   r)   T):r   
__future__r   astr   collections.abcr   ra   mathr   r   rP   r  typingtunittestr  r   r	   r
   r   r   EnvironmentenvironLocalMusic21Exceptionr   r   r   r   r   r<  r=  rY  r]  r>  r  r;  r`   r  r  r0   r[   rk   rw   r{   r   r   r   r   r   r   r  TestCaser  r  __annotations__r   mainTestr   r   r   <module>r     s  (R #  $            &{&&w/	L11 		55 		\22 		,"?"? 		,77 	 
			
&#r3	'	#&:z>J#L&R4.l4X XxT TpU UBt  t tk kBv.8 v.| 
J zGT r   