code: def lstm_update(
      x: Union[ivy.Array, ivy.NativeArray],
      init_h: Union[ivy.Array, ivy.NativeArray],
      init_c: Union[ivy.Array, ivy.NativeArray],
      kernel: Union[ivy.Array, ivy.NativeArray],
      recurrent_kernel: Union[ivy.Array, ivy.NativeArray],
      /,
      *,
      bias: Optional[Union[ivy.Array, ivy.NativeArray]] = None,
      recurrent_bias: Optional[
          Union[ivy.Array, ivy.NativeArray]
      ] = None,
      time_major: bool = False,
  ) -> Tuple[ivy.Array, Tuple[ivy.Array, ivy.Array]]:
      """Perform long-short term memory update by unrolling time dimension of
      input array.
  
      Parameters
      ----------
      x
          input tensor of LSTM layer *[batch_shape, t, in]* if time_major=False,
          else *[t, batch_shape, in]*.
      init_h
          initial state tensor for the cell output *[batch_shape, out]*.
      init_c
          initial state tensor for the cell hidden state *[batch_shape, out]*.
      kernel
          weights for cell kernel *[in, 4 x out]*.
      recurrent_kernel
          weights for cell recurrent kernel *[out, 4 x out]*.
      bias
          bias for cell kernel *[4 x out]*. (Default value = None)
      recurrent_bias
          bias for cell recurrent kernel *[4 x out]*. (Default value = None)
      time_major
          whether or not the input tensor `x` has the time dimension before batch dim.
  
      Returns
      -------
      ret
          hidden state for all timesteps of shape *[batch_shape,t,out]* if time_major
          is False, else *[t, batch_shape, out]*, and a tuple containing the final cell
          states, both of shape *[batch_shape,out]*.
      """
      # ToDo: test_lstm_update needs to be fixed
      if time_major:
          x = ivy.swapaxes(x, 0, 1)
      # get shapes
      x_shape = list(x.shape)
      batch_shape = x_shape[:-2]
      timesteps = x_shape[-2]
      input_channels = x_shape[-1]
      x_flat = ivy.reshape(x, (-1, input_channels))
  
      # input kernel
      Wi = kernel
      Wi_x = ivy.reshape(
          ivy.matmul(x_flat, Wi) + (bias if bias is not None else 0),
          batch_shape + [timesteps, -1],
      )
      Wii_x, Wif_x, Wig_x, Wio_x = ivy.split(
          Wi_x, num_or_size_splits=4, axis=-1
      )
  
      # recurrent kernel
      Wh = recurrent_kernel
  
      # lstm states
      ht = init_h
      ct = init_c
  
      # lstm outputs
      hts_list = []
  
      # unrolled time dimension with lstm steps
      for Wii_xt, Wif_xt, Wig_xt, Wio_xt in zip(
          ivy.unstack(Wii_x, axis=-2),
          ivy.unstack(Wif_x, axis=-2),
          ivy.unstack(Wig_x, axis=-2),
          ivy.unstack(Wio_x, axis=-2),
      ):
          htm1 = ht
          ctm1 = ct
  
          Wh_htm1 = ivy.matmul(htm1, Wh) + (
              recurrent_bias if recurrent_bias is not None else 0
          )
          Whi_htm1, Whf_htm1, Whg_htm1, Who_htm1 = ivy.split(
              Wh_htm1, num_or_size_splits=4, axis=-1
          )
  
          it = ivy.sigmoid(Wii_xt + Whi_htm1)
          ft = ivy.sigmoid(Wif_xt + Whf_htm1)
          gt = ivy.tanh(Wig_xt + Whg_htm1)
          ot = ivy.sigmoid(Wio_xt + Who_htm1)
          ct = ft * ctm1 + it * gt
          ht = ot * ivy.tanh(ct)
  
          hts_list.append(ivy.expand_dims(ht, axis=-2))
  
      ret = ivy.concat(hts_list, axis=-2)
      if time_major:
          ret = ivy.swapaxes(ret, 0, 1)
  
      return ret, (ht, ct)
  
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 17 for calling a global function with example usage: lstm_update() and returns: ret,  ht,  ct