code: def universal_test_unary(a, dtype, op):
      if not isinstance(op, tuple):
          op = (op, op)
      out: Tensor = op[0](Tensor([a], dtype=dtype))
      ast = out.lazydata.schedule()[-1].ast
      tensor_value = out.numpy()
      numpy_value = op[1](np.array([a]).astype(dtype.np))
      if dtype in dtypes_float:
          atol = (
              2
              if (Device.DEFAULT == "METAL" or getenv("PTX"))
              and op[0] == Tensor.sin
              else 1e-3
          )
          rtol = (
              2
              if Device.DEFAULT == "METAL" and op[0] == Tensor.sin
              else 1e-4
              if dtype == dtypes.float32
              else 1e-2
          )
          # exp and log and sin are approximations (in METAL, the default fast-math versions are less precise)
          np.testing.assert_allclose(
              tensor_value, numpy_value, atol=atol, rtol=rtol
          )
      else:
          np.testing.assert_equal(tensor_value, numpy_value)
      if (
          op[0] != Tensor.reciprocal
      ):  # reciprocal is not supported in most backends
          op = [x for x in ast.lazyops if x.op in UnaryOps][0]
          assert get_lazyop_info(op).dtype == dtype
  
imports: import unittest
  from tinygrad import Tensor, dtypes, Device
  import operator
  import numpy
  from hypothesis import given, strategies, settings
  from tinygrad.dtype import DType
  from tinygrad.helpers import CI, getenv, OSX
  from tinygrad.ops import UnaryOps, get_lazyop_info
label_desc: Use image node_id 2 for calling a global function with example usage: universal_test_unary(a, dtype, op) without return types