code: def reduce_dataset_size_if_too_large(
      X: Union[np.ndarray, spmatrix],
      y: np.ndarray,
      memory_limit: int,
      is_classification: bool,
      random_state: Union[int, np.random.RandomState] = None,
      operations: List[str] = ["precision", "subsample"],
      memory_allocation: Union[int, float] = 0.1,
  ) -> Tuple[Union[np.ndarray, spmatrix], np.ndarray]:
      f"""Reduces the size of the dataset if it's too close to the memory limit.
  
      Follows the order of the operations passed in and retains the type of its
      input.
  
      Precision reduction will only work on the following float types:
      -   {supported_precision_reductions}
  
      Subsampling will ensure that the memory limit is satisfied while precision reduction
      will only perform one level of precision reduction. Technically, you could supply
      multiple rounds of precision reduction, i.e. to reduce np.float128 to np.float32
      you could use `operations = ['precision'] * 2`.
  
      However, if that's the use case, it'd be advised to simply use the function
      `autosklearn.util.data.reduce_precision`.
  
      NOTE: limitations
      * Does not support dataframes yet
          -   Requires implementing column wise precision reduction
          -   Requires calculating memory usage
  
      Parameters
      ----------
      X: np.ndarray | spmatrix
          The features of the dataset.
  
      y: np.ndarray
          The labels of the dataset.
  
      memory_limit: int
          The amount of memory allocated in megabytes
  
      is_classification: bool
          Whether it's a classificaiton dataset or not. This is important when
          considering how to subsample.
  
      random_state: int | RandomState = None
          The random_state to use for subsampling.
  
      operations: List[str] = ['precision', 'subsampling']
          A list of operations that are permitted to be performed to reduce
          the size of the dataset.
  
          **precision**
  
          Reduce the precision of float types
  
          **subsample**
  
          Reduce the amount of samples of the dataset such that it fits into the allocated
          memory. Ensures stratification and that unique labels are present
  
      memory_allocation: Union[int, float] = 0.1
          The amount of memory to allocate to the dataset. A float specifys that the
          dataset will try to be fit into that percentage of memory. An int specifies an
          absolute amount.
  
      Returns
      -------
      (spmatrix | np.ndarray, np.ndarray)
          The reduced X, y if reductions were needed
      """
      # Validation
      assert memory_limit > 0
  
      if isinstance(memory_allocation, float):
          if not (0.0 < memory_allocation < 1.0):
              raise ValueError(
                  "memory_allocation if float must be in (0, 1)"
              )
  
          allocated_memory = memory_limit * memory_allocation
  
      elif isinstance(memory_allocation, int):
          if not (0 < memory_allocation < memory_limit):
              raise ValueError(
                  "memory_allocation if int must be in (0, memory_limit)"
              )
  
          allocated_memory = memory_allocation
  
      else:
          raise ValueError(
              f"Unknown type for `memory_allocation` {type(memory_allocation)}"
          )
  
      if (
          "precision" in operations
          and X.dtype not in supported_precision_reductions
      ):
          raise ValueError(
              f"Unsupported type `{X.dtype}` for precision reduction"
          )
  
      def megabytes(arr: Union[np.ndarray, spmatrix]) -> float:
          return (
              arr.nbytes
              if isinstance(X, np.ndarray)
              else arr.data.nbytes
          ) / (2**20)
  
      for operation in operations:
          if operation == "precision":
              # If the dataset is too big for the allocated memory,
              # we then try to reduce the precision if it's a high precision dataset
              if megabytes(X) > allocated_memory:
                  X, precision = reduce_precision(X)
                  warnings.warn(
                      f"Dataset too large for allocated memory {allocated_memory}MB, "
                      f"reduced the precision from {X.dtype} to {precision}",
                  )
  
          elif operation == "subsample":
              # If the dataset is still too big such that we couldn't fit
              # into the allocated memory, we subsample it so that it does
              if megabytes(X) > allocated_memory:
                  n_samples_before = X.shape[0]
                  sample_percentage = allocated_memory / megabytes(X)
  
                  # NOTE: type ignore
                  #
                  # Tried the generic `def subsample(X: T) -> T` approach but it was
                  # failing elsewhere, keeping it simple for now
                  X, y = subsample(  # type: ignore
                      X,
                      y,
                      sample_size=sample_percentage,
                      is_classification=is_classification,
                      random_state=random_state,
                  )
  
                  n_samples_after = X.shape[0]
                  warnings.warn(
                      f"Dataset too large for allocated memory {allocated_memory}MB,"
                      f" reduced number of samples from {n_samples_before} to"
                      f" {n_samples_after}."
                  )
  
          else:
              raise ValueError(f"Unknown operation `{operation}`")
  
      return X, y
  
imports: from typing import Any, Dict, Iterator, List, Mapping, Optional, Sequence, Tuple, Type, Union, cast
  import warnings
  import numpy
  import pandas
  from scipy.sparse import spmatrix
  from sklearn.model_selection import train_test_split
  from autosklearn.evaluation.splitter import CustomStratifiedShuffleSplit
label_desc: Use image node_id 9 for calling a global function with example usage: reduce_dataset_size_if_too_large(X, y, memory_limit, is_classification, random_state, operations, memory_allocation) and returns: X,  y, unknown