code: def projection_l1_1(
      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.
  
      If a[0] <= ... <= a[n-1], then the projection can be characterized using the largest  j  such that
      a[j+1] +...+ a[n-1] - a[j]*(n-j-1) >= eps. The  ith  coordinate of projection is equal to  0
      if i=0,...,j.
  
      :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)
      mat = np.zeros((m, 2))
  
      #   if  a_sorted[i, n-1]  >= a_sorted[i, n-2] + eps,  then the projection is  [0,...,0,eps]
      done = early_done = False
      active = np.array([1] * m)
      after_vec = np.zeros((m, n))
      proj = a_sorted.copy()
      j = n - 2
      while j >= 0:
          mat[:, 0] += a_sorted[
              :, j + 1
          ]  # =  sum(a_sorted[: i] :  i = j + 1,...,n-1
          mat[:, 1] = a_sorted[:, j] * (n - j - 1) + eps
          #  Find the max in each problem  max{ sum{a_sorted[:, i] : i=j+1,..,n-1} , a_sorted[:, j] * (n-j-1) + eps }
          row_maxes = np.max(mat, axis=1)
          #  Set to  1  if  max >  a_sorted[:, j] * (n-j-1) + eps  >  sum ;  otherwise, set to  0
          ind_set = np.sign(np.sign(row_maxes - mat[:, 0]))
          #  ind_set = ind_set.reshape((m, 1))
          #   Multiplier for activation
          act_multiplier = (1 - ind_set) * active
          act_multiplier = np.transpose(
              [np.transpose(act_multiplier)] * n
          )
          #  if done, the projection is supported by the current indices  j+1,..,n-1   and the amount by which each
          #  has to be reduced is  delta
          delta = (mat[:, 0] - eps) / (n - j - 1)
          #    The vector of reductions
          delta_vec = np.transpose(np.array([delta] * (n - j - 1)))
          #   The sub-vectors:  a_sorted[:, (j+1):]
          a_sub = a_sorted[:, int(j + 1) :]
          #   After reduction by delta_vec
          a_after = a_sub - delta_vec
          after_vec[:, int(j + 1) :] = a_after
          proj += act_multiplier * (after_vec - proj)
          active = active * ind_set
          if sum(active) == 0:
              done = early_done = True
              break
          j -= 1
      if not early_done:
          delta = (mat[:, 0] + a_sorted[:, 0] - eps) / n
          ind_set = np.sign(np.maximum(delta, 0))
          act_multiplier = ind_set * active
          act_multiplier = np.transpose(
              [np.transpose(act_multiplier)] * n
          )
          delta_vec = np.transpose(np.array([delta] * n))
          a_after = a_sorted - delta_vec
          proj += act_multiplier * (a_after - proj)
          done = True
      if not done:
          proj = active * (a_sorted - proj)
  
      for i in range(m):
          proj[i, :] = proj[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 3 for calling a global function with example usage: projection_l1_1(values, eps) and returns: proj