
    AVh                    F   d Z ddlZddlmZmZmZmZmZm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 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 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 ddlmZ ddl m!Z! ddl"m#Z# ddl$m%Z%  G d dejL                        Z' e%d       G d dejP                               Z)de)de)de)fdZ*d e)fd!Z+d"e)d#e)fd$Z,d% Z- e#j\                  ej^                  ej^                        d&        Z0 e#jb                  ej^                  ej^                        d'        Z2d( Z3d) Z4d*ee   d+eejj                     deejj                     fd,Z6 G d- d.ejn                        Z8 G d/ d0e8      Z9 G d1 d2      Z:d3 Z;d4 Z<d5 Z=d6 Z>d7 Z?d8e8d9edee8ef   fd:Z@d8e8d;e8d9ed<edeee8e8f   f
d=ZAd8e8d;e8d9ed<edeee8e8f   f
d>ZBd8e8d;e8d9ed<edeee8e8f   f
d?ZCd@e8dAe8dBee   dCee   deee   ee8   ee8   f   f
dDZDd"e)d#e)fdEZEd"e)d#e)dCee   dFee   dGee8   dHee8   dee)e:e:f   fdIZFd"e)d#e)dee)e:e:f   fdJZGdK ZHdL ZIdM ZJdN ZKdO ZL	 dmdPeeeMeeM   f      deee   eMf   fdQZNdR ZOdS ZPdT ZQdU ZRdV ZSdWej                  dXej                  dej                  fdYZUdZ ZVee)e!j                  f   ZXd[ee   defd\ZYd]ej                  d^ej                  d_eMd`eMdeej                  ej                  f   f
daZ\dbedceeM   defddZ]deedceeM   defdfZ^dgej                  dceeM   dej                  fdhZ_dgej                  dceMdej                  fdiZ`dgej                  dceeM   dej                  fdjZaej                  dfd e)dkeec   dej^                  fdlZdy)nzShapes & broadcasting for RaggedTensors.

TODO(martinz): make this suitable for output for tf.shape
TODO(martinz): replace ragged_tensor_shape with this.
    N)AnyIterableOptionalSequenceTupleUnion)constant_op)dtypes)extension_type)ops)tensor)tensor_shape)tensor_util)	array_ops)array_ops_stack)	check_opscond)control_flow_ops)math_ops)ragged_tensor)RowPartition)RowPartitionSpec)core)dispatch)	tf_exportc                       e Zd ZdZ	 	 ddZ	 	 	 	 ddZ	 	 ddZ	 ddddeej                  e
j                  f   fdZdddeej                  e
j                  f   fd	Zy
)_DynamicRaggedShapeBatchEncoderz-A batch encoder for DynamicRaggedShape below.specDynamicRaggedShape.Specreturnc                    |j                   rzt        |j                  d   |      }|j                  D cg c]  }t        ||       }}|g|z   }t	        |j
                  |      }t        j                  |||j                        S ||j                  dk(  r-t        j                  j                  d gd|j                        S t        |j                  d      |j                        }t	        |j
                  |      }t        j                  |g||j                        S t        j                  g t        |j
                  |      |j                        S c c}w )Nr   row_partitionsstatic_inner_shapedtyper&   uniform_row_lengthr&   )num_row_partitions_batch_rp_spec_head_row_partitions_batch_rp_spec_batch_static_inner_shape_static_inner_shapeDynamicRaggedShapeSpecr&   
inner_rank_from_tensor_shaper   
_dimension_batch_tensor_shape)selfr   
batch_sizenew_headrpnew_tailnew_rpnew_static_inner_shapes           a/home/dcms/DCMS/lib/python3.12/site-packages/tensorflow/python/ops/ragged/dynamic_ragged_shape.pybatchz%_DynamicRaggedShapeBatchEncoder.batch1   sj   $T%9%9!%<jIh;?;O;OPR.Z0PhPzH$f8

"
"J 0  $$3

 %   
		A	!&&99F** :  	 $#q1** ";$$j"2!&&$:5** '  	  $$0&& 

 %  9 Qs   Ec           	         |j                   r=g }|j                  d   }|j                  d n|j                  }|j                  dd  D ]  }|3|j	                  t        d d |j                  |j                               8|j                  d n|j                  |z  }|j                  +d }|j	                  t        |d d |j                               |j	                  t        ||j                  |z  |j                  |j                                t        j                  |t        |j                  |      |j                        S t        j                  g |j                  dd  |j                        S )Nr      nrowsnvalsr)   r&   r#   )r*   r,   r)   rB   appendr   r&   rC   r0   r1   _unbatch_static_inner_shaper/   )r6   r   resultheadscaler9   rB   s          r=   unbatchz'_DynamicRaggedShapeBatchEncoder.unbatchX   sq   f!!!$d--5d4::e$$QR( '"=
--%'%:%:

	$% ((*$E0A%""*EMM '+**	&' MM ((e+')'<'<**	&'''2  $$8&&/

	 %    $$!55ab9

 %      c                 D    t         j                  ||j                        S Nr'   )r0   from_tensorr&   )r6   r   encodings      r=   decodez&_DynamicRaggedShapeBatchEncoder.decode   s    ))($**)EErJ   c                 8    t        |t        j                        S rL   )onesr
   bool)r6   r   valueminimum_ranks       r=   encodez&_DynamicRaggedShapeBatchEncoder.encode   s    
 V[[))rJ   c                     |j                   dk7  r|j                  }nd}t        j                  |j	                         t
        j                  ||j                        S )Nr   )shaper&   ragged_rankrow_splits_dtype)rankr*   r   RaggedTensorSpec_to_tensor_shaper
   rR   r&   )r6   r   rY   s      r=   encoding_specsz._DynamicRaggedShapeBatchEncoder.encoding_specs   sQ     yyA~++k k))##%kk	% %rJ   N)r   r    r!   r    )r   r    r!   r0   )r   )__name__
__module____qualname____doc__r>   rI   rO   r   r   RaggedTensor
tensor_libTensorrU   r\   
TensorSpecr^    rJ   r=   r   r   .   s    5%4%N)-)2K)VF.F 	*%* }99:;L;LLM	*%+%]++Z-B-BBC%rJ   r   zexperimental.DynamicRaggedShapec                   x   e Zd ZU dZeedf   ed<   ej                  ed<   e	j                  ed<    e       ZdZ 	 	 	 d4dee   d	ej                  d
eej$                     deddf
dZedej,                  fdeeee   ef      fd       Zed5d       Zed5d       Zed5d       Zed        Zed        Zed        Z d Z!d6dZ"d Z#de	j                  fdZ$d Z%d Z&d Z'd Z(d Z)d  Z*ed!        Z+ed"        Z,ed#        Z-d$ Z.d% Z/d& Z0d' Z1d(ed)edd fd*Z2d+ Z3d7d,Z4	 	 	 	 d8d-Z5d. Z6d/ Z7d0 Z8d9d1Z9 G d2 d3      Z:y):r0   a  The shape of a ragged or dense tensor.

  Ragged shapes are encoded using two fields:

  * `inner_shape`: An integer vector giving the shape of a dense tensor.
  * `row_partitions`: A list of `RowPartition` objects, describing how
    that flat shape should be partitioned to add ragged axes.

  If a DynamicRaggedShape is the shape of a RaggedTensor rt, then:
  1. row_partitions = rt._nested_row_partitions
     (and thus len(row_partitions) > 0)
  2. inner_shape is the shape of rt.flat_values

  If a DynamicRaggedShape is the shape of a dense tensor t, then:
  1. row_partitions = []
  2. inner_shape is the shape of t.

  Examples:

  The following table gives a few examples (where `RP(lengths)` is short
  for `RowPartition.from_lengths(lengths)`):

  Row Partitions              | Inner Shape  | Example Tensor
  --------------------------- | ------------ | ----------------------------
  []                          | [2, 3]       | `[[1, 2, 3], [4, 5, 6]]`
  [RP([2, 0, 3])]             | [5]          | `[[1, 2], [], [3, 4, 5]]`
  [RP([2, 1])]                | [3, 2]       | `[[[1, 2], [3, 4]], [[5, 6]]]`
  [RP([2, 1]), RP([2, 1, 2])] | [5]          | `[[[1, 2], [3]], [[4, 5]]]`
  .r,   _inner_shaper/   ztf.DynamicRaggedShapeNr$   inner_shaper&   validater%   c                    t        |t              st        dt        |      z         |D ],  }t        |t              rt        dt        |      z   dz          t        ||      }t        ||      }t        |t        j                        r/|j                  t        j                  k(  r|t        j                  }t        t        j                  |      }t        |D cg c]  }|j                  |       c}      }|| _        t!        j"                  ||d      | _        | j$                  j                  |k7  r%t'        j(                  | j$                  |      | _        g }| j                  rt+        | j                        D ]  \  }	}|	dkD  s| j                  |	dz
     }
d	|	dz
   d
|	 }|j,                  }|
j.                  }||||k7  rt1        |      V|sY|j3                  t5        j6                  |
j9                         |j;                         |              | j$                  j<                  j?                  d       tA        jB                  | j$                        | _"        | | jD                  jG                  |      | _"        |r|d   }|j.                  }tI        jJ                  | jD                  d         }||||k7  rOt1        d      |rB|j3                  t5        j6                  |j9                         | j$                  d   d             |rVtM        jN                  || j$                  d      | _        | j                  D cg c]  }|jQ                  |       c}| _        yyc c}w c c}w )a  Core constructor for a DynamicRaggedShape.

    Create a DynamicRaggedShape. This can be used to construct a
    DynamicRaggedShape representing a ragged or dense shape. If row_partitions
    is an empty list, then this is equivalent to a dense shape.

    If row_partitions is specified, then the num_row_partitions will be equal
    to len(row_partitions). There are several checks made.
    Specifically:
    1. Consecutive row_partitions must have consistent nvals and nrows.
    2. The last row_partitions must have nvals equal to the first element of
       inner_shape.

    The inner_shape is converted to a tensor.
    All row_partitions and the inner_shape are converted to the same dtype
    (int64 or int32).

    Args:
      row_partitions: the row_partitions of the shape.
      inner_shape: if len(row_partitions) > 0, the shape of the flat_values.
        Otherwise, the shape of the tensor.
      dtype: tf.int64, tf.int32, or None representing the preferred dtype.
      validate: if true, dynamic validation is applied to the shape.
      static_inner_shape: if len(row_partitions) > 0, the static shape of the
        flat_values. Otherwise, the static shape of the tensor. Should be
        convertible to a TensorShape.
    z@row_partitions should be a list of row partitions. Instead, got zrow_partitions contains z which is not a RowPartitionNinner_dim_sizes)
dtype_hintnamer   r@   z9RowPartitions in DynamicRaggedShape do not align between z and messagerW   z.Last row partition does not match inner_shape.inner_shape_validated)ro   ))
isinstancer   	TypeErrorstrr   _find_dtype_iterable_find_dtypenpndarrayr&   int32r
   int64tuple
with_dtyper,   r   convert_to_tensorri   r   cast	enumeratestatic_nrowsstatic_nvals
ValueErrorrD   r   assert_equalrC   rB   rX   assert_has_rankr   constant_value_as_shaper/   
merge_withr   dimension_valuer   with_dependencies_with_dependencies)r6   r$   rj   r&   rk   r%   xr9   checksaxisprevious_row_partitionmsgr   r   last_row_partitionstatic_inner_shape_nvalss                   r=   __init__zDynamicRaggedShape.__init__   sP   B nh/
L
n
   8<(2SV;67 8 	88 !7EU+E;

+RXX%%-llee,E>JRBMM%0JKN)D--,=?D%'"--(9(95AdF 4 45 N($!8#'#7#7q#A
  1H:U4&2#,/<<,&\-E|+sO#MM&&*002BHHJMNN" 	++A.*BB D%!%!9!9!D!D
"d )"-'44l!-!=!=

"
"1
%"'		!&>&J33KL
L"""((*!!!$HJ	K
 *<<
$##*ACd 372F2F,."


'd c Khs   M0M5lengthsc                 T   t        |t              st        d      |D ]  }t        |      rt        d|       |R|D cg c]  }t        |t                }}t        |      r't        |      |ddd   j                  d      z
  dz
  }nd}t        |t              st        d      |s|dkD  rt        d	      t        g g |
      S |t        |      k  st        d      |dkD  r.t        |d|dz          \  }}|g||dz   d z   }t        |||
      S t        g ||
      S c c}w )a
  Creates a shape with the given lengths and num_row_partitions.

    The lengths can either be a nonnegative int or a list of nonnegative ints.

    If num_row_partitions is None, then the minimal num_row_partitions is used.

    For example, [2, (3, 2)] is the shape of [[0, 0, 0], [0, 0]], and
    [2, 2] is the shape of [[0, 0], [0, 0]]

    This chooses the minimal num_row_partitions required (including zero).

    The following table gives a few examples (where `RP(lengths)` is short
    for `RowPartition.from_lengths(lengths)`):

    For example:
    from_lengths           | row_partitions            | inner_shape
    ---------------------- | --------------------------| -------------
    []                     | []                        | []
    [2, (3, 2)]            | [RP([3, 2])]              | [5]
    [2, 2]                 | []                        | [2, 2]
    [2, (3, 2), 7]         | [RP([3, 2])]              | [5, 7]
    [2, (2, 2), 3]         | [RP([2, 2])]              | [4, 3]
    [2, 2, 3]              | []                        | [2, 2, 3]
    [2, (2, 1), (2, 0, 3)] | [RP(2, 1), RP([2, 0, 3])] | [5]

    If we want the row partitions to end with uniform row partitions, then
    we can set num_row_partitions.

    For example,
    below URP(3, 12) is RowPartition.from_uniform_row_length(3, 12)

    from_lengths   | num_row_partitions | row_partitions           | inner_shape
    ---------------| -------------------|--------------------------|------------
    [2, (3, 2), 2] | 2                  | [RP([3, 2]), URP(2, 10)] | [10]
    [2, 2]         | 1                  | [URP(2, 4)]              | [4]
    [2, 2, 3]      | 0                  | []                       | [2, 2, 3]
    [2, 2, 3]      | 1                  | [URP(2, 4)]              | [4, 3]
    [2, 2, 3]      | 2                  | [URP(2, 4), URP(3, 12)]  | [12]



    Representing the shapes from init():

    from_lengths             | Tensor Example
    ------------------------ | ------------------------------
    `[2, 3]`                 | `[[1, 2, 3], [4, 5, 6]]`
    `[3, (2, 0, 3)]`         | `[[1, 2], [], [3, 4, 5]]`
    `[2, (2, 1), 2]`         | `[[[1, 2], [3, 4]], [[5, 6]]]`
    `[2, (2, 1), (2, 1, 2)]` | `[[[1, 2], [3]], [[4, 5]]]`

    Args:
      lengths: the lengths of sublists along each axis.
      num_row_partitions: the num_row_partitions of the result or None
        indicating the minimum number of row_partitions.
      dtype: the dtype of the shape (tf.int32 or tf.int64).

    Returns:
      a new DynamicRaggedShape
    zlengths should be a listz;element of lengths should be int or tuple of ints: instead NrW   Tr@   r   z+num_row_partitions should be an int or Nonez(num_row_partitions==0 for a scalar shaper'   zMnum_row_partitions should be less than `len(lengths)` if shape is not scalar.)
rs   listr   _is_int_or_tuple_of_intsintanylenindexr0   )_to_row_partitions_and_nvals_from_lengths)	clsr   r*   r&   r   is_listr$   rC   rj   s	            r=   from_lengthszDynamicRaggedShape.from_lengths4  sd   @ gt$122 %a( 	 !189AZ3''9g9	W \GBFFO,A,A$,GG!K(#.DEE	a	CDDBe44G, 1 2 2 A I
)%)
*!,~uGg&81&<&=>>k5IIG5993 :s   D%c                 `    |st        d      |d   j                         g}t        |||      S )zCreate a shape from row_partitions.

    Args:
      row_partitions: a nonempty list of RowPartition objects.
      dtype: the dtype to use, or None to use the row_partitions dtype.

    Returns:
      a DynamicRaggedShape with inner_rank==1.
    zrow_partitions cannot be emptyrW   r'   )r   rC   r0   )r   r$   r&   rj   s       r=   from_row_partitionsz&DynamicRaggedShape.from_row_partitions  s8     788!"%++-.KnkGGrJ   c                     t        g ||      S )z?Create a shape from inner_shape, where num_row_partitions == 0.r'   )r0   )r   rj   r&   s      r=   _from_inner_shapez$DynamicRaggedShape._from_inner_shape  s     b+U;;rJ   c                     t        j                  |      r!t        |j                  t	        |      |      S t        j                  t        j                  |      |      S )z:Constructs a ragged shape for a potentially ragged tensor.r'   )r   	is_raggedr0   _nested_row_partitions_flat_values_shaper   r   rX   )r   tr&   s      r=   rM   zDynamicRaggedShape.from_tensor  s\     q!

