code: def projection_l1_2(
      values: np.ndarray, eps: Union[int, float, np.ndarray]
  ) -> np.ndarray:
      """
      This function computes the orthogonal projections of a batch of points on L1-balls of given radii
      The batch size is  m = values.shape[0].  The points are flattened to dimension
      n = np.prod(value.shape[1:]).  This is required to facilitate sorting.
  
      Starting from a vector  a = (a1,...,an)  such that  a1 >= ... >= an >= 0,  a1 + ... + an > 1,
      we first move to  a' = a - (t,...,t)  such that either a1 + ... + an >= 1 ,  an >= 0,
      and  min( a1 + ... + an  - nt - 1, an -t ) = 0.  This means  t = min( (a1 + ... + an - 1)/n, an).
      If  t = (a1 + ... + an - 1)/n , then  a' is the desired projection.  Otherwise, the problem is reduced to
      finding the projection of  (a1 - t, ... , a{n-1} - t ).
  
      :param values:  A batch of  m  points, each an ndarray
      :param eps:  The radii of the respective L1-balls
      :return: projections
      """
      # pylint: disable=C0103
      shp = values.shape
      a = values.copy()
      n = np.prod(a.shape[1:])
      m = a.shape[0]
      a = a.reshape((m, n))
      sgns = np.sign(a)
      a = np.abs(a)
      a_argsort = a.argsort(axis=1)
      a_sorted = np.zeros((m, n))
      for i in range(m):
          a_sorted[i, :] = a[i, a_argsort[i, :]]
  
      a_argsort_inv = a.argsort(axis=1).argsort(axis=1)
      row_sums = np.sum(a, axis=1)
      mat = np.zeros((m, 2))
      mat0 = np.zeros((m, 2))
      a_var = a_sorted.copy()
      for j in range(n):
          mat[:, 0] = (row_sums - eps) / (n - j)
          mat[:, 1] = a_var[:, j]
          mat0[:, 1] = np.min(mat, axis=1)
          min_t = np.max(mat0, axis=1)
          if np.max(min_t) < 1e-8:
              continue
          row_sums = row_sums - a_var[:, j] * (n - j)
          a_var[:, (j + 1) :] = a_var[:, (j + 1) :] - np.matmul(
              min_t.reshape((m, 1)), np.ones((1, n - j - 1))
          )
          a_var[:, j] = a_var[:, j] - min_t
      proj = np.zeros((m, n))
      for i in range(m):
          proj[i, :] = a_var[i, a_argsort_inv[i, :]]
  
      proj = sgns * proj
      proj = proj.reshape(shp)
      return proj
  
imports: from __future__ import absolute_import, division, print_function, unicode_literals
  import logging
  import math
  import os
  import shutil
  import sys
  import tarfile
  import warnings
  import zipfile
  from functools import wraps
  from inspect import signature
  from typing import TYPE_CHECKING, Callable, List, Dict, Optional, Tuple, Union
  import numpy
  import six
  from scipy.special import gammainc
  from tqdm.auto import tqdm
  from art import config
label_desc: Use image node_id 4 for calling a global function with example usage: projection_l1_2(values, eps) and returns: proj