text: import numpy as np
  
  
  class Matrices:
  
      _NAMES = ["I", "H", "X", "Y", "Z", "S", "T", "CNOT", "CZ", "SWAP", "TOFFOLI"]
  
      def __init__(self, backend):
          self.backend = backend
          self._I = None
          self._H = None
          self._X = None
          self._Y = None
          self._Z = None
          self._S = None
          self._T = None
          self._CNOT = None
          self._CZ = None
          self._SWAP = None
          self._TOFFOLI = None
          self.allocate_matrices()
  
      def allocate_matrices(self):
          for name in self._NAMES:
              getattr(self, f"_set{name}")()
  
      @property
      def dtype(self):
          return self.backend._dtypes.get('DTYPECPX')
  
      @property
      def I(self):
          return self._I
  
      @property
      def H(self):
          return self._H
  
      @property
      def X(self):
          return self._X
  
      @property
      def Y(self):
          return self._Y
  
      @property
      def Z(self):
          return self._Z
  
      @property
      def S(self):
          return self._S
  
      @property
      def T(self):
          return self._T
  
      @property
      def CNOT(self):
          return self._CNOT
  
      @property
      def CZ(self):
          return self._CZ
  
      @property
      def SWAP(self):
          return self._SWAP
  
      @property
      def TOFFOLI(self):
          return self._TOFFOLI
  
      def _setI(self):
          self._I = self.backend.cast(np.eye(2, dtype=self.dtype))
  
      def _setH(self):
          m = np.ones((2, 2), dtype=self.dtype)
          m[1, 1] = -1
          self._H = self.backend.cast(m / np.sqrt(2))
  
      def _setX(self):
          m = np.zeros((2, 2), dtype=self.dtype)
          m[0, 1], m[1, 0] = 1, 1
          self._X = self.backend.cast(m)
  
      def _setY(self):
          m = np.zeros((2, 2), dtype=self.dtype)
          m[0, 1], m[1, 0] = -1j, 1j
          self._Y = self.backend.cast(m)
  
      def _setZ(self):
          m = np.eye(2, dtype=self.dtype)
          m[1, 1] = -1
          self._Z = self.backend.cast(m)
  
      def _setS(self):
          m = np.eye(2, dtype=self.dtype)
          m[1, 1] = 1j
          self._S = self.backend.cast(m)
  
      def _setT(self):
          m = np.eye(2, dtype=self.dtype)
          m[1, 1] = np.exp(1j * np.pi / 4.0)
          self._T = self.backend.cast(m)
  
      def _setCNOT(self):
          m = np.eye(4, dtype=self.dtype)
          m[2, 2], m[2, 3] = 0, 1
          m[3, 2], m[3, 3] = 1, 0
          self._CNOT = self.backend.cast(m)
  
      def _setCZ(self):
          m = np.eye(4, dtype=self.dtype)
          m[3, 3] = -1
          self._CZ = self.backend.cast(m)
  
      def _setSWAP(self):
          m = np.eye(4, dtype=self.dtype)
          m[1, 1], m[1, 2] = 0, 1
          m[2, 1], m[2, 2] = 1, 0
          self._SWAP = self.backend.cast(m)
  
      def _setTOFFOLI(self):
          m = np.eye(8, dtype=self.dtype)
          m[-2, -2], m[-2, -1] = 0, 1
          m[-1, -2], m[-1, -1] = 1, 0
          self._TOFFOLI = self.backend.cast(m)
  