"
"$6q$9H H  11
//!
E 2 + +rJ   c                     | j                   S )z The row_partitions of the shape.)r,   r6   s    r=   r$   z!DynamicRaggedShape.row_partitions  s     rJ   c                 ,    t        | j                        S )z*The number of row_partitions of the shape.r   r,   r   s    r=   r*   z%DynamicRaggedShape.num_row_partitions  s     t##$$rJ   c                 .    | j                   j                  S )z6The dtype of the shape -- one of tf.int32 or tf.int64.ri   r&   r   s    r=   r&   zDynamicRaggedShape.dtype       """rJ   c                 z    | j                   j                  dgS | j                   j                         }|r|dd S |S )zAReturns the lengths of the inner shape (if rank known), or [...].N.r@   )r/   r[   as_list)r6   truncate_firstrF   s      r=   _static_inner_shape_as_listz.DynamicRaggedShape._static_inner_shape_as_list  sC    $$,Ul%%--/FABZMrJ   c                 N   | j                   dk(  r| j                  d      S | j                  d   j                  }t	        |t
        j                        r|j                  }|g}| j                  D ]  }|j                         r|j                  |j                         /|r`t        j                  |j                               }||j                  d       h|j                  t        |j                                      |j                  d        || j                  d      z   S )a  Returns a list of statically known axis lengths.

    This represents what values are known. For each row partition, it presents
    either the uniform row length (if statically known),
    the list of row lengths, or none if it is not statically known.
    For the inner shape, if the rank is known, then each dimension is reported
    if known, and None otherwise. If the rank of the inner shape is not known,
    then the returned list ends with an ellipsis.

    Args:
      ragged_lengths: If false, returns None for all ragged dimensions.

    Returns:
      A Sequence[Union[Sequence[int],int, None]] of lengths, with a possible
      Ellipsis at the end.
    r   FNT)r*   r   r$   r   rs   r   	DimensionrS   
is_uniformrD   static_uniform_row_lengthr   constant_valuerow_lengthsr|   tolist)r6   ragged_lengths	first_dimrp_dimsr9   
const_valss         r=   static_lengthsz!DynamicRaggedShape.static_lengths  s    " !#--e44##A&33I)\334//ikG!! 
	r334 //0@A

..

..z0023
4t
 T55d;;;rJ   c                 Z    t        | j                               }d|d| j                  dS )Nz<DynamicRaggedShape lengths=z num_row_partitions=>)_list_with_ellipsis_to_strr   r*   r6   r   s     r=   __repr__zDynamicRaggedShape.__repr__  s,    ()<)<)>?G d--/ 0rJ   r!   c                     | j                  d      }|st        j                  d      S |d   t        k(  rt        j                  d      S t        j                  |      S )z2Returns a TensorShape representation of the shape.F)r   rg   rW   N)r   r   TensorShapeEllipsisr   s     r=   r]   z#DynamicRaggedShape._to_tensor_shape  sW    !!!7G%%b))r{h%%d++##G,,rJ   c                    ||k  rt         j                  g       S |dk(  r|| j                  k  rh|dk(  r1t         j                  | j                  d   j	                         g      S | j                  d|dz
   }|d   j                         g}t        ||      S | j                  7|| j                  z
  }| j                  d| }t        | j                  |dd      S | j                  |k  r| S || j                  z
  }| j                  d| }t        | j                  |t        j                  dg|z        d      S | j                  || j                  k  r| j                  d|      }n| }|j                  D ]  }|j                         rt        d       |j                  t        d      t         j                  |j                  d      j                  |d       S )	aH  Returns a shape self[start:stop].

    If start == 0, then this truncates dimensions after stop.
    If start != 0, then this will return a shape with num_row_partitions == 0.

    See __getitem__.

    Args:
      start: the first dimension. 0 <= start <= rank
      stop: the last dimension (exclusive). 0 <= stop <= rank
    r   r@   NrW   F)r$   rj   r%   rk   z'All relevant dimensions must be uniformz7__getitem__[start:stop] where start > 0 not implemented)r0   r   r*   r$   rB   rC   r[   rj   r   r   _slice_shaper   r   NotImplementedError_with_num_row_partitions)r6   startstopnew_row_partitionsnew_inner_shapenew_inner_rankpartialr   s           r=   r   zDynamicRaggedShape._slice_shape  s    u}11"55	!	((	(19#55""1%++-.0 0!00$(;-b1779:!"4oFF99$"9"99. ,,_n=/#!00)!%	  YY$+ 7 77**?N;!..'+778F9G  H 	 
	dTYY.##At,%% F!||~DE
EF 
	 "EG 	G  11

*
*1
-
9
9%&
AC CrJ   c                 j   | j                   }t        |t              st        d      | j                  dk(  s|| j                  dz   kD  r8|t        d      ||k\  r&t        dt        |      z   dz   t        |      z         |dk  rt        dt        |      z         | j                  |      st        dt        |      z   d	z         |dk(  rh| j                  dkD  rY| j                  d   j                  }|!t        j                  || j                  
      S | j                  d   j                         S | j                  dk(  rTt        j                   | j"                  |         }|!t        j                  || j                  
      S | j$                  |   S || j                  kD  rnt        j                   | j"                  || j                  z
           }|!t        j                  || j                  
      S | j$                  || j                  z
     S | j                  |dz
     j'                         S )zEReturn a dimension, if the dimension is not ragged (see __getitem__).zindex should be an intr   r@   7Rank must be known to use __getitem__ on a large index.zIndex is too big: z>=zIndex must be non-negative: zIndex z is not uniformr'   )r[   rs   r   rt   r*   r   
IndexErrorru   r   r$   r   r	   constantr&   rB   r   r   r/   rj   r)   )r6   r   r[   r   static_results        r=   r4   zDynamicRaggedShape._dimensionA  s   99DeS!.//1$0G0G!0K(K 
EG 	G	$-E
:TACIMNNqy5E
BCC__U#x#e*,/@@AA	!//!3((+88l		!##L

CC  #))++		 	 A	%"22

"
"5
)+m		"##MDDe$$	((	("22

"
"54+B+B#B
CEm		"##MDDed&=&==>>  +>>@@rJ   c                    | j                   }t        |t              rw|j                  |j                  dk7  rt	        d      |j
                  }|j                  }|d}t        ||| j                        }t        ||      }| j                  ||      S t        |t              r7|dk  r!|t        d      | j                  ||z         S | j                  |      S t        d      )a  Returns a dimension or a slice of the shape.

    Ragged shapes can have ragged dimensions that depend upon other dimensions.
    Therefore, if you ask for a dimension that is ragged, this function returns
    a ValueError. For similar reasons, if a slice is selected that includes
    a ragged dimension without including the zero dimension, then this fails.

    Any slice that does not start at zero will return a shape
    with num_row_partitions == 0.

    Args:
      index: the index: can be an int or a slice.

    Raises:
      IndexError: if the index is not in range.
      ValueError: if the rank is unknown, or a ragged rank is requested
      incorrectly.
    r@   zCannot stride through a shaper   z<Rank must be known to use __getitem__ with a negative index.z!Argument is not an int or a slice)r[   rs   slicestepr   r   r   _fix_start_indexr*   _fix_stop_indexr   r   r   r4   rt   )r6   r   r[   r   r   s        r=   __getitem__zDynamicRaggedShape.__getitem__g  s    & 99D%
**
 uzzQ899kkeZZd	udD,C,CDeT4(dud++	E3		<LN Nte|,,__U##9::rJ   c                 @    t        j                  | j                        S )z]Number of elements in a shape.

    Returns:
      The number of elements in the shape.

    )r   reduce_prodrj   r   s    r=   _num_elementsz DynamicRaggedShape._num_elements  s      0 011rJ   c                 \   t        |t              st        d      |dk  r| j                  }|t	        d      ||z   }|dk(  r| j                  d      S || j                  k  r | j                  |dz
     j                         S || j                  dz
  z
  }t        | j                  d|       S )ae  The total size of a dimension (like nvals).

    Effectively, this is self[:axis+1]._num_elements()

    Example:
    shape = DynamicRaggedShape._from_inner_shape([2, 3, 4])
    shape._num_slices_in_dimension(0) = 2
    shape._num_slices_in_dimension(1) = 6
    shape._num_slices_in_dimension(2) = 24
    shape._num_slices_in_dimension(-1) = 24
    shape._num_slices_in_dimension(-2) = 6
    shape._num_slices_in_dimension(-2) = 2

    Args:
      axis: the last axis to include in the number of elements. If negative,
        then axis = axis + rank.

    Returns:
      The number of elements in the shape.
    axis must be an integerr   Nz6You can't use negative values if the rank is undefinedr@   )rs   r   rt   r[   r   r4   r*   r$   rC   _reduce_prod_patchrj   )r6   r   r[   	remainders       r=   _num_slices_in_dimensionz+DynamicRaggedShape._num_slices_in_dimension  s    * dC /00axYYd	DF 	FD[dqy__Qt&&&  *0022 //!34Id..z	:;;rJ   c                 "   t        |t              st        d      | j                  }|dk  rt	        d      |||k\  rt	        d|d|      |dk(  xs |t        | j                        kD  xs  | j                  |dz
     j                         S )z3Returns true if the indicated dimension is uniform.r   r   z&Negative axis values are not supportedzExpected axis=z < rank=r@   )rs   r   rt   r[   r   r   r,   r   )r6   r   r[   s      r=   r   zDynamicRaggedShape.is_uniform  s    dC /0099Dax?@@		ddltTBCCqy<D3t';';#<< =%%dQh/::<>rJ   c                 >    | j                   }|y| j                  |z   S )z;The number of dimensions in this shape, or None if unknown.Nr2   r*   r6   r2   s     r=   r[   zDynamicRaggedShape.rank  s'     J$$z11rJ   c                     | j                   S )zZThe inner dimension sizes for this shape.

    Returns:
      A 1-D integer `Tensor`.
    )ri   r   s    r=   rj   zDynamicRaggedShape.inner_shape  s     rJ   c                 T    t        j                  | j                  j                        S )zThe rank of inner_shape.)r   r   r/   r[   r   s    r=   r2   zDynamicRaggedShape.inner_rank  s!     ''(@(@(E(EFFrJ   c                    |dk(  rt        d      | j                  dk(  rt        d      || j                  k(  r| j                  S || j                  k  r| j                  j	                         r!t        | j                  | j                  |      S | j                  |       }|dk(  rt        j                  |d      S | j                  d|z
  d }t        j                  t        j                  |d      |gd      S || j                  kD  sJ || j                  z
  }t        | j                  | d D cg c]  }|j                           c}      rt        d      | j                  |       }|| j                  z
  }|g| j                  | d D cg c]  }|j                          c}z   }t        j                  t        j                   |      | j                  dd gd      S c c}w c c}w )a5  Get an alternative inner shape with higher or lower rank.

    For the rank of the inner shape to be be higher, the last few ragged
    dimensions must have uniform_row_length.

    Args:
      new_inner_rank: the new rank of the inner_shape

    Returns:
       A new inner_shape of rank new_inner_rank.
    r   znew_inner_rank cannot be zerozold inner_rank cannot be zeror@   Nr   z1Cannot get an inner shape over a ragged dimension)r   r2   rj   r/   is_fully_defined"_alt_inner_shape_from_tensor_shaper&   r   r   expand_dimsconcatr   r$   r   r)   r   stack)r6   r   first_dimensionremaining_dimensionsnew_dimensionsr   new_dimss          r=   _alt_inner_shapez#DynamicRaggedShape._alt_inner_shape  s    677	A	677	4??	*	$//	)		!	!	2	2	41$2J2J26**nN 	N55~oFo	1	$$_a88!--a..@.AB  !46J
K  doo---%7n	'+':':N?;K'L
M!q||~
M
OLMM55~oFo%7n!"*.*=*=~o>N*O&%&!


 & h   *D,<,<QR,@
AK K N&s   3G'G,c                 l    t        j                  | j                  |         }|| j                  |   S |S )z@Returns an int or a tensor representing _inner_shape[dimension].)r   r   r/   ri   )r6   	dimensionrF   s      r=   _inner_shape_dimz#DynamicRaggedShape._inner_shape_dim  s7    ))$*B*B9*MNF+1>4Y'EvErJ   c                     | j                   }|t        d      |dk  r||k(  r| S t        d      ||z
  }| j                  |      S )at  Returns the same shape but a different inner_rank.

    All dimensions that are to be represented in the inner_shape must be dense.
    See inner_rank.

    Args:
      inner_rank: the new inner_rank of the shape.

    Returns:
      the same shape but a different inner_rank

    Raises:
      ValueError if the new dense rank is invalid, or the old rank is unknown.
    z'Rank must be known to adjust inner_rank   z$Cannot change inner_rank if rank < 2)r[   r   r   )r6   r2   r[   new_num_row_partitionss       r=   _with_inner_rankz#DynamicRaggedShape._with_inner_rank  s]     99D|@AA		t	=>>  $j0**+ABBrJ   c                    | j                   }|t        d      t        |t              st        d      |dk  rt        d      || j                  k(  r| S ||k\  rt        d      || j                  kD  r|| j                  z
  }| j                   |z
  }| j                  d      }g }t        |      D ]P  }|}| j                  |dz         }	||	z  }t        j                  |	|| j                        }
|j                  |
       R | j                  |      }t        t        | j                        |z   |      S || j                  k  sJ t        | j                  d| | j                  | j                   |z
              S )	a  Creates an identical shape with the given num_row_partitions.

    Note that the shape must be statically refactorable to this rank.
    In particular:
    * rank must be known.
    * num_row_partitions must be a nonnegative int.
    * num_row_partitions must be less than the rank of the shape
    * num_row_partitions must be greater or equal to the index of any ragged
    dimension.

    Note that if the num_row_partitions is the same, self is returned.

    Args:
      num_row_partitions: the target num_row_partitions (must be a nonnegative
        int).

    Returns:
      a shape with a (possibly) different num_row_partitions.

    Raises:
      ValueError: if the rank is unknown, the argument is not a nonnegative int,
        or there is a dimension that is nonuniform.
    Nz/Rank must be known to adjust num_row_partitionsz!num_row_partitions must be an intr   z&num_row_partitions must be nonnegative)num_row_partitions must be less than rankr@   )rB   r&   )r[   r   rs   r   r*   r   ranger   from_uniform_row_lengthr&   rD   r   r0   r   r$   )r6   r*   r[   num_row_partitions_diffr   rC   more_rpirB   
row_lengthr9   	alt_inners               r=   r   z+DynamicRaggedShape._with_num_row_partitions5  s   0 99D|HII(#.:;;A?@@T444kT!BCCD333 2T5L5L Lyy#55n##A&eg,- !**1q51

"11e4::7r ''7iT%8%8 9G CYOO$"9"9999


11
2


		,> >
?A ArJ   
outer_axis
inner_axisc                    t        j                  || j                  dd      }t        j                  || j                  dd      }||k  st        d| d| d      ||k(  r| S | j                  dk(  r>t        | j                  | j                  ||      \  }}t        g || j                  |	      S || j                  k  r|dk(  r:t        | j                  |d
 | j                  | j                  | j                  	      S | j                  d
|dz
   }| j                  |d
 }| j                  |dz
  | }|t        |      fz   |z   }t        || j                  | j                  | j                  	      S || j                  kD  rbt        | j                  | j                  || j                  z
  || j                  z
        \  }}t        | j                  || j                  |	      S | j                  }	|	t        d      |dk(  r)| j                  |	|z
        }t        j                  |      S | j                  d
|dz
   }
t        | j                  |dz
  d
       }| j                  |	|z
        }|| j                  z
  }t        | j                  d|dz          }t!        j"                  |j%                         |z        }t        |
|fz   |      S )a1  Merges outer_axis...inner_axis into a single dimension.

    Returns a copy of this shape with the specified range of dimensions
    flattened into a single dimension, with elements in row-major order.

    #### Examples:

    >>> tf.experimental.DynamicRaggedShape.from_lengths([2, (2,1),
    ...     (1,2,3)])._merge_dims(0, 1)
    <DynamicRaggedShape lengths=[3, (1, 2, 3)] num_row_partitions=1>
    >>> tf.experimental.DynamicRaggedShape.from_lengths([2, (2,1),
    ...     (1,2,3)])._merge_dims(1, 2)
    <DynamicRaggedShape lengths=[2, (3, 3)] num_row_partitions=1>
    >>> tf.experimental.DynamicRaggedShape.from_lengths([2, (2,1),
    ...     (1,2,3)])._merge_dims(0, 2)
    <DynamicRaggedShape lengths=[6] num_row_partitions=0>

    To mimic the behavior of `np.flatten` (which flattens all dimensions), use
    `rt.merge_dims(0, -1).  To mimic the behavior of `tf.layers.Flatten` (which
    flattens all dimensions except the outermost batch dimension), use
    `rt.merge_dims(1, -1)`.

    Args:
      outer_axis: `int`: The first dimension in the range of dimensions to
        merge. May be negative if `self.shape.rank` is statically known.
      inner_axis: `int`: The last dimension in the range of dimensions to merge.
        May be negative if `self.shape.rank` is statically known.

    Returns:
      A copy of this shape, with the specified dimensions merged into a
      single dimension.  The returned shape will be
      `self.shape[:outer_axis] + [N] + self.shape[inner_axis + 1:]`, where `N`
      is the total number of slices in the merged dimensions.
    r  z
rank(self))	axis_name
ndims_namer  zExpected outer_axis (z*) to be less than or equal to inner_axis (z).r   )r&   r%   Nr@   zOCannot merge_dims of the inner shape if the dimension of inner_shape is unknown)r   get_positive_axisr[   r   r*   _merge_inner_shaperi   r/   r0   r&   r,   rj   _merge_row_partitionsr   r   r   r   from_row_splits
row_splits)r6   r  r  r   r<   	prefix_rp	suffix_rpinternal_rpr;   r[   prefixsuffixnum_merged_innerprodtail_suffixs                  r=   _merge_dimszDynamicRaggedShape._merge_dimsl  s   H ,,DII,PJ,,DII,PJ#.zl ;//9l"> ? ?Zk!# "4D4E4E484L4L4>
"L   /&*jj3IK K T,,, 
q!  -**#77	9 	9
 &&
Q7i&&z{3i((a
Ck1+>@@9Lf





!55	7 7
 
d--	- 3E


T55
t..
.
t..
.30/.  





3	5 5 YYd	 ? @ 	@	q//z0AB!33ODD%%ozA~6&t';';JNO'LM//z0AB%(?(??!$"3"3A6F6J"KL"2263D3D3F3MN!&K>"9?KKrJ   c                 h    || j                   k(  r| S t        | j                  | j                  |      S )zChange the dtype of the shape.r'   )r&   r0   r$   rj   r6   r&   s     r=   r}   zDynamicRaggedShape.with_dtype  s3    

k


t//u> >rJ   c                    t        | j                  |j                        }| j                  |      }|j                  |      }t        |j                  |j                        D cg c]  \  }}|j                  |       }}}|j                  t        j                  k(  r|j                  nt        j                  }|j                  j                  |j                        }	|j                  }
t        ||
|d|	      S c c}}w )a  Merge two shapes that are equal modulo num_row_partitions.

    The resulting num_row_partitions is the maximum of the two
    num_row_partitions.

    Args:
      other: a DynamicRaggedShape representing the same shape with a possibly
        different number of row partitions.

    Returns:
      A DynamicRaggedShape with the same shape and the maximum of the
      num_row_partitions of the two shapes.
    T)maxr*   r   zipr,   _merge_precomputed_encodingsr&   r
   rz   r{   r/   r   ri   r0   r6   othermax_num_row_partitionsabrp_arp_br   	new_dtyper<   r   s              r=   _merge_withzDynamicRaggedShape._merge_with  s     !!8!8!&!9!9;%%&<=A&&'=>A   1 113D3DET4 	))$/  77fll2I22==	nnO0/9"$:< <   &C=c                    t        | j                  |j                        }| j                  |      }|j                  |      }t        |j                  |j                        D cg c]  \  }}|j                  |       }}}|j                  t        j                  k(  r|j                  nt        j                  }|j                  j                  |j                        }	|j                  }
t        ||
|d|	      S c c}}w )z'Merge a spec with a DynamicRaggedShape.T)r  r*   r   r  r,   _merge_with_specr&   r
   rz   r{   r/   r   ri   r0   r  s              r=   r*  z#DynamicRaggedShape._merge_with_spec  s     !!8!8!&!9!9;%%&<=A&&'=>A   1 113D3DET4 	d#  77fll2I22==	nnO0/9"$:< <r(  c                     | j                   }|t        d      |dk  rt        d      | j                  |dz
        }|j                  S )aE  Returns row partitions representing this shape.

    In order to represent a shape as row partitions, the rank of the shape
    must be known, and the shape must have rank at least one.

    Returns:
      A list of RowPartition objects.
    Raises:
      ValueError, if the shape cannot be represented by RowPartitions.
    z)rank must be known for _as_row_partitionsr@   z(rank must be >= 1 for _as_row_partitions)r[   r   r   r$   )r6   r[   fully_raggeds      r=   _as_row_partitionsz%DynamicRaggedShape._as_row_partitions  sQ     99D|BCC	ABB00:L&&&rJ   c                     | j                   rlt        j                  | j                   d   j                         t	        j
                  || j                        d   d      }t        j                  |g|      S |S )z5Test if flat_values have the right nvals dynamically.rW   )out_typer   .Last row partition does not match flat_values.rp   )	r$   r   r   rC   r   rX   r&   r   r   )r6   flat_values	assert_ops      r=   !_validate_flat_values_dynamicallyz4DynamicRaggedShape._validate_flat_values_dynamically%  sj    ((


b
!
'
'
)
//+


;A
>BDi //[IIrJ   c                    t        |t        j                        s|S | j                  r| j                  d   }|j                  }|| j                  |      S |d   }t        |t        j                        r|j                  }|| j                  |      S |j                  }|| j                  |      S ||k7  rt        d      |S )z)Test if flat_values have the right nvals.rW   r   r0  )rs   rd   re   r$   rX   r3  r   r   rS   r   r   )r6   r1  r   flat_values_shapefirst_dim_flat_valuesr   s         r=   _validate_flat_valuesz(DynamicRaggedShape._validate_flat_values/  s    k:#4#45..r2%++		"55kBB/2	)<+A+A	B 5 ; ;		&55kBB'44l		55kBB	,	.IJJrJ   c                     | j                   r?|r| j                  |      }t        j                  j	                  || j                   d      S |S )a  Add row partitions to flat_values, if necessary.

    If the shape is truly ragged, then this adds the row_partitions.

    The shape is dense, then this just returns flat_values.

    Args:
      flat_values: the flat_values of a ragged tensor with this shape, or a
        dense tensor with this shape.
      validate: validate the flat_values have the right first dimension.

    Returns:
      flat_values reshaped to have row_partitions.
    Frk   )r$   r7  r   rc   _from_nested_row_partitions)r6   r1  rk   s      r=   _add_row_partitionsz&DynamicRaggedShape._add_row_partitionsD  sT     	00=''CC
t**U D < < rJ   c            	       D    e Zd ZdZdeedf   dej                  dej                  fdZ
d Zeded	d f fd
       Zedededej                  d	d fd       Zeej"                  fded ej(                  ej,                  f   dej                  d	d fd       Zed	ej                  fd       Zed	ee   fd       Zed	efd       Zed	ee   fd       Zded	ee   fdZded	ee   fdZdej                  d	d fdZ 	 	 	 	 d dZ!ded	d fdZ"ded	d fdZ#ded	d fdZ$d Z% xZ&S )!r    z9A Spec for DynamicRaggedShape: similar to a static shape.r$   .r%   r&   c                    t        |t              st        d      t        |      }t	        j
                  |      }t        j                  |      }t        d |D              st        d      |t        j                  k7  r|t        j                  k7  rt        d      |D ]/  }|j                  |k7  st        d|d|j                  d|       t        |      }|j                  }|dk(  r|rt        d	      g }t        t        |            D ]  }||   }t	        j                   |j"                        }	|dkD  rD||d
z
     }
|	j%                  |
j&                        }	|	j%                  |d   |
j(                  z        }	|j+                  |	        |rp|d   }|d   |j(                  z  j%                  |j&                        }	|-|	j%                  t	        j,                  |d            }	|	|d
d z   }|j+                  |	       t        t        |      d
z
  dd      D ]<  }||d
z
     j%                  t/        ||   ||d
z
     j(                              ||d
z
  <   > t1        |      D cg c]E  \  }}t3        ||   j4                  |j(                  ||d
z      j4                  |j                        G }}}|| _        t9        j:                  |g|      | _        || _        yc c}}w )aY  Create a Spec given row partitions, a static inner shape, and a dtype.

      Args:
        row_partitions: A sequence of `RowPartitionSpec`s describing how the
          ragged shape is partitioned.
        static_inner_shape: The static shape of the flat_values.
        dtype: The DType used to encode the shape (tf.int64 or tf.int32).
      z$row_partitions should be an Iterablec              3   <   K   | ]  }t        |t                y wN)rs   r   ).0r9   s     r=   	<genexpr>z3DynamicRaggedShape.Spec.__init__.<locals>.<genexpr>s  s     KbB 01Ks   z9row_partitions should be an Iterable of RowPartitionSpecs"dtype must be tf.int32 or tf.int64z	dtype of z is z: expected r   z8If row_partitions are provided, must have inner_rank > 0r@   rW   N)rB   r)   rC   r&   r'   ) rs   r   rt   r|   r   as_shaper
   as_dtypeallrz   r{   r   r&   r[   r   r   r   rB   r   rC   r)   rD   dimension_at_index_safe_floor_divr   r   rS   r/   rd   rf   ri   r,   )r6   r$   r%   r&   r   r2   num_slices_in_dimensionr  r9   rF   previous_rplast_rps               r=   r   z DynamicRaggedShape.Spec.__init__^  s&    1>??^,n'001CDooe$eKNKKGI 	I 
