o
    ?en                     @   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   e/home/www/facesmatcher.com/pyenv/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argsZconstant_argsZ
condition_Zx_Z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)Zdtyper   )ZaxisNr   )hasattr-_experimental_parameter_ndims_to_matrix_ndimsitemsgetattrr   map_structure_up_to	functoolspartial%_broadcast_parameter_with_batch_shapedict
parameterstyper   concatZonesr   Zint32Zbroadcast_toZbroadcast_dynamic_shapeshape)	paramparam_ndims_to_matrix_ndimsr   override_dictnameZndimsZ	sub_paramr#   Z
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   r+   
isinstanceslicestartstopstepr   append)slicesintended_shapedeficient_shapeZsanitized_slicesidxslcZ num_remaining_non_newaxis_slicesZis_broadcastr5   r6   r7   r   r   r   _sanitize_slices?   s8   

r>   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   )r:   r;   c                 S   s   g | ]	}t |s|qS r   )r   Z	is_tensor)r	   r=   r   r   r   r      s
    
z'_slice_single_param.<locals>.<listcomp>)r!   r   Z	ones_liker   r   r&   sizer   r   r>   r.   r8   r4   __getitem__tuple)r'   r(   r9   r   Zparam_batch_shapeZparam_batch_rankZparam_slicesr   r   r   _slice_single_parami   s0   





rB   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)r9   r   r   )r3   collectionsabcSequencelenr.   r   r   r   r   r   r   r   r    rB   updater"   r#   r$   )	ZlinopZparams_overridesr9   r)   r   
param_namer(   r'   r#   r   r   r   r      s&   

)__doc__rC   r   numpyr   Ztensorflow.python.frameworkr   r   Ztensorflow.python.opsr   Ztensorflow.python.utilr   __all__r   r!   r>   rB   r   r   r   r   r   <module>   s   
*2