class_docstr: An `Op` with a C implementation.
docstr: Create a thunk for a C implementation.
  
  Like :meth:`Op.make_thunk`, but will only try to make a C thunk.
docstr_tok: ["Create","a","thunk","for","a","C","implementation",".","Like",":","meth",":","`","Op.make_thunk","`",",","but","will","only","try","to","make","a","C","thunk","."]
code: def make_c_thunk(
      self,
      node: Apply,
      storage_map: StorageMapType,
      compute_map: ComputeMapType,
      no_recycling: Collection[Variable],
  ) -> CThunkWrapperType:
      """Create a thunk for a C implementation.
  
      Like :meth:`Op.make_thunk`, but will only try to make a C thunk.
  
      """
      # FIXME: Putting the following import on the module level causes an import cycle.
      #        The conclusion should be that the antire "make_c_thunk" method should be defined
      #        in pytensor.link.c and dispatched onto the Op!
      import pytensor.link.c.basic
      from pytensor.graph.fg import FunctionGraph
  
      node_input_storage = [storage_map[r] for r in node.inputs]
      node_output_storage = [storage_map[r] for r in node.outputs]
  
      e = FunctionGraph(node.inputs, node.outputs)
      e_no_recycling = [
          new_o
          for (new_o, old_o) in zip(e.outputs, node.outputs)
          if old_o in no_recycling
      ]
      cl = pytensor.link.c.basic.CLinker().accept(
          e, no_recycling=e_no_recycling
      )
      # float16 gets special treatment since running
      # unprepared C code will get bad results.
      if not getattr(self, "_f16_ok", False):
  
          def is_f16(t):
              return getattr(t, "dtype", "") == "float16"
  
          if any(is_f16(i.type) for i in node.inputs) or any(
              is_f16(o.type) for o in node.outputs
          ):
              # get_dynamic_module is a subset of make_thunk that is reused.
              # This just try to build the c code
              # It will raise an error for ops
              # that don't implement c code. In those cases, we
              # don't want to print a warning.
              cl.get_dynamic_module()
              print(
                  f"Disabling C code for {self} due to unsupported float16"
              )
              raise NotImplementedError("float16")
      outputs = cl.make_thunk(
          input_storage=node_input_storage,
          output_storage=node_output_storage,
      )
      thunk, node_input_filters, node_output_filters = outputs
  
      @is_cthunk_wrapper_type
      def rval():
          thunk()
          for o in node.outputs:
              compute_map[o][0] = True
  
      rval.thunk = thunk
      rval.cthunk = thunk.cthunk
      rval.inputs = node_input_storage
      rval.outputs = node_output_storage
      rval.lazy = False
      return rval
  
imports: import inspect
  import os
  import re
  import warnings
  from collections.abc import Collection
  from re import Pattern
  from typing import TYPE_CHECKING, Any, Callable, ClassVar, Optional, Union, cast
  import numpy
  from pytensor.configdefaults import config
  from pytensor.graph.basic import Apply, Variable
  from pytensor.graph.op import ComputeMapType, Op, StorageMapType, ThunkType
  from pytensor.graph.type import HasDataType
  from pytensor.graph.utils import MethodNotDefined
  from pytensor.link.c.interface import CLinkerOp
  from pytensor.link.c.params_type import ParamsType
  from pytensor.utils import hash_from_code
label_desc: Use image node_id 1 for calling the COp obj's underlying member method code with example usage: obj.make_c_thunk(node, storage_map, compute_map, no_recycling) and returns: rval, unknown