&,,	5FLL#8=>> ! J$::$djj^;uiHJ JJ
 ^,n%**j	qHJ J #%
 s>*+ 	1Aa "))"((3&U(Q/K&&{'8'89F&&'>r'B'2'E'E(F GF
!
(
(
0	1 "2&'+B/../0:
7==0I #&&//0BAFHF!'*<QR*@!@
!
(
(
0 s23a7B? 	MA+B!e,Z!"9!"<"0Q"7"J"JLM "!a%
(	M .7~-F

 %*Ar	 -a066#%#8#8-a!e4::hh	 
 
 "4d$//EJd+d
s   .A
K'c                 f    d| j                   dd| j                  dz   d| j                  dz   S )Nz'DynamicRaggedShape.Spec(row_partitions=, zstatic_inner_shape=zdtype=))r,   r/   r&   r   s    r=   r   z DynamicRaggedShape.Spec.__repr__  sG    3D4H4H3K2
N 8 8;2
>?4::.
"#$rJ   rS   r!   c                     t         t        j                  |   |      }t        j                  |j                  |j
                  |j                  j                        S )z(Create a Spec from a DynamicRaggedShape.r#   )superr0   r1   
from_valuer,   r/   ri   r&   )r   rS   initial	__class__s      r=   rP  z"DynamicRaggedShape.Spec.from_value  sX    
 (--s>uEg  $$ 00$88$$** % , ,rJ   rX   r*   c           	      6   |t         j                  k7  r|t         j                  k7  rt        d      t	        j
                  |      }|j                  Mt        |      D cg c]  }t        |       }}t        j                  |t	        j                  d      |      S |j                  dk  r%|rt        d      t        j                  g ||      S |j                  |k  rt        d      t	        j                  |d         }g }t        |      D ]I  }t	        j                  ||dz            }	|	|d}
n||	z  }
|j                  t        ||
|	|	             |
}K t	        j                  |g      ||dz   d z   }t        j                  |||      S c c}w )
a  Creates a `DynamicRaggedShape.Spec` corresponding to a `tf.TensorShape`.

      It is assumed that this is a `tf.TensorShape` coming from a
      `tf.TensorSpec`, not from `RaggedTensor.shape`.

      In addition to the shape, we need to know the number of row partitions,
      and the dtype used in the shape (tf.int32 or tf.int64).

      Within the dimensions that are partitioned, all dimensions are assumed
      to be uniform.

      Args:
        shape: a TensorShape.
        num_row_partitions: the ragged rank of the RaggedShape.
        dtype: the dtype of the shape (not the tensor); tf.int64 or tf.int32.

      Returns:
        a DynamicRaggedShape.Spec representing a TensorShape.
      rB  Nr'   r#   r@   zAnum_row_partitions should be zero if shape is a scalar or vector.r   r   rA   )r
   rz   r{   r   r   rC  r[   r   r   r0   r1   r   r   rD   )r   rX   r*   r&   _r$   num_elements_so_farrp_specsr  current_dimrC   r%   s               r=   r3   z*DynamicRaggedShape.Spec._from_tensor_shape  s   , 
&,,	5FLL#8=>>##E*e		389K3L
./5)
 
 "&&)+77= '  	
 
q = > >!&&%u ' F 	F 
)	)DEE(88qBh'( $!"225Q<@"5"=%%3%)#.		 $$ (33
!#();a)?)@#AB$$!/ %  K
s    Fr   c                 B   t        |t        j                        r|S t        |t        j                        r1| j                  |j                  |j                  |j                        S t        |t        j                        r| j                  |j                  d|      S y)a#  Create a TypeSpec for the shape of an object with a given TypeSpec.

      I.e., if `x_spec = tf.type_spec_from_value(x)`, then
      `DynamicRaggedShape.from_spec(x_spec)` returns a TypeSpec compatible with
      `tf.type_spec_from_value(tf.shape(x))`.

      >>> rt = tf.ragged.constant([[1, 2], [3], [4, 5, 6]])
      >>> rt_spec = tf.type_spec_from_value(rt)
      >>> rt_shape = DynamicRaggedShape.from_tensor(rt)

      >>> shape_spec_1 = tf.type_spec_from_value(rt_shape)
      >>> shape_spec_2 = DynamicRaggedShape.Spec._from_spec(rt_spec)
      >>> assert shape_spec_1.is_compatible_with(shape_spec_2)

      Args:
        spec: a Spec of a Tensor or RaggedTensor.
        dtype: the default dtype (if necessary).

      Returns:
        A Spec of the shape of a Tensor or RaggedTensor.

      r   )rX   r*   r&   N)rs   r0   r1   r   r\   r3   rX   rY   rZ   rd   rf   )r   r   r&   s      r=   
_from_specz"DynamicRaggedShape.Spec._from_spec  s    : 
D,11	2dM::;%%djj$2B2B&*&;&;= 	=dJ112%%**% & A 	A 3rJ   c                 .    | j                   j                  S r?  r   r   s    r=   r&   zDynamicRaggedShape.Spec.dtype?  s    $$$rJ   c                     | j                   j                  | j                   j                  S | j                  j                  j                  y t	        j
                  | j                  j                  d         S Nr   )r/   r[   ri   rX   r   r   r   s    r=   r2   z"DynamicRaggedShape.Spec.inner_rankC  sc    		!	!	&	&	2'',,,				 	 	%	%	-))$*;*;*A*A!*DEErJ   c                 ,    t        | j                        S r?  r   r   s    r=   r*   z*DynamicRaggedShape.Spec.num_row_partitionsK  s    %%&&rJ   c                 @    | j                   }|d S || j                  z   S r?  r   r   s     r=   r[   zDynamicRaggedShape.Spec.rankO  s&    ??j'TQZ$:Q:Q-QQrJ   r   c                    |dk(  rn| j                   r| j                   d   j                  S | j                  y| j                  dk(  rt        d      t	        j
                  | j                  d         S |t        | j                         k  r| j                   |dz
     j                  S || j                  z
  }| j                  y| j                  |k  rt        d| d      t	        j
                  | j                  |         S )z5Get the size of dimension index, if known statically.r   NzIndex out of range: 0.r@   zIndex out of range: .)
r,   rB   r2   r   r   r   r/   r   r)   r*   )r6   r   relative_indexs      r=   r4   z"DynamicRaggedShape.Spec._dimensionT  s    	!%%a(..
.__$__!34
4--d.F.Fq.IJ
J	#d**+	+##EAI.AAAt666n		 ??n,/wa899++$$^46 	6rJ   r   c                 `   t        |t              st        d      t        j                  || j
                  d      }|dk(  r| j                  d      S || j                  k  r| j                  |dz
     j                  S || j                  dz
  z
  }| j                  d| }|j                         S )au  The total size of a dimension (like nvals).

      This is a static version of DynamicRaggedShape._num_slices_in_dimension()

      Example:

      ```
      shape = DynamicRaggedShape.Spec(
        _row_partitions=[
          RowPartitionSpec(nrows=3, nvals=14, dtype=tf.int32)
          RowPartitionSpec(nrows=14, nvals=25, dtype=tf.int32)

        ],
        _static_inner_shape=tf.TensorShape([25, 3, 4]),
        _inner_shape=tf.TensorSpec(tf.TensorShape([3]), dtype=tf.int32))
      shape._num_slices_in_dimension(0) = 3
      shape._num_slices_in_dimension(1) = 14
      shape._num_slices_in_dimension(2) = 25
      shape._num_slices_in_dimension(3) = 3
      shape._num_slices_in_dimension(4) = 4
      shape._num_slices_in_dimension(-2) = 3
      ```

      Args:
        axis: the last dimension to include.

      Returns:
        the number of values in a dimension.
      r   r[   )r
  r   r@   N)rs   r   rt   r   r  r[   r4   r*   r,   rC   r/   num_elements)r6   r   r   head_inner_shapes       r=   r   z0DynamicRaggedShape.Spec._num_slices_in_dimensionl  s    < c"122((tyyVLd	q!!	((	(##D1H-333$11A56i11*9=**,,rJ   c                     | j                   D cg c]  }|j                  |       }}t        j                  || j                  |      S c c}w )z1Return the same spec, but with a different DType.r#   )r,   r}   r0   r1   r/   )r6   r&   r9   new_rp_specss       r=   r}   z"DynamicRaggedShape.Spec.with_dtype  sQ    595I5IJrbmmE*JlJ$$%!55 %   Ks   Ac                     t        | j                  |j                        }| j                  |      }|j                  |      }t        |j                  |j                        D cg c]  \  }}|j                  |       }}}j                  j                  j                        }|j                  t        j                  k(  r|j                  nt        j                  }t        j                  |||      S c c}}w )a<  Merges all information between two specs.

      Specs are expected to represent the same information modulo
      num_row_partitons.

      If the specs are of different ranks, then fail.

      Args:
        other: another Spec of the same rank.

      Returns:
        a Spec with the union of information.
      r'   )r  r*   r   r  r,   r'  r/   r   r&   r
   rz   r{   r0   r1   )r6   r   r!  r"  r#  r;   r<   r&   s           r=   r'  z#DynamicRaggedShape.Spec._merge_with  s      #4#:#:#(#;#; =

'
'(>
?a

(
()?
@a A--q/@/@Aq! --
f 
  !44??


 ! ''V\\1agge$$
( % 7 7s   &C:r   c                 &   | j                   }|t        d      |t        |dz
  d      kD  rt        d      |dk  rt        d      | j                  |k(  r| S | j                  |k  r|| j                  z
  }t        j
                  j                  | j                  || j                        }t        j                  | j                  |j                  z   |j                  | j                        S | j                  |kD  sJ | j                  d| }|d   }| j                  |d }t        j                  |j                  g|D cg c]  }|j                   c}z         | j                  dd z   }	t        j                  ||	| j                        S c c}w )	z0Change the number of row partitions in the spec.Nz9Changing num_row_partitions with unknown rank unsupportedr@   r   z"Number of row partitions too largez!Number of row partitions negativer#   rW   )r[   r   r  r*   r0   r1   r3   r/   r&   r,   r   r   rC   r)   )
r6   r   r[   rp_delta
tail_shaper   r   old_row_partitionsr   r<   s
             r=   r   z0DynamicRaggedShape.Spec._with_num_row_partitions  s    YYd	GI 	I	#dQh"2	2=>>	!	#<==		 	 $:	:""%;;)D,C,CC',,??$$h

<
!&&//*2L2LL)==** '  	
 &&)????!112I3IJ/3!112H2IJ$$#))*/AB!%%BCD $$QR() 	
 "&&'9'=tzzK 	K Cs   F
new_rankc                    |t        d      |dk  rt        d      | j                  }|!||k  rt        dj                  ||            || S | j                  rSt        || j                  z
  d      }| j                  d   j                  }t        j                  |gdg|dz
  z  z         }nt        j                  dg|z        }t        j                  | j                  || j                  	      S )
z0Ensures this has a known rank at least new_rank.Nz"new_rank is None, but expected intr   zRank must be non-negativez5Rank is {current_rank}, expected at least {new_rank}.)current_rankrl  r@   rW   r#   )rt   r   r[   formatr,   r  r*   rC   r   r   r0   r1   r&   )r6   rl  rn  r   r   r%   s         r=   _set_rank_if_unknownz,DynamicRaggedShape.Spec._set_rank_if_unknown  s   		<==	A455YYl		!lX&=CJJ)H K >? 	? 
	!			X(?(??C((,22	)55ykTF7E7IEK 7K L *55tfx6GH$$--/

 %  rJ   c                    | j                    | j                  |      j                  |      S |dk(  r+t        j                  j                  g d| j                        S |dk(  r=| j                  d      }t        j                  j                  |gd| j                        S || j                  dz   k  rW| j                  d|dz
   }t        j                  |d   j                  g      }t        j	                  ||| j                        S || j                  z
  }| j                  d| }t        j	                  | j                  || j                        S )a:  Truncate a ragged shape spec.

      For example, if the original spec s was for a shape:
      [3, [4, 1], 2, 7]

      Then truncate_dynamic_ragged_shape_spec(s, 3) is a spec for:
      [3, [4, 1], 2]

      Args:
        new_rank: the new rank

      Returns:
        A truncated DynamicRaggedShape.Spec.
      Nr   r@   rW   r#   )r[   rp  	_truncater0   r1   r3   r&   r4   r*   r,   r   r   rC   r/   )r6   rl  vector_sizer   r<   r   s         r=   rr  z!DynamicRaggedShape.Spec._truncate  sP    
	((2<<XFF	Q!&&99"aLL	Qooa(!&&99;-:>**F 	F 
D++a/	/!11-8a<@!-!9!9#))*",!&&-5** '  	
 t666	!%!9!9*9!E!&&//5** '  	rJ   c                    | }|j                   j                  t        j                  d      S |j                   j                  dk(  r|j                  rJ |j                   S |j                  d      g}|j                  |j                  D cg c]  }|j                   c}       |j                   dd }t        j                  |      |z   S c c}w )z.Get a tensor shape corresponding to this type.Nr   r@   )r/   r[   r   r   r,   r4   extendr)   )r6   altr  r9   r  s        r=   r]   z(DynamicRaggedShape.Spec._to_tensor_shape)  s    c		 	 	%	%	-''--		 	 	%	%	*&&&&&&&q!"fmmS5H5HIrR**IJ&&qr*f%%f-66 Js   C)r   r    r!   r    )'r_   r`   ra   rb   r   r   r   r   r
   DTyper   r   classmethodr   rP  r   r3   r{   r   r   r\   rd   rf   rY  propertyr&   r   r2   r*   r[   r4   r   r}   r'  r   rp  rr  r]   __classcell__)rR  s   @r=   r1   zDynamicRaggedShape.Spec[  s%   CW,u-=s-B'C W,%1%=%=W,W,r$ ,s ,'@ , ,, Bs B B"(,,B3LB BH 
 %ll	#A-}/M/M))* +#A ||	#A 0I	#A #AJ %v|| % % FHSM F F 'C ' ' Rhsm R R6 6 60)-S )-Xc] )-V 1J 7.73L7B!K&)!K.G!KFS 5N 8(# (*C (T7rJ   r1   )NFNr?  T)r   r0   r!   r0   )r   r    r!   r0   )F);r_   r`   ra   rb   r   r   __annotations__rd   re   r   r   r   __batch_encoder__r   r   
TensorLiker   r
   rw  rR   r   rx  r{   r   r   r   r   r   rM   ry  r$   r*   r&   r   r   r   r]   r   r4   r   r   r   r   r[   rj   r2   r   r   r   r   r  r}   r'  r*  r-  r3  r7  r;  r1   rg   rJ   r=   r0   r0      sQ   : s*++!!!#///57$(
 04 %)-f'5f OOf v||,f 	f
 $'fP  '+b:$U8C=#+=%>?b: b:H H H < <
 + +     % % # ##<J0- 8 8 -:Cx$AL';R2*<X> 2 2   G G)KVF
C85AnjLC jL!jL&:jLX><<<,<1E<('&*.Y7 Y7rJ   r0   shape_xshape_yr!   c                     t        | t              st        d      t        |t              st        d      t        | |      d   S )a  Returns the shape formed by broadcasting two shapes to be compatible.

  1. If shape_x and shape_y both have row_partitions, then fail if their dtypes
     don't match.
  2. If neither has row_partitions and they have different dtypes,
     go with int64.
  3. If one has row_partitions, go with that dtype.

  Args:
    shape_x: A `DynamicRaggedShape`
    shape_y: A `DynamicRaggedShape`

  Returns:
    A `DynamicRaggedShape`.
  Raises:
    ValueError: If `shape_x` and `shape_y` are not broadcast-compatible.
  z$shape_x must be a DynamicRaggedShapez$shape_y must be a DynamicRaggedShaper   )rs   r0   rt    broadcast_dynamic_shape_extended)r  r  s     r=   broadcast_dynamic_shaper  7  sD    & 
G/	0
:
;;	G/	0
:
;;	)'7	;A	>>rJ   rX   c                    t        |t              st        d      t        j                  |       } d}t        j
                  |       rx|j                  dk7  r.| j                  j                  |j                  k7  r0t        d      |j                  | j                  j                        }t        j                  |       }nv|j                  dk7  r"t        j                  | |j                        }nEt        j                  | t        j                        }|j                  t        j                        }t        ||      }|j                  |       S )a  Broadcasts a potentially ragged tensor to a ragged shape.

  Tiles `rt_input` as necessary to match the given shape.

  Behavior is undefined if `rt_input` is not broadcast-compatible with `shape`.

  Args:
    rt_input: The potentially ragged tensor to broadcast.
    shape: A `DynamicRaggedShape`

  Returns:
    A potentially ragged tensor whose values are taken from
    `rt_input`, and whose shape matches `shape`.
  z"shape must be a DynamicRaggedShapeNr   zCannot coerce row_splits.dtyper'   )rs   r0   rt   r   "convert_to_tensor_or_ragged_tensorr   r*   r  r&   r   r}   rM   r
   r{   _get_broadcaster	broadcast)rt_inputrX   origin_shapebroadcasters       r=   broadcast_tor  R  s    
E-	.
8
99==hG(,X&1$				"	"ekk	19::x22889e%11(;L1$'33HEKK3Pl'33
&,, 4 (lV\\2e u5+			x	((rJ   r"  r#  c                 
   | j                   r0|j                   r$| j                  |j                  k7  rt        d      | j                  |j                  k7  r| j                   r|j                  | j                        }nf|j                   r| j                  |j                        } n>| j                  t        j
                        } |j                  t        j
                        }| j                  |j                  t        d      | j                  dk(  r|t        | |g       t        |      fS |j                  dk(  r| t        |       t        || g       fS | j                  dk(  re|j                  dk(  rVt        | j                  |j                        \  }}}t        j                  |      }|t        | ||g      t        |||g      fS | j                  |j                  kD  rt        ||       \  }}}|||fS t        | |      S )aA  Gets the smallest shape to which a and b can broadcast.

  In order to create the smallest shape, one must also do most of the
  work to figure out how to transform from the shapes given. Thus, in addition
  to returning the shape, it also creates transformations from the
  original shapes to the result.

  This is the equivalent of:

  c = broadcast_dynamic_shape(a, b)
  ac = get_broadcaster(a, c)
  bc = get_broadcaster(b, c)
  return (c, ac, bc)

  Args:
    a: a DynamicRaggedShape
    b: a DynamicRaggedShape

  Returns:
    A triple of a shape and two broadcasters.
  zDtypes don't matchz!Unable to broadcast: unknown rankr   r@   )r$   r&   r   r}   r
   r{   r[   _Broadcaster_get_identity_broadcaster"_broadcast_dynamic_shape_one_layerrj   r0   r   (_broadcast_dynamic_shape_extended_helper)	r"  r#  a_layerb_layertargettarget_shapecbcacs	            r=   r  r  x  s   0 !**ww!''+,,ww!''
,,qww
a	
		
,,qww
a
,,v||
$a
,,v||
$affn
8
99vv{|Aq"%'@'CDDvv{(+\!Q-CDDvv{qvv{1!--OWg%77?L,q,	BL7)46 6 VVaff_:1a@KQBr2;	1!Q	77rJ   c                     | j                   |j                   k(  xr0 t        d t        | j                  |j                        D              S )z<Returns True iff all row_partitions in shapes are identical.c              3   *   K   | ]  \  }}||u   y wr?  rg   )r@  r"  r#  s      r=   rA  z,_row_partitions_identical.<locals>.<genexpr>  s!      MNAa1fMNs   )r*   rE  r  r$   )shape_ashape_bs     r=   _row_partitions_identicalr    sO    %%)C)CC N MNW33W5K5KLMN JN OrJ   c                 P   t        j                  |      }t        j                  |      }t        j                  ||r|j                  nd      }t        j                  ||j                        }|r|rt        j                  ||      \  }}|r|st|r7|j
                  j                  j                  |j                  j                  k  s;|rB|j
                  j                  j                  |j                  j                  k  r
t        j                  |      }t        j                  |      }|j                  |j                  k7  r;|s|j                  |j                        }n|s|j                  |j                        }t        ||      r.|j                   | |j
                  |j
                        d      S t        ||      \  }}}	|j                  |d      }
|	j                  |d      } | |
|      }|j                  |d      S t        j                  |      r|j
                  n|}t        j                  |      r|j
                  n|} | ||      }t        |t               r|S t        j                  |      r|j#                  |      S |j#                  |      S )z1Binary elementwise api handler for RaggedTensors.Npreferred_dtypeFr9  inner_dimensionsT)r   r   r  r&   match_row_splits_dtypesr1  rX   ndimsr0   rM   r}   r  r;  r  broadcast_flat_valuesrs   rR   with_flat_values)opr   yx_is_raggedy_is_raggedr  r  shape_zbcast_xzbcast_yz
x_new_flat
y_new_flatz_flatx_valuesy_valuesmapped_valuess                   r=   !ragged_binary_elementwise_op_implr    s7    ''*+''*+ 66[!''d=!66"! [00A6DAq{q}}**00AGGMMAq}}**00AGGMMA ,,Q/G ,,Q/G}}%$$W]]3$$W]]3 '2((
Q]]AMM
* )  
 2'7CWh//E/JJ//E/JJ
J'F&&v&==+55a8Q]]a(+55a8Q]]a(Xx(-t$Qm,,m,,rJ   c                 t   t        j                  |      }t        j                  |      }t        j                  ||r|j                  nd      }t        j                  ||j                        }|r|rt        j                  ||      \  }}|r|ss|r7|j
                  j                  j                  |j                  j                  k  s:|r|j
                  j                  j                  |j                  j                  k  rt        j                  |      }t        j                  |      }|j                  |j                  k7  r;|s|j                  |j                        }n|s|j                  |j                        }t        ||      r | |j
                  |j
                        S t        ||      \  }}}	|j                  |d      }
|	j                  |d      } | |
|      S t        j                  |      r|j
                  n|}t        j                  |      r|j
                  n|} | ||      S )a  Binary elementwise assert api handler for RaggedTensors.

  This handles binary assert operations for ragged tensors. Compared with
  `ragged_binary_elementwise_op_impl`, this handler does not compute a ragged
  tensor as output. Instead, it applies the assert operation `op` to input
  tensors based on their ragged shapes and flat_values, and returns the result
  of the assertion operation.

  Args:
    op: a binary assert operation on Tensors.
    x: something that can be coerced to a Tensor or RaggedTensor.
    y: something that can be coerced to a Tensor or RaggedTensor.

  Returns:
    the result of the assertion operation.

  Nr  Fr  )r   r   r  r&   r  r1  rX   r  r0   rM   r}   r  r  r  )r  r   r  r  r  r  r  rT  r  r  r  r  r  r  s                 r=   (ragged_binary_elementwise_assert_op_implr    s   ( ''*+''*+ 66[!''d=!66"! [00A6DAq{q}}**00AGGMMAq}}**00AGGMMA ,,Q/G ,,Q/G}}%$$W]]3$$W]]3 '2q}}-->wPQ(//E/JJ//E/JJj*%%+55a8Q]]a(+55a8Q]]a(	Hh	rJ   c                 D   ||S t        | t              r| j                  S t        | t        j                        r| S t        | t
              ryt        | t              ryt        | t              ryt        | t        j                        r| j                  S | j                  S )zHelper for _find_dtype.N)
rs   r   r&   r
   rw  r   r   r|   r   re   )rS   	preferreds     r=   _find_dtype_helperr  $  s~    %&;;%&L%%%%%;;	rJ   c                     t        | |      }|t        j                  k(  s|t        j                  k(  s||S t	        dt        |      z         )a  Returns the preferred dtype of value or preferred if preferred != None.

  This is used as an operator to pass over multiple objects in decreasing order
  of priority until there is a preferred dtype for one. For example, if you were
  adding three tensor-ish things (some tensors, some lists), and needed a
  preferred dtype, you could use this as:

  def adding(a, b, c, dtype = None):
    dtype = _find_dtype(a, dtype)
    dtype = _find_dtype(b, dtype)
    dtype = _find_dtype(c, dtype)
    if dtype is None:
      dtype = tf.float32
    ...Code continues here...

  Args:
    value: a list, value, RowPartition, or tensor.
    preferred: a given dtype. If not None, this will be returned.

  Returns:
    an optional dtype.
  zIllegal dtype: )r  r
   r{   rz   r   ru   )rS   r  rF   s      r=   rw   rw   7  sE    . eY/&&,, 6&.M$s6{233rJ   iterabler&   c                 4    ||S | D ]  }t        ||      } |S )aT  Find the preferred dtype of a list of objects.

  This will go over the iterable, and use the first object with a preferred
  dtype. The dtype passed has highest priority if it is not None.

  Args:
    iterable: an iterable with things that might have a dtype.
    dtype: an overriding dtype, or None.

  Returns:
    an optional dtype.
  )rw   )r  r&   r   s      r=   rv   rv   T  s/     L "a5!E"	,rJ   c                       e Zd ZdZeej                  d               Zed        Zej                  d        Z	d Z
ed        Zed        Zed        Zej                  d	        Zedd       Zd Zd Zd Zd Zy
)_LayerBroadcasteraJ  A broadcaster of a single layer.

  Although this class does not literally contain a gather_index, the reference
  implementation is defined through a gather_index. Thus, any subclasses should
  first define the gather_index property. Other functions can be overridden
  for optimization, but it should not change the behavior.
  c                      y)zReturns a 1D tensor.

    The size of the 1D tensor is equal to the destination size.

    The ith element of the result is the index of the source of the ith element.
    Nrg   r   s    r=   gather_indexz_LayerBroadcaster.gather_indexs  s     	rJ   c                 .    | j                   j                  S )z#Returns the dtype of the broadcast.)r  r&   r   s    r=   r&   z_LayerBroadcaster.dtype~  r   rJ   c                      y)z>Returns an identical _LayerBroadcaster with a different dtype.Nrg   r  s     r=   r}   z_LayerBroadcaster.with_dtype  s     	rJ   c                 ,    t        | j                        S r?  )ru   r  r   s    r=   r   z_LayerBroadcaster.__repr__  s    t  !!rJ   c                     t        |      S z)Create a broadcaster from a gather_index.)_GatherLayerBroadcaster)r   r  s     r=   from_gather_indexz#_LayerBroadcaster.from_gather_index  s     #<00rJ   c                 D    t        ||      }t        j                  |      S r  )_first_layer_gather_indexr  r  )r   nrows_sourcenrows_targetr  s       r=   first_layerz_LayerBroadcaster.first_layer  s!     -\<HL..|<<rJ   c                 j    t         j                  t        j                  ||j                              S )z1Broadcast from 1 element to target_size elements.r'   )r  r  r   zerosr&   )r   target_sizes     r=   get_singleton_broadcasterz+_LayerBroadcaster.get_singleton_broadcaster  s+     ..;+<+<=? ?rJ   c                      y)zAdd dependencies to a _LayerBroadcaster.

    Args:
      checks: a list of ops that need to be run before any tensors from the
        Broadcaster are used.

    Returns:
      a copy of this _LayerBroadcaster with dependencies added.
    Nrg   )r6   r   s     r=   r   z#_LayerBroadcaster.with_dependencies  s     	rJ   Nc                 B    t        t        j                  ||            S )a  Create an identity broadcaster.

    TODO(martinz): an identity broadcaster can be far more efficient than a
    generic broadcaster. Add an optimized implementation.
    Args:
      nvals: the number of values for the broadcaster.
      dtype: the dtype of the broadcaster, or None to use the dtype of nvals.

    Returns:
      an identity broadcaster from [0....nvals-1] to [0...nvals-1]
    r'   )r  r   r   )r   rC   r&   s      r=   get_identity_broadcasterz*_LayerBroadcaster.get_identity_broadcaster  s     #8>>%u#EFFrJ   c                 B    t        j                  || j                        S )a+  Broadcast from a dense tensor.

    It is assumed that the first axis of the dense tensor is indexed by the
    source shape, and at the end, the first axis of the dense tensor is
    indexed by the destination shape.

    Args:
      tensor: a dense tensor.

    Returns:
      A dense tensor.
    )r   gatherr  )r6   r   s     r=   broadcast_tensorz"_LayerBroadcaster.broadcast_tensor  s     FD$5$566rJ   c                     t        j                  t        j                  | j                        d   | j
                        S )zEReturn the number of rows in the resulting gather, or None if tiling.r   r'   )r   r   r   rX   r  r&   r   s    r=   
dest_nrowsz_LayerBroadcaster.dest_nrows  s2    ==))*1-TZZA ArJ   c                 ,   |j                         s2t        j                  | j                  |j	                                     S t        j
                  |j                         |j                         | j                         z  | j                               S )a  Return a new shape where the rows are broadcasted.

        *--self--->*
        |          |
        rp       result
        |          |
        V          V
        *--------->*

    This is equivalent to:
      return RowPartition.from_row_lengths(self.broadcast(rp.row_lengths()))

    However, if the shape has uniform row length, then that property is
    maintained.

    Args:
      rp: a row partition.

    Returns:
      a RowPartition representing a broadcast version of this row partition.
    rC   rB   )r   r   from_row_lengthsr  r   r   r)   r  )r6   r9   s     r=   broadcast_row_partitionz)_LayerBroadcaster.broadcast_row_partition  sx    , ==?**


 0
13 3 11



!%%'$//*;;!# #rJ   c                 F    t        | ||      }t        j                  |      S )a  Create the next layer gather_index whether or not a broadcast happens.

       *---------self------->*
       |                     |
    original_rp           broadcast_rp
       |                     |
      \|/                   \|/
       *--next_broadcaster-->*
    Args:
      original_rp: the original row partition.
      broadcast_rp: the target row partition.

    Returns:
      the gather_index for next_broadcaster.

    )_next_layer_gather_indexr  r  )r6   original_rpbroadcast_rpr  s       r=   
next_layerz_LayerBroadcaster.next_layer  s#    " ,D+|LL..|<<rJ   r?  )r_   r`   ra   rb   ry  abcabstractmethodr  r&   r}   r   rx  r  r  r  r   r  r  r  r  r  rg   rJ   r=   r  r  j  s     	  	 # # 	 	" 1 1 = =
 ? ?
 
	 
	 G G7A
#>=rJ   r  c                   2    e Zd ZdZd Zed        Zd Zd Zy)r  zImplements _LayerBroadcaster with an explicit gather_index.

  For example, suppose that the source shape is:
  [*],[*,*]
  And the target shape is:
  [*],[*,*],[*],[*,*]
  Then, this can be represented with a map:
  [0,1,2,0,1,2]

  c                     t        j                  |      }|j                  t        j                  k7  r(|j                  t        j
                  k7  rt        d      || _        y )Nz#gather_index must be int64 or int32)r   r~   r&   r
   r{   rz   r   _gather_index)r6   r  s     r=   r   z _GatherLayerBroadcaster.__init__  sJ    ((6Lfll*fll*<==%DrJ   c                     | j                   S r?  )r  r   s    r=   r  z$_GatherLayerBroadcaster.gather_index      rJ   c                 T    t        t        j                  | j                  |            S r?  )r  r   r   r  r  s     r=   r}   z"_GatherLayerBroadcaster.with_dtype  s    "8==1C1CU#KLLrJ   c                 X    t        j                  || j                        }t        |      S r?  )r   r   r  r  )r6   r   new_gather_indexs      r=   r   z)_GatherLayerBroadcaster.with_dependencies  s*    '99""$"#344rJ   N)	r_   r`   ra   rb   r   ry  r  r}   r   rg   rJ   r=   r  r     s+    	&  M5rJ   r  c                   j    e Zd ZdZ	 ddZd Zd Zed        Zed        Z	ed        Z
d	 Zdd
Zd Zy)r  zA _Broadcaster represents a transformation from one shape to another.

  It provides a transform for each axis of the source shape to the
  corresponding axis of the destination shape.

  Nc                 @   t        |t              st        d      t        |t              st        d      t        |t              st        dt	        |      z         |D ])  }t        |t
              rt        dt	        |      z          t        ||      }t        ||      }t        ||      }t        t        j                  |      }|j                  |      | _        |j                  |      | _        |D cg c]  }|j                  |       c}| _        yc c}w )a  Create a broadcaster.

    Do not call directly.
    The source_shape, target_shape, and layer_broadcasters are converted
    to have the same dtype.

    Note: source_shape.rank and target_shape.rank must be known.
    Args:
      source_shape: the source DynamicRaggedShape
      target_shape: the target DynamicRaggedShape
      layer_broadcasters: List[_LayerBroadcaster] of length source_shape.rank.
      dtype: the preferred dtype of the broadcaster.

    Raises:
      TypeError: if the input types don't match.
    z(source_shape is not a DynamicRaggedShapez(target_shape is not a DynamicRaggedShapezlayer_broadcasters not a list: zNot a LayerBroadcaster: N)rs   r0   rt   r   ru   r  rw   rv   r
   r{   r}   _source_shape_target_shape_layer_broadcasters)r6   source_shaper  layer_broadcastersr&   r  r   s          r=   r   z_Broadcaster.__init__(  s   * l$67@AAl$67@AA($/7,-. / /  >-.2SW<==> e,Ee,E !3U;Ee,E%007D%007D=OPU 3PDPs   :Dc                     dt        | j                        z   dz   t        | j                        z   dz   t        | j                        z   dz   S )Nz{src_shape:z, target_shape:z layer_broadcasters: })ru   r  r  r  r   s    r=   r   z_Broadcaster.__repr__P  sV    C 2 2336GG""#$&=>(()*,/0 1rJ   c                 Z    t        | j                  | j                  | j                  |      S )z9Return a copy of this Broadcaster with a different dtype.)r  r  r  r  r  s     r=   r}   z_Broadcaster.with_dtypeU  s*    **D,>,>00%9 9rJ   c                     | j                   S r?  )r  r   s    r=   r  z_Broadcaster.source_shapeZ  r  rJ   c                     | j                   S r?  )r  r   s    r=   r  z_Broadcaster.target_shape^  r  rJ   c                 .    | j                   j                  S r?  )r  r&   r   s    r=   r&   z_Broadcaster.dtypeb  s    ###rJ   c                     | j                   j                  }|j                  t        j                  k(  r%t        j                  |t        j                        }|S rL   )r  rj   r&   r
   r{   r   r   rz   )r6   r   s     r=   _target_inner_shape_int32z&_Broadcaster._target_inner_shape_int32f  s?    ''33O, oV\\JorJ   c                    t        j                  |      r|j                  }| j                  j                  dk(  r|S | j                  j
                  }|| j                  j                  kD  r| j                  j                  dkD  rCt        j                  || j                  j                  | j                  j                              }|r$t        j                  || j                               S |S | j                  j
                  |k7  r/t        j                  || j                  j                  |            }| j                  |    }|j                  |      }|r$t        j                  || j                               }|S )a  flat_values of a ragged tensor broadcast to target_shape.

    If inner_dimensions==True, then the result is a dense tensor with shape
    target_shape.inner_shape, the flat values of the broadcasted shape.

    If you add target_shape.row_partitions, you will get the full broadcasted
    shape.

    If inner_dimensions==False, the result is a dense tensor that satsifies
    certain properties:
    1. broadcast_to(result, target_shape.inner_shape) will give the result
       if inner_dimensions==True.
    2. Either (a) (result.rank < target_shape.inner_rank)
       or (b) (result.shape[0] == target_shape.inner_shape[0]).
    3. result.rank = min(target_shape.inner_rank, rt.rank)
    4. For i < target_shape.inner_rank - 1, and i < rt.rank,
       and if rt.shape[-i]!=1, then result.shape[-i]=target_shape[-i].
    Args:
      rt: a ragged or dense tensor.
      inner_dimensions: if true, broadcast the inner dimensions as well.

    Returns:
      a dense tensor
    r   )r   r   r1  r  r[   r2   r  r  r*   r   reshaper   r  r  r  r  )r6   rtr  r2   flat_broadcasters        r=   r  z"_Broadcaster.broadcast_flat_valuesm  sK   2 r">>b"i""--JD&&+++ 
			-	-	1!!2243D3D3I3IJL 
%%b$*H*H*JKKi				&	&*	4r#11BB:NP 11:+>,,R0b	##B(F(F(HIirJ   c                 Z    | j                  |      }| j                  j                  |      S )z3Broadcast a tensor of source_shape to target_shape.)r  r  r;  )r6   r  r1  s      r=   r  z_Broadcaster.broadcast  s)    ,,R0K00==rJ   r?  r{  )r_   r`   ra   rb   r   r   r}   ry  r  r  r&   r  r  r  rg   rJ   r=   r  r     si     	&QP1
9
     $ $4l>rJ   r  c                     t        | t              st        dt        |       z         t	        |      t	        |      k(  sJ |s| gS | j                  |d   |d         }t        ||dd |dd       }| g|z   S )a  Get LayerBroadcasters from RowPartitions.

           *--zero_broadcaster->*
           |                    |
         source_rps[0]     target_rps[0]
           |                    |
           V                    V
           *---result[1]------->*
           |                    |
         source_rps[1]     target_rps[1]
           |                    |
           V                    V
           *---result[2]------->*
                  .
                  .
                  .
           *---result[k-1]----->*
           |                    |
         source_rps[k]     target_rps[k]
           |                    |
           V                    V
           *---result[k]------->*

  Note: result[0] = zero_broadcaster

  Args:
    zero_broadcaster: a broadcaster between the source and target row
      partitions' rows, and equal to result[0].
    source_rps: source row partitions.
    target_rps: target row partitions (same length as source_rps).

  Returns:
    result: a list of LayerBroadcasters.
  zNot a _LayerBroadcaster: r   r@   N)rs   r  rt   ru   r   r   _get_layer_broadcasters_from_rps)zero_broadcaster
source_rps
target_rpsnext_broadcastertail_broadcasterss        r=   r   r     s    F 
$&7	8
/#6F2GG
HH	ZC
O	++	+	%00A
1N67G7A!"~7A!"~G 	/	//rJ   c                    | j                   |j                   k7  rt        d      | j                  |j                  t        d      | j                  |j                  kD  rt        d      | j                  dk(  rt        | |g       S |j                  dk(  rO| j                  dk(  sJ t        j                  | j                  d   |j                  d         }t        | ||g      S | j                  |j                  k  sJ |j                  dk\  sJ | j                  dk\  sJ | j                         }|j                         }t        |      dk\  sJ t        |      t        |      k  sJ | d   }t        |      t        |      k  rt        j                  |d|      }|t        |      dz       }t        j                  |j                               }|j                  ||      }	t        |      dk\  r|t        |       d ng }
t        |	||
      }t        | ||      S t        |      t        |      k(  sJ t        j                  |d   j                         |d   j                               }	t        |	||      }t        | ||      S )	z5Get a _Broadcaster from source_shape to target_shape.z6The source and target row_split dtypes should be equalNz2Rank of source and target must be statically knownz-Cannot broadcast to a shape with smaller rankr   r@   r   r)   rB   rC   )r&   r   r[   r  r  r  rj   r-  r   r   r   r  rB   r  r   )r  r  layerr  r  source_nrowsneg_one_source_rpneg_one_target_rpneg_one_broadcasterzeroth_broadcastertarget_rps_taillayerss               r=   r  r    s   <---
M
NN<#4#4#<
I
JJ<,,,
D
EEAlB77A!!!)),*B*B1*E*6*B*B1*EGElUG<<			l//	//	/			a					a		..0*..0*	ZA			ZC
O	++	+a,_s:& %<<'qF"S_q%8#9:+EE!#,778I8IK7:88j#j/!1!23   ..@*.=?FlF;;z?c*o---*66z!}7J7J7L7A!}7J7J7LN-.@*.8:F lF;;rJ   c                     | j                   t        d      t        | j                         D cg c]&  }t        j	                  | j                  |            ( }}t        | | |      S c c}w )z,Gets a Broadcaster for two identical shapes.zShape must have a defined rank)r[   r   r   r  r  r   r  )rX   r  r  s      r=   r  r  	  so    
ZZ
5
66 7<EJJ6G12 00

(
(
+-&  
eUF	++	s   +A)c                      d   d   fd}t        j                         }|B|d   dk(  r: |       \  }}}t        j                  |      }t        j                  |      }|||gS  fdt        j                        }	|	B|	d   dk(  r:        \  }}}t        j                  |      }t        j                  |      }|||gS fdt	        j
                  d      }
t	        j
                  d      fd}t	        j
                        }t	        j                  |
t	        j                  |            }t        j                  |dd	      }t        j                  |
||
      }|D cg c]  }t        j                  |g|       }}|\  }}}t        j                  |      }t        j                  |      }|||gS c c}w )a  Broadcast two vectors, given their shapes.

  Args:
    a: the number of rows in a.
    b: the number of rows in b.

  Returns:
    (layer_a, layer_b, target_shape)
    layer_a is a _LayerBroadcaster from a to the target_shape.
    layer_b is a _LayerBroadcaster from b to the target_shape.
    target_shape is the target_shape

  Raises:
    InvalidArgumentError if the shapes are not consistent.
  r   c                  ~    t        j                  j                        } t        j                        }}| ||gS rL   r   r  r&   r   r   )r  r  r  r#  b_0s      r=   broadcast_from_az<_broadcast_dynamic_shape_one_layer.<locals>.broadcast_from_a1	  s7    ooc3GnnS!GFWf%%rJ   r@   c                  ~    t        j                        } t        j                  j                        }}| ||gS rL   r   r   r   r  r&   )r  r  r  r"  a_0s      r=   broadcast_from_bz<_broadcast_dynamic_shape_one_layer.<locals>.broadcast_from_b?	  s7    nnS!Gooc3GFWf%%rJ   c                  f    t        j                        } t        j                        }}| ||gS r?  r   r   )r  r  r  r  r#  r  s      r=   broadcast_noopz:_broadcast_dynamic_shape_one_layer.<locals>.broadcast_noopM	  s1    nnS!GnnS!GFWf%%rJ   c                  4    t        j                          S Ntrue_fnfalse_fnr   r  r  can_broadcast_from_bs   r=   broadcast_not_from_az@_broadcast_dynamic_shape_one_layer.<locals>.broadcast_not_from_aW	      99&6Q QrJ   TCannot broadcastrp   r  )r   r   r  r  r   equal
logical_orr   r   r   r   r   )r"  r#  r  a_statica_gib_gir  r  r  b_staticcan_broadcast_from_ar$  nrows_equalcan_broadcastcheck_can_broadcastresultsr   r  r  r  r  r#  s   ``               @@@@@r=   r  r  	  s     	
!#	!#& ''*(hqkQ.+-T411$7G11$7GWf%%& ''*(hqkQ.+-T411$7G11$7GWf%%& "Q/!Q/Q sC(+%%.<>- "..T#57 II#%' 
 ((*=)>B'  !4v//5'//5'
7F	##s   >Gc                     fd}t        j                         }t        j                        }|Y||k(  r%t        j                  | j                        }||gS |dk(  r*t        j                        t        j                        gS |dk(  r*t        j                         t        j                         gS  fd fdt        j                   t        j                  d j                              }t        j                  t        j                  dj                              fd}t        j                  t        j                  |      t        j                               }t        j                  |||      }	|	D 
cg c]@  }
t        j                  t        j                  t        j                   |d      g|
            B c}
S c c}
w )	a{  Broadcast the first layer of two dynamic shapes given the dimensions.

  Args:
    a_0: the number of rows in a.
    b_0: the number of rows in b.

  Returns:
    (use_a, layer_a, layer_b)
    where use_a is true if the target provably equals a, false otherwise.
    layer_a is a _LayerBroadcaster from a to the target.
    layer_b is a _LayerBroadcaster from b to the target.
  c                  x    t        j                  j                        } t        j                        }| |gS rL   r  )r  r  r  s     r=   r  z>_broadcast_dynamic_shape_first_layer.<locals>.broadcast_from_a	  s0    ooc3GnnS!GWrJ   r'   r@   c                  x    t        j                        } t        j                  j                        }| |gS rL   r  )r  r  r  s     r=   r  z>_broadcast_dynamic_shape_first_layer.<locals>.broadcast_from_b	  s0    nnS!Gooc3GWrJ   c                  `    t        j                        } t        j                        }| |gS r?  r  )r  r  r  r  s     r=   r  z<_broadcast_dynamic_shape_first_layer.<locals>.broadcast_noop	  s*    nnS!GnnS!GWrJ   c                  4    t        j                          S r  r   r"  s   r=   r$  zB_broadcast_dynamic_shape_first_layer.<locals>.broadcast_not_from_a	  r%  rJ   r  T)r   r   r  r  r&   r  r   r'  r	   r   r(  r   r  r   r   r   r   )r  r  r  
static_a_0
static_b_0id_broadcasterr-  r$  r/  rF   r   r  r  r#  s   ``         @@@r=   $_broadcast_dynamic_shape_first_layerr:  r	  s    ))#.*))#.*Z(AA
CII B 'nn--	q

5
5c
:

4
4S
9 
 1_223733C8 
 "[-A-A!SYY-OP![-A-A!SYY-OPQ %%.0DEnnS# - 99#%& KQ
 FG ))

,
,%%mT:;Q@A
  
s   AGac_0a_1c                    | j                  |      }t        j                  | j                  |j	                               }t        j                  |j                         |      }||j                         z   }t        j                  |      |gS )a  Does a NOOP broadcast of a_1.

      *-ac_0-->*
      |        |
     a_1      c_1
      |        |
      V        V
      *-ac_1-->*

  Note that by definition this cannot fail: there is always a well-defined
  NOOP broadcast. This is usually intended as half of broadcasting two shapes
  together.
  Args:
    ac_0: previous LayerBroadcaster
    a_1: previous RowPartition

  Returns:
    [ac_1, c_1] where ac_1 is the next LayerBroadcaster, and c_1 is the
    broadcast RowPartition
  )	r  r   r  r  value_rowidsr  offsets_in_rowsr  r  )r;  r<  c_1old_value_rowidsold_row_startsr  s         r=   _broadcast_halfrC  	  sy    . 	$$S)#%%d&7&79I9I9KL##CNN$46FG.#"5"5"77,

-
-l
;S	AArJ   bc_0b_1c                     t         t              st        d      t        t              st        d      t        t              st        d      t        t              st        d      j	                         sJ j	                         rJ t        j                  j                               }|dk(  rt              \  }}t        j                   j                  |j                               }t        j                  |j                               }t        j                  |      }	t        j                  |j                        }||	|gS  fd}
 fd}t!        j"                  j                         d      }t%        j$                  |||
      \  }}}t        j                  |      }t        j                  |      }	t        j                  |      }||	|gS )	a  Broadcast target and next layer broadcaster of two dynamic shapes.

  a_1 is uniform, and b_1 is ragged.
     *--ac_0-->*<--bc_0--*
     |         |         |
    a_1       c_1       b_1
     |         |         |
     V         V         V
     *--ac_1-->*<--bc_1--*

  Args:
    ac_0: _LayerBroadcaster from a to c in the previous layer.
    bc_0: _LayerBroadcaster from b to c in the previous layer.
    a_1: a uniform RowPartition for the next layer of a.
    b_1: a ragged RowPartition for the next layer of b.

  Returns:
    (c_1, ac_1, bc_1)
    c_1: a RowPartition for the next layer of the dynamic shape.
    ac_1: _LayerBroadcaster from a to c in the next layer.
    bc_1: _LayerBroadcaster from b to c in the next layer.
  "ac_0 should be a _LayerBroadcaster"bc_0 should be a _LayerBroadcastera_1 should be a RowPartitionb_1 should be a RowPartitionr@   c                  B   t              \  } }t        	      \  }}t        j                  |j                         |j                               g}j                         | j                  |j                  fD cg c]  }t        j                  ||       c}S c c}w r?  )rC  r   r   r  r  r   r   )
ac_1c_1abc_1c_1br   r   r<  r;  rE  rD  s
         r=   r  zG_broadcast_dynamic_shape_next_layer_half_ragged.<locals>.broadcast_noop
  s    "4-LT4"4-LT4$$T__%68IJKF .."D$5$5t7H7HI 	**615  s   <Bc                      t              \  } }t        j                  j                  |j	                               }|j                         || j                  gS r?  )rC  r   r  r  r>  r  rN  rO  ac_1_gather_indexr;  rE  rD  s      r=   broadcast_azD_broadcast_dynamic_shape_next_layer_half_ragged.<locals>.broadcast_a
  sU    "4-LT4!(():):D<M<M<OP rJ   r  )rs   r  rt   r   r   r   r   r)   rC  r   r  r  r>  r  r  r  r   r'  r   )r;  rD  r<  rE  
static_a_1rN  rO  rR  r@  rL  r  rS  can_broadcast_ac_1_row_splitsbc_1_gather_indexs   ````           r=   /_broadcast_dynamic_shape_next_layer_half_raggedrX  	  s   4 
D+	,
8
99	D+	,
8
99	C	&
2
33	C	&
2
33			^^	))#*@*@*BC*1_"4-LT4!(():):D<M<M<OP

&
&t'8
9C../@AD..t/@/@ADt NN3#9#9#;Q?/ 		nF>$ 	$$^4#		,	,->	?$		,	,->	?$
tT	rJ   c           
          t         t              st        d      t        t              st        d      t        t              st        d      t        t              st        d      j	                         sJ j	                         sJ t        j                  j                               }t        j                  j                               }|||k(  rHt               \  }}t              \  }}t        j                  | j                               }	|	||gS |dk(  rt              \  }}
t        j                  t        j                   j                  |
j                                     }t        j                  j                         j                               }	|	||gS |dk(  rt               \  }}t        j                  t        j                  j                  |j                                     }t        j                  j                          j                               }	|	||gS  fd fd} fd	t!        j"                  j                         d      fd
}t!        j"                  j                         d      }t%        j&                  t!        j(                  t!        j(                  |      t!        j"                  j                         j                                     d      g}t+        j*                  |||      }|D cg c]  }t-        j.                  ||       c}\  }}}t        j                  || j                         z   j                               }	t        j                  |      }t        j                  |      }|	||gS c c}w )a  Broadcast target and next layer broadcaster of two uniform dynamic shapes.

     *--ac_0-->*<--bc_0--*
     |         |         |
    a_1       c_1       b_1
     |         |         |
     V         V         V
     *--ac_1-->*<--bc_1--*

  Args:
    ac_0: _LayerBroadcaster from a to c in the previous layer.
    bc_0: _LayerBroadcaster from b to c in the previous layer.
    a_1: a RowPartition for the next layer of a.
    b_1: a RowPartition for the next layer of b.

  Returns:
    (c_1, ac_1, bc_1)
    c_1: a RowPartition for the next layer of the dynamic shape.
    ac_1: _LayerBroadcaster from a to c in the next layer.
    bc_1: _LayerBroadcaster from b to c in the next layer.
  rG  rH  rI  rJ  )rB   r@   c                      t              \  } }t              \  }}j                         | j                  |j                  gS r?  )rC  r)   r  )rL  rT  rN  r<  r;  rE  rD  s      r=   r  zH_broadcast_dynamic_shape_next_layer_both_uniform.<locals>.broadcast_noopj
  sG      c*IT1c*IT1""$d&7&79J9JKKrJ   c                      t              \  } }t        j                  j                  |j	                               }j                         || j                  gS r?  rC  r   r  r  r>  r)   rQ  s      r=   rS  zE_broadcast_dynamic_shape_next_layer_both_uniform.<locals>.broadcast_aq
  sW    "4-LT4!(():):D<M<M<OP  rJ   c                      t              \  } }t        j                  j                  |j	                               }j                         | j                  |gS r?  r\  )rL  rM  rW  r<  r;  rD  s      r=   broadcast_bzE_broadcast_dynamic_shape_next_layer_both_uniform.<locals>.broadcast_bz
  sR    "4-LT4!(():):D<M<M<OP""$d&7&79JKKrJ   c                  4    t        j                          S r  r   )r^  r  can_broadcast_bs   r=   no_broadcast_azH_broadcast_dynamic_shape_next_layer_both_uniform.<locals>.no_broadcast_a
  s    99~G GrJ   Tr  r  )rs   r  rt   r   r   r   r   r)   rC  r   r  r  r   r  r  r>  r   r'  r   r   r(  r   r   r   )r;  rD  r<  rE  rT  
static_b_1rL  rT  rN  r@  rO  rM  rS  ra  rU  broadcast_assertsrF   r   c_1_uniform_row_lengthrR  rW  r^  r  r`  s   ````                 @@@r=   0_broadcast_dynamic_shape_next_layer_both_uniformre  *
  sX   2 
D+	,
8
99	D+	,
8
99	C	&
2
33	C	&
2
33						))#*@*@*BC*))#*@*@*BC*Z "$,itQ!$,itQ00
DOO-/c4	q$T3/ltT00


4,,d.?.?.A
BDd00

 
 
"$//*;=c41_"4-LT4..**D,=,=,?@BD

.
. (9;CtLL
 NN3#9#9#;Q?/G NN3#9#9#;Q?/ 


!!/?CnnS335 33578 :>	? 99{^E& IODCD(():A>D@,.? 	,,"T__%66OO	# 
	,	,->	?$		,	,->	?$
tT	Ds   7Oc                    t        | t              st        d      t        |t              st        d      t        |t              st        d      t        |t              st        d      |j	                         r,|j	                         rt        | |||      S t        | |||      S |j	                         rt        || ||      \  }}}|||fS t        | |      \  }}t        ||      \  }}t        j                  |j                         |j                               g}	|j                  |	      |j                  |	      |j                  |	      fS )a  Broadcast target and next layer broadcaster of two dynamic shapes.

     *--ac_0-->*<--bc_0--*
     |         |         |
    a_1       c_1       b_1
     |         |         |
     V         V         V
     *--ac_1-->*<--bc_1--*

  Args:
    ac_0: _LayerBroadcaster from a to c in the previous layer.
    bc_0: _LayerBroadcaster from b to c in the previous layer.
    a_1: a RowPartition for the next layer of a.
    b_1: a RowPartition for the next layer of b.

  Returns:
    (c_1, ac_1, bc_1)
    c_1: a RowPartition for the next layer of the dynamic shape.
    ac_1: _LayerBroadcaster from a to c in the next layer.
    bc_1: _LayerBroadcaster from b to c in the next layer.
  rG  rH  rI  rJ  )rs   r  rt   r   r   re  rX  rC  r   r   r  r   r   )
r;  rD  r<  rE  r@  rN  rL  rM  rO  check_valids
             r=   #_broadcast_dynamic_shape_next_layerrh  
  sP   2 
D+	,
8
99	D+	,
8
99	C	&
2
33	C	&
2
33^^
~~=
c3    =
c3    ~~I
c3 sD$4 %T3/ltT$T3/ltT

 
 !2DOO4E
Fk 
!
!+
.

 
 
-

 
 
-/ /rJ   a_zerob_zeroa_rpsb_rpsc                     t        |      t        |      k(  sJ |rAt        | ||d   |d         \  }}}t        |||dd |dd       \  }}}	|g|z   |g|z   |g|	z   fS g g g fS )aY  Create BroadcastLayers from two shapes to a target shape.


      *--a_zero->*<-b_zero-*
      |          |         |
   a_rps[0]    c_rps[0]  b_rps[0]
      |          |         |
      V          V         V
      *--ac[1]-->*<-bc[1]--*
      |          |         |
   a_rps[1]   c_rps[0]   b_rps[1]
      |          |         |
      V          V         V
      *--ac[2]-->*<-bc[2]--*

  Note: ac[0]=a_zero, and bc[0]=b_zero.
  Args:
    a_zero: broadcaster from rows of a_rps[0] to target shape.
    b_zero: broadcaster from rows of b_rps[0] to target shape.
    a_rps: RowPartitions of first shape.
    b_rps: RowPartitions of second shape, equal in length to a_rps.

  Returns:
    (c_rps, ac, bc) where:
    c_rps: RowPartitions of target shape.
    ac: layers broadcasting from the first shape.
    bc: layers broadcasting from the second shape.
  r   r@   N)r   rh  !_broadcast_dynamic_shape_from_rps)
ri  rj  rk  rl  r@  rL  rN  c_suffixa_layersb_layerss
             r=   rn  rn  
  s    B 
Us5z	!!	!
0q16q;S$	 34uQRy389>Xx EHtfx/$(1BCCB<rJ   c                 \   | j                   dk(  r|j                   dk(  ry| j                   t        d|j                  | j                  z
        z   }|j                   t        d| j                  |j                  z
        z   }| j                   dk(  r|S |j                   dk(  r|S t        ||      S )z9Returns broadcast_dynamic_shape(a, b).num_row_partitions.r   )r*   r  r[   )r"  r#  expanded_num_row_partitions_aexpanded_num_row_partitions_bs       r=   !_get_broadcast_num_row_partitionsru  	  s     aA$8$8A$="#"6"6Q9P"P"#"6"6Q9P"PQ((Q((	*,I	JJrJ   ro  r  	bc_suffixc                    |dt        |        }|j                  t        |      z
  }t        |      D cg c]&  }t        j	                  |j                  |            ( }	}t        | |      }
t        j                  |t        |      z         }|j                  |
      }|t        | ||      t        |||	|z         fS c c}w )z,Helper for broadcast_dynamic_shape_extended.N)r   r[   r   r  r  r   ru  r0   r   r|   r   r  )r"  r#  rl  ro  r  rv  c_prefixbc_prefix_lengthr  	bc_prefixc_num_row_partitionsc_rawr  s                r=   *_broadcast_dynamic_shape_extended_completer}    s     ?S]N#(VVc)n, %&
 001K1KA1NO)  ;1a@

0
0E(O1K
L%$$%9:!
\!Q#\!Q	I8M%N	OOs   +B>c           	         | j                   |j                   k  sJ d|j                   k  sJ d| j                   k  sJ | j                         }|j                         }t        |      t        |      k  r| d   }t        j                  |      }||}t        j                  |d|      }|t        |      dz       }t        t        j                  d|d   j                        |j                               \  }}	t        ||	||      \  }
}}t        |      dk\  r|t        |       d ng }t        ||||      \  }}}t        | |||
g|z   |g|z   |	|g|z         S t        |      t        |      k(  sJ t        |d   j                         |d   j                               \  }}t        ||||      \  }}}t        | ||||g|z   |g|z         S )zHelper for broadcast_dynamic_shape_extended.

  Here, we force:
    a.rank <= b.rank
    2 <= b.rank
    1 <= a.rank
  Args:
    a: a DynamicRaggedShape
    b: a DynamicRaggedShape

  Returns:
    A triple of a shape and two broadcasters.
  r   r@   r   Nr  r'   )r"  r#  rl  ro  r  rv  )r[   r-  r   r   r   r   r   r:  r	   r   r&   rB   rh  rn  r}  )r"  r#  rk  rl  a_nrowsa_nrows_staticneg_one_a_rpneg_one_b_rp
neg_one_ac
neg_one_bcc_zeroac_zerobc_zero
b_rps_tailro  	ac_layers	bc_layersc_rpsrp  rq  s                       r=   r  r  /  s     
166			
aff	
aff



 %



 %Z#e* dG //8N!g77"!7<L3u:>*+LCQeAhnn5|7I7I7K MZ
 4J
4@,PVW(+E
aE
{|$RJ 4GWe4>@Xy 6

H$9y w')35 5 u:U###4U1X^^5E5:1X^^5EGW 37GU38:UH5

9x)h&( (rJ   c                     | dk  r|t        d      || z   } | dk  rd} |dkD  r
| |dz   k  r| S | dk(  r| S |t        d      | |k\  r|} | S ),Slice indexes are always silently truncated.r   :Rank must be known to use __getitem__ on a negative index.r@   r   )r   )r   r[   r*   s      r=   r   r   }  s}    
QY|
FH H5LE
QYE1*<q*@!@L
aZL	\
N
OO
d]E	,rJ   c                     | |t        d      |} | dk  r|t        d      || z   } | dk  rd} |t        ||       } | S )r  z5Rank must be known to use __getitem__ without a stop.r   r  )r   min)r   r[   s     r=   r   r     sg    
]|NOOE
QY|
FH H5LE
QYE	eE	,rJ   c                 b   fd}fd}t        j                  | t        j                  d| j                              }t        j                  |       }t        j                  t        j                  ||      dd      }t        j                  |||      }t        j                  |g|      S )zReturn the first layer gather_index.

  Args:
    nrows_source: the number of rows in the source.
    nrows_target: the number of rows in the target.

  Returns:
    A tensor, usable as a gather_index for a _LayerBroadcaster.
  c                  F    t        j                    j                        S rL   )r   r  r&   )r  s   r=   gi_broadcast_firstz5_first_layer_gather_index.<locals>.gi_broadcast_first  s    ??<|/A/ABBrJ   c                  J    t        j                  j                        } | S rL   )r   r   r&   )r  r  s    r=   gi_no_broadcast_firstz8_first_layer_gather_index.<locals>.gi_no_broadcast_first  s    >>,l6H6HILrJ   r@   Tr&  rp   r  )r   r'  r	   r   r&   r   r   r(  r   r   r   )r  r  r  r  do_broadcastr.  r/  r  s    `      r=   r  r    s    C  + 4 4Q8J8J KM,|\:+((,4
 "-
 .9NP, 
	+	+]O\	JJrJ   c                 f    t        j                   j                  j                                fd}fd}j	                         s |       S t        j                  j                         t        j                  dj                              }t        j                  |||      }|S )a  Create the next layer gather_index whether or not a broadcast happens.

     *----------bc-------->*
     |                     |
  original_rp           broadcast_rp
     |                     |
    \|/                   \|/
     *--next_broadcaster-->*

  Args:
    bc: the old broadcaster.
    original_rp: the original row partition.
    broadcast_rp: the target row partition.

  Returns:
    the gather_index for next_broadcaster.
  Raises:
    InvalidArgumentError if the shapes are incompatible.
  c                  N   t        j                  j                               } t        j                  j                         j                        }j                         }t        j                  ||d      }| j                         z   }t        j                  |g|      S )N)paramsindicesr&  rp   )
r   r  r  r   r  r   r   r?  r   r   )	rB  expected_row_lengthsactual_row_lengthsrg  r  r  r  rA  r  s	        r=   gi_no_broadcastz1_next_layer_gather_index.<locals>.gi_no_broadcast  s    %%k&<&<&>&68N$++&&("//C%113((0:LNK!L$@$@$BBL--{m\JJrJ   c                       S r?  rg   )rA  s   r=   gi_broadcastz._next_layer_gather_index.<locals>.gi_broadcast  s     rJ   r@   r  )r   r  r  r>  r   r   r'  r)   r	   r   r&   r   )r  r  r  r  r  r  r  rA  s   ```    @r=   r  r    s    ( %%boo&2&?&?&AC
K	 
			! > > @ + 4 4Q8I8I JL,L?D, 
rJ   c                     t        | t        j                        rt        j                  | j
                        S | j
                  j                  S r?  )rs   r   rc   r   rX   r1  )r  s    r=   r   r     s5    M../??2>>**			rJ   r   c           	      D   | d   }g }| dd D ]  }t        |t              r2|}||z  }|}|j                  t        j                  ||||             E|t        |      k7  rt        d      |j                  t        j                  ||             t        |      } ||fS )a[  Allow ragged and uniform shapes to be specified.

  For example, [2, [2,1], 2] represents a shape like:
  [[[0, 0], [0, 0]], [[0, 0]]]

  Args:
    lengths: a list of integers and lists of integers.
    dtype: dtype of the shape (tf.int32 or tf.int64)

  Returns:
    a sequence of RowPartitions, and the number of values of the last partition.
  r   r@   N)rB   rn   zShape not consistent.)rn   )	rs   r   rD   r   r   r   r   r  sum)r   r&   size_so_farrF   current_lengthsrB   rC   s          r=   r   r     s     
+&  )o/3'e%ekmm

.
.uEeEF 
O,	,011mm

'
'E
JL(k) +	rJ   c                 Z    | t         u ryt        | t              rd| z   dz   S t        |       S )z"element to a string within a list.z...')r   rs   ru   r   s    r=   _element_to_stringr  %  s-    (]37S=	Q-rJ   c                 H    | sydt        | d         z   t        | dd       z   S )z?Print the tail of a list where the list might have an ellipsis.]rL  r   r@   Nr  _list_tail_with_ellipsisarrs    r=   r  r  .  s.    	$SV,,/GAB/PPPrJ   c                 H    | sydt        | d         z   t        | dd       z   S )z&Print a list that might have ellipsis.z[][r   r@   Nr  r  s    r=   r   r   6  s.    		!#a&)	),DSW,M	MMrJ   c                 z    t        | t              ryt        | t              sy| D ]  }t        |t              r y y)NTF)rs   r   r|   )r   r  s     r=   r   r   =  s=    3	Au	 aa 
rJ   c                     |dk(  r&t        j                  | j                         g|      S |dz
  }| | d j                         }| d|  j                         }t        j                  |g|z   |      S )zGHelper for _alt_inner_shape, used directly in _with_num_row_partitions.r@   r'   N)r	   r   rc  r   )rX   r&   r   new_inner_rank_tail_lengthinner_shape_tailr   s         r=   r   r   H  s    q!3!3!5 6eDD-16678@@B0001>>@)			yk,<<E	JJrJ   dividenddivisorc                 >    t        j                  |      dk(  ry | |z  S r\  )r   r   )r  r  s     r=   rG  rG  R  s#    !!'*a/	W	rJ   c                    | j                   t        j                  k(  rYt        j                  t        j
                  t        j                  | t        j                              t        j                        S t        j
                  |       S r?  )r&   r
   r{   r   r   r   rz   r  s    r=   r   r   Z  sY    WW==X]]1fll;<fllL L			a	  rJ   r$   c                     | d   j                         }| dd  D ]&  }t        j                  |j                         |      }( t        j                  |      S )Nr   r@   )r  r   r  r   r  )r$   r  r9   s      r=   r  r  e  sV     a ++-*12 ?b!!"--/:>J?		%	%j	11rJ   rj   r%   r  r  c                    | d| }| |dz   d }| ||dz    }t        |      g}t        j                  |||gd      }|d| }	||dz   d }
|||dz    }t        j                  |j                         g      }|	|z   |
z   }||fS )z.Merge the inner shape of a DynamicRaggedShape.Nr@   r   r   )r   r   r   r   r   rc  )rj   r%   r  r  r  r  internalinternal_valuenew_internalprefix_staticsuffix_staticinternal_staticinternal_value_staticnew_internal_statics                 r=   r  r  q  s     {
#&zA~'&JN3(&x01.!!6>6"BK,$[j1-$Z!^_5-&z*q.A/&22##%&(%(==M
+	,,rJ   rp_specr7   c                    |!t        | j                  | j                        S | j                  dn| j                  |z  }| j                  dn| j                  |z  }t        ||| j                  | j                        S )a  Batches a RowPartitionSpec.

  Given a RowPartitionSpec and a batch_size, create a RowPartitionSpec that
  will be the spec for the concatenation of batch_size RowPartitions.

  A RowPartition can be considered a transformation from a list of a given
  length to a list of lists. Assume rp_a is a map from list_a to nlist_a,
  And rp_b is a map from list_b to nlist_b. concat(rp_a, rp_b) is a
  transform of concat(list_a, list_b) to concat(nlist_a, nlist_b).

  If batch_size is None, then have the spec be able to handle an arbitrary
  number of RowPartitions.

  Args:
    rp_spec: a RowPartitionSpec for all the RowPartitions to be concatenated.
    batch_size: the number of rp_specs to be concatenated.

  Returns:
    a batched RowPartitionSpec.
  Nr(   rA   )r   r)   r&   rB   rC   )r  r7   rB   rC   s       r=   r-   r-     s}    , "55W]]L L--'$W]]Z-G%--'$W]]Z-G%	 33MM	
 rJ   old_headc                     | j                   |dn|| j                   z  }t        ||| j                   | j                        S )zBCreates a RowPartitionSpec representing the new dimension created.NrA   )rB   r   r&   )r  r7   rC   s      r=   r+   r+     sK     >>)% ,6,G 	!NN	
 rJ   	old_shapec                 D    t        j                  | d      |z  }|| dd z   S )a  Returns a copy of old_shape with axis=0 multiplied by batch_size.

  Only use if this is the inner_shape of a DynamicRaggedShape.Spec with one
  or more row partitions.

  Args:
    old_shape: the original inner_shape.
    batch_size: the batch size.

  Returns:
    a new shape.
  r   r@   Nr   rF  r  r7   head_dims      r=   r.   r.     s,     ,,Y:ZG(	IabM	!!rJ   c                 4    t        j                  |g      | z   S r?  )r   r   )r  r7   s     r=   r5   r5     s    		!	!:,	/)	;;rJ   c                 D    t        j                  | d      |z  }|| dd z   S )z9Unbatch a static_inner_shape when num_row_partitions > 0.r   r@   Nr  r  s      r=   rE   rE     s,     ,,Y:jH(	IabM	!!rJ   ro   c                     t        j                  | j                  ||      }t        j                  j                  || j                        S )zReturns ones shaped like x.)r&   ro   )r   rQ   rj   r   rc   r:  r$   )rX   r&   ro   r1  s       r=   rQ   rQ     s@     u00DI+		#	#	?	?5''
) )rJ   r?  )erb   r  typingr   r   r   r   r   r   numpyrx   tensorflow.python.frameworkr	   r
   r   r   r   rd   r   r   tensorflow.python.opsr   r   r   r   r   r   tensorflow.python.ops.raggedr   *tensorflow.python.ops.ragged.row_partitionr   r   tensorflow.python.typesr   tensorflow.python.utilr    tensorflow.python.util.tf_exportr   ExtensionTypeBatchEncoderr   BatchableExtensionTyper0   r  r  r  r  $dispatch_for_binary_elementwise_apisRaggedOrDenser  +dispatch_for_binary_elementwise_assert_apisr  r  rw   rw  rv   ABCr  r  r  r   r  r  r  r:  rC  rX  re  rh  rn  ru  r}  r  r   r   r  r  r   r   r   r  r  r   r   r   r   rG  r   r~  DenseOrRaggedShaper  re   r   r  r-   r+   r.   r5   rE   float32ru   rQ   rg   rJ   r=   <module>r     s    B B  3 . 6 + < 4 3 + 1 + & 2 * 6 C G ( + 6l%n&N&N l%r ,-L7>> L7 .L7^,?%7 ?%7?<N?6#)"4 #)L6868068rO /..}/J/J/</J/JL.-L.-b 655!<!<>4 >4 n&4:smFLL!&.v||&<,S= S=l5/ 5@F> F>R,0^8<v,Q$hIXB
B	B 1< ?@B<K
K#4K;GK	K <*,==>K\r
r#4r;Gr	r <*,==>rj8/
8/#48/;G8/	8/ <*,==>8/v,,'8,L!,*2<*@, 8L!8,=#>%&' (,^K); K);K&PP0P9A,9OP|$P*23D*EP )*P |\9:	P&K(K(0K(
|\9:K(\*$K@6r eC#./0,/45DQNKl44 )338D8N8N! -t>? 	2\*	2/;	2-""-$00- - 	- j//1I1IIJ	-,, '}1AD	"2 	$,SM	6F	"''""".":":"&<<#;#; <$'<,8,D,D<
"''""".":":" ~~#)" )})(5(C(C)rJ   