code: def lstm(
      input: ivy.Array,
      initial_states: Tuple[ivy.Array],
      all_weights: Tuple[ivy.Array],
      has_biases: bool,
      num_layers: int,
      dropout: float,
      train: bool,
      bidirectional: bool,
      batch_first: bool = False,
      batch_sizes: Sequence = None,
  ):
      """Applies a multi-layer long-short term memory to an input sequence.
  
      Parameters
      ----------
      input
          input array of shape (seq_len, batch, input_size) when `batch_first` is False
          or (batch, seq_len, input_size) when `batch_first` is True
      initial_states
          tuple of two arrays (h_0, c_0) where h_0 is the initial hidden state of shape
          (num_layers * num_directions, batch, hidden_size) and c_0 is the initial cell
          state of shape (num_layers * num_directions, batch, hidden_size)
  
          (num_directions being 2 when `bidirectional`, otherwise 1)
      all_weights
          tuple of arrays representing the learnable weights of the lstm, with each
          layer having either four arrays (w_ih, w_hh, b_ih, b_hh), when has_biases=True,
          or two (w_ih, w_hh), when has_biases=False
  
          w_ih: weight of shape (4 * hidden_size, input_size)
          w_hh: weight of shape (4 * hidden_size, hidden_size)
          b_ih: bias of shape (4 * hidden_size,)
          b_hh: bias of shape (4 * hidden_size,)
      has_biases
          indicates whether the `all_weights` argument includes biases
      num_layers
          number of layers for the lstm to use
      dropout
          dropout rate
      train
          whether to run the lstm in train mode or eval mode
      bidirectional
          whether the lstm is bidirectional or unidirectional
      batch_first
          defines the data format of the input and output arrays
      batch_sizes
          specifies the batch size at each timestep, when the input is a packed sequence
  
      Returns
      -------
      output
          output array of shape (seq_len, batch, num_directions * hidden_size) or
          (batch, seq_len, num_directions * hidden_size), depending on `batch_first`
      h_outs
          final hidden state of shape (num_layers * num_directions, batch, hidden_size)
      c_outs
          final cell state of shape (num_layers * num_directions, batch, hidden_size)
      """
      weights_per_layer = 4 if has_biases else 2
  
      assert len(all_weights) == num_layers * weights_per_layer * (
          1 + bidirectional
      )
      layer_weights = [
          all_weights[i : i + weights_per_layer]
          for i in range(0, len(all_weights), weights_per_layer)
      ]
  
      if batch_sizes is not None:
          input, batch_sizes = _pad_packed_sequence(input, batch_sizes)
  
      if batch_first:
          input = ivy.swapaxes(input, 0, 1)
  
      if dropout and train:
          raise ivy.utils.exceptions.IvyNotImplementedException()
  
      unidirectional = not bidirectional
  
      h0, c0 = initial_states
      h_outs, c_outs = [], []
  
      output = input
      for i in range(num_layers):
          if unidirectional:
              if weights_per_layer == 4:
                  (
                      weight_ih,
                      weight_hh,
                      (bias_i, bias_h),
                  ) = _transform_weights(layer_weights, i)
              else:
                  weight_ih, weight_hh = _transform_weights_no_bias(
                      layer_weights, i
                  )
                  bias_i = bias_h = None
  
              state_indices = i, i + 1
          else:
              if weights_per_layer == 4:
                  (
                      weight_ih_f,
                      weight_hh_f,
                      (bias_i_f, bias_h_f),
                  ) = _transform_weights(layer_weights, 2 * i)
                  (
                      weight_ih_b,
                      weight_hh_b,
                      (bias_i_b, bias_h_b),
                  ) = _transform_weights(layer_weights, 2 * i + 1)
              else:
                  weight_ih_f, weight_hh_f = _transform_weights_no_bias(
                      layer_weights, 2 * i
                  )
                  weight_ih_b, weight_hh_b = _transform_weights_no_bias(
                      layer_weights, 2 * i + 1
                  )
                  bias_i_f = bias_h_f = bias_i_b = bias_h_b = None
  
              weight_ih = weight_ih_f, weight_ih_b
              weight_hh = weight_hh_f, weight_hh_b
              bias_i = bias_i_f, bias_i_b
              bias_h = bias_h_f, bias_h_b
  
              state_indices = 2 * i, 2 * i + 2
  
          output, (h_out, c_out) = _lstm_layer(
              output,
              (
                  _retrieve_state(h0, *state_indices, num_layers),
                  _retrieve_state(c0, *state_indices, num_layers),
              ),
              (weight_ih, weight_hh),
              (bias_i, bias_h),
              bidirectional,
              batch_first=False,
              batch_sizes=batch_sizes,
          )
          h_outs.append(h_out)
          c_outs.append(c_out)
  
      if batch_first:
          output = ivy.swapaxes(output, 0, 1)
  
      h_outs = h_out if num_layers == 1 else ivy.concat(h_outs, axis=0)
      c_outs = c_out if num_layers == 1 else ivy.concat(c_outs, axis=0)
  
      if batch_sizes is not None:
          output = _pack_padded_sequence(output, batch_sizes)[0]
  
      return output, h_outs, c_outs
  
imports: from typing import Optional, Tuple, Union, Sequence
  import ivy
  from ivy.utils.backend import current_backend
  from ivy.func_wrapper import handle_array_function, handle_partial_mixed_function, inputs_to_ivy_arrays, to_native_arrays_and_back, inputs_to_native_shapes, handle_out_argument, handle_nestable, handle_array_like_without_promotion, handle_device, handle_backend_invalid
  from ivy.utils.exceptions import handle_exceptions
label_desc: Use image node_id 18 for calling a global function with example usage: lstm(input, initial_states, all_weights, has_biases, num_layers, dropout, train, bidirectional, batch_first, batch_sizes) and returns: output,  h_outs,  c_outs