Repository: PennyLaneAI/pennylane

Issue:
Define the `matrix` and `eigvals` class attributes for all non-parametric operations
### Feature details

Most non-parametric operations have their matrix representation and eigenvalues defined as class attributes (`matrix` and `eigvals`). There are some, however, which define these directly within the `_matrix` and `_eigvals` classmethods (e.g., [`S` gate](https://github.com/PennyLaneAI/pennylane/blob/8e57efa4a85ea635665a44b19c9113f3f38acd3b/pennylane/ops/qubit/non_parametric_ops.py#L276)).

We would like all [non-parametric operation](https://github.com/PennyLaneAI/pennylane/blob/master/pennylane/ops/qubit/non_parametric_ops.py) to define the  `matrix` and `eigvals` class attributes.

### Implementation

Organize the numeric values of matrices and eigenvalues into class attributes for the remaining non-parametric operation in the file linked above.

### How important would you say this feature is?

1: Not important. Would be nice to have.

### Additional information

_No response_


Discussion:

Resolving patch:
diff --git a/pennylane/ops/qubit/non_parametric_ops.py b/pennylane/ops/qubit/non_parametric_ops.py
--- a/pennylane/ops/qubit/non_parametric_ops.py
+++ b/pennylane/ops/qubit/non_parametric_ops.py
@@ -294,14 +294,16 @@ class S(DiagonalOperation):
     num_wires = 1
     par_domain = None
     basis = "Z"
+    op_eigvals = np.array([1, 1j])
+    op_matrix = np.array([[1, 0], [0, 1j]])
 
     @classmethod
     def _matrix(cls, *params):
-        return np.array([[1, 0], [0, 1j]])
+        return cls.op_matrix
 
     @classmethod
     def _eigvals(cls, *params):
-        return np.array([1, 1j])
+        return cls.op_eigvals
 
     @staticmethod
     def decomposition(wires):
@@ -337,14 +339,16 @@ class T(DiagonalOperation):
     num_wires = 1
     par_domain = None
     basis = "Z"
+    op_matrix = np.array([[1, 0], [0, cmath.exp(1j * np.pi / 4)]])
+    op_eigvals = np.array([1, cmath.exp(1j * np.pi / 4)])
 
     @classmethod
     def _matrix(cls, *params):
-        return np.array([[1, 0], [0, cmath.exp(1j * np.pi / 4)]])
+        return cls.op_matrix
 
     @classmethod
     def _eigvals(cls, *params):
-        return np.array([1, cmath.exp(1j * np.pi / 4)])
+        return cls.op_eigvals
 
     @staticmethod
     def decomposition(wires):
@@ -380,14 +384,16 @@ class SX(Operation):
     num_wires = 1
     par_domain = None
     basis = "X"
+    op_matrix = 0.5 * np.array([[1 + 1j, 1 - 1j], [1 - 1j, 1 + 1j]])
+    op_eigvals = np.array([1, 1j])
 
     @classmethod
     def _matrix(cls, *params):
-        return 0.5 * np.array([[1 + 1j, 1 - 1j], [1 - 1j, 1 + 1j]])
+        return cls.op_matrix
 
     @classmethod
     def _eigvals(cls, *params):
-        return np.array([1, 1j])
+        return cls.op_eigvals
 
     @staticmethod
     def decomposition(wires):
@@ -621,14 +627,16 @@ class ISWAP(Operation):
     num_params = 0
     num_wires = 2
     par_domain = None
+    op_matrix = np.array([[1, 0, 0, 0], [0, 0, 1j, 0], [0, 1j, 0, 0], [0, 0, 0, 1]])
+    op_eigvals = np.array([1j, -1j, 1, 1])
 
     @classmethod
     def _matrix(cls, *params):
-        return np.array([[1, 0, 0, 0], [0, 0, 1j, 0], [0, 1j, 0, 0], [0, 0, 0, 1]])
+        return cls.op_matrix
 
     @classmethod
     def _eigvals(cls, *params):
-        return np.array([1j, -1j, 1, 1])
+        return cls.op_eigvals
 
     @staticmethod
     def decomposition(wires):
@@ -668,21 +676,23 @@ class SISWAP(Operation):
     num_params = 0
     num_wires = 2
     par_domain = None
+    op_matrix = np.array(
+        [
+            [1, 0, 0, 0],
+            [0, INV_SQRT2, INV_SQRT2 * 1j, 0],
+            [0, INV_SQRT2 * 1j, INV_SQRT2, 0],
+            [0, 0, 0, 1],
+        ]
+    )
+    op_eigvals = np.array([INV_SQRT2 * (1 + 1j), INV_SQRT2 * (1 - 1j), 1, 1])
 
     @classmethod
     def _matrix(cls, *params):
-        return np.array(
-            [
-                [1, 0, 0, 0],
-                [0, INV_SQRT2, INV_SQRT2 * 1j, 0],
-                [0, INV_SQRT2 * 1j, INV_SQRT2, 0],
-                [0, 0, 0, 1],
-            ]
-        )
+        return cls.op_matrix
 
     @classmethod
     def _eigvals(cls, *params):
-        return np.array([INV_SQRT2 * (1 + 1j), INV_SQRT2 * (1 - 1j), 1, 1])
+        return cls.op_eigvals
 
     @staticmethod
     def decomposition(wires):


Test patch: