<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def surface_normal(self, param):
 """Unit vector perpendicular to the detector surface at ``param``. The orientation is chosen as follows: - In 2D, the system ``(normal, tangent)`` should be right-handed. - In 3D, the system ``(tangent[0], tangent[1], normal)`` should be right-handed. Here, ``tangent`` is the return value of `surface_deriv` at ``param``. Parameters param : `array-like` or sequence Parameter value(s) at which to evaluate. If ``ndim >= 2``, a sequence of length `ndim` must be provided. Returns ------- normal : `numpy.ndarray` Unit vector(s) perpendicular to the detector surface at ``param``. If ``param`` is a single parameter, an array of shape ``(space_ndim,)`` representing a single vector is returned. Otherwise the shape of the returned array is - ``param.shape + (space_ndim,)`` if `ndim` is 1, - ``param.shape[:-1] + (space_ndim,)`` otherwise. """

        # Checking is done by `surface_deriv`
        if self.ndim == 1 and self.space_ndim == 2:
            return -perpendicular_vector(self.surface_deriv(param))
        elif self.ndim == 2 and self.space_ndim == 3:
            deriv = self.surface_deriv(param)
            if deriv.ndim > 2:
                # Vectorized, need to reshape (N, 2, 3) to (2, N, 3)
                deriv = moveaxis(deriv, -2, 0)
            normal = np.cross(*deriv, axis=-1)
            normal /= np.linalg.norm(normal, axis=-1, keepdims=True)
            return normal
        else:
            raise NotImplementedError(
                'no default implementation of `surface_normal` available '
                'for `ndim = {}` and `space_ndim = {}`'
                ''.format(self.ndim, self.space_ndim))