o
    2hn                     @   s~   d Z ddlZddlZddlZddlmZ ddlmZ ddlm	Z	 ddl
mZ dgZdd	 Zd
d Zdd Zdd Zdd ZdS )z/Utilities for slicing in to a `LinearOperator`.    N)dtypes)tensor_util)	array_ops)nestbatch_slicec                 C   sP   | ||g}dd |D }t dd |D r!|\}}}t|||S t| ||S )Nc                 S   s   g | ]}t |qS  )r   constant_value).0ar   r   _/var/www/html/chatgem/venv/lib/python3.10/site-packages/tensorflow/python/ops/linalg/slicing.py
<listcomp>    s    z(_prefer_static_where.<locals>.<listcomp>c                 s   s    | ]}|d uV  qd S Nr   )r	   argr   r   r   	<genexpr>"   s    z'_prefer_static_where.<locals>.<genexpr>)allnpwherer   )	conditionxyargsconstant_args
condition_x_y_r   r   r   _prefer_static_where   s   

r   c           	   	   C   s   t | dr7i }| j D ]\}}t| |}t|tjt|d||||< qt	| j
fi |}t| di |S tj|tj|gtjdgdd}t| t|t| S )z;Broadcasts `param` with the given batch shape, recursively.batch_shape_tensor)batch_shape)dtyper   )axisNr   )hasattr-_experimental_parameter_ndims_to_matrix_ndimsitemsgetattrr   map_structure_up_to	functoolspartial%_broadcast_parameter_with_batch_shapedict
parameterstyper   concatonesr   int32broadcast_tobroadcast_dynamic_shapeshape)	paramparam_ndims_to_matrix_ndimsr   override_dictnamendims	sub_paramr)   
base_shaper   r   r   r'   (   s.   


r'   c                 C   s  g }d}| D ]y}|t u r-|dk rtd| tdd | | t d d D }| }nM|tju r3nG|| || k}t|trp|j	|j
|j}}	}
|durUt|d|}|	dur_t|d|	}	|
durit|d|
}
t||	|
}nt|d|}|d7 }|| q|S )a  Restricts slices to avoid overflowing size-1 (broadcast) dimensions.

  Args:
    slices: iterable of slices received by `__getitem__`.
    intended_shape: int `Tensor` shape for which the slices were intended.
    deficient_shape: int `Tensor` shape to which the slices will be applied.
      Must have the same rank as `intended_shape`.
  Returns:
    sanitized_slices: Python `list` of slice objects.
  r   z!Found multiple `...` in slices {}c                 s   s    | ]}|t juV  qd S r   )r   newaxis)r	   sr   r   r   r   P   s    

z#_sanitize_slices.<locals>.<genexpr>   N)Ellipsis
ValueErrorformatsumindexr   r8   
isinstanceslicestartstopstepr   append)slicesintended_shapedeficient_shapesanitized_slicesidxslc num_remaining_non_newaxis_slicesis_broadcastrB   rC   rD   r   r   r   _sanitize_slices?   s8   

rN   c                 C   s   t | |t|} t| dr|  }nt| }t|}|d||  }tt|dkr;tt|dkr;| S t	|||d}|dkr]t
dd |D vrT|t
 |tdg| 7 }| t|S )a  Slices into the batch shape of a single parameter.

  Args:
    param: The original parameter to slice; either a `Tensor` or an object
      with batch shape (LinearOperator).
    param_ndims_to_matrix_ndims: `int` number of right-most dimensions used for
      inferring matrix shape of the `LinearOperator`. For non-Tensor
      parameters, this is the number of this param's batch dimensions used by
      the matrix shape of the parent object.
    slices: iterable of slices received by `__getitem__`.
    batch_shape: The parameterized object's batch shape `Tensor`.

  Returns:
    new_param: Instance of the same type as `param`, batch-sliced according to
      `slices`.
  r   Nr   )rG   rH   c                 S   s   g | ]	}t |s|qS r   )r   	is_tensor)r	   rK   r   r   r   r      s
    
z'_slice_single_param.<locals>.<listcomp>)r'   r   	ones_liker    r   r0   sizer   r   rN   r;   rE   rA   __getitem__tuple)r1   r2   rF   r   param_batch_shapeparam_batch_rankparam_slicesr   r   r   _slice_single_parami   s.   





rW   c           	   	   C   s   t |tjjs
|f}t|dkr|d tu ri }n)|  }i }| j D ]\}}t	| |}|durAt
|tjt||d||||< q$|| t| jfi |}t| di |S )a[  Slices `linop` along its batch dimensions.

  Args:
    linop: A `LinearOperator` instance.
    params_overrides: A `dict` of parameter overrides.
    slices: A `slice` or `int` or `int` `Tensor` or `tf.newaxis` or `tuple`
      thereof. (e.g. the argument of a `__getitem__` method).

  Returns:
    new_linop: A batch-sliced `LinearOperator`.
  r:   r   N)rF   r   r   )r@   collectionsabcSequencelenr;   r   r!   r"   r#   r   r$   r%   r&   rW   updater(   r)   r*   )	linopparams_overridesrF   r3   r   
param_namer2   r1   r)   r   r   r   r      s&   

)__doc__rX   r%   numpyr   tensorflow.python.frameworkr   r   tensorflow.python.opsr   tensorflow.python.utilr   __all__r   r'   rN   rW   r   r   r   r   r   <module>   s   
*2