
    2Vh5                     Z    d dl Z d dlmc mZ d dlmZ d dlm	Z	 d Z
d Zd Zd Zd Zd Zy)	    N)	jax_utilsc                 r   | t        d      t        | t              r| f} t        t	        |             t        |       k7  rt        d|        t        |      }|r|t        |       z  }g }| D ]<  }| |cxk  r|k  sn t        d| d|       |dk  r||z   }|j                  |       > t        t	        |            t        |      k7  rt        d|       t        |      }t        |      }|D ]  }|r|j                  |d       d||<    t        |      D cg c]	  }||vs| }}|||fS c c}w )a  Turn the `axis` argument to the arguments needed by `broadcast_in_dim`.

    Args:
        axis: single int or a tuple of ints for the axis argument. The list of
          dimensions to reduce or insert.
        input_shape: the shape of the input as a tuple ints.
        insert_dims: `False` turns dimensions in `axis` to 1s (use case:
          reduction along `axis` with `keep_dims=True`). `True`, inserts 1s
          according to `axis` (use case: `expand_dims`).
    Returns:
        A tuple of three lists
        - The canonical value for `axis`: always a list, negative values have
          been resolved and values are sorted in ascending order.
        - The output shape: `input_shape` with 1s at the indices in `axis`, for
          use as the `shape` argument of `broadcast_in_dim`.
        - The broadcast dimensions: list of dimensions not in `axis`, for use as
          the `broadcast_dimensions` argument of `broadcast_in_dim`.
    z Received `None` value for `axis`zRepeated axis in `axis`: zIn `axis`, axis z) is out of bounds for array of dimension r      )

ValueError
isinstanceintlensetappendsortedlistinsertrange)	axisinput_shapeinsert_dimsresult_dimscanonical_axisaoutput_shapeibroadcast_dimss	            L/home/dcms/DCMS/lib/python3.12/site-packages/keras/src/backend/jax/sparse.py$axis_shape_dims_for_broadcast_in_dimr   	   sr   & |;<<$w
3t9~T"4TF;<<k"Ks4y  N !|q.;."1# &  +}.  q5KAa ! 3~3~#664^4DEFFN+N $L  1%LO	 
 "'{!3OAq7NaONO<77 Ps   	D4)D4c                    t        j                  |j                  j                  | j                  j                        }t        | j                  j                        dz
  }t        j                  | j                  |j                  g|      }t        j                  | j                  |g|      }t        j                  ||f| j                        }|rt        j                  |      }|S )au  Add the indices of `x2` to `x1` with zero values.

    Args:
        x1: `BCOO` tensor to add indices to.
        x2: `BCOO` tensor to take the indices to add to x1.
        sum_duplicates: if `True` calls `bcoo_sum_duplicates` on the output.
    Returns:
        a `BCOO` tensor equal to `x1` but with extra zeros at indices in `x2`
        that were missing in `x1`.
       )r   shape)jnpzerosdatar   dtyper	   indicesconcatenate
jax_sparseBCOObcoo_sum_duplicates)x1x2sum_duplicatesx2_zerosconcat_axisoutput_indicesoutput_dataoutputs           r   bcoo_add_indicesr0   C   s     yy6Hbjj&&'!+K__bjj"**%=KPN//277H"5KHK__k>:"((KF//7M    c                 B     t        j                          fd       }|S )a  Decorator to add support for `JAXSparse` tensors (including `BCOO`) to a
    non-zero-preserving element-wise unary operator.

    There are requirements on the operator for this decorator to work correctly:

    - The operator must be element-wise
    - The operator must be unary (one input tensor and one output tensor)
    - The operator must return a tensor of the same shape.

    Additional arguments to the function (besides the input tensor) are
    supported. The returned result is a dense tensor.

    Args:
        func: The unary operator to wrap.
    Returns:
        Wrapped function that supports `JAXSparse` tensors.
    c                 p    t        | t        j                        r| j                         }  | g|i |S )N)r   r%   	JAXSparsetodense)xargskwargsfuncs      r   sparse_wrapperz(densifying_unary.<locals>.sparse_wrapperk   s3    a--.		AA''''r1   	functoolswraps)r9   r:   s   ` r   densifying_unaryr>   X   s(    & __T( (
 r1   c                       fd}|S )a   Decorator to add support for `BCOO` sparse tensors to a zero-preserving
    element-wise unary operator.

    There are requirements on the operator for this decorator to work correctly:

    - The operator must be element-wise
    - The operator must be unary (one input tensor and one output tensor)
    - The operator must return a tensor of the same shape, and if it is a
      `BCOO` tensor, the indices of the result must be the same. Therefore:
        - Reduction operations are not supported (e.g. `mean`).
        - Operations for which the result may be dense (e.g. `reciprocal`), or
          the sparse indices depend on the inputs are not supported (e.g.
          `clip`). This implies that `func(0)` must be 0.

    Additional arguments to the function (besides the input tensor) are
    supported as long as they cannot change the indices of the result. For
    instance,`round` is supported, but `clip` is not supported as
    `clip(x, 1.0, 2.0)` would always return a dense tensor.

    Note that if an input sparse tensor contains zero values, the indices and
    the zero values are preserved.

    Args:
        linear: if `True`, means that the operation is such that
            `op(a + b) == op(a) + op(b)`.
    Returns:
        Wrapped function that supports `BCOO` sparse tensors.
    c                 F     t        j                          fd       }|S )Nc                    t        | t        j                        rds!| j                  st        j                  |       } t        j                   | j
                  g|i || j                  f| j                        S  | g|i |S )Nr   )r   r%   r&   unique_indicesr'   r!   r#   r   )r6   r7   r8   r9   linears      r   r:   zIelementwise_unary.<locals>.wrap_elementwise_unary.<locals>.sparse_wrapper   sy    !Z__-a&6&6"66q9A!!&&24262AII>agg  A////r1   r;   )r9   r:   rC   s   ` r   wrap_elementwise_unaryz1elementwise_unary.<locals>.wrap_elementwise_unary   s&    			0 
	0 r1    )rC   rD   s   ` r   elementwise_unaryrF   t   s    < "!r1   c                       fd}|S )a9  Decorator to add support for `JAXSparse` tensors (including `BCOO`) to an
    element-wise binary operator such that the indices present in the result are
    are the union of the indices in the two operand.

    The primary use case for this is the `add` and `subtract` operators.

    There are requirements on the operator for this decorator to work correctly:

    - The operator must be element-wise.
    - The operator must be binary (two input tensors and one output tensor).
    - Both inputs must be of the same shape or one input must be a scalar.
    - The output must be of the same shape as the (non scalar) inputs.
    - The indices of the output must be the union of the indices of the inputs.
      This implies that func(0, 0) must be 0. As a result, if one operand is
      dense or a scalar, then the result will be dense.

    Additional arguments to the function (besides the input tensors) are not
    supported.

    Note that if the result of the operation is zero at some indices, including
    because the operands were zero at these indices, the zeros and indices are
    preserved.

    The `BCOO` format is the only supported one in all cases. Other formats are
    not supported when `use_sparsify` is `False`.

    Args:
        use_sparsify: indicates that the JAX `sparsify` transform supports this
            operation.
        linear: if `True`, mean that the operation is such that
            `op(a + b, c) == op(a, c) + op(b, c)` and
            `op(a, c + d) == op(a, c) + op(a, d)`.
    Returns:
        Wrapped function that supports `JAXSparse`.
    c                 ~     rt        j                         nd t        j                          fd       }|S )Nc                 V   t        | t        j                        rt        |t        j                        r| j                  |j                  u rt        | t        j                        rt        |t        j                        rs6| j
                  s*t        j                  |       } t        j                  |      }t        j                   | j                  |j                        | j                  f| j                  | j                  | j
                        S r	 | |      S t        | t        j                        rt        |t        j                        rht        | |       } t        ||        }t        j                   | j                  |j                        | j                  f| j                  dd      S t        d| j                   d|j                          n;| j                         } n*t        |t        j                        r|j                         } | |      S )Nr   indices_sortedrB   r*   TUnsupported sparse format: z and )r   r%   r4   r#   r&   rB   r'   r!   r   rK   r0   r   	__class__r5   )r(   r)   r9   rC   sparse_funcuse_sparsifys     r   r:   zWelementwise_binary_union.<locals>.wrap_elementwise_binary_union.<locals>.sparse_wrapper   s   "j223b*"6"67
 

bjj0&r:??;&r:??;%b.?.?!+!?!?!CB!+!?!?!CB)!"''2773RZZ@"$((+-+<+<+-+<+<	   &*2r22#B
8ZJOO> .b"ZP-b"ZP)!"''2773RZZ@"$((+/+/	   #9!||nE",,A BB
 4 45ZZ\B<r1   r%   sparsifyr<   r=   )r9   r:   rO   rC   rP   s   ` @r   wrap_elementwise_binary_unionz?elementwise_binary_union.<locals>.wrap_elementwise_binary_union   s;    3?j))$/T		,	  
,	 \ r1   rE   )rC   rP   rS   s   `` r   elementwise_binary_unionrT      s    J2h )(r1   c                 p     t        j                         t        j                          fd       }|S )aW  Decorator to add support for `BCOO` sparse tensors to element-wise binary
    division and related operators.

    This decorator is designed for operations related to the division of two
    two operands (e.g. `divide`). It accepts `BCOO` tensors for both the
    dividend and the divisor, but handles them differently based on whether they
    are the dividend or the divisor.

    - If the divisor is sparse, it is densified and the result is dense because
      the result contains Inf or Nan outside of the indices of the dividend.
    - If the dividend is sparse and the divisor is dense, it finds occurrences
      of zeros and NaNs in the divisor. The result may therefore have more
      indices than there were in the dividend to return correct values where the
      divisor was zero or NaN.
    - If the dividend is sparse and the divisor is a scalar, it does the
      division element-wise. Note that the result is incorrectly sparse if the
      scalar divisor is zero.

    Args:
        func: The function to wrap.
    Returns:
        Wrapped function that supports `BCOO` sparse tensors.
    c                 "   t        | t        j                        rt        |t        j                        r"| j                         } |j                         }nt        | t        j                        rRt        |d      rt        |j                        dk(  rTt        j                   | j                  |      | j                  f| j                  | j                  | j                        S t        j                  |      st        j                  |d      }t        j                   |j"                  t        j$                        s)t        j&                  |t        j(                  |            }t        j*                  || j,                  | j.                  | j                  j"                        }t1        | |d      }  | |      S t3        d| j4                         t        |t        j                        r|j                         } | |      S )Nr   r   rJ   )n_batchn_denseindex_dtypeTrL   rM   )r   r%   r4   r5   r&   hasattrr	   r   r!   r#   rK   rB   r   is_in_jax_tracing_scoper   equal
issubdtyper"   integer
logical_orisnanbcoo_fromdenserW   rX   r0   r   rN   )r(   r)   x2_zeros_and_nansr9   rO   s      r   r:   z,elementwise_division.<locals>.sparse_wrapper  s   b*../"j223 ZZ\ZZ\B
0r7+s288}/A%??bggr*BJJ7 hh')'8'8')'8'8	  %<<R@ -0IIb!,<)"~~bhhD03 1399R=1- -7,E,E-$&JJ$&JJ(*

(8(8	-) . 1$ 'r2.. #>r||n!MNNJ001BB|r1   rQ   )r9   r:   rO   s   ` @r   elementwise_divisionrc      s9    0 %%d+K__T, ,\ r1   )r<   jax.experimental.sparseexperimentalsparser%   	jax.numpynumpyr   keras.src.utilsr   r   r0   r>   rF   rT   rc   rE   r1   r   <module>rj      s7     , ,  %78t*8,"^Y)xIr1   