• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

FEniCS / ffcx / 29918047386

22 Jul 2026 12:02PM UTC coverage: 84.71% (+0.03%) from 84.685%
29918047386

push

github

web-flow
Support `numba>=0.66.0` and tidy optional dependency (#846)

* Simplify optional dependency management and support numba>=0.66.0

* This has been a redirect for >5 years?

* Consistent optional dependency management

* Use core.types everywhere

* Apply suggestions from code review

Co-authored-by: Paul T. Kühner <56360279+schnellerhase@users.noreply.github.com>

* ruff

* fix

* ignore

* revert copyright

* use pythonic redirect supported by numba

3 of 4 new or added lines in 1 file covered. (75.0%)

4205 of 4964 relevant lines covered (84.71%)

0.85 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

61.22
/ffcx/codegeneration/utils.py
1
# Copyright (C) 2020-2024 Michal Habera, Chris Richardson and Garth N. Wells
2
#
3
# This file is part of FFCx.(https://www.fenicsproject.org)
4
#
5
# SPDX-License-Identifier:    LGPL-3.0-or-later
6
"""Utilities."""
7

8
import numpy as np
1✔
9
import numpy.typing as npt
1✔
10

11
try:
1✔
12
    import numba
1✔
13
except ImportError:
×
NEW
14
    numba = None  # type: ignore
×
15

16

17
def dtype_to_c_type(dtype: npt.DTypeLike | str) -> str:
1✔
18
    """For a NumPy dtype, return the corresponding C type.
19

20
    Args:
21
        dtype: Numpy data type,
22

23
    Returns:
24
        Corresponding C type.
25
    """
26
    # Note: Possible aliases, e.g. numpy.longdouble, should test against char ID
27
    if np.dtype(dtype).char == "g":
1✔
28
        return "long double"
×
29
    if np.dtype(dtype) == np.intc:
1✔
30
        return "int"
1✔
31
    elif np.dtype(dtype).char == "f":
1✔
32
        return "float"
1✔
33
    elif np.dtype(dtype).char == "d":
1✔
34
        return "double"
1✔
35
    elif np.dtype(dtype) == np.complex64:
1✔
36
        return "float _Complex"
1✔
37
    elif np.dtype(dtype) == np.complex128:
1✔
38
        return "double _Complex"
1✔
39
    else:
40
        raise RuntimeError(f"Unknown NumPy type for: {dtype}")
×
41

42

43
def dtype_to_scalar_dtype(dtype: npt.DTypeLike | str) -> np.dtype:
1✔
44
    """For a NumPy dtype, return the corresponding real dtype.
45

46
    Args:
47
        dtype: Numpy data type
48

49
    Returns:
50
        ``numpy.dtype`` for the real component of ``dtype``.
51
    """
52
    if np.issubdtype(dtype, np.floating):
1✔
53
        return np.dtype(dtype)
1✔
54
    elif np.issubdtype(dtype, np.complexfloating):
1✔
55
        return np.dtype(dtype).type(0).real.dtype
1✔
56
    elif np.issubdtype(dtype, np.integer):
1✔
57
        return np.dtype(dtype)
1✔
58
    else:
59
        raise RuntimeError(f"Cannot get value dtype for '{dtype}'. ")
×
60

61

62
if numba is not None:
1✔
63

64
    def numba_ufcx_kernel_signature(dtype: npt.DTypeLike, xdtype: npt.DTypeLike):
1✔
65
        """Return a Numba C signature for the UFCx ``tabulate_tensor`` interface.
66

67
        Args:
68
            dtype: The scalar type for the finite element data.
69
            xdtype: The geometry float type.
70

71
        Returns:
72
            A Numba signature (``numba.core.typing.templates.Signature``).
73
        """
74
        return numba.types.void(
1✔
75
            numba.types.CPointer(numba.from_dtype(dtype)),
76
            numba.types.CPointer(numba.from_dtype(dtype)),
77
            numba.types.CPointer(numba.from_dtype(dtype)),
78
            numba.types.CPointer(numba.from_dtype(xdtype)),
79
            numba.types.CPointer(numba.types.intc),
80
            numba.types.CPointer(numba.types.uint8),
81
            numba.types.CPointer(numba.types.void),
82
        )
83

84
    @numba.extending.intrinsic
1✔
85
    def empty_void_pointer(typingctx):
1✔
86
        """Custom intrinsic to return an empty void* pointer.
87

88
        This function creates a void pointer initialized to null (0).
89
        This is used to pass a nullptr to the UFCx tabulate_tensor interface.
90

91
        Args:
92
            typingctx: The typing context.
93

94
        Returns:
95
            A Numba signature and a code generation function that returns a void pointer.
96
        """
97

98
        def codegen(context, builder, signature, args):
×
99
            null_ptr = context.get_constant(numba.types.voidptr, 0)
×
100
            return null_ptr
×
101

102
        sig = numba.types.voidptr()
×
103
        return sig, codegen
×
104

105
    @numba.extending.intrinsic
1✔
106
    def get_void_pointer(typingctx, arr):
1✔
107
        """Custom intrinsic to get a void* pointer from a NumPy array.
108

109
        This function takes a NumPy array and returns a void pointer to the array's data.
110
        This is used to pass custom data organised in a NumPy array
111
        to the UFCx tabulate_tensor interface.
112

113
        Args:
114
            typingctx: The typing context.
115
            arr: The NumPy array to get the void pointer to the first element from.
116
            In a multi-dimensional NumPy array, the memory is laid out in a contiguous
117
            block of memory, see
118
            https://numpy.org/doc/stable/reference/arrays.ndarray.html#internal-memory-layout-of-an-ndarray
119

120
        Returns:
121
            sig: A Numba signature, which specifies the numba type (here voidptr),
122
            codegen: A code generation function, which returns the LLVM IR to cast
123
            the raw data pointer to the first element of the of the contiguous block of memory
124
            of the NumPy array to void*.
125
        """
126
        if not isinstance(arr, numba.types.Array):
×
127
            raise TypeError("Expected a NumPy array")
×
128

129
        def codegen(context, builder, signature, args):
×
130
            """Generate LLVM IR code to convert a NumPy array to a void* pointer.
131

132
            This function generates the necessary LLVM IR instructions to:
133
            1. Allocate memory for the array on the stack.
134
            2. Cast the allocated memory to a void* pointer.
135

136
            Args:
137
                context: The LLVM context.
138
                builder: The LLVM IR builder.
139
                signature: The function signature.
140
                args: The input arguments (NumPy array).
141

142
            Returns:
143
                A void* pointer to the array's data.
144
            """
145
            [arr] = args
×
146
            raw_ptr = numba.core.cgutils.alloca_once_value(builder, arr)
×
147
            void_ptr = builder.bitcast(raw_ptr, context.get_value_type(numba.types.voidptr))
×
148
            return void_ptr
×
149

150
        sig = numba.types.voidptr(arr)
×
151
        return sig, codegen
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc