diff --git a/erfa/ufunc.c.templ b/erfa/ufunc.c.templ index e0e2729..e8e18b8 100644 --- a/erfa/ufunc.c.templ +++ b/erfa/ufunc.c.templ @@ -147,21 +147,6 @@ static inline void copy_to_eraLDBODY(char *ptr, npy_intp s, npy_intp n, * not contiguous. */ -{%- macro inner_loop_steps_and_copy(arg, arg_name) %} - {%- for i in range(arg.ndim or 1) %} - npy_intp is_{{ arg_name }}{{ i }} = *steps++; - {%- endfor %} - {#- /* copy should be made if buffer not contiguous; - note: one can only have 1 or 2 dimensions */ #} - {%- if arg.ndim == 2 %} - int copy_{{ arg_name - }} = (is_{{ arg_name }}1 != sizeof({{ arg.ctype }}) || - is_{{ arg_name }}0 != {{ arg.shape[1] }} * sizeof({{ arg.ctype }})); - {%- else %} - int copy_{{ arg_name }} = (is_{{ arg_name }}0 != sizeof({{ arg.ctype }})); - {%- endif %} -{%- endmacro %} - {%- for func in funcs %} static void ufunc_loop_{{ func.pyname }}( @@ -213,20 +198,8 @@ static void ufunc_loop_{{ func.pyname }}( {%- if arg.ctype == 'eraLDBODY' %} int nb = (int)dimensions[0]; /* Refuse to worry about INT_MAX */ {%- endif %} - {%- if arg.signature_shape != '()' -%} - {{ inner_loop_steps_and_copy(arg, arg.name) }} - {%- endif %} - {%- endfor %} - {%- for arg in func.args_by_inout('inout') %} - {%- if arg.signature_shape != '()' -%} - {{ inner_loop_steps_and_copy(arg, arg.name + '_in') }} - {%- endif %} - {%- endfor %} - {%- for arg in func.args_by_inout('inout|out') %} - {%- if arg.signature_shape != '()' -%} - {{ inner_loop_steps_and_copy(arg, arg.name) }} - {%- endif %} {%- endfor %} + {{ func.inner_loop_steps_and_copies() | indent(4) }} {#- /* if needed, allocate memory for contiguous eraLDBODY copies */ #} {%- if func.user_dtype == 'dt_eraLDBODY' %} if (copy_b) { diff --git a/erfa_generator.py b/erfa_generator.py index 140cc93..d19ff23 100644 --- a/erfa_generator.py +++ b/erfa_generator.py @@ -196,6 +196,23 @@ def signature_shape(self): return "(3, 3)" return super().signature_shape + def inner_loop_steps_and_copy(self, name_suffix: str = "") -> str | None: + if self.signature_shape == "()": + return None + name = self.name + name_suffix + lines = [f"npy_intp is_{name}{i} = *steps++;" for i in range(self.ndim or 1)] + # copy should be made if buffer not contiguous; + # note: one can only have 1 or 2 dimensions + lines.append( + f"int copy_{name} = (is_{name}0 != sizeof({self.ctype}));" + if self.ndim <= 1 + else ( + f"int copy_{name} = (is_{name}1 != sizeof({self.ctype}) ||\n" + f" is_{name}0 != {self.shape[1]} * sizeof({self.ctype}));" + ) + ) + return "\n".join(lines) + class StatusCode(Variable): def __init__(self, ctype: str, doc: FunctionDoc, funcname: str) -> None: @@ -369,6 +386,14 @@ def generate_python_body(self) -> str: lines.append(f"return {ret_val}") return "\n".join(lines) + def inner_loop_steps_and_copies(self) -> str: + in_only = [a.inner_loop_steps_and_copy() for a in self.args_by_inout("in")] + inout = [ + a.inner_loop_steps_and_copy("_in") for a in self.args_by_inout("inout") + ] + out = [a.inner_loop_steps_and_copy() for a in self.args_by_inout("inout|out")] + return "\n".join(filter(None, in_only + inout + out)) + class Constant: