
    "/a R                     @    d Z ddlmZ ddlmZmZ d Z G d de      Zy)a  
intervaltree: A mutable, self-balancing interval tree for Python 2 and 3.
Queries may be by point, by range overlap, or by range envelopment.

Core logic: internal tree nodes.

Copyright 2013-2018 Chaim Leib Halbert
Modifications Copyright 2014 Konstantin Tretyakov

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
    )
attrgetter)floorlogc                     t        | d      S )z$
    log base 2
    :rtype real
       )r   )nums    1lib/python3.12/site-packages/intervaltree/node.pyl2r
      s    
 sA;    c                      e Zd ZdZd e       ddfdZed        Zed        Ze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 Zd Zd Zd Zd Zd Z e       fdZd Zd Zd Z d Z!d Z"d  Z#d"d!Z$y)#Node)x_centers_center	left_node
right_nodedepthbalanceNc                     || _         t        |      | _        || _        || _        d| _        d| _        | j                          y Nr   )r   setr   r   r   r   r   rotate)selfr   r   r   r   s        r	   __init__zNode.__init__.   s;    
 !H"$
r   c                 4    |j                   }t        ||g      S )
        :rtype : Node
        )beginr   )clsintervalcenters      r	   from_intervalzNode.from_interval;   s    
 FXJ''r   c                 D    |syt         j                  t        |            S r   N)r   from_sorted_intervalssorted)r   	intervalss     r	   from_intervalszNode.from_intervalsC   s     
 ))&*;<<r   c                 B    |syt               }|j                  |      }|S r"   )r   init_from_sorted)r   r%   nodes      r	   r#   zNode.from_sorted_intervalsL   s&    
 v$$Y/r   c                    |t        |      dz     }|j                  | _        t               | _        g }g }|D ]s  }|j
                  | j                  k  r|j                  |       .|j                  | j                  kD  r|j                  |       Y| j                  j                  |       u t        j                  |      | _
        t        j                  |      | _        | j                         S )Nr   )lenr   r   r   r   endappendaddr   r#   r   r   r   )r   r%   	center_ivs_lefts_rightks         r	   r(   zNode.init_from_sortedW   s     c)n12	!Auu%a 4==(q!!!!$  33F;44W={{}r   c                 8    |j                  | j                        S )z0Returns whether interval overlaps self.x_center.)contains_pointr   r   r   s     r	   
center_hitzNode.center_hitj   s    &&t}}55r   c                 4    |j                   | j                  kD  S )zr
        Assuming not center_hit(interval), return which branch
        (left=0, right=1) interval is in.
        )r   r   r5   s     r	   
hit_branchzNode.hit_branchn   s    
 ~~--r   c                     | j                   r| j                   j                  nd}| j                  r| j                  j                  nd}dt        ||      z   | _        ||z
  | _        y)zU
        Recalculate self.balance and self.depth based on child node values.
        r      N)r   r   r   maxr   r   
left_depthright_depths      r	   refresh_balancezNode.refresh_balanceu   sQ     .2^^T^^))
/3doo++AZ55
"Z/r   c                     | j                   r| j                   j                         nd}| j                  r| j                  j                         nd}dt        ||      z   S )z
        Recursively computes true depth of the subtree. Should only
        be needed for debugging. Unless something is wrong, the
        depth field should reflect the correct depth of the subtree.
        r   r:   )r   compute_depthr   r;   r<   s      r	   rA   zNode.compute_depth~   sJ     8<~~T^^1131
9=doo335a3z;///r   c                    | j                          t        | j                        dk  r| S | j                  dkD  }| |   j                  dkD  }||k(  s| |   j                  dk(  r| j                         S | j	                         S )zj
        Does rotating, if necessary, to balance this node, and
        returns the new top node.
        r   r   )r?   absr   srotatedrotate)r   my_heavychild_heavys      r	   r   zNode.rotate   s{    
 	t||q K<<!#8n,,q0{"d8n&<&<&A <<>!<<>!r   c                 f   | j                   dkD  }| }| |   }||   | |<   | j                         ||<   ||   j                  D cg c]  }|j                  |      s| }}|r9|D ]  }||   j	                  |      ||<    |j                  j                  |       |j                          |S c c}w )z-Single rotation. Assumes that balance is +-2.r   )r   r   r   r6   removeupdater?   )r   heavylightsaveiv	promoteess         r	   rD   zNode.srotate   s     q 	E{ 5kUkkmU #'u+"6"6N"6B$//":MR"6	N"5k004U  
 MM  + Os   B.B.c                     | j                   dkD  }| |   j                         | |<   | j                          | j                         }|S r   )r   rD   r?   )r   rF   results      r	   rE   zNode.drotate   sD    <<!#h//1X r   c                 ,   | j                  |      r| j                  j                  |       | S | j                  |      }| |   s*t        j                  |      | |<   | j                          | S | |   j                  |      | |<   | j                         S )zG
        Returns self after adding the interval and balancing.
        )r6   r   r.   r8   r   r    r?   r   )r   r   	directions      r	   r.   zNode.add   s     ??8$MMh'K1I	?"&"4"4X">Y$$&"&y/"5"5h"?Y{{}$r   c                 .    g }| j                  ||d      S )z
        Returns self after removing the interval and balancing.

        If interval is not present, raise ValueError.
        Tshould_raise_errorremove_interval_helperr   r   dones      r	   rI   zNode.remove   s!     **8Td*SSr   c                 .    g }| j                  ||d      S )zv
        Returns self after removing interval and balancing.

        If interval is not present, do nothing.
        FrU   rW   rY   s      r	   discardzNode.discard   s!     **8Te*TTr   c                    | j                  |      rn|s!|| j                  vr|j                  d       | S 	 | j                  j                  |       | j                  r|j                  d       | S | j                         S | j                  |      }| |   s|rt        |j                  d       | S | |   j                  |||      | |<   |s| j                         S | S #  | j	                          t        |      xY w)aU  
        Returns self after removing interval and balancing.
        If interval doesn't exist, raise ValueError.

        This method may set done to [1] to tell all callers that
        rebalancing has completed.

        See Eternally Confuzzled's jsw_remove_r function (lines 1-32)
        in his AVL tree article for reference.
        r:   )r6   r   r-   rI   print_structureKeyErrorpruner8   
ValueErrorrX   r   )r   r   rZ   rV   rS   s        r	   rX   zNode.remove_interval_helper   s     ??8$%($--*GA) $$X. }}A ::<1I	?%$$A #9oDDXtUghDO  {{}$KA)$$&x((s   C C;c                 L    t               }|D ]  }| j                  ||        |S )zD
        Returns all intervals that overlap the point_list.
        )r   search_point)r   
point_listrQ   js       r	   search_overlapzNode.search_overlap,  s*     Aa( r   c                 4   | j                   D ]6  }|j                  |cxk  r|j                  k  s#n &|j                  |       8 || j                  k  r| d   r| d   j                  ||      S || j                  kD  r| d   r| d   j                  ||      S |S )z;
        Returns all intervals that contain point.
        r   r:   )r   r   r,   r.   r   rc   )r   pointrQ   r2   s       r	   rc   zNode.search_point5  s     Aww%'!%%'

1  4== T!W7''v66T]]"tAw7''v66r   c                     | d   r| d   s| d    }| |   }|S | d   j                         \  }| d<   | d   | d   c|d<   |d<   |j                          |j                         }|S )z}
        On a subtree where the root node's s_center is empty,
        return a new subtree with no empty s_centers.
        r   r:   )pop_greatest_childr?   r   )r   rS   rQ   heirs       r	   r`   z
Node.pruneB  s    
 Awd1g GI
 )_FM !G668MD$q' #'q'47T!Wd1g   ";;=D Kr   c                 :   	  j                   st         j                  t        dd            }|j	                         } j
                  	|rC|j	                         }|j                  |j                  k(  r,t        	|j                        	|rC	 fd}t        	 |             } xj                  |j                  z  c_         j                  r| fS | d   fS  d   j                         \  } d<   t         j                        D ]J  }|j                  |j
                        s j                  j                  |       |j                  |       L  j                  r$ j                           j                         }||fS  j!                         }||fS )a  
        Used when pruning a node with both a left and a right branch.
        Returns (greatest_child, node), where:
          * greatest_child is a new node to replace the removed node.
          * node is the subtree after:
              - removing the greatest child
              - balancing
              - moving overlapping nodes into greatest_child

        Assumes that self.s_center is not empty.

        See Eternally Confuzzled's jsw_remove_r function (lines 34-54)
        in his AVL tree article for reference.
        r,   r   )keyc               3   \   K   j                   D ]  } | j                        s|   y wN)r   r4   )rN   new_x_centerr   s    r	   get_new_s_centerz1Node.pop_greatest_child.<locals>.get_new_s_center  s'     --B((6b (s   !,,r   r:   )r   r$   r   r   popr   r,   r;   r   rj   r   r4   rI   r.   r?   r   r`   )
r   ivsmax_ivnext_max_ivrq   childgreatest_childrN   new_selfrp   s
   `        @r	   rj   zNode.pop_greatest_childk  sh      Jug,FGCWWYF==L!ggi??fjj0("<A A
 '7'9:EMMU^^+M }} d{" d1g~% )-Q(B(B(D%^T!W $--($$^%<%<=MM((,"&&r* ) }}
 $$&;;=%x//::<
 &x//r   c                     | j                   D ]  }|j                  |      s y | || j                  kD     }|xr |j                  |      S )zB
        Returns whether this node or a child overlaps p.
        T)r   r4   r   )r   prN   branchs       r	   r4   zNode.contains_point  sN     --B  #   a$--'(2&//22r   c                 4    | j                  t                     S ro   )all_children_helperr   r   s    r	   all_childrenzNode.all_children  s    ''..r   c                     |j                  | j                         | d   r| d   j                  |       | d   r| d   j                  |       |S )Nr   r:   )rJ   r   r}   )r   rQ   s     r	   r}   zNode.all_children_helper  sI    dmm$7G''/7G''/r   c           
         t        | j                  t              sJ | j                  }t	        |      dk  s&J dj                  | j                  d                   | j                          || j                  k(  s&J dj                  | j                  d                   | j                  s&J dj                  | j                  d                   | j                  D ]  }t        |d      sJ t        |d      sJ |j                  |j                  k  sJ |j                  | j                        sJ t        |      D ];  }|j                  |      sJ d	j                  ||| j                  d                     | d
   rj| d
   j                  | j                  k  s J dj                  | j                               | d
   j                  |j!                  | j                  g             | d   rk| d   j                  | j                  kD  s J dj                  | j                               | d   j                  |j!                  | j                  g             yy)zw
        ## DEBUG ONLY ##
        Recursively ensures that the invariants of an interval subtree
        hold.
        r   z5Error: Rotation should have happened, but didn't! 
{}T)tostringz*Error: self.balance not set correctly! 
{}zError: s_center is empty! 
{}r   r,   z&Error: Overlaps ancestor ({})! 
{}

{}r   z"Error: Out-of-order left child! {}r:   z#Error: Out-of-order right child! {}N)
isinstancer   r   r   rC   formatr^   r?   hasattrr   r,   overlapsr   r$   r4   verifyunion)r   parentsbalrN   parents        r	   r   zNode.verify  s:    $---.-ll3x!| 	DKK$$d$3	| 	dll" 	9@@$$d$3	"
 }} 	,33$$d$3	} --B2w'''2u%%%88bff$$$;;t}}--- /,,V4 ?FFD$8$8$$8$G4 *   77##dmm3 K4;;DMMJK3GNN7==$--9:77##dmm3 L5<<T]]KL3GNN7==$--9: r   c                 6    |r| j                   S | j                  S )zn
        Returns the left child if input is equivalent to False, or
        the right side otherwise.
        r   r   )r   indexs     r	   __getitem__zNode.__getitem__  s    
 ??">>!r   c                 &    |r|| _         y|| _        y)z%Sets the left (0) or right (1) child.Nr   )r   rm   values      r	   __setitem__zNode.__setitem__  s    #DO"DNr   c                 d    dj                  | j                  | j                  | j                        S )z
        Shows info about this node.

        Since Nodes are internal data structures not revealed to the
        user, I'm not bothering to make this copy-paste-executable as a
        constructor.
        z!Node<{0}, depth={1}, balance={2}>)r   r   r   r   r~   s    r	   __str__zNode.__str__
  s,     399MMJJLL
 	
r   c                     d}| j                   r|| j                   j                         z  }| j                  r|| j                  j                         z  }|S )zP
        Count the number of Nodes in this subtree.
        :rtype: int
        r:   )r   count_nodesr   )r   counts     r	   r   zNode.count_nodes  sJ    
 >>T^^//11E??T__0022Er   c                     |dk(  rydt        t        t        |                  z   }dt        d|z   |z
        z  }|| j	                  d|      z  S )z
        Calculates flaws in balancing the tree.
        :param n: size of tree
        :param m: number of Nodes in tree
        :rtype: real
        r   g        r:   )intr   r
   floatdepth_score_helper)r   nmdoptfs        r	   depth_scorezNode.depth_score+  sV     6 3uRU|$$a!edl##4**1d333r   c                    ||z
  }|dkD  r|t        | j                        z  }nd}| j                  r"|| j                  j                  |dz   |      z  }| j                  r"|| j                  j                  |dz   |      z  }|S )z
        Gets a weighted count of the number of Intervals deeper than dopt.
        :param d: current depth, starting from 0
        :param dopt: optimal maximum depth of a leaf Node
        :rtype: real
        r   r:   )r+   r   r   r   r   )r   dr   dir   s        r	   r   zNode.depth_score_helper:  s}     X6T]]++EE??T__77AtDDE>>T^^66q1udCCEr   c                 :   d}|dz  }t        |       |z   g}| j                  r=t        | j                        D ]%  }|j                  |dz   t	        |      z   |z          ' | j
                  rB|j                  |dz          |j                  | j
                  j                  |dz   d             | j                  rB|j                  |dz          |j                  | j                  j                  |dz   d             dj                  |      }|r|S t        |       y	)
z 
        For debugging.
        
z     z<:  r:   Tz>:   N)
strr   r$   r-   reprr   r^   r   joinprint)r   indentr   nlsprlistrN   rQ   s           r	   r^   zNode.print_structureM  s     f_TR ==T]]+R#XR0256 ,>>LLf%LL77
DIJ??LLf%LL88!TJKM&Mr   )r   F)%__name__
__module____qualname__	__slots__r   r   classmethodr    r&   r#   r(   r6   r8   r?   rA   r   rD   rE   r.   rI   r\   rX   rf   rc   r`   rj   r4   r   r}   r   r   r   r   r   r   r   r^    r   r	   r   r   %   s    I % 	 ( ( = =  &6.00"2B	%"	TU8t'RM0^3/ !U (;T"#
*
4&r   r   N)	__doc__operatorr   mathr   r   r
   objectr   r   r   r	   <module>r      s%   *   }6 }r   