code: def _compute_diagonal(
      T_A,
      T_B,
      m,
      μ_Q,
      M_T,
      σ_Q_inverse,
      Σ_T_inverse,
      cov_a,
      cov_b,
      cov_c,
      cov_d,
      T_A_subseq_isfinite,
      T_B_subseq_isfinite,
      T_A_subseq_isconstant,
      T_B_subseq_isconstant,
      diags,
      diags_start_idx,
      diags_stop_idx,
      thread_idx,
      ρ,
      ρL,
      ρR,
      I,
      IL,
      IR,
      ignore_trivial,
  ):
      """
      Compute (Numba JIT-compiled) and update the (top-k) Pearson correlation (ρ),
      ρL, ρR, I, IL, and IR sequentially along individual diagonals using a single
      thread and avoiding race conditions.
  
      Parameters
      ----------
      T_A : numpy.ndarray
          The time series or sequence for which to compute the matrix profile
  
      T_B : numpy.ndarray
          The time series or sequence that will be used to annotate `T_A`. For every
          subsequence in `T_A`, its nearest neighbor in `T_B` will be recorded.
  
      m : int
          Window size
  
      μ_Q : numpy.ndarray
          Mean of the query sequence, `Q`, relative to the current sliding window
  
      M_T : numpy.ndarray
          Sliding mean of time series, `T`
  
      σ_Q_inverse : numpy.ndarray
          Inverse standard deviation of the query sequence, `Q`, relative to the current
          sliding window
  
      Σ_T_inverse : numpy.ndarray
          Inverse sliding standard deviation of time series, `T`
  
      cov_a : numpy.ndarray
          The first covariance term relating T_A[i + g + m - 1] and M_T_m_1[i + g]
  
      cov_b : numpy.ndarray
          The second covariance term relating T_B[i + m - 1] and μ_Q_m_1[i]
  
      cov_c : numpy.ndarray
          The third covariance term relating T_A[i + g - 1] and M_T_m_1[i + g]
  
      cov_d : numpy.ndarray
          The fourth covariance term relating T_B[i - 1] and μ_Q_m_1[i]
  
      T_A_subseq_isfinite : numpy.ndarray
          A boolean array that indicates whether a subsequence in `T_A` contains a
          `np.nan`/`np.inf` value (False)
  
      T_B_subseq_isfinite : numpy.ndarray
          A boolean array that indicates whether a subsequence in `T_B` contains a
          `np.nan`/`np.inf` value (False)
  
      T_A_subseq_isconstant : numpy.ndarray
          A boolean array that indicates whether a subsequence in `T_A` is constant (True)
  
      T_B_subseq_isconstant : numpy.ndarray
          A boolean array that indicates whether a subsequence in `T_B` is constant (True)
  
      diags : numpy.ndarray
          The diagonal indices
  
      diags_start_idx : int
          The starting (inclusive) diagonal index
  
      diags_stop_idx : int
          The stopping (exclusive) diagonal index
  
      thread_idx : int
          The thread index
  
      ρ : numpy.ndarray
          The (top-k) Pearson correlations, sorted in ascending order per row
  
      ρL : numpy.ndarray
          The top-1 left Pearson correlations
  
      ρR : numpy.ndarray
          The top-1 right Pearson correlations
  
      I : numpy.ndarray
          The (top-k) matrix profile indices
  
      IL : numpy.ndarray
          The top-1 left matrix profile indices
  
      IR : numpy.ndarray
          The top-1 right matrix profile indices
  
      ignore_trivial : bool
          Set to `True` if this is a self-join. Otherwise, for AB-join, set this to
          `False`. Default is `True`.
  
      Returns
      -------
      None
  
      Notes
      -----
      `DOI: 10.1007/s10115-017-1138-x \
      <https://www.cs.ucr.edu/~eamonn/ten_quadrillion.pdf>`__
  
      See Section 4.5
  
      The above reference outlines a general approach for traversing the distance
      matrix in a diagonal fashion rather than in a row-wise fashion.
  
      `DOI: 10.1145/3357223.3362721 \
      <https://www.cs.ucr.edu/~eamonn/public/GPU_Matrix_profile_VLDB_30DraftOnly.pdf>`__
  
      See Section 3.1 and Section 3.3
  
      The above reference outlines the use of the Pearson correlation via Welford's
      centered sum-of-products along each diagonal of the distance matrix in place of the
      sliding window dot product found in the original STOMP method.
      """
      n_A = T_A.shape[0]
      n_B = T_B.shape[0]
      m_inverse = 1.0 / m
      constant = (m - 1) * m_inverse * m_inverse  # (m - 1)/(m * m)
      uint64_m = np.uint64(m)
  
      for diag_idx in range(diags_start_idx, diags_stop_idx):
          g = diags[diag_idx]
  
          if g >= 0:
              iter_range = range(0, min(n_A - m + 1, n_B - m + 1 - g))
          else:
              iter_range = range(-g, min(n_A - m + 1, n_B - m + 1 - g))
  
          for i in iter_range:
              uint64_i = np.uint64(i)
              uint64_j = np.uint64(i + g)
  
              if uint64_i == 0 or uint64_j == 0:
                  cov = (
                      np.dot(
                          (
                              T_B[uint64_j : uint64_j + uint64_m]
                              - M_T[uint64_j]
                          ),
                          (
                              T_A[uint64_i : uint64_i + uint64_m]
                              - μ_Q[uint64_i]
                          ),
                      )
                      * m_inverse
                  )
              else:
                  # The next lines are equivalent and left for reference
                  # cov = cov + constant * (
                  #     (T_B[i + g + m - 1] - M_T_m_1[i + g])
                  #     * (T_A[i + m - 1] - μ_Q_m_1[i])
                  #     - (T_B[i + g - 1] - M_T_m_1[i + g]) * (T_A[i - 1] - μ_Q_m_1[i])
                  # )
                  cov = cov + constant * (
                      cov_a[uint64_j] * cov_b[uint64_i]
                      - cov_c[uint64_j] * cov_d[uint64_i]
                  )
  
              if (
                  T_B_subseq_isfinite[uint64_j]
                  and T_A_subseq_isfinite[uint64_i]
              ):
                  # Neither subsequence contains NaNs
                  if (
                      T_B_subseq_isconstant[uint64_j]
                      and T_A_subseq_isconstant[uint64_i]
                  ):
                      pearson = 1.0
                  elif (
                      T_B_subseq_isconstant[uint64_j]
                      or T_A_subseq_isconstant[uint64_i]
                  ):
                      pearson = 0.5
                  else:
                      pearson = (
                          cov
                          * Σ_T_inverse[uint64_j]
                          * σ_Q_inverse[uint64_i]
                      )
                      pearson = min(1.0, pearson)
  
                  # `ρ[thread_idx, i, :]` is sorted in ascending order and MUST be updated
                  # when the newly-calculated `pearson` value becomes greater than the
                  # first (i.e. smallest) element in this array. Note that a higher
                  # pearson value corresponds to a lower distance.
                  if pearson > ρ[thread_idx, uint64_i, 0]:
                      idx = np.searchsorted(
                          ρ[thread_idx, uint64_i], pearson
                      )
                      core._shift_insert_at_index(
                          ρ[thread_idx, uint64_i],
                          idx,
                          pearson,
                          shift="left",
                      )
                      core._shift_insert_at_index(
                          I[thread_idx, uint64_i],
                          idx,
                          uint64_j,
                          shift="left",
                      )
  
                  if ignore_trivial:  # self-joins only
                      if pearson > ρ[thread_idx, uint64_j, 0]:
                          idx = np.searchsorted(
                              ρ[thread_idx, uint64_j], pearson
                          )
                          core._shift_insert_at_index(
                              ρ[thread_idx, uint64_j],
                              idx,
                              pearson,
                              shift="left",
                          )
                          core._shift_insert_at_index(
                              I[thread_idx, uint64_j],
                              idx,
                              uint64_i,
                              shift="left",
                          )
  
                      if uint64_i < uint64_j:
                          # left pearson correlation and left matrix profile index
                          if pearson > ρL[thread_idx, uint64_j]:
                              ρL[thread_idx, uint64_j] = pearson
                              IL[thread_idx, uint64_j] = uint64_i
  
                          # right pearson correlation and right matrix profile index
                          if pearson > ρR[thread_idx, uint64_i]:
                              ρR[thread_idx, uint64_i] = pearson
                              IR[thread_idx, uint64_i] = uint64_j
  
      return
  
imports: import numba
  import numpy
  from numba import njit, prange
  from .None import config, core
  from .aamp import aamp
label_desc: Use image node_id 1 for calling a global function with example usage: _compute_diagonal(T_A, T_B, m, μ_Q, M_T, σ_Q_inverse, Σ_T_inverse, cov_a, cov_b, cov_c, cov_d, T_A_subseq_isfinite, T_B_subseq_isfinite, T_A_subseq_isconstant, T_B_subseq_isconstant, diags, diags_start_idx, diags_stop_idx, thread_idx, ρ, ρL, ρR, I, IL, IR, ignore_trivial) without return types