code: def project_onto_l1_ball(x: ep.Tensor, eps: ep.Tensor) -> ep.Tensor:
      """Computes Euclidean projection onto the L1 ball for a batch. [#Duchi08]_
  
      Adapted from the pytorch version by Tony Duan:
      https://gist.github.com/tonyduan/1329998205d88c566588e57e3e2c0c55
  
      Args:
          x: Batch of arbitrary-size tensors to project, possibly on GPU
          eps: radius of l-1 ball to project onto
  
      References:
        ..[#Duchi08] Efficient Projections onto the l1-Ball for Learning in High Dimensions
           John Duchi, Shai Shalev-Shwartz, Yoram Singer, and Tushar Chandra.
           International Conference on Machine Learning (ICML 2008)
      """
      original_shape = x.shape
      x = flatten(x)
      mask = (
          (ep.norms.l1(x, axis=1) <= eps).astype(x.dtype).expand_dims(1)
      )
      mu = ep.flip(ep.sort(ep.abs(x)), axis=-1).astype(x.dtype)
      cumsum = ep.cumsum(mu, axis=-1)
      arange = ep.arange(x, 1, x.shape[1] + 1).astype(x.dtype)
      rho = (
          ep.max(
              ((mu * arange > (cumsum - eps.expand_dims(1)))).astype(
                  x.dtype
              )
              * arange,
              axis=-1,
          )
          - 1
      )
      # samples already under norm will have to select
      rho = ep.maximum(rho, 0)
      theta = (
          cumsum[
              ep.arange(x, x.shape[0]),
              rho.astype(ep.arange(x, 1).dtype),
          ]
          - eps
      ) / (rho + 1.0)
      proj = (ep.abs(x) - theta.expand_dims(1)).clip(
          min_=0, max_=ep.inf
      )
      x = mask * x + (1 - mask) * proj * ep.sign(x)
      return x.reshape(original_shape)
  
imports: import math
  from abc import abstractmethod, ABC
  from typing import Union, Optional, Any, Tuple
  import eagerpy
  from eagerpy.astensor import T
  from .base import MinimizationAttack, raise_if_kwargs, get_criterion, get_is_adversarial
  from .gradient_descent_base import uniform_l1_n_balls, normalize_lp_norms, uniform_l2_n_balls
  from ..None import Model, Misclassification, TargetedMisclassification
  from ..devutils import atleast_kd, flatten
  from ..distances import l1, linf, l2, l0, LpDistance
label_desc: Use image node_id 2 for calling a global function with example usage: project_onto_l1_ball(x, eps) and returns: x