diff --git a/codegen/src/targets/python/extension.rs b/codegen/src/targets/python/extension.rs index e65e4fb..0780dfc 100644 --- a/codegen/src/targets/python/extension.rs +++ b/codegen/src/targets/python/extension.rs @@ -3,11 +3,8 @@ use anyhow::Result; use crate::{ model::{CompiledFunction, Output}, output::GeneratedFile, - render::{ - Writer, - c::{self, Dialect}, - }, - targets::group_by_source, + render::Writer, + targets::{group_by_source, native::c_result_name}, }; use super::C_HEADER; @@ -19,7 +16,9 @@ pub(crate) fn render(functions: &[CompiledFunction]) -> Result\n#include \"ufunc.h\"\n\n" + )); for function in functions { source.write(ufunc(function)?); } @@ -27,7 +26,7 @@ pub(crate) fn render(functions: &[CompiledFunction]) -> Result Result #include #include "#, @@ -88,50 +88,102 @@ fn ufunc(function: &CompiledFunction) -> Result { ], Output::Struct(fields) => fields.clone(), }; - let types = std::iter::repeat_n("NPY_DOUBLE", inputs.len() + values.len()) - .collect::>() - .join(", "); let mut writer = Writer::new(); - writer.line(format_args!("static void {name}_loop(char **args, const npy_intp *dimensions, const npy_intp *steps, void *data) {{")); + writer.line(format_args!( + "static int {name}_contiguous_loop(PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, const npy_intp *strides, NpyAuxData *transferdata) {{" + )); writer.indented(|writer| { - writer.line("npy_intp index;"); - writer.line("for (index = 0; index < dimensions[0]; index++) {"); + writer.line("(void)context;"); + writer.line("(void)strides;"); + writer.line("(void)transferdata;"); + for (index, input) in inputs.iter().enumerate() { + writer.line(format_args!( + "const double *in_{input} = (const double *)data[{index}];" + )); + } + for (index, value) in values.iter().enumerate() { + writer.line(format_args!( + "double *out_{value} = (double *)data[{}];", + inputs.len() + index + )); + } + writer.line("for (npy_intp index = 0; index < dimensions[0]; index++) {"); writer.indented(|writer| { - for (index, input) in inputs.iter().enumerate() { - writer.line(format_args!( - "const double {input} = *(const double *)args[{index}];" - )); - } - for variable in &function.ir.variables { - writer.write(format_args!("const double {} = ", variable.name)); - writer.write(c::expression( - &variable.expression, - inputs, - &function.ir.variables, - Dialect::C, - )); - writer.line(";"); + for input in inputs { + writer.line(format_args!("const double {input} = in_{input}[index];")); } - for (index, value) in values.iter().enumerate() { + render_kernel_call(writer, function, inputs, &values, Some("[index]")); + }); + writer.line("}"); + writer.line("return 0;"); + }); + writer.line("}"); + writer.blank_line(); + writer.line(format_args!( + "static int {name}_strided_loop(PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, const npy_intp *strides, NpyAuxData *transferdata) {{" + )); + writer.indented(|writer| { + writer.line("(void)context;"); + writer.line("(void)transferdata;"); + writer.line("for (npy_intp index = 0; index < dimensions[0]; index++) {"); + writer.indented(|writer| { + for (index, input) in inputs.iter().enumerate() { writer.line(format_args!( - "*(double *)args[{}] = {value};", - inputs.len() + index + "const double {input} = *(const double *)(data[{index}] + index * strides[{index}]);" )); } - writer.line(format_args!( - "for (int arg = 0; arg < {}; arg++) args[arg] += steps[arg];", - inputs.len() + values.len() - )); + render_kernel_call(writer, function, inputs, &values, None); }); writer.line("}"); + writer.line("return 0;"); }); writer.line("}"); writer.write(format_args!( - "static PyUFuncGenericFunction {name}_functions[] = {{ {name}_loop }};\nstatic char {name}_types[] = {{ {types} }};\n\n" + "static PyType_Slot {name}_slots[] = {{\n {{NPY_METH_strided_loop, {name}_strided_loop}},\n {{NPY_METH_contiguous_loop, {name}_contiguous_loop}},\n {{0, NULL}},\n}};\nstatic PyArrayMethod_Spec {name}_spec = {{\n .name = \"{name}\",\n .nin = {},\n .nout = {},\n .casting = NPY_SAME_KIND_CASTING,\n .slots = {name}_slots,\n}};\n\n", + inputs.len(), + values.len(), )); Ok(writer.into_string()) } +fn render_kernel_call( + writer: &mut Writer, + function: &CompiledFunction, + inputs: &[String], + values: &[String], + output_index: Option<&str>, +) { + let arguments = inputs.join(", "); + let result = match &function.core.output { + Output::Scalar => "double".to_owned(), + Output::Struct(_) => c_result_name( + function.entry.spec.functions[function.function_index] + .result_class() + .expect("record output has a result class"), + ), + }; + writer.line(format_args!( + "const {result} ptfkit_result = {}({arguments});", + function.core.name + )); + for (index, value) in values.iter().enumerate() { + let result_value = match &function.core.output { + Output::Scalar => "ptfkit_result".to_owned(), + Output::Struct(_) => format!("ptfkit_result.{value}"), + }; + match output_index { + None => writer.line(format_args!( + "*(double *)(data[{}] + index * strides[{}]) = {result_value};", + inputs.len() + index, + inputs.len() + index + )), + Some(output_index) => { + writer.line(format_args!("out_{value}{output_index} = {result_value};")) + } + } + } +} + fn output_count(output: &Output) -> usize { match output { Output::Scalar => 1, diff --git a/codegen/src/targets/python/wrapper.rs b/codegen/src/targets/python/wrapper.rs index 3a08d34..6078a4c 100644 --- a/codegen/src/targets/python/wrapper.rs +++ b/codegen/src/targets/python/wrapper.rs @@ -140,6 +140,7 @@ fn module_source( module.write(format_args!( "from __future__ import annotations\n\nfrom typing import {typing_imports}\n\n" )); + module.line("from ptfkit._dispatch import call as _call"); module.block( "from ptfkit._ptfkit import (", |writer| { @@ -204,16 +205,6 @@ fn render_function(module: &mut Module, function: &PythonFunction<'_>) { .result_class .map(|class| format!("{class}[NDArray[floating]]")) .unwrap_or_else(|| "NDArray[floating]".into()); - let out = if function.result_class.is_some() { - "tuple(out)" - } else { - "out" - }; - let result = if let Some(result_class) = function.result_class { - format!("return {result_class}(*values)") - } else { - "return values".into() - }; module.line("@overload"); module.line(format_args!( "def {}(*, {}) -> {scalar_result}: ...", @@ -242,22 +233,23 @@ fn render_function(module: &mut Module, function: &PythonFunction<'_>) { module.line(format_args!(") -> {scalar_result} | {array_result}:")); module.indented(|writer| { render_docstring(writer, &function.docstring, 4); - writer.line("if out is None:"); - writer.indented(|writer| { - writer.line(format_args!( - "values = _{}({})", - function.rust_name, function.parameters - )); - }); - writer.line("else:"); + if function.result_class.is_some() { + writer.line("values = _call("); + } else { + writer.line("return _call("); + } writer.indented(|writer| { - writer.line(format_args!( - "values = _{}({}, out={out})", - function.rust_name, function.parameters - )); + writer.line(format_args!("_{},", function.rust_name)); + for parameter in function.parameters.split(", ") { + writer.line(format_args!("{parameter},")); + } + writer.line("out=out,"); }); - writer.blank_line(); - writer.line(result); + writer.line(")"); + if let Some(result_class) = function.result_class { + writer.blank_line(); + writer.line(format_args!("return {result_class}(*values)")); + } }); } diff --git a/targets/ptfkit-py/CMakeLists.txt b/targets/ptfkit-py/CMakeLists.txt index f26d264..1da44b0 100644 --- a/targets/ptfkit-py/CMakeLists.txt +++ b/targets/ptfkit-py/CMakeLists.txt @@ -4,7 +4,12 @@ project(ptfkit LANGUAGES C) find_package(Python REQUIRED COMPONENTS Interpreter Development.Module NumPy) +set(PTFKIT_NATIVE_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/vendor/ptfkit-native/include") +if(NOT EXISTS "${PTFKIT_NATIVE_INCLUDE_DIR}/ptfkit/ptfkit.h") + set(PTFKIT_NATIVE_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../ptfkit-native/include") +endif() + Python_add_library(_ptfkit MODULE WITH_SOABI src/ptfkit/ptfkit.c) target_link_libraries(_ptfkit PRIVATE Python::NumPy) -target_include_directories(_ptfkit PRIVATE src/ptfkit) +target_include_directories(_ptfkit PRIVATE src/ptfkit "${PTFKIT_NATIVE_INCLUDE_DIR}") install(TARGETS _ptfkit DESTINATION ptfkit) diff --git a/targets/ptfkit-py/pyproject.toml b/targets/ptfkit-py/pyproject.toml index 7da2568..f01530b 100644 --- a/targets/ptfkit-py/pyproject.toml +++ b/targets/ptfkit-py/pyproject.toml @@ -62,3 +62,6 @@ testpaths = ["tests"] [tool.scikit-build] minimum-version = "build-system.requires" wheel.exclude = ["*.c", "*.h"] + +[tool.scikit-build.sdist.force-include] +"../ptfkit-native/include" = "vendor/ptfkit-native/include" diff --git a/targets/ptfkit-py/src/ptfkit/_dispatch.py b/targets/ptfkit-py/src/ptfkit/_dispatch.py new file mode 100644 index 0000000..b812004 --- /dev/null +++ b/targets/ptfkit-py/src/ptfkit/_dispatch.py @@ -0,0 +1,14 @@ +from __future__ import annotations + +from typing import Any + +from numpy import asarray, float64, ufunc + + +def call(function: ufunc, *inputs: object, out: object) -> Any: # noqa: ANN401 + inputs = tuple(asarray(value, dtype=float64) for value in inputs) + if out is None: + return function(*inputs) + if isinstance(out, tuple): + out = tuple(out) + return function(*inputs, out=out) diff --git a/targets/ptfkit-py/src/ptfkit/ahuja1984.c b/targets/ptfkit-py/src/ptfkit/ahuja1984.c index 9188663..bfda466 100644 --- a/targets/ptfkit-py/src/ptfkit/ahuja1984.c +++ b/targets/ptfkit-py/src/ptfkit/ahuja1984.c @@ -1,28 +1,61 @@ /* @generated by ptfkit-codegen; DO NOT EDIT. */ +#include #include "ufunc.h" -static void calc_ptf_ahuja1984_loop(char **args, const npy_intp *dimensions, const npy_intp *steps, - void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double total_porosity = *(const double *)args[0]; - const double theta_33 = *(const double *)args[1]; - const double coefficient_b = *(const double *)args[2]; - const double exponent_n = *(const double *)args[3]; - const double effective_porosity = total_porosity - theta_33; - const double k_sat = coefficient_b * pow(effective_porosity, exponent_n); - *(double *)args[4] = k_sat; - for (int arg = 0; arg < 5; arg++) - args[arg] += steps[arg]; +static int calc_ptf_ahuja1984_contiguous_loop(PyArrayMethod_Context *context, char *const *data, + const npy_intp *dimensions, const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_total_porosity = (const double *)data[0]; + const double *in_theta_33 = (const double *)data[1]; + const double *in_coefficient_b = (const double *)data[2]; + const double *in_exponent_n = (const double *)data[3]; + double *out_k_sat = (double *)data[4]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double total_porosity = in_total_porosity[index]; + const double theta_33 = in_theta_33[index]; + const double coefficient_b = in_coefficient_b[index]; + const double exponent_n = in_exponent_n[index]; + const double ptfkit_result = + calc_ptf_ahuja1984(total_porosity, theta_33, coefficient_b, exponent_n); + out_k_sat[index] = ptfkit_result; } + return 0; +} + +static int calc_ptf_ahuja1984_strided_loop(PyArrayMethod_Context *context, char *const *data, + const npy_intp *dimensions, const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double total_porosity = *(const double *)(data[0] + index * strides[0]); + const double theta_33 = *(const double *)(data[1] + index * strides[1]); + const double coefficient_b = *(const double *)(data[2] + index * strides[2]); + const double exponent_n = *(const double *)(data[3] + index * strides[3]); + const double ptfkit_result = + calc_ptf_ahuja1984(total_porosity, theta_33, coefficient_b, exponent_n); + *(double *)(data[4] + index * strides[4]) = ptfkit_result; + } + return 0; } -static PyUFuncGenericFunction calc_ptf_ahuja1984_functions[] = {calc_ptf_ahuja1984_loop}; -static char calc_ptf_ahuja1984_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE}; +static PyType_Slot calc_ptf_ahuja1984_slots[] = { + {NPY_METH_strided_loop, calc_ptf_ahuja1984_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_ahuja1984_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ahuja1984_spec = { + .name = "calc_ptf_ahuja1984", + .nin = 4, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ahuja1984_slots, +}; int ptfkit_register_ahuja1984(PyObject *module) { - if (ptfkit_add_ufunc(module, "calc_ptf_ahuja1984", calc_ptf_ahuja1984_functions, - calc_ptf_ahuja1984_types, 4, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_ahuja1984", 4, 1, &calc_ptf_ahuja1984_spec) < 0) return -1; return 0; } diff --git a/targets/ptfkit-py/src/ptfkit/ahuja1984.py b/targets/ptfkit-py/src/ptfkit/ahuja1984.py index 1d62a16..5f6da5c 100644 --- a/targets/ptfkit-py/src/ptfkit/ahuja1984.py +++ b/targets/ptfkit-py/src/ptfkit/ahuja1984.py @@ -23,6 +23,7 @@ from typing import TYPE_CHECKING, overload +from ptfkit._dispatch import call as _call from ptfkit._ptfkit import ( calc_ptf_ahuja1984 as _calc_ptf_ahuja1984, ) @@ -100,9 +101,11 @@ def calc_ptf_ahuja1984( total_porosity must be greater than or equal to theta_33. """ - if out is None: - values = _calc_ptf_ahuja1984(total_porosity, theta_33, coefficient_b, exponent_n) - else: - values = _calc_ptf_ahuja1984(total_porosity, theta_33, coefficient_b, exponent_n, out=out) - - return values + return _call( + _calc_ptf_ahuja1984, + total_porosity, + theta_33, + coefficient_b, + exponent_n, + out=out, + ) diff --git a/targets/ptfkit-py/src/ptfkit/aimrun2009.c b/targets/ptfkit-py/src/ptfkit/aimrun2009.c index ad81407..eb7ab8e 100644 --- a/targets/ptfkit-py/src/ptfkit/aimrun2009.c +++ b/targets/ptfkit-py/src/ptfkit/aimrun2009.c @@ -1,31 +1,59 @@ /* @generated by ptfkit-codegen; DO NOT EDIT. */ +#include #include "ufunc.h" -static void calc_ptf_aimrun2009_loop(char **args, const npy_intp *dimensions, const npy_intp *steps, - void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double clay = *(const double *)args[0]; - const double bulk_density = *(const double *)args[1]; - const double organic_matter = *(const double *)args[2]; - const double gmd = *(const double *)args[3]; - const double ln_k_sat_m_per_day = -2.368 + 3.846 * bulk_density + 0.091 * organic_matter - - 6.203 * log(bulk_density) - 0.343 * log(organic_matter) - - 2.334 * log(clay) - 0.411 * log(gmd); - const double k_sat_m_per_day = exp(ln_k_sat_m_per_day); - const double k_sat = k_sat_m_per_day * (1.0 / 86400.0); - *(double *)args[4] = k_sat; - for (int arg = 0; arg < 5; arg++) - args[arg] += steps[arg]; +static int calc_ptf_aimrun2009_contiguous_loop(PyArrayMethod_Context *context, char *const *data, + const npy_intp *dimensions, const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_clay = (const double *)data[0]; + const double *in_bulk_density = (const double *)data[1]; + const double *in_organic_matter = (const double *)data[2]; + const double *in_gmd = (const double *)data[3]; + double *out_k_sat = (double *)data[4]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = in_clay[index]; + const double bulk_density = in_bulk_density[index]; + const double organic_matter = in_organic_matter[index]; + const double gmd = in_gmd[index]; + const double ptfkit_result = calc_ptf_aimrun2009(clay, bulk_density, organic_matter, gmd); + out_k_sat[index] = ptfkit_result; } + return 0; +} + +static int calc_ptf_aimrun2009_strided_loop(PyArrayMethod_Context *context, char *const *data, + const npy_intp *dimensions, const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = *(const double *)(data[0] + index * strides[0]); + const double bulk_density = *(const double *)(data[1] + index * strides[1]); + const double organic_matter = *(const double *)(data[2] + index * strides[2]); + const double gmd = *(const double *)(data[3] + index * strides[3]); + const double ptfkit_result = calc_ptf_aimrun2009(clay, bulk_density, organic_matter, gmd); + *(double *)(data[4] + index * strides[4]) = ptfkit_result; + } + return 0; } -static PyUFuncGenericFunction calc_ptf_aimrun2009_functions[] = {calc_ptf_aimrun2009_loop}; -static char calc_ptf_aimrun2009_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE}; +static PyType_Slot calc_ptf_aimrun2009_slots[] = { + {NPY_METH_strided_loop, calc_ptf_aimrun2009_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_aimrun2009_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_aimrun2009_spec = { + .name = "calc_ptf_aimrun2009", + .nin = 4, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_aimrun2009_slots, +}; int ptfkit_register_aimrun2009(PyObject *module) { - if (ptfkit_add_ufunc(module, "calc_ptf_aimrun2009", calc_ptf_aimrun2009_functions, - calc_ptf_aimrun2009_types, 4, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_aimrun2009", 4, 1, &calc_ptf_aimrun2009_spec) < 0) return -1; return 0; } diff --git a/targets/ptfkit-py/src/ptfkit/aimrun2009.py b/targets/ptfkit-py/src/ptfkit/aimrun2009.py index ccaf6d5..ce3b6c7 100644 --- a/targets/ptfkit-py/src/ptfkit/aimrun2009.py +++ b/targets/ptfkit-py/src/ptfkit/aimrun2009.py @@ -22,6 +22,7 @@ from typing import TYPE_CHECKING, overload +from ptfkit._dispatch import call as _call from ptfkit._ptfkit import ( calc_ptf_aimrun2009 as _calc_ptf_aimrun2009, ) @@ -84,9 +85,11 @@ def calc_ptf_aimrun2009( The formula uses natural logarithms of all inputs. """ - if out is None: - values = _calc_ptf_aimrun2009(clay, bulk_density, organic_matter, gmd) - else: - values = _calc_ptf_aimrun2009(clay, bulk_density, organic_matter, gmd, out=out) - - return values + return _call( + _calc_ptf_aimrun2009, + clay, + bulk_density, + organic_matter, + gmd, + out=out, + ) diff --git a/targets/ptfkit-py/src/ptfkit/beniaich2023.c b/targets/ptfkit-py/src/ptfkit/beniaich2023.c index 9d7bf8b..09e5095 100644 --- a/targets/ptfkit-py/src/ptfkit/beniaich2023.c +++ b/targets/ptfkit-py/src/ptfkit/beniaich2023.c @@ -1,281 +1,618 @@ /* @generated by ptfkit-codegen; DO NOT EDIT. */ +#include #include "ufunc.h" -static void calc_ptf_beniaich2023_slr1_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double clay = *(const double *)args[0]; - const double water_saturation = (46.307 + 0.556 * clay) / 100.0; - const double water_field_capacity = (10.277 + 0.365 * clay) / 100.0; - const double water_wilting_point = (3.081 + 0.327 * clay) / 100.0; - *(double *)args[1] = water_saturation; - *(double *)args[2] = water_field_capacity; - *(double *)args[3] = water_wilting_point; - for (int arg = 0; arg < 4; arg++) - args[arg] += steps[arg]; +static int calc_ptf_beniaich2023_slr1_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_clay = (const double *)data[0]; + double *out_water_saturation = (double *)data[1]; + double *out_water_field_capacity = (double *)data[2]; + double *out_water_wilting_point = (double *)data[3]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = in_clay[index]; + const beniaich2023_ptf_result ptfkit_result = calc_ptf_beniaich2023_slr1(clay); + out_water_saturation[index] = ptfkit_result.water_saturation; + out_water_field_capacity[index] = ptfkit_result.water_field_capacity; + out_water_wilting_point[index] = ptfkit_result.water_wilting_point; } + return 0; +} + +static int calc_ptf_beniaich2023_slr1_strided_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = *(const double *)(data[0] + index * strides[0]); + const beniaich2023_ptf_result ptfkit_result = calc_ptf_beniaich2023_slr1(clay); + *(double *)(data[1] + index * strides[1]) = ptfkit_result.water_saturation; + *(double *)(data[2] + index * strides[2]) = ptfkit_result.water_field_capacity; + *(double *)(data[3] + index * strides[3]) = ptfkit_result.water_wilting_point; + } + return 0; +} +static PyType_Slot calc_ptf_beniaich2023_slr1_slots[] = { + {NPY_METH_strided_loop, calc_ptf_beniaich2023_slr1_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_beniaich2023_slr1_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_beniaich2023_slr1_spec = { + .name = "calc_ptf_beniaich2023_slr1", + .nin = 1, + .nout = 3, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_beniaich2023_slr1_slots, +}; + +static int calc_ptf_beniaich2023_slr2_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_silt = (const double *)data[0]; + double *out_water_saturation = (double *)data[1]; + double *out_water_field_capacity = (double *)data[2]; + double *out_water_wilting_point = (double *)data[3]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double silt = in_silt[index]; + const beniaich2023_ptf_result ptfkit_result = calc_ptf_beniaich2023_slr2(silt); + out_water_saturation[index] = ptfkit_result.water_saturation; + out_water_field_capacity[index] = ptfkit_result.water_field_capacity; + out_water_wilting_point[index] = ptfkit_result.water_wilting_point; + } + return 0; +} + +static int calc_ptf_beniaich2023_slr2_strided_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double silt = *(const double *)(data[0] + index * strides[0]); + const beniaich2023_ptf_result ptfkit_result = calc_ptf_beniaich2023_slr2(silt); + *(double *)(data[1] + index * strides[1]) = ptfkit_result.water_saturation; + *(double *)(data[2] + index * strides[2]) = ptfkit_result.water_field_capacity; + *(double *)(data[3] + index * strides[3]) = ptfkit_result.water_wilting_point; + } + return 0; +} +static PyType_Slot calc_ptf_beniaich2023_slr2_slots[] = { + {NPY_METH_strided_loop, calc_ptf_beniaich2023_slr2_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_beniaich2023_slr2_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_beniaich2023_slr2_spec = { + .name = "calc_ptf_beniaich2023_slr2", + .nin = 1, + .nout = 3, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_beniaich2023_slr2_slots, +}; + +static int calc_ptf_beniaich2023_slr3_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + double *out_water_saturation = (double *)data[1]; + double *out_water_field_capacity = (double *)data[2]; + double *out_water_wilting_point = (double *)data[3]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const beniaich2023_ptf_result ptfkit_result = calc_ptf_beniaich2023_slr3(sand); + out_water_saturation[index] = ptfkit_result.water_saturation; + out_water_field_capacity[index] = ptfkit_result.water_field_capacity; + out_water_wilting_point[index] = ptfkit_result.water_wilting_point; + } + return 0; } -static PyUFuncGenericFunction calc_ptf_beniaich2023_slr1_functions[] = { - calc_ptf_beniaich2023_slr1_loop}; -static char calc_ptf_beniaich2023_slr1_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; -static void calc_ptf_beniaich2023_slr2_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double silt = *(const double *)args[0]; - const double water_saturation = (59.508 + 0.299 * silt) / 100.0; - const double water_field_capacity = (16.178 + 0.290 * silt) / 100.0; - const double water_wilting_point = (10.521 + 0.187 * silt) / 100.0; - *(double *)args[1] = water_saturation; - *(double *)args[2] = water_field_capacity; - *(double *)args[3] = water_wilting_point; - for (int arg = 0; arg < 4; arg++) - args[arg] += steps[arg]; +static int calc_ptf_beniaich2023_slr3_strided_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const beniaich2023_ptf_result ptfkit_result = calc_ptf_beniaich2023_slr3(sand); + *(double *)(data[1] + index * strides[1]) = ptfkit_result.water_saturation; + *(double *)(data[2] + index * strides[2]) = ptfkit_result.water_field_capacity; + *(double *)(data[3] + index * strides[3]) = ptfkit_result.water_wilting_point; } + return 0; } -static PyUFuncGenericFunction calc_ptf_beniaich2023_slr2_functions[] = { - calc_ptf_beniaich2023_slr2_loop}; -static char calc_ptf_beniaich2023_slr2_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; +static PyType_Slot calc_ptf_beniaich2023_slr3_slots[] = { + {NPY_METH_strided_loop, calc_ptf_beniaich2023_slr3_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_beniaich2023_slr3_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_beniaich2023_slr3_spec = { + .name = "calc_ptf_beniaich2023_slr3", + .nin = 1, + .nout = 3, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_beniaich2023_slr3_slots, +}; -static void calc_ptf_beniaich2023_slr3_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double water_saturation = (81.420 - 0.427 * sand) / 100.0; - const double water_field_capacity = (34.680 - 0.324 * sand) / 100.0; - const double water_wilting_point = (23.927 - 0.257 * sand) / 100.0; - *(double *)args[1] = water_saturation; - *(double *)args[2] = water_field_capacity; - *(double *)args[3] = water_wilting_point; - for (int arg = 0; arg < 4; arg++) - args[arg] += steps[arg]; +static int calc_ptf_beniaich2023_slr4_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_clay = (const double *)data[0]; + const double *in_silt = (const double *)data[1]; + double *out_water_saturation = (double *)data[2]; + double *out_water_field_capacity = (double *)data[3]; + double *out_water_wilting_point = (double *)data[4]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = in_clay[index]; + const double silt = in_silt[index]; + const beniaich2023_ptf_result ptfkit_result = calc_ptf_beniaich2023_slr4(clay, silt); + out_water_saturation[index] = ptfkit_result.water_saturation; + out_water_field_capacity[index] = ptfkit_result.water_field_capacity; + out_water_wilting_point[index] = ptfkit_result.water_wilting_point; } + return 0; } -static PyUFuncGenericFunction calc_ptf_beniaich2023_slr3_functions[] = { - calc_ptf_beniaich2023_slr3_loop}; -static char calc_ptf_beniaich2023_slr3_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; -static void calc_ptf_beniaich2023_slr4_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double clay = *(const double *)args[0]; - const double silt = *(const double *)args[1]; - const double clay_silt = clay + silt; - const double water_saturation = (89.401 - 0.298 * clay_silt) / 100.0; - const double water_field_capacity = (45.178 - 0.290 * clay_silt) / 100.0; - const double water_wilting_point = (29.265 - 0.187 * clay_silt) / 100.0; - *(double *)args[2] = water_saturation; - *(double *)args[3] = water_field_capacity; - *(double *)args[4] = water_wilting_point; - for (int arg = 0; arg < 5; arg++) - args[arg] += steps[arg]; +static int calc_ptf_beniaich2023_slr4_strided_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = *(const double *)(data[0] + index * strides[0]); + const double silt = *(const double *)(data[1] + index * strides[1]); + const beniaich2023_ptf_result ptfkit_result = calc_ptf_beniaich2023_slr4(clay, silt); + *(double *)(data[2] + index * strides[2]) = ptfkit_result.water_saturation; + *(double *)(data[3] + index * strides[3]) = ptfkit_result.water_field_capacity; + *(double *)(data[4] + index * strides[4]) = ptfkit_result.water_wilting_point; } + return 0; } -static PyUFuncGenericFunction calc_ptf_beniaich2023_slr4_functions[] = { - calc_ptf_beniaich2023_slr4_loop}; -static char calc_ptf_beniaich2023_slr4_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE}; +static PyType_Slot calc_ptf_beniaich2023_slr4_slots[] = { + {NPY_METH_strided_loop, calc_ptf_beniaich2023_slr4_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_beniaich2023_slr4_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_beniaich2023_slr4_spec = { + .name = "calc_ptf_beniaich2023_slr4", + .nin = 2, + .nout = 3, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_beniaich2023_slr4_slots, +}; -static void calc_ptf_beniaich2023_slr5_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double clay = *(const double *)args[0]; - const double silt = *(const double *)args[1]; - const double clay_silt_ratio = clay / silt; - const double water_saturation = (68.851 - 0.546 * clay_silt_ratio) / 100.0; - const double water_field_capacity = (23.278 + 1.819 * clay_silt_ratio) / 100.0; - const double water_wilting_point = (16.298 - 0.244 * clay_silt_ratio) / 100.0; - *(double *)args[2] = water_saturation; - *(double *)args[3] = water_field_capacity; - *(double *)args[4] = water_wilting_point; - for (int arg = 0; arg < 5; arg++) - args[arg] += steps[arg]; +static int calc_ptf_beniaich2023_slr5_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_clay = (const double *)data[0]; + const double *in_silt = (const double *)data[1]; + double *out_water_saturation = (double *)data[2]; + double *out_water_field_capacity = (double *)data[3]; + double *out_water_wilting_point = (double *)data[4]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = in_clay[index]; + const double silt = in_silt[index]; + const beniaich2023_ptf_result ptfkit_result = calc_ptf_beniaich2023_slr5(clay, silt); + out_water_saturation[index] = ptfkit_result.water_saturation; + out_water_field_capacity[index] = ptfkit_result.water_field_capacity; + out_water_wilting_point[index] = ptfkit_result.water_wilting_point; } + return 0; } -static PyUFuncGenericFunction calc_ptf_beniaich2023_slr5_functions[] = { - calc_ptf_beniaich2023_slr5_loop}; -static char calc_ptf_beniaich2023_slr5_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE}; -static void calc_ptf_beniaich2023_slr6_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double soil_organic_matter = *(const double *)args[0]; - const double water_saturation = (61.163 + 2.793 * soil_organic_matter) / 100.0; - const double water_field_capacity = (21.331 + 1.339 * soil_organic_matter) / 100.0; - const double water_wilting_point = (13.758 + 0.902 * soil_organic_matter) / 100.0; - *(double *)args[1] = water_saturation; - *(double *)args[2] = water_field_capacity; - *(double *)args[3] = water_wilting_point; - for (int arg = 0; arg < 4; arg++) - args[arg] += steps[arg]; +static int calc_ptf_beniaich2023_slr5_strided_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = *(const double *)(data[0] + index * strides[0]); + const double silt = *(const double *)(data[1] + index * strides[1]); + const beniaich2023_ptf_result ptfkit_result = calc_ptf_beniaich2023_slr5(clay, silt); + *(double *)(data[2] + index * strides[2]) = ptfkit_result.water_saturation; + *(double *)(data[3] + index * strides[3]) = ptfkit_result.water_field_capacity; + *(double *)(data[4] + index * strides[4]) = ptfkit_result.water_wilting_point; } + return 0; } -static PyUFuncGenericFunction calc_ptf_beniaich2023_slr6_functions[] = { - calc_ptf_beniaich2023_slr6_loop}; -static char calc_ptf_beniaich2023_slr6_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; +static PyType_Slot calc_ptf_beniaich2023_slr5_slots[] = { + {NPY_METH_strided_loop, calc_ptf_beniaich2023_slr5_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_beniaich2023_slr5_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_beniaich2023_slr5_spec = { + .name = "calc_ptf_beniaich2023_slr5", + .nin = 2, + .nout = 3, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_beniaich2023_slr5_slots, +}; -static void calc_ptf_beniaich2023_mlr1_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double silt = *(const double *)args[0]; - const double sand = *(const double *)args[1]; - const double soil_organic_matter = *(const double *)args[2]; - const double water_saturation = - (87.342 - 0.281 * silt - 0.548 * sand + 2.377 * soil_organic_matter) / 100.0; - const double water_field_capacity = - (35.844 - 0.085 * silt - 0.359 * sand + 0.947 * soil_organic_matter) / 100.0; - const double water_wilting_point = - (28.734 - 0.148 * silt - 0.324 * sand + 0.636 * soil_organic_matter) / 100.0; - *(double *)args[3] = water_saturation; - *(double *)args[4] = water_field_capacity; - *(double *)args[5] = water_wilting_point; - for (int arg = 0; arg < 6; arg++) - args[arg] += steps[arg]; +static int calc_ptf_beniaich2023_slr6_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_soil_organic_matter = (const double *)data[0]; + double *out_water_saturation = (double *)data[1]; + double *out_water_field_capacity = (double *)data[2]; + double *out_water_wilting_point = (double *)data[3]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double soil_organic_matter = in_soil_organic_matter[index]; + const beniaich2023_ptf_result ptfkit_result = + calc_ptf_beniaich2023_slr6(soil_organic_matter); + out_water_saturation[index] = ptfkit_result.water_saturation; + out_water_field_capacity[index] = ptfkit_result.water_field_capacity; + out_water_wilting_point[index] = ptfkit_result.water_wilting_point; } + return 0; } -static PyUFuncGenericFunction calc_ptf_beniaich2023_mlr1_functions[] = { - calc_ptf_beniaich2023_mlr1_loop}; -static char calc_ptf_beniaich2023_mlr1_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; -static void calc_ptf_beniaich2023_mlr2_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double soil_organic_matter = *(const double *)args[1]; - const double water_saturation = - (75.366 - 0.417 * sand + 2.219 * soil_organic_matter) / 100.0; - const double water_field_capacity = - (32.227 - 0.320 * sand + 0.899 * soil_organic_matter) / 100.0; - const double water_wilting_point = - (22.421 - 0.254 * sand + 0.552 * soil_organic_matter) / 100.0; - *(double *)args[2] = water_saturation; - *(double *)args[3] = water_field_capacity; - *(double *)args[4] = water_wilting_point; - for (int arg = 0; arg < 5; arg++) - args[arg] += steps[arg]; +static int calc_ptf_beniaich2023_slr6_strided_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double soil_organic_matter = *(const double *)(data[0] + index * strides[0]); + const beniaich2023_ptf_result ptfkit_result = + calc_ptf_beniaich2023_slr6(soil_organic_matter); + *(double *)(data[1] + index * strides[1]) = ptfkit_result.water_saturation; + *(double *)(data[2] + index * strides[2]) = ptfkit_result.water_field_capacity; + *(double *)(data[3] + index * strides[3]) = ptfkit_result.water_wilting_point; } + return 0; } -static PyUFuncGenericFunction calc_ptf_beniaich2023_mlr2_functions[] = { - calc_ptf_beniaich2023_mlr2_loop}; -static char calc_ptf_beniaich2023_mlr2_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE}; +static PyType_Slot calc_ptf_beniaich2023_slr6_slots[] = { + {NPY_METH_strided_loop, calc_ptf_beniaich2023_slr6_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_beniaich2023_slr6_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_beniaich2023_slr6_spec = { + .name = "calc_ptf_beniaich2023_slr6", + .nin = 1, + .nout = 3, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_beniaich2023_slr6_slots, +}; -static void calc_ptf_beniaich2023_mlr3_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double silt = *(const double *)args[0]; - const double soil_organic_matter = *(const double *)args[1]; - const double water_saturation = - (53.777 + 0.278 * silt + 2.457 * soil_organic_matter) / 100.0; - const double water_field_capacity = - (13.847 + 0.281 * silt + 0.999 * soil_organic_matter) / 100.0; - const double water_wilting_point = - (8.929 + 0.182 * silt + 0.683 * soil_organic_matter) / 100.0; - *(double *)args[2] = water_saturation; - *(double *)args[3] = water_field_capacity; - *(double *)args[4] = water_wilting_point; - for (int arg = 0; arg < 5; arg++) - args[arg] += steps[arg]; +static int calc_ptf_beniaich2023_mlr1_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_silt = (const double *)data[0]; + const double *in_sand = (const double *)data[1]; + const double *in_soil_organic_matter = (const double *)data[2]; + double *out_water_saturation = (double *)data[3]; + double *out_water_field_capacity = (double *)data[4]; + double *out_water_wilting_point = (double *)data[5]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double silt = in_silt[index]; + const double sand = in_sand[index]; + const double soil_organic_matter = in_soil_organic_matter[index]; + const beniaich2023_ptf_result ptfkit_result = + calc_ptf_beniaich2023_mlr1(silt, sand, soil_organic_matter); + out_water_saturation[index] = ptfkit_result.water_saturation; + out_water_field_capacity[index] = ptfkit_result.water_field_capacity; + out_water_wilting_point[index] = ptfkit_result.water_wilting_point; } + return 0; } -static PyUFuncGenericFunction calc_ptf_beniaich2023_mlr3_functions[] = { - calc_ptf_beniaich2023_mlr3_loop}; -static char calc_ptf_beniaich2023_mlr3_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE}; -static void calc_ptf_beniaich2023_mlr4_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double clay = *(const double *)args[0]; - const double soil_organic_matter = *(const double *)args[1]; - const double water_saturation = - (39.432 + 0.553 * clay + 2.699 * soil_organic_matter) / 100.0; - const double water_field_capacity = - (7.023 + 0.364 * clay + 1.278 * soil_organic_matter) / 100.0; - const double water_wilting_point = - (0.923 + 0.327 * clay + 0.847 * soil_organic_matter) / 100.0; - *(double *)args[2] = water_saturation; - *(double *)args[3] = water_field_capacity; - *(double *)args[4] = water_wilting_point; - for (int arg = 0; arg < 5; arg++) - args[arg] += steps[arg]; +static int calc_ptf_beniaich2023_mlr1_strided_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double silt = *(const double *)(data[0] + index * strides[0]); + const double sand = *(const double *)(data[1] + index * strides[1]); + const double soil_organic_matter = *(const double *)(data[2] + index * strides[2]); + const beniaich2023_ptf_result ptfkit_result = + calc_ptf_beniaich2023_mlr1(silt, sand, soil_organic_matter); + *(double *)(data[3] + index * strides[3]) = ptfkit_result.water_saturation; + *(double *)(data[4] + index * strides[4]) = ptfkit_result.water_field_capacity; + *(double *)(data[5] + index * strides[5]) = ptfkit_result.water_wilting_point; } + return 0; } -static PyUFuncGenericFunction calc_ptf_beniaich2023_mlr4_functions[] = { - calc_ptf_beniaich2023_mlr4_loop}; -static char calc_ptf_beniaich2023_mlr4_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE}; +static PyType_Slot calc_ptf_beniaich2023_mlr1_slots[] = { + {NPY_METH_strided_loop, calc_ptf_beniaich2023_mlr1_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_beniaich2023_mlr1_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_beniaich2023_mlr1_spec = { + .name = "calc_ptf_beniaich2023_mlr1", + .nin = 3, + .nout = 3, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_beniaich2023_mlr1_slots, +}; -static void calc_ptf_beniaich2023_mlr5_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double clay = *(const double *)args[0]; - const double silt = *(const double *)args[1]; - const double soil_organic_matter = *(const double *)args[2]; - const double water_saturation = - (32.505 + 0.548 * clay + 0.267 * silt + 2.377 * soil_organic_matter) / 100.0; - const double water_field_capacity = - (-0.094 + 0.359 * clay + 0.274 * silt + 0.947 * soil_organic_matter) / 100.0; - const double water_wilting_point = - (-3.623 + 0.324 * clay + 0.175 * silt + 0.636 * soil_organic_matter) / 100.0; - *(double *)args[3] = water_saturation; - *(double *)args[4] = water_field_capacity; - *(double *)args[5] = water_wilting_point; - for (int arg = 0; arg < 6; arg++) - args[arg] += steps[arg]; +static int calc_ptf_beniaich2023_mlr2_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_soil_organic_matter = (const double *)data[1]; + double *out_water_saturation = (double *)data[2]; + double *out_water_field_capacity = (double *)data[3]; + double *out_water_wilting_point = (double *)data[4]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double soil_organic_matter = in_soil_organic_matter[index]; + const beniaich2023_ptf_result ptfkit_result = + calc_ptf_beniaich2023_mlr2(sand, soil_organic_matter); + out_water_saturation[index] = ptfkit_result.water_saturation; + out_water_field_capacity[index] = ptfkit_result.water_field_capacity; + out_water_wilting_point[index] = ptfkit_result.water_wilting_point; } + return 0; +} + +static int calc_ptf_beniaich2023_mlr2_strided_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double soil_organic_matter = *(const double *)(data[1] + index * strides[1]); + const beniaich2023_ptf_result ptfkit_result = + calc_ptf_beniaich2023_mlr2(sand, soil_organic_matter); + *(double *)(data[2] + index * strides[2]) = ptfkit_result.water_saturation; + *(double *)(data[3] + index * strides[3]) = ptfkit_result.water_field_capacity; + *(double *)(data[4] + index * strides[4]) = ptfkit_result.water_wilting_point; + } + return 0; +} +static PyType_Slot calc_ptf_beniaich2023_mlr2_slots[] = { + {NPY_METH_strided_loop, calc_ptf_beniaich2023_mlr2_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_beniaich2023_mlr2_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_beniaich2023_mlr2_spec = { + .name = "calc_ptf_beniaich2023_mlr2", + .nin = 2, + .nout = 3, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_beniaich2023_mlr2_slots, +}; + +static int calc_ptf_beniaich2023_mlr3_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_silt = (const double *)data[0]; + const double *in_soil_organic_matter = (const double *)data[1]; + double *out_water_saturation = (double *)data[2]; + double *out_water_field_capacity = (double *)data[3]; + double *out_water_wilting_point = (double *)data[4]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double silt = in_silt[index]; + const double soil_organic_matter = in_soil_organic_matter[index]; + const beniaich2023_ptf_result ptfkit_result = + calc_ptf_beniaich2023_mlr3(silt, soil_organic_matter); + out_water_saturation[index] = ptfkit_result.water_saturation; + out_water_field_capacity[index] = ptfkit_result.water_field_capacity; + out_water_wilting_point[index] = ptfkit_result.water_wilting_point; + } + return 0; +} + +static int calc_ptf_beniaich2023_mlr3_strided_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double silt = *(const double *)(data[0] + index * strides[0]); + const double soil_organic_matter = *(const double *)(data[1] + index * strides[1]); + const beniaich2023_ptf_result ptfkit_result = + calc_ptf_beniaich2023_mlr3(silt, soil_organic_matter); + *(double *)(data[2] + index * strides[2]) = ptfkit_result.water_saturation; + *(double *)(data[3] + index * strides[3]) = ptfkit_result.water_field_capacity; + *(double *)(data[4] + index * strides[4]) = ptfkit_result.water_wilting_point; + } + return 0; +} +static PyType_Slot calc_ptf_beniaich2023_mlr3_slots[] = { + {NPY_METH_strided_loop, calc_ptf_beniaich2023_mlr3_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_beniaich2023_mlr3_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_beniaich2023_mlr3_spec = { + .name = "calc_ptf_beniaich2023_mlr3", + .nin = 2, + .nout = 3, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_beniaich2023_mlr3_slots, +}; + +static int calc_ptf_beniaich2023_mlr4_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_clay = (const double *)data[0]; + const double *in_soil_organic_matter = (const double *)data[1]; + double *out_water_saturation = (double *)data[2]; + double *out_water_field_capacity = (double *)data[3]; + double *out_water_wilting_point = (double *)data[4]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = in_clay[index]; + const double soil_organic_matter = in_soil_organic_matter[index]; + const beniaich2023_ptf_result ptfkit_result = + calc_ptf_beniaich2023_mlr4(clay, soil_organic_matter); + out_water_saturation[index] = ptfkit_result.water_saturation; + out_water_field_capacity[index] = ptfkit_result.water_field_capacity; + out_water_wilting_point[index] = ptfkit_result.water_wilting_point; + } + return 0; +} + +static int calc_ptf_beniaich2023_mlr4_strided_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = *(const double *)(data[0] + index * strides[0]); + const double soil_organic_matter = *(const double *)(data[1] + index * strides[1]); + const beniaich2023_ptf_result ptfkit_result = + calc_ptf_beniaich2023_mlr4(clay, soil_organic_matter); + *(double *)(data[2] + index * strides[2]) = ptfkit_result.water_saturation; + *(double *)(data[3] + index * strides[3]) = ptfkit_result.water_field_capacity; + *(double *)(data[4] + index * strides[4]) = ptfkit_result.water_wilting_point; + } + return 0; +} +static PyType_Slot calc_ptf_beniaich2023_mlr4_slots[] = { + {NPY_METH_strided_loop, calc_ptf_beniaich2023_mlr4_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_beniaich2023_mlr4_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_beniaich2023_mlr4_spec = { + .name = "calc_ptf_beniaich2023_mlr4", + .nin = 2, + .nout = 3, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_beniaich2023_mlr4_slots, +}; + +static int calc_ptf_beniaich2023_mlr5_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_clay = (const double *)data[0]; + const double *in_silt = (const double *)data[1]; + const double *in_soil_organic_matter = (const double *)data[2]; + double *out_water_saturation = (double *)data[3]; + double *out_water_field_capacity = (double *)data[4]; + double *out_water_wilting_point = (double *)data[5]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = in_clay[index]; + const double silt = in_silt[index]; + const double soil_organic_matter = in_soil_organic_matter[index]; + const beniaich2023_ptf_result ptfkit_result = + calc_ptf_beniaich2023_mlr5(clay, silt, soil_organic_matter); + out_water_saturation[index] = ptfkit_result.water_saturation; + out_water_field_capacity[index] = ptfkit_result.water_field_capacity; + out_water_wilting_point[index] = ptfkit_result.water_wilting_point; + } + return 0; +} + +static int calc_ptf_beniaich2023_mlr5_strided_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = *(const double *)(data[0] + index * strides[0]); + const double silt = *(const double *)(data[1] + index * strides[1]); + const double soil_organic_matter = *(const double *)(data[2] + index * strides[2]); + const beniaich2023_ptf_result ptfkit_result = + calc_ptf_beniaich2023_mlr5(clay, silt, soil_organic_matter); + *(double *)(data[3] + index * strides[3]) = ptfkit_result.water_saturation; + *(double *)(data[4] + index * strides[4]) = ptfkit_result.water_field_capacity; + *(double *)(data[5] + index * strides[5]) = ptfkit_result.water_wilting_point; + } + return 0; } -static PyUFuncGenericFunction calc_ptf_beniaich2023_mlr5_functions[] = { - calc_ptf_beniaich2023_mlr5_loop}; -static char calc_ptf_beniaich2023_mlr5_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; +static PyType_Slot calc_ptf_beniaich2023_mlr5_slots[] = { + {NPY_METH_strided_loop, calc_ptf_beniaich2023_mlr5_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_beniaich2023_mlr5_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_beniaich2023_mlr5_spec = { + .name = "calc_ptf_beniaich2023_mlr5", + .nin = 3, + .nout = 3, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_beniaich2023_mlr5_slots, +}; int ptfkit_register_beniaich2023(PyObject *module) { - if (ptfkit_add_ufunc(module, "calc_ptf_beniaich2023_slr1", calc_ptf_beniaich2023_slr1_functions, - calc_ptf_beniaich2023_slr1_types, 1, 3) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_beniaich2023_slr1", 1, 3, + &calc_ptf_beniaich2023_slr1_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_beniaich2023_slr2", calc_ptf_beniaich2023_slr2_functions, - calc_ptf_beniaich2023_slr2_types, 1, 3) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_beniaich2023_slr2", 1, 3, + &calc_ptf_beniaich2023_slr2_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_beniaich2023_slr3", calc_ptf_beniaich2023_slr3_functions, - calc_ptf_beniaich2023_slr3_types, 1, 3) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_beniaich2023_slr3", 1, 3, + &calc_ptf_beniaich2023_slr3_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_beniaich2023_slr4", calc_ptf_beniaich2023_slr4_functions, - calc_ptf_beniaich2023_slr4_types, 2, 3) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_beniaich2023_slr4", 2, 3, + &calc_ptf_beniaich2023_slr4_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_beniaich2023_slr5", calc_ptf_beniaich2023_slr5_functions, - calc_ptf_beniaich2023_slr5_types, 2, 3) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_beniaich2023_slr5", 2, 3, + &calc_ptf_beniaich2023_slr5_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_beniaich2023_slr6", calc_ptf_beniaich2023_slr6_functions, - calc_ptf_beniaich2023_slr6_types, 1, 3) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_beniaich2023_slr6", 1, 3, + &calc_ptf_beniaich2023_slr6_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_beniaich2023_mlr1", calc_ptf_beniaich2023_mlr1_functions, - calc_ptf_beniaich2023_mlr1_types, 3, 3) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_beniaich2023_mlr1", 3, 3, + &calc_ptf_beniaich2023_mlr1_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_beniaich2023_mlr2", calc_ptf_beniaich2023_mlr2_functions, - calc_ptf_beniaich2023_mlr2_types, 2, 3) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_beniaich2023_mlr2", 2, 3, + &calc_ptf_beniaich2023_mlr2_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_beniaich2023_mlr3", calc_ptf_beniaich2023_mlr3_functions, - calc_ptf_beniaich2023_mlr3_types, 2, 3) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_beniaich2023_mlr3", 2, 3, + &calc_ptf_beniaich2023_mlr3_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_beniaich2023_mlr4", calc_ptf_beniaich2023_mlr4_functions, - calc_ptf_beniaich2023_mlr4_types, 2, 3) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_beniaich2023_mlr4", 2, 3, + &calc_ptf_beniaich2023_mlr4_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_beniaich2023_mlr5", calc_ptf_beniaich2023_mlr5_functions, - calc_ptf_beniaich2023_mlr5_types, 3, 3) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_beniaich2023_mlr5", 3, 3, + &calc_ptf_beniaich2023_mlr5_spec) < 0) return -1; return 0; } diff --git a/targets/ptfkit-py/src/ptfkit/beniaich2023.py b/targets/ptfkit-py/src/ptfkit/beniaich2023.py index 331a327..f97e4e3 100644 --- a/targets/ptfkit-py/src/ptfkit/beniaich2023.py +++ b/targets/ptfkit-py/src/ptfkit/beniaich2023.py @@ -26,6 +26,7 @@ from typing import TYPE_CHECKING, Generic, NamedTuple, TypeVar, overload +from ptfkit._dispatch import call as _call from ptfkit._ptfkit import ( calc_ptf_beniaich2023_slr1 as _calc_ptf_beniaich2023_slr1, calc_ptf_beniaich2023_slr2 as _calc_ptf_beniaich2023_slr2, @@ -117,10 +118,11 @@ def calc_ptf_beniaich2023_slr1( source territory. """ - if out is None: - values = _calc_ptf_beniaich2023_slr1(clay) - else: - values = _calc_ptf_beniaich2023_slr1(clay, out=tuple(out)) + values = _call( + _calc_ptf_beniaich2023_slr1, + clay, + out=out, + ) return Beniaich2023PTFResult(*values) @@ -163,10 +165,11 @@ def calc_ptf_beniaich2023_slr2( source territory. """ - if out is None: - values = _calc_ptf_beniaich2023_slr2(silt) - else: - values = _calc_ptf_beniaich2023_slr2(silt, out=tuple(out)) + values = _call( + _calc_ptf_beniaich2023_slr2, + silt, + out=out, + ) return Beniaich2023PTFResult(*values) @@ -209,10 +212,11 @@ def calc_ptf_beniaich2023_slr3( source territory. """ - if out is None: - values = _calc_ptf_beniaich2023_slr3(sand) - else: - values = _calc_ptf_beniaich2023_slr3(sand, out=tuple(out)) + values = _call( + _calc_ptf_beniaich2023_slr3, + sand, + out=out, + ) return Beniaich2023PTFResult(*values) @@ -258,10 +262,12 @@ def calc_ptf_beniaich2023_slr4( source territory. """ - if out is None: - values = _calc_ptf_beniaich2023_slr4(clay, silt) - else: - values = _calc_ptf_beniaich2023_slr4(clay, silt, out=tuple(out)) + values = _call( + _calc_ptf_beniaich2023_slr4, + clay, + silt, + out=out, + ) return Beniaich2023PTFResult(*values) @@ -307,10 +313,12 @@ def calc_ptf_beniaich2023_slr5( source territory. """ - if out is None: - values = _calc_ptf_beniaich2023_slr5(clay, silt) - else: - values = _calc_ptf_beniaich2023_slr5(clay, silt, out=tuple(out)) + values = _call( + _calc_ptf_beniaich2023_slr5, + clay, + silt, + out=out, + ) return Beniaich2023PTFResult(*values) @@ -355,10 +363,11 @@ def calc_ptf_beniaich2023_slr6( source territory. """ - if out is None: - values = _calc_ptf_beniaich2023_slr6(soil_organic_matter) - else: - values = _calc_ptf_beniaich2023_slr6(soil_organic_matter, out=tuple(out)) + values = _call( + _calc_ptf_beniaich2023_slr6, + soil_organic_matter, + out=out, + ) return Beniaich2023PTFResult(*values) @@ -409,10 +418,13 @@ def calc_ptf_beniaich2023_mlr1( source territory. """ - if out is None: - values = _calc_ptf_beniaich2023_mlr1(silt, sand, soil_organic_matter) - else: - values = _calc_ptf_beniaich2023_mlr1(silt, sand, soil_organic_matter, out=tuple(out)) + values = _call( + _calc_ptf_beniaich2023_mlr1, + silt, + sand, + soil_organic_matter, + out=out, + ) return Beniaich2023PTFResult(*values) @@ -460,10 +472,12 @@ def calc_ptf_beniaich2023_mlr2( source territory. """ - if out is None: - values = _calc_ptf_beniaich2023_mlr2(sand, soil_organic_matter) - else: - values = _calc_ptf_beniaich2023_mlr2(sand, soil_organic_matter, out=tuple(out)) + values = _call( + _calc_ptf_beniaich2023_mlr2, + sand, + soil_organic_matter, + out=out, + ) return Beniaich2023PTFResult(*values) @@ -511,10 +525,12 @@ def calc_ptf_beniaich2023_mlr3( source territory. """ - if out is None: - values = _calc_ptf_beniaich2023_mlr3(silt, soil_organic_matter) - else: - values = _calc_ptf_beniaich2023_mlr3(silt, soil_organic_matter, out=tuple(out)) + values = _call( + _calc_ptf_beniaich2023_mlr3, + silt, + soil_organic_matter, + out=out, + ) return Beniaich2023PTFResult(*values) @@ -562,10 +578,12 @@ def calc_ptf_beniaich2023_mlr4( source territory. """ - if out is None: - values = _calc_ptf_beniaich2023_mlr4(clay, soil_organic_matter) - else: - values = _calc_ptf_beniaich2023_mlr4(clay, soil_organic_matter, out=tuple(out)) + values = _call( + _calc_ptf_beniaich2023_mlr4, + clay, + soil_organic_matter, + out=out, + ) return Beniaich2023PTFResult(*values) @@ -616,9 +634,12 @@ def calc_ptf_beniaich2023_mlr5( source territory. """ - if out is None: - values = _calc_ptf_beniaich2023_mlr5(clay, silt, soil_organic_matter) - else: - values = _calc_ptf_beniaich2023_mlr5(clay, silt, soil_organic_matter, out=tuple(out)) + values = _call( + _calc_ptf_beniaich2023_mlr5, + clay, + silt, + soil_organic_matter, + out=out, + ) return Beniaich2023PTFResult(*values) diff --git a/targets/ptfkit-py/src/ptfkit/chakraborty2011.c b/targets/ptfkit-py/src/ptfkit/chakraborty2011.c index e9696d5..d66f6ac 100644 --- a/targets/ptfkit-py/src/ptfkit/chakraborty2011.c +++ b/targets/ptfkit-py/src/ptfkit/chakraborty2011.c @@ -1,196 +1,392 @@ /* @generated by ptfkit-codegen; DO NOT EDIT. */ +#include #include "ufunc.h" -static void calc_ptf_chakraborty2011_eq1_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double clay = *(const double *)args[0]; - const double silt = *(const double *)args[1]; - const double water_content_33 = (0.297 * clay + 0.478 * silt + 4.600) / 100.0; - const double water_content_100 = (0.270 * clay + 0.379 * silt + 2.988) / 100.0; - const double water_content_500 = (0.251 * clay + 0.185 * silt + 2.958) / 100.0; - const double water_content_1500 = (0.184 * clay + 0.144 * silt + 3.702) / 100.0; - *(double *)args[2] = water_content_33; - *(double *)args[3] = water_content_100; - *(double *)args[4] = water_content_500; - *(double *)args[5] = water_content_1500; - for (int arg = 0; arg < 6; arg++) - args[arg] += steps[arg]; +static int calc_ptf_chakraborty2011_eq1_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_clay = (const double *)data[0]; + const double *in_silt = (const double *)data[1]; + double *out_water_content_33 = (double *)data[2]; + double *out_water_content_100 = (double *)data[3]; + double *out_water_content_500 = (double *)data[4]; + double *out_water_content_1500 = (double *)data[5]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = in_clay[index]; + const double silt = in_silt[index]; + const chakraborty2011_ptf_result ptfkit_result = calc_ptf_chakraborty2011_eq1(clay, silt); + out_water_content_33[index] = ptfkit_result.water_content_33; + out_water_content_100[index] = ptfkit_result.water_content_100; + out_water_content_500[index] = ptfkit_result.water_content_500; + out_water_content_1500[index] = ptfkit_result.water_content_1500; } + return 0; +} + +static int calc_ptf_chakraborty2011_eq1_strided_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = *(const double *)(data[0] + index * strides[0]); + const double silt = *(const double *)(data[1] + index * strides[1]); + const chakraborty2011_ptf_result ptfkit_result = calc_ptf_chakraborty2011_eq1(clay, silt); + *(double *)(data[2] + index * strides[2]) = ptfkit_result.water_content_33; + *(double *)(data[3] + index * strides[3]) = ptfkit_result.water_content_100; + *(double *)(data[4] + index * strides[4]) = ptfkit_result.water_content_500; + *(double *)(data[5] + index * strides[5]) = ptfkit_result.water_content_1500; + } + return 0; +} +static PyType_Slot calc_ptf_chakraborty2011_eq1_slots[] = { + {NPY_METH_strided_loop, calc_ptf_chakraborty2011_eq1_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_chakraborty2011_eq1_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_chakraborty2011_eq1_spec = { + .name = "calc_ptf_chakraborty2011_eq1", + .nin = 2, + .nout = 4, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_chakraborty2011_eq1_slots, +}; + +static int calc_ptf_chakraborty2011_eq2_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_bulk_density = (const double *)data[1]; + double *out_water_content_33 = (double *)data[2]; + double *out_water_content_100 = (double *)data[3]; + double *out_water_content_500 = (double *)data[4]; + double *out_water_content_1500 = (double *)data[5]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double bulk_density = in_bulk_density[index]; + const chakraborty2011_ptf_result ptfkit_result = + calc_ptf_chakraborty2011_eq2(sand, bulk_density); + out_water_content_33[index] = ptfkit_result.water_content_33; + out_water_content_100[index] = ptfkit_result.water_content_100; + out_water_content_500[index] = ptfkit_result.water_content_500; + out_water_content_1500[index] = ptfkit_result.water_content_1500; + } + return 0; +} + +static int calc_ptf_chakraborty2011_eq2_strided_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double bulk_density = *(const double *)(data[1] + index * strides[1]); + const chakraborty2011_ptf_result ptfkit_result = + calc_ptf_chakraborty2011_eq2(sand, bulk_density); + *(double *)(data[2] + index * strides[2]) = ptfkit_result.water_content_33; + *(double *)(data[3] + index * strides[3]) = ptfkit_result.water_content_100; + *(double *)(data[4] + index * strides[4]) = ptfkit_result.water_content_500; + *(double *)(data[5] + index * strides[5]) = ptfkit_result.water_content_1500; + } + return 0; +} +static PyType_Slot calc_ptf_chakraborty2011_eq2_slots[] = { + {NPY_METH_strided_loop, calc_ptf_chakraborty2011_eq2_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_chakraborty2011_eq2_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_chakraborty2011_eq2_spec = { + .name = "calc_ptf_chakraborty2011_eq2", + .nin = 2, + .nout = 4, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_chakraborty2011_eq2_slots, +}; + +static int calc_ptf_chakraborty2011_eq3_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_clay = (const double *)data[0]; + const double *in_silt = (const double *)data[1]; + const double *in_bulk_density = (const double *)data[2]; + double *out_water_content_33 = (double *)data[3]; + double *out_water_content_100 = (double *)data[4]; + double *out_water_content_500 = (double *)data[5]; + double *out_water_content_1500 = (double *)data[6]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = in_clay[index]; + const double silt = in_silt[index]; + const double bulk_density = in_bulk_density[index]; + const chakraborty2011_ptf_result ptfkit_result = + calc_ptf_chakraborty2011_eq3(clay, silt, bulk_density); + out_water_content_33[index] = ptfkit_result.water_content_33; + out_water_content_100[index] = ptfkit_result.water_content_100; + out_water_content_500[index] = ptfkit_result.water_content_500; + out_water_content_1500[index] = ptfkit_result.water_content_1500; + } + return 0; } -static PyUFuncGenericFunction calc_ptf_chakraborty2011_eq1_functions[] = { - calc_ptf_chakraborty2011_eq1_loop}; -static char calc_ptf_chakraborty2011_eq1_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; -static void calc_ptf_chakraborty2011_eq2_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double bulk_density = *(const double *)args[1]; - const double water_content_33 = (-0.377 * sand - 0.215 * bulk_density + 41.114) / 100.0; - const double water_content_100 = (-0.330 * sand + 2.611 * bulk_density + 30.160) / 100.0; - const double water_content_500 = (-0.244 * sand - 0.795 * bulk_density + 27.495) / 100.0; - const double water_content_1500 = (-0.187 * sand + 1.241 * bulk_density + 19.320) / 100.0; - *(double *)args[2] = water_content_33; - *(double *)args[3] = water_content_100; - *(double *)args[4] = water_content_500; - *(double *)args[5] = water_content_1500; - for (int arg = 0; arg < 6; arg++) - args[arg] += steps[arg]; +static int calc_ptf_chakraborty2011_eq3_strided_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = *(const double *)(data[0] + index * strides[0]); + const double silt = *(const double *)(data[1] + index * strides[1]); + const double bulk_density = *(const double *)(data[2] + index * strides[2]); + const chakraborty2011_ptf_result ptfkit_result = + calc_ptf_chakraborty2011_eq3(clay, silt, bulk_density); + *(double *)(data[3] + index * strides[3]) = ptfkit_result.water_content_33; + *(double *)(data[4] + index * strides[4]) = ptfkit_result.water_content_100; + *(double *)(data[5] + index * strides[5]) = ptfkit_result.water_content_500; + *(double *)(data[6] + index * strides[6]) = ptfkit_result.water_content_1500; } + return 0; } -static PyUFuncGenericFunction calc_ptf_chakraborty2011_eq2_functions[] = { - calc_ptf_chakraborty2011_eq2_loop}; -static char calc_ptf_chakraborty2011_eq2_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; +static PyType_Slot calc_ptf_chakraborty2011_eq3_slots[] = { + {NPY_METH_strided_loop, calc_ptf_chakraborty2011_eq3_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_chakraborty2011_eq3_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_chakraborty2011_eq3_spec = { + .name = "calc_ptf_chakraborty2011_eq3", + .nin = 3, + .nout = 4, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_chakraborty2011_eq3_slots, +}; -static void calc_ptf_chakraborty2011_eq3_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double clay = *(const double *)args[0]; - const double silt = *(const double *)args[1]; - const double bulk_density = *(const double *)args[2]; - const double water_content_33 = - (0.280 * clay + 0.481 * silt - 7.566 * bulk_density + 17.095) / 100.0; - const double water_content_100 = - (0.262 * clay + 0.380 * silt - 3.167 * bulk_density + 8.219) / 100.0; - const double water_content_500 = - (0.244 * clay + 0.187 * silt - 3.079 * bulk_density + 8.046) / 100.0; - const double water_content_1500 = - (0.183 * clay + 0.144 * silt - 0.689 * bulk_density + 4.840) / 100.0; - *(double *)args[3] = water_content_33; - *(double *)args[4] = water_content_100; - *(double *)args[5] = water_content_500; - *(double *)args[6] = water_content_1500; - for (int arg = 0; arg < 7; arg++) - args[arg] += steps[arg]; +static int calc_ptf_chakraborty2011_eq4_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_clay = (const double *)data[0]; + const double *in_silt = (const double *)data[1]; + const double *in_sand = (const double *)data[2]; + double *out_water_content_33 = (double *)data[3]; + double *out_water_content_100 = (double *)data[4]; + double *out_water_content_500 = (double *)data[5]; + double *out_water_content_1500 = (double *)data[6]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = in_clay[index]; + const double silt = in_silt[index]; + const double sand = in_sand[index]; + const chakraborty2011_ptf_result ptfkit_result = + calc_ptf_chakraborty2011_eq4(clay, silt, sand); + out_water_content_33[index] = ptfkit_result.water_content_33; + out_water_content_100[index] = ptfkit_result.water_content_100; + out_water_content_500[index] = ptfkit_result.water_content_500; + out_water_content_1500[index] = ptfkit_result.water_content_1500; } + return 0; } -static PyUFuncGenericFunction calc_ptf_chakraborty2011_eq3_functions[] = { - calc_ptf_chakraborty2011_eq3_loop}; -static char calc_ptf_chakraborty2011_eq3_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; -static void calc_ptf_chakraborty2011_eq4_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double clay = *(const double *)args[0]; - const double silt = *(const double *)args[1]; - const double sand = *(const double *)args[2]; - const double water_content_33 = - (0.078 * clay + 0.248 * silt - 0.241 * sand + 27.447) / 100.0; - const double water_content_100 = - (0.049 * clay + 0.147 * silt - 0.242 * sand + 25.945) / 100.0; - const double water_content_500 = - (0.067 * clay - 0.008 * silt - 0.204 * sand + 22.216) / 100.0; - const double water_content_1500 = - (0.021 * clay - 0.028 * silt - 0.179 * sand + 20.695) / 100.0; - *(double *)args[3] = water_content_33; - *(double *)args[4] = water_content_100; - *(double *)args[5] = water_content_500; - *(double *)args[6] = water_content_1500; - for (int arg = 0; arg < 7; arg++) - args[arg] += steps[arg]; +static int calc_ptf_chakraborty2011_eq4_strided_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = *(const double *)(data[0] + index * strides[0]); + const double silt = *(const double *)(data[1] + index * strides[1]); + const double sand = *(const double *)(data[2] + index * strides[2]); + const chakraborty2011_ptf_result ptfkit_result = + calc_ptf_chakraborty2011_eq4(clay, silt, sand); + *(double *)(data[3] + index * strides[3]) = ptfkit_result.water_content_33; + *(double *)(data[4] + index * strides[4]) = ptfkit_result.water_content_100; + *(double *)(data[5] + index * strides[5]) = ptfkit_result.water_content_500; + *(double *)(data[6] + index * strides[6]) = ptfkit_result.water_content_1500; } + return 0; } -static PyUFuncGenericFunction calc_ptf_chakraborty2011_eq4_functions[] = { - calc_ptf_chakraborty2011_eq4_loop}; -static char calc_ptf_chakraborty2011_eq4_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; +static PyType_Slot calc_ptf_chakraborty2011_eq4_slots[] = { + {NPY_METH_strided_loop, calc_ptf_chakraborty2011_eq4_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_chakraborty2011_eq4_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_chakraborty2011_eq4_spec = { + .name = "calc_ptf_chakraborty2011_eq4", + .nin = 3, + .nout = 4, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_chakraborty2011_eq4_slots, +}; -static void calc_ptf_chakraborty2011_eq5_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double clay = *(const double *)args[0]; - const double silt = *(const double *)args[1]; - const double sand = *(const double *)args[2]; - const double bulk_density = *(const double *)args[3]; - const double water_content_33 = - (0.093 * clay + 0.276 * silt - 0.213 * sand - 4.481 * bulk_density + 32.210) / 100.0; - const double water_content_100 = - (0.048 * clay + 0.145 * silt - 0.245 * sand + 0.370 * bulk_density + 25.551) / 100.0; - const double water_content_500 = - (0.067 * clay - 0.008 * silt - 0.203 * sand - 0.135 * bulk_density + 22.359) / 100.0; - const double water_content_1500 = - (0.014 * clay - 0.041 * silt - 0.192 * sand + 2.093 * bulk_density + 18.470) / 100.0; - *(double *)args[4] = water_content_33; - *(double *)args[5] = water_content_100; - *(double *)args[6] = water_content_500; - *(double *)args[7] = water_content_1500; - for (int arg = 0; arg < 8; arg++) - args[arg] += steps[arg]; +static int calc_ptf_chakraborty2011_eq5_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_clay = (const double *)data[0]; + const double *in_silt = (const double *)data[1]; + const double *in_sand = (const double *)data[2]; + const double *in_bulk_density = (const double *)data[3]; + double *out_water_content_33 = (double *)data[4]; + double *out_water_content_100 = (double *)data[5]; + double *out_water_content_500 = (double *)data[6]; + double *out_water_content_1500 = (double *)data[7]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = in_clay[index]; + const double silt = in_silt[index]; + const double sand = in_sand[index]; + const double bulk_density = in_bulk_density[index]; + const chakraborty2011_ptf_result ptfkit_result = + calc_ptf_chakraborty2011_eq5(clay, silt, sand, bulk_density); + out_water_content_33[index] = ptfkit_result.water_content_33; + out_water_content_100[index] = ptfkit_result.water_content_100; + out_water_content_500[index] = ptfkit_result.water_content_500; + out_water_content_1500[index] = ptfkit_result.water_content_1500; } + return 0; } -static PyUFuncGenericFunction calc_ptf_chakraborty2011_eq5_functions[] = { - calc_ptf_chakraborty2011_eq5_loop}; -static char calc_ptf_chakraborty2011_eq5_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; -static void calc_ptf_chakraborty2011_eq6_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double clay = *(const double *)args[0]; - const double silt = *(const double *)args[1]; - const double sand = *(const double *)args[2]; - const double organic_carbon = *(const double *)args[3]; - const double bulk_density = *(const double *)args[4]; - const double water_content_33 = (0.095 * clay + 0.268 * silt - 0.206 * sand + - 2.420 * organic_carbon - 4.402 * bulk_density + 30.960) / - 100.0; - const double water_content_100 = (0.053 * clay + 0.113 * silt - 0.230 * sand + - 6.434 * organic_carbon + 1.528 * bulk_density + 21.236) / - 100.0; - const double water_content_500 = (0.069 * clay - 0.017 * silt - 0.195 * sand + - 2.461 * organic_carbon + 0.079 * bulk_density + 20.895) / - 100.0; - const double water_content_1500 = (0.017 * clay - 0.053 * silt - 0.184 * sand + - 2.950 * organic_carbon + 2.327 * bulk_density + 16.802) / - 100.0; - *(double *)args[5] = water_content_33; - *(double *)args[6] = water_content_100; - *(double *)args[7] = water_content_500; - *(double *)args[8] = water_content_1500; - for (int arg = 0; arg < 9; arg++) - args[arg] += steps[arg]; +static int calc_ptf_chakraborty2011_eq5_strided_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = *(const double *)(data[0] + index * strides[0]); + const double silt = *(const double *)(data[1] + index * strides[1]); + const double sand = *(const double *)(data[2] + index * strides[2]); + const double bulk_density = *(const double *)(data[3] + index * strides[3]); + const chakraborty2011_ptf_result ptfkit_result = + calc_ptf_chakraborty2011_eq5(clay, silt, sand, bulk_density); + *(double *)(data[4] + index * strides[4]) = ptfkit_result.water_content_33; + *(double *)(data[5] + index * strides[5]) = ptfkit_result.water_content_100; + *(double *)(data[6] + index * strides[6]) = ptfkit_result.water_content_500; + *(double *)(data[7] + index * strides[7]) = ptfkit_result.water_content_1500; } + return 0; +} +static PyType_Slot calc_ptf_chakraborty2011_eq5_slots[] = { + {NPY_METH_strided_loop, calc_ptf_chakraborty2011_eq5_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_chakraborty2011_eq5_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_chakraborty2011_eq5_spec = { + .name = "calc_ptf_chakraborty2011_eq5", + .nin = 4, + .nout = 4, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_chakraborty2011_eq5_slots, +}; + +static int calc_ptf_chakraborty2011_eq6_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_clay = (const double *)data[0]; + const double *in_silt = (const double *)data[1]; + const double *in_sand = (const double *)data[2]; + const double *in_organic_carbon = (const double *)data[3]; + const double *in_bulk_density = (const double *)data[4]; + double *out_water_content_33 = (double *)data[5]; + double *out_water_content_100 = (double *)data[6]; + double *out_water_content_500 = (double *)data[7]; + double *out_water_content_1500 = (double *)data[8]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = in_clay[index]; + const double silt = in_silt[index]; + const double sand = in_sand[index]; + const double organic_carbon = in_organic_carbon[index]; + const double bulk_density = in_bulk_density[index]; + const chakraborty2011_ptf_result ptfkit_result = + calc_ptf_chakraborty2011_eq6(clay, silt, sand, organic_carbon, bulk_density); + out_water_content_33[index] = ptfkit_result.water_content_33; + out_water_content_100[index] = ptfkit_result.water_content_100; + out_water_content_500[index] = ptfkit_result.water_content_500; + out_water_content_1500[index] = ptfkit_result.water_content_1500; + } + return 0; +} + +static int calc_ptf_chakraborty2011_eq6_strided_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = *(const double *)(data[0] + index * strides[0]); + const double silt = *(const double *)(data[1] + index * strides[1]); + const double sand = *(const double *)(data[2] + index * strides[2]); + const double organic_carbon = *(const double *)(data[3] + index * strides[3]); + const double bulk_density = *(const double *)(data[4] + index * strides[4]); + const chakraborty2011_ptf_result ptfkit_result = + calc_ptf_chakraborty2011_eq6(clay, silt, sand, organic_carbon, bulk_density); + *(double *)(data[5] + index * strides[5]) = ptfkit_result.water_content_33; + *(double *)(data[6] + index * strides[6]) = ptfkit_result.water_content_100; + *(double *)(data[7] + index * strides[7]) = ptfkit_result.water_content_500; + *(double *)(data[8] + index * strides[8]) = ptfkit_result.water_content_1500; + } + return 0; } -static PyUFuncGenericFunction calc_ptf_chakraborty2011_eq6_functions[] = { - calc_ptf_chakraborty2011_eq6_loop}; -static char calc_ptf_chakraborty2011_eq6_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; +static PyType_Slot calc_ptf_chakraborty2011_eq6_slots[] = { + {NPY_METH_strided_loop, calc_ptf_chakraborty2011_eq6_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_chakraborty2011_eq6_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_chakraborty2011_eq6_spec = { + .name = "calc_ptf_chakraborty2011_eq6", + .nin = 5, + .nout = 4, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_chakraborty2011_eq6_slots, +}; int ptfkit_register_chakraborty2011(PyObject *module) { - if (ptfkit_add_ufunc(module, "calc_ptf_chakraborty2011_eq1", - calc_ptf_chakraborty2011_eq1_functions, calc_ptf_chakraborty2011_eq1_types, - 2, 4) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_chakraborty2011_eq1", 2, 4, + &calc_ptf_chakraborty2011_eq1_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_chakraborty2011_eq2", - calc_ptf_chakraborty2011_eq2_functions, calc_ptf_chakraborty2011_eq2_types, - 2, 4) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_chakraborty2011_eq2", 2, 4, + &calc_ptf_chakraborty2011_eq2_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_chakraborty2011_eq3", - calc_ptf_chakraborty2011_eq3_functions, calc_ptf_chakraborty2011_eq3_types, - 3, 4) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_chakraborty2011_eq3", 3, 4, + &calc_ptf_chakraborty2011_eq3_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_chakraborty2011_eq4", - calc_ptf_chakraborty2011_eq4_functions, calc_ptf_chakraborty2011_eq4_types, - 3, 4) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_chakraborty2011_eq4", 3, 4, + &calc_ptf_chakraborty2011_eq4_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_chakraborty2011_eq5", - calc_ptf_chakraborty2011_eq5_functions, calc_ptf_chakraborty2011_eq5_types, - 4, 4) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_chakraborty2011_eq5", 4, 4, + &calc_ptf_chakraborty2011_eq5_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_chakraborty2011_eq6", - calc_ptf_chakraborty2011_eq6_functions, calc_ptf_chakraborty2011_eq6_types, - 5, 4) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_chakraborty2011_eq6", 5, 4, + &calc_ptf_chakraborty2011_eq6_spec) < 0) return -1; return 0; } diff --git a/targets/ptfkit-py/src/ptfkit/chakraborty2011.py b/targets/ptfkit-py/src/ptfkit/chakraborty2011.py index 2ec320e..0ab0c9b 100644 --- a/targets/ptfkit-py/src/ptfkit/chakraborty2011.py +++ b/targets/ptfkit-py/src/ptfkit/chakraborty2011.py @@ -25,6 +25,7 @@ from typing import TYPE_CHECKING, Generic, NamedTuple, TypeVar, overload +from ptfkit._dispatch import call as _call from ptfkit._ptfkit import ( calc_ptf_chakraborty2011_eq1 as _calc_ptf_chakraborty2011_eq1, calc_ptf_chakraborty2011_eq2 as _calc_ptf_chakraborty2011_eq2, @@ -115,10 +116,12 @@ def calc_ptf_chakraborty2011_eq1( Use outside the source Indian-soil dataset requires independent validation. """ - if out is None: - values = _calc_ptf_chakraborty2011_eq1(clay, silt) - else: - values = _calc_ptf_chakraborty2011_eq1(clay, silt, out=tuple(out)) + values = _call( + _calc_ptf_chakraborty2011_eq1, + clay, + silt, + out=out, + ) return Chakraborty2011PTFResult(*values) @@ -168,10 +171,12 @@ def calc_ptf_chakraborty2011_eq2( Use outside the source Indian-soil dataset requires independent validation. """ - if out is None: - values = _calc_ptf_chakraborty2011_eq2(sand, bulk_density) - else: - values = _calc_ptf_chakraborty2011_eq2(sand, bulk_density, out=tuple(out)) + values = _call( + _calc_ptf_chakraborty2011_eq2, + sand, + bulk_density, + out=out, + ) return Chakraborty2011PTFResult(*values) @@ -224,10 +229,13 @@ def calc_ptf_chakraborty2011_eq3( Use outside the source Indian-soil dataset requires independent validation. """ - if out is None: - values = _calc_ptf_chakraborty2011_eq3(clay, silt, bulk_density) - else: - values = _calc_ptf_chakraborty2011_eq3(clay, silt, bulk_density, out=tuple(out)) + values = _call( + _calc_ptf_chakraborty2011_eq3, + clay, + silt, + bulk_density, + out=out, + ) return Chakraborty2011PTFResult(*values) @@ -280,10 +288,13 @@ def calc_ptf_chakraborty2011_eq4( Use outside the source Indian-soil dataset requires independent validation. """ - if out is None: - values = _calc_ptf_chakraborty2011_eq4(clay, silt, sand) - else: - values = _calc_ptf_chakraborty2011_eq4(clay, silt, sand, out=tuple(out)) + values = _call( + _calc_ptf_chakraborty2011_eq4, + clay, + silt, + sand, + out=out, + ) return Chakraborty2011PTFResult(*values) @@ -339,10 +350,14 @@ def calc_ptf_chakraborty2011_eq5( Use outside the source Indian-soil dataset requires independent validation. """ - if out is None: - values = _calc_ptf_chakraborty2011_eq5(clay, silt, sand, bulk_density) - else: - values = _calc_ptf_chakraborty2011_eq5(clay, silt, sand, bulk_density, out=tuple(out)) + values = _call( + _calc_ptf_chakraborty2011_eq5, + clay, + silt, + sand, + bulk_density, + out=out, + ) return Chakraborty2011PTFResult(*values) @@ -401,11 +416,14 @@ def calc_ptf_chakraborty2011_eq6( Use outside the source Indian-soil dataset requires independent validation. """ - if out is None: - values = _calc_ptf_chakraborty2011_eq6(clay, silt, sand, organic_carbon, bulk_density) - else: - values = _calc_ptf_chakraborty2011_eq6( - clay, silt, sand, organic_carbon, bulk_density, out=tuple(out) - ) + values = _call( + _calc_ptf_chakraborty2011_eq6, + clay, + silt, + sand, + organic_carbon, + bulk_density, + out=out, + ) return Chakraborty2011PTFResult(*values) diff --git a/targets/ptfkit-py/src/ptfkit/cosby1984.c b/targets/ptfkit-py/src/ptfkit/cosby1984.c index 420cc18..82c2df3 100644 --- a/targets/ptfkit-py/src/ptfkit/cosby1984.c +++ b/targets/ptfkit-py/src/ptfkit/cosby1984.c @@ -1,41 +1,80 @@ /* @generated by ptfkit-codegen; DO NOT EDIT. */ +#include #include "ufunc.h" -static void calc_ptf_cosby1984_univariate_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double silt = *(const double *)args[1]; - const double clay = *(const double *)args[2]; - const double mean_b = 2.91 + 0.159 * clay; - const double mean_log_psi_s = 1.88 - 0.0131 * sand; - const double mean_log_k_sat = -0.884 + 0.0153 * sand; - const double mean_theta_s = 48.9 - 0.126 * sand; - const double sd_b = 1.34 + 0.0500 * clay; - const double sd_log_k_sat = 0.459 + 0.00321 * silt; - const double sd_theta_s = 7.73 - 0.0730 * clay; - *(double *)args[3] = mean_b; - *(double *)args[4] = mean_log_psi_s; - *(double *)args[5] = mean_log_k_sat; - *(double *)args[6] = mean_theta_s; - *(double *)args[7] = sd_b; - *(double *)args[8] = sd_log_k_sat; - *(double *)args[9] = sd_theta_s; - for (int arg = 0; arg < 10; arg++) - args[arg] += steps[arg]; +static int calc_ptf_cosby1984_univariate_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_silt = (const double *)data[1]; + const double *in_clay = (const double *)data[2]; + double *out_mean_b = (double *)data[3]; + double *out_mean_log_psi_s = (double *)data[4]; + double *out_mean_log_k_sat = (double *)data[5]; + double *out_mean_theta_s = (double *)data[6]; + double *out_sd_b = (double *)data[7]; + double *out_sd_log_k_sat = (double *)data[8]; + double *out_sd_theta_s = (double *)data[9]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double silt = in_silt[index]; + const double clay = in_clay[index]; + const cosby1984_univariate_ptf_result ptfkit_result = + calc_ptf_cosby1984_univariate(sand, silt, clay); + out_mean_b[index] = ptfkit_result.mean_b; + out_mean_log_psi_s[index] = ptfkit_result.mean_log_psi_s; + out_mean_log_k_sat[index] = ptfkit_result.mean_log_k_sat; + out_mean_theta_s[index] = ptfkit_result.mean_theta_s; + out_sd_b[index] = ptfkit_result.sd_b; + out_sd_log_k_sat[index] = ptfkit_result.sd_log_k_sat; + out_sd_theta_s[index] = ptfkit_result.sd_theta_s; } + return 0; +} + +static int calc_ptf_cosby1984_univariate_strided_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double silt = *(const double *)(data[1] + index * strides[1]); + const double clay = *(const double *)(data[2] + index * strides[2]); + const cosby1984_univariate_ptf_result ptfkit_result = + calc_ptf_cosby1984_univariate(sand, silt, clay); + *(double *)(data[3] + index * strides[3]) = ptfkit_result.mean_b; + *(double *)(data[4] + index * strides[4]) = ptfkit_result.mean_log_psi_s; + *(double *)(data[5] + index * strides[5]) = ptfkit_result.mean_log_k_sat; + *(double *)(data[6] + index * strides[6]) = ptfkit_result.mean_theta_s; + *(double *)(data[7] + index * strides[7]) = ptfkit_result.sd_b; + *(double *)(data[8] + index * strides[8]) = ptfkit_result.sd_log_k_sat; + *(double *)(data[9] + index * strides[9]) = ptfkit_result.sd_theta_s; + } + return 0; } -static PyUFuncGenericFunction calc_ptf_cosby1984_univariate_functions[] = { - calc_ptf_cosby1984_univariate_loop}; -static char calc_ptf_cosby1984_univariate_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE, NPY_DOUBLE}; +static PyType_Slot calc_ptf_cosby1984_univariate_slots[] = { + {NPY_METH_strided_loop, calc_ptf_cosby1984_univariate_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_cosby1984_univariate_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_cosby1984_univariate_spec = { + .name = "calc_ptf_cosby1984_univariate", + .nin = 3, + .nout = 7, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_cosby1984_univariate_slots, +}; int ptfkit_register_cosby1984(PyObject *module) { - if (ptfkit_add_ufunc(module, "calc_ptf_cosby1984_univariate", - calc_ptf_cosby1984_univariate_functions, - calc_ptf_cosby1984_univariate_types, 3, 7) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_cosby1984_univariate", 3, 7, + &calc_ptf_cosby1984_univariate_spec) < 0) return -1; return 0; } diff --git a/targets/ptfkit-py/src/ptfkit/cosby1984.py b/targets/ptfkit-py/src/ptfkit/cosby1984.py index d9ce429..cc768d5 100644 --- a/targets/ptfkit-py/src/ptfkit/cosby1984.py +++ b/targets/ptfkit-py/src/ptfkit/cosby1984.py @@ -21,6 +21,7 @@ from typing import TYPE_CHECKING, Generic, NamedTuple, TypeVar, overload +from ptfkit._dispatch import call as _call from ptfkit._ptfkit import ( calc_ptf_cosby1984_univariate as _calc_ptf_cosby1984_univariate, ) @@ -110,9 +111,12 @@ def calc_ptf_cosby1984_univariate( Log-transformed output units use the pilot contract `reported log value`. """ - if out is None: - values = _calc_ptf_cosby1984_univariate(sand, silt, clay) - else: - values = _calc_ptf_cosby1984_univariate(sand, silt, clay, out=tuple(out)) + values = _call( + _calc_ptf_cosby1984_univariate, + sand, + silt, + clay, + out=out, + ) return Cosby1984UnivariatePTFResult(*values) diff --git a/targets/ptfkit-py/src/ptfkit/dharumarajan2019.c b/targets/ptfkit-py/src/ptfkit/dharumarajan2019.c index 41e76d4..852e214 100644 --- a/targets/ptfkit-py/src/ptfkit/dharumarajan2019.c +++ b/targets/ptfkit-py/src/ptfkit/dharumarajan2019.c @@ -1,122 +1,283 @@ /* @generated by ptfkit-codegen; DO NOT EDIT. */ +#include #include "ufunc.h" -static void calc_ptf_dharumarajan2019_nkp_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double clay = *(const double *)args[0]; - const double sand = *(const double *)args[1]; - const double cation_exchange_capacity = *(const double *)args[2]; - const double field_capacity = - 13.82 + 0.205 * clay - 0.088 * sand + 0.316 * cation_exchange_capacity; - const double permanent_wilting_point = - -5.776 + 0.315 * clay + 0.050 * sand + 0.271 * cation_exchange_capacity; - *(double *)args[3] = field_capacity; - *(double *)args[4] = permanent_wilting_point; - for (int arg = 0; arg < 5; arg++) - args[arg] += steps[arg]; +static int calc_ptf_dharumarajan2019_nkp_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_clay = (const double *)data[0]; + const double *in_sand = (const double *)data[1]; + const double *in_cation_exchange_capacity = (const double *)data[2]; + double *out_field_capacity = (double *)data[3]; + double *out_permanent_wilting_point = (double *)data[4]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = in_clay[index]; + const double sand = in_sand[index]; + const double cation_exchange_capacity = in_cation_exchange_capacity[index]; + const dharumarajan2019_water_retention_result ptfkit_result = + calc_ptf_dharumarajan2019_nkp(clay, sand, cation_exchange_capacity); + out_field_capacity[index] = ptfkit_result.field_capacity; + out_permanent_wilting_point[index] = ptfkit_result.permanent_wilting_point; } + return 0; } -static PyUFuncGenericFunction calc_ptf_dharumarajan2019_nkp_functions[] = { - calc_ptf_dharumarajan2019_nkp_loop}; -static char calc_ptf_dharumarajan2019_nkp_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE}; -static void calc_ptf_dharumarajan2019_nkp_clay_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double clay = *(const double *)args[0]; - const double field_capacity = 4.968 + 0.586 * clay; - const double permanent_wilting_point = -2.443 + 0.500 * clay; - *(double *)args[1] = field_capacity; - *(double *)args[2] = permanent_wilting_point; - for (int arg = 0; arg < 3; arg++) - args[arg] += steps[arg]; +static int calc_ptf_dharumarajan2019_nkp_strided_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = *(const double *)(data[0] + index * strides[0]); + const double sand = *(const double *)(data[1] + index * strides[1]); + const double cation_exchange_capacity = *(const double *)(data[2] + index * strides[2]); + const dharumarajan2019_water_retention_result ptfkit_result = + calc_ptf_dharumarajan2019_nkp(clay, sand, cation_exchange_capacity); + *(double *)(data[3] + index * strides[3]) = ptfkit_result.field_capacity; + *(double *)(data[4] + index * strides[4]) = ptfkit_result.permanent_wilting_point; } + return 0; } -static PyUFuncGenericFunction calc_ptf_dharumarajan2019_nkp_clay_functions[] = { - calc_ptf_dharumarajan2019_nkp_clay_loop}; -static char calc_ptf_dharumarajan2019_nkp_clay_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; +static PyType_Slot calc_ptf_dharumarajan2019_nkp_slots[] = { + {NPY_METH_strided_loop, calc_ptf_dharumarajan2019_nkp_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_dharumarajan2019_nkp_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_dharumarajan2019_nkp_spec = { + .name = "calc_ptf_dharumarajan2019_nkp", + .nin = 3, + .nout = 2, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_dharumarajan2019_nkp_slots, +}; -static void calc_ptf_dharumarajan2019_skp_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double clay = *(const double *)args[0]; - const double sand = *(const double *)args[1]; - const double cation_exchange_capacity = *(const double *)args[2]; - const double field_capacity = - 39.179 - 0.041 * clay - 0.371 * sand + 0.257 * cation_exchange_capacity; - const double permanent_wilting_point = - 8.227 + 0.168 * clay - 0.101 * sand + 0.217 * cation_exchange_capacity; - *(double *)args[3] = field_capacity; - *(double *)args[4] = permanent_wilting_point; - for (int arg = 0; arg < 5; arg++) - args[arg] += steps[arg]; +static int calc_ptf_dharumarajan2019_nkp_clay_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_clay = (const double *)data[0]; + double *out_field_capacity = (double *)data[1]; + double *out_permanent_wilting_point = (double *)data[2]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = in_clay[index]; + const dharumarajan2019_water_retention_result ptfkit_result = + calc_ptf_dharumarajan2019_nkp_clay(clay); + out_field_capacity[index] = ptfkit_result.field_capacity; + out_permanent_wilting_point[index] = ptfkit_result.permanent_wilting_point; } + return 0; } -static PyUFuncGenericFunction calc_ptf_dharumarajan2019_skp_functions[] = { - calc_ptf_dharumarajan2019_skp_loop}; -static char calc_ptf_dharumarajan2019_skp_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE}; -static void calc_ptf_dharumarajan2019_skp_clay_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double clay = *(const double *)args[0]; - const double field_capacity = 3.724 + 0.581 * clay; - const double permanent_wilting_point = -1.979 + 0.428 * clay; - *(double *)args[1] = field_capacity; - *(double *)args[2] = permanent_wilting_point; - for (int arg = 0; arg < 3; arg++) - args[arg] += steps[arg]; +static int calc_ptf_dharumarajan2019_nkp_clay_strided_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = *(const double *)(data[0] + index * strides[0]); + const dharumarajan2019_water_retention_result ptfkit_result = + calc_ptf_dharumarajan2019_nkp_clay(clay); + *(double *)(data[1] + index * strides[1]) = ptfkit_result.field_capacity; + *(double *)(data[2] + index * strides[2]) = ptfkit_result.permanent_wilting_point; } + return 0; } -static PyUFuncGenericFunction calc_ptf_dharumarajan2019_skp_clay_functions[] = { - calc_ptf_dharumarajan2019_skp_clay_loop}; -static char calc_ptf_dharumarajan2019_skp_clay_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; +static PyType_Slot calc_ptf_dharumarajan2019_nkp_clay_slots[] = { + {NPY_METH_strided_loop, calc_ptf_dharumarajan2019_nkp_clay_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_dharumarajan2019_nkp_clay_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_dharumarajan2019_nkp_clay_spec = { + .name = "calc_ptf_dharumarajan2019_nkp_clay", + .nin = 1, + .nout = 2, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_dharumarajan2019_nkp_clay_slots, +}; -static void calc_ptf_dharumarajan2019_infiltration_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double silt = *(const double *)args[1]; - const double clay = *(const double *)args[2]; - const double infiltration_rate = 177.55 - 1.47 * sand - 1.80 * clay - 1.58 * silt; - *(double *)args[3] = infiltration_rate; - for (int arg = 0; arg < 4; arg++) - args[arg] += steps[arg]; +static int calc_ptf_dharumarajan2019_skp_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_clay = (const double *)data[0]; + const double *in_sand = (const double *)data[1]; + const double *in_cation_exchange_capacity = (const double *)data[2]; + double *out_field_capacity = (double *)data[3]; + double *out_permanent_wilting_point = (double *)data[4]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = in_clay[index]; + const double sand = in_sand[index]; + const double cation_exchange_capacity = in_cation_exchange_capacity[index]; + const dharumarajan2019_water_retention_result ptfkit_result = + calc_ptf_dharumarajan2019_skp(clay, sand, cation_exchange_capacity); + out_field_capacity[index] = ptfkit_result.field_capacity; + out_permanent_wilting_point[index] = ptfkit_result.permanent_wilting_point; } + return 0; +} + +static int calc_ptf_dharumarajan2019_skp_strided_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = *(const double *)(data[0] + index * strides[0]); + const double sand = *(const double *)(data[1] + index * strides[1]); + const double cation_exchange_capacity = *(const double *)(data[2] + index * strides[2]); + const dharumarajan2019_water_retention_result ptfkit_result = + calc_ptf_dharumarajan2019_skp(clay, sand, cation_exchange_capacity); + *(double *)(data[3] + index * strides[3]) = ptfkit_result.field_capacity; + *(double *)(data[4] + index * strides[4]) = ptfkit_result.permanent_wilting_point; + } + return 0; +} +static PyType_Slot calc_ptf_dharumarajan2019_skp_slots[] = { + {NPY_METH_strided_loop, calc_ptf_dharumarajan2019_skp_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_dharumarajan2019_skp_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_dharumarajan2019_skp_spec = { + .name = "calc_ptf_dharumarajan2019_skp", + .nin = 3, + .nout = 2, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_dharumarajan2019_skp_slots, +}; + +static int calc_ptf_dharumarajan2019_skp_clay_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_clay = (const double *)data[0]; + double *out_field_capacity = (double *)data[1]; + double *out_permanent_wilting_point = (double *)data[2]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = in_clay[index]; + const dharumarajan2019_water_retention_result ptfkit_result = + calc_ptf_dharumarajan2019_skp_clay(clay); + out_field_capacity[index] = ptfkit_result.field_capacity; + out_permanent_wilting_point[index] = ptfkit_result.permanent_wilting_point; + } + return 0; +} + +static int calc_ptf_dharumarajan2019_skp_clay_strided_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = *(const double *)(data[0] + index * strides[0]); + const dharumarajan2019_water_retention_result ptfkit_result = + calc_ptf_dharumarajan2019_skp_clay(clay); + *(double *)(data[1] + index * strides[1]) = ptfkit_result.field_capacity; + *(double *)(data[2] + index * strides[2]) = ptfkit_result.permanent_wilting_point; + } + return 0; +} +static PyType_Slot calc_ptf_dharumarajan2019_skp_clay_slots[] = { + {NPY_METH_strided_loop, calc_ptf_dharumarajan2019_skp_clay_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_dharumarajan2019_skp_clay_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_dharumarajan2019_skp_clay_spec = { + .name = "calc_ptf_dharumarajan2019_skp_clay", + .nin = 1, + .nout = 2, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_dharumarajan2019_skp_clay_slots, +}; + +static int calc_ptf_dharumarajan2019_infiltration_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_silt = (const double *)data[1]; + const double *in_clay = (const double *)data[2]; + double *out_infiltration_rate = (double *)data[3]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double silt = in_silt[index]; + const double clay = in_clay[index]; + const double ptfkit_result = calc_ptf_dharumarajan2019_infiltration(sand, silt, clay); + out_infiltration_rate[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_dharumarajan2019_infiltration_strided_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double silt = *(const double *)(data[1] + index * strides[1]); + const double clay = *(const double *)(data[2] + index * strides[2]); + const double ptfkit_result = calc_ptf_dharumarajan2019_infiltration(sand, silt, clay); + *(double *)(data[3] + index * strides[3]) = ptfkit_result; + } + return 0; } -static PyUFuncGenericFunction calc_ptf_dharumarajan2019_infiltration_functions[] = { - calc_ptf_dharumarajan2019_infiltration_loop}; -static char calc_ptf_dharumarajan2019_infiltration_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE}; +static PyType_Slot calc_ptf_dharumarajan2019_infiltration_slots[] = { + {NPY_METH_strided_loop, calc_ptf_dharumarajan2019_infiltration_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_dharumarajan2019_infiltration_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_dharumarajan2019_infiltration_spec = { + .name = "calc_ptf_dharumarajan2019_infiltration", + .nin = 3, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_dharumarajan2019_infiltration_slots, +}; int ptfkit_register_dharumarajan2019(PyObject *module) { - if (ptfkit_add_ufunc(module, "calc_ptf_dharumarajan2019_nkp", - calc_ptf_dharumarajan2019_nkp_functions, - calc_ptf_dharumarajan2019_nkp_types, 3, 2) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_dharumarajan2019_nkp", 3, 2, + &calc_ptf_dharumarajan2019_nkp_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_dharumarajan2019_nkp_clay", - calc_ptf_dharumarajan2019_nkp_clay_functions, - calc_ptf_dharumarajan2019_nkp_clay_types, 1, 2) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_dharumarajan2019_nkp_clay", 1, 2, + &calc_ptf_dharumarajan2019_nkp_clay_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_dharumarajan2019_skp", - calc_ptf_dharumarajan2019_skp_functions, - calc_ptf_dharumarajan2019_skp_types, 3, 2) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_dharumarajan2019_skp", 3, 2, + &calc_ptf_dharumarajan2019_skp_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_dharumarajan2019_skp_clay", - calc_ptf_dharumarajan2019_skp_clay_functions, - calc_ptf_dharumarajan2019_skp_clay_types, 1, 2) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_dharumarajan2019_skp_clay", 1, 2, + &calc_ptf_dharumarajan2019_skp_clay_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_dharumarajan2019_infiltration", - calc_ptf_dharumarajan2019_infiltration_functions, - calc_ptf_dharumarajan2019_infiltration_types, 3, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_dharumarajan2019_infiltration", 3, 1, + &calc_ptf_dharumarajan2019_infiltration_spec) < 0) return -1; return 0; } diff --git a/targets/ptfkit-py/src/ptfkit/dharumarajan2019.py b/targets/ptfkit-py/src/ptfkit/dharumarajan2019.py index 030a36c..67fc59c 100644 --- a/targets/ptfkit-py/src/ptfkit/dharumarajan2019.py +++ b/targets/ptfkit-py/src/ptfkit/dharumarajan2019.py @@ -26,6 +26,7 @@ from typing import TYPE_CHECKING, Generic, NamedTuple, TypeVar, overload +from ptfkit._dispatch import call as _call from ptfkit._ptfkit import ( calc_ptf_dharumarajan2019_nkp as _calc_ptf_dharumarajan2019_nkp, calc_ptf_dharumarajan2019_nkp_clay as _calc_ptf_dharumarajan2019_nkp_clay, @@ -121,12 +122,13 @@ def calc_ptf_dharumarajan2019_nkp( see the scientific notes. """ - if out is None: - values = _calc_ptf_dharumarajan2019_nkp(clay, sand, cation_exchange_capacity) - else: - values = _calc_ptf_dharumarajan2019_nkp( - clay, sand, cation_exchange_capacity, out=tuple(out) - ) + values = _call( + _calc_ptf_dharumarajan2019_nkp, + clay, + sand, + cation_exchange_capacity, + out=out, + ) return Dharumarajan2019WaterRetentionResult(*values) @@ -181,10 +183,11 @@ def calc_ptf_dharumarajan2019_nkp_clay( see the scientific notes. """ - if out is None: - values = _calc_ptf_dharumarajan2019_nkp_clay(clay) - else: - values = _calc_ptf_dharumarajan2019_nkp_clay(clay, out=tuple(out)) + values = _call( + _calc_ptf_dharumarajan2019_nkp_clay, + clay, + out=out, + ) return Dharumarajan2019WaterRetentionResult(*values) @@ -243,12 +246,13 @@ def calc_ptf_dharumarajan2019_skp( volumetric. """ - if out is None: - values = _calc_ptf_dharumarajan2019_skp(clay, sand, cation_exchange_capacity) - else: - values = _calc_ptf_dharumarajan2019_skp( - clay, sand, cation_exchange_capacity, out=tuple(out) - ) + values = _call( + _calc_ptf_dharumarajan2019_skp, + clay, + sand, + cation_exchange_capacity, + out=out, + ) return Dharumarajan2019WaterRetentionResult(*values) @@ -301,10 +305,11 @@ def calc_ptf_dharumarajan2019_skp_clay( volumetric. """ - if out is None: - values = _calc_ptf_dharumarajan2019_skp_clay(clay) - else: - values = _calc_ptf_dharumarajan2019_skp_clay(clay, out=tuple(out)) + values = _call( + _calc_ptf_dharumarajan2019_skp_clay, + clay, + out=out, + ) return Dharumarajan2019WaterRetentionResult(*values) @@ -358,9 +363,10 @@ def calc_ptf_dharumarajan2019_infiltration( Predictor calibration ranges are not reported for the 100-observation dataset. """ - if out is None: - values = _calc_ptf_dharumarajan2019_infiltration(sand, silt, clay) - else: - values = _calc_ptf_dharumarajan2019_infiltration(sand, silt, clay, out=out) - - return values + return _call( + _calc_ptf_dharumarajan2019_infiltration, + sand, + silt, + clay, + out=out, + ) diff --git a/targets/ptfkit-py/src/ptfkit/ferrerjulia2004.c b/targets/ptfkit-py/src/ptfkit/ferrerjulia2004.c index af32d66..6d8c810 100644 --- a/targets/ptfkit-py/src/ptfkit/ferrerjulia2004.c +++ b/targets/ptfkit-py/src/ptfkit/ferrerjulia2004.c @@ -1,896 +1,2072 @@ /* @generated by ptfkit-codegen; DO NOT EDIT. */ +#include #include "ufunc.h" -static void calc_ptf_ferrerjulia2004_campbell_shiozawa_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double clay = *(const double *)args[1]; - const double k_sat = 54.0 * exp(-0.07 * sand - 0.167 * clay); - *(double *)args[2] = k_sat; - for (int arg = 0; arg < 3; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_ferrerjulia2004_campbell_shiozawa_functions[] = { - calc_ptf_ferrerjulia2004_campbell_shiozawa_loop}; -static char calc_ptf_ferrerjulia2004_campbell_shiozawa_types[] = {NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_saxton_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double clay = *(const double *)args[1]; - const double k_sat = - 10.0 * exp(1.01 - 0.0755 * sand + - (-3.895 + 0.03671 * sand - 0.1103 * clay + 0.00087546 * (clay * clay)) / - (0.33 - 0.000751 * sand + 0.176 * log10(clay))); - *(double *)args[2] = k_sat; - for (int arg = 0; arg < 3; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_ferrerjulia2004_saxton_functions[] = { - calc_ptf_ferrerjulia2004_saxton_loop}; -static char calc_ptf_ferrerjulia2004_saxton_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_dane_puckett_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double clay = *(const double *)args[0]; - const double k_sat = 303.84 * exp(-0.144 * clay); - *(double *)args[1] = k_sat; - for (int arg = 0; arg < 2; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_ferrerjulia2004_dane_puckett_functions[] = { - calc_ptf_ferrerjulia2004_dane_puckett_loop}; -static char calc_ptf_ferrerjulia2004_dane_puckett_types[] = {NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_puckett_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double clay = *(const double *)args[0]; - const double k_sat = 156.96 * exp(-0.1975 * clay); - *(double *)args[1] = k_sat; - for (int arg = 0; arg < 2; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_ferrerjulia2004_puckett_functions[] = { - calc_ptf_ferrerjulia2004_puckett_loop}; -static char calc_ptf_ferrerjulia2004_puckett_types[] = {NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_cosby_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double clay = *(const double *)args[1]; - const double k_sat = 25.4 + pow(10.0, -0.6 + 0.012 * sand - 0.0064 * clay); - *(double *)args[2] = k_sat; - for (int arg = 0; arg < 3; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_ferrerjulia2004_cosby_functions[] = { - calc_ptf_ferrerjulia2004_cosby_loop}; -static char calc_ptf_ferrerjulia2004_cosby_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_humic_acrisol_sand_loop(char **args, - const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double k_sat = 1.5162 * exp(0.0452 * sand); - *(double *)args[1] = k_sat; - for (int arg = 0; arg < 2; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_ferrerjulia2004_humic_acrisol_sand_functions[] = { - calc_ptf_ferrerjulia2004_humic_acrisol_sand_loop}; -static char calc_ptf_ferrerjulia2004_humic_acrisol_sand_types[] = {NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_humic_acrisol_texture_organic_matter_loop( - char **args, const npy_intp *dimensions, const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double clay = *(const double *)args[1]; - const double organic_matter = *(const double *)args[2]; - const double k_sat = 16.019 + 0.345 * sand - 0.548 * clay - 0.00221 * organic_matter; - *(double *)args[3] = k_sat; - for (int arg = 0; arg < 4; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction - calc_ptf_ferrerjulia2004_humic_acrisol_texture_organic_matter_functions[] = { - calc_ptf_ferrerjulia2004_humic_acrisol_texture_organic_matter_loop}; -static char calc_ptf_ferrerjulia2004_humic_acrisol_texture_organic_matter_types[] = { - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_calcic_cambisol_sand_loop(char **args, - const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double k_sat = 1.043 * exp(0.0452 * sand); - *(double *)args[1] = k_sat; - for (int arg = 0; arg < 2; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_ferrerjulia2004_calcic_cambisol_sand_functions[] = { - calc_ptf_ferrerjulia2004_calcic_cambisol_sand_loop}; -static char calc_ptf_ferrerjulia2004_calcic_cambisol_sand_types[] = {NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_calcic_cambisol_texture_organic_matter_loop( - char **args, const npy_intp *dimensions, const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double clay = *(const double *)args[1]; - const double organic_matter = *(const double *)args[2]; - const double k_sat = -7.878 + 0.51 * sand - 0.00183 * clay - 0.424 * organic_matter; - *(double *)args[3] = k_sat; - for (int arg = 0; arg < 4; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction - calc_ptf_ferrerjulia2004_calcic_cambisol_texture_organic_matter_functions[] = { - calc_ptf_ferrerjulia2004_calcic_cambisol_texture_organic_matter_loop}; -static char calc_ptf_ferrerjulia2004_calcic_cambisol_texture_organic_matter_types[] = { - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_dystric_cambisol_sand_loop(char **args, - const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double k_sat = 1.3182 * exp(0.0464 * sand); - *(double *)args[1] = k_sat; - for (int arg = 0; arg < 2; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_ferrerjulia2004_dystric_cambisol_sand_functions[] = { - calc_ptf_ferrerjulia2004_dystric_cambisol_sand_loop}; -static char calc_ptf_ferrerjulia2004_dystric_cambisol_sand_types[] = {NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_dystric_cambisol_texture_organic_matter_loop( - char **args, const npy_intp *dimensions, const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double clay = *(const double *)args[1]; - const double organic_matter = *(const double *)args[2]; - const double k_sat = -5.125 + 0.631 * sand - 0.165 * clay - 0.604 * organic_matter; - *(double *)args[3] = k_sat; - for (int arg = 0; arg < 4; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction - calc_ptf_ferrerjulia2004_dystric_cambisol_texture_organic_matter_functions[] = { - calc_ptf_ferrerjulia2004_dystric_cambisol_texture_organic_matter_loop}; -static char calc_ptf_ferrerjulia2004_dystric_cambisol_texture_organic_matter_types[] = { - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_eutric_cambisol_sand_loop(char **args, - const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double k_sat = 0.9356 * exp(0.0503 * sand); - *(double *)args[1] = k_sat; - for (int arg = 0; arg < 2; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_ferrerjulia2004_eutric_cambisol_sand_functions[] = { - calc_ptf_ferrerjulia2004_eutric_cambisol_sand_loop}; -static char calc_ptf_ferrerjulia2004_eutric_cambisol_sand_types[] = {NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_eutric_cambisol_texture_organic_matter_loop( - char **args, const npy_intp *dimensions, const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double clay = *(const double *)args[1]; - const double organic_matter = *(const double *)args[2]; - const double k_sat = -0.399 + 0.541 * sand - 0.243 * clay - 0.421 * organic_matter; - *(double *)args[3] = k_sat; - for (int arg = 0; arg < 4; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction - calc_ptf_ferrerjulia2004_eutric_cambisol_texture_organic_matter_functions[] = { - calc_ptf_ferrerjulia2004_eutric_cambisol_texture_organic_matter_loop}; -static char calc_ptf_ferrerjulia2004_eutric_cambisol_texture_organic_matter_types[] = { - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_gleyic_cambisol_sand_loop(char **args, - const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double k_sat = 0.2336 * exp(0.0667 * sand); - *(double *)args[1] = k_sat; - for (int arg = 0; arg < 2; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_ferrerjulia2004_gleyic_cambisol_sand_functions[] = { - calc_ptf_ferrerjulia2004_gleyic_cambisol_sand_loop}; -static char calc_ptf_ferrerjulia2004_gleyic_cambisol_sand_types[] = {NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_gleyic_cambisol_texture_organic_matter_loop( - char **args, const npy_intp *dimensions, const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double clay = *(const double *)args[1]; - const double organic_matter = *(const double *)args[2]; - const double k_sat = -12.986 + 0.638 * sand - 0.244 * clay - 0.52 * organic_matter; - *(double *)args[3] = k_sat; - for (int arg = 0; arg < 4; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction - calc_ptf_ferrerjulia2004_gleyic_cambisol_texture_organic_matter_functions[] = { - calc_ptf_ferrerjulia2004_gleyic_cambisol_texture_organic_matter_loop}; -static char calc_ptf_ferrerjulia2004_gleyic_cambisol_texture_organic_matter_types[] = { - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_humic_cambisol_sand_loop(char **args, - const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double k_sat = 2.1622 * exp(0.0371 * sand); - *(double *)args[1] = k_sat; - for (int arg = 0; arg < 2; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_ferrerjulia2004_humic_cambisol_sand_functions[] = { - calc_ptf_ferrerjulia2004_humic_cambisol_sand_loop}; -static char calc_ptf_ferrerjulia2004_humic_cambisol_sand_types[] = {NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_humic_cambisol_texture_organic_matter_loop( - char **args, const npy_intp *dimensions, const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double clay = *(const double *)args[1]; - const double organic_matter = *(const double *)args[2]; - const double k_sat = 6.4429 + 0.475 * sand - 0.331 * clay - 0.406 * organic_matter; - *(double *)args[3] = k_sat; - for (int arg = 0; arg < 4; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction - calc_ptf_ferrerjulia2004_humic_cambisol_texture_organic_matter_functions[] = { - calc_ptf_ferrerjulia2004_humic_cambisol_texture_organic_matter_loop}; -static char calc_ptf_ferrerjulia2004_humic_cambisol_texture_organic_matter_types[] = { - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_calcaric_fluvisol_sand_loop(char **args, +static int calc_ptf_ferrerjulia2004_campbell_shiozawa_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_clay = (const double *)data[1]; + double *out_k_sat = (double *)data[2]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double clay = in_clay[index]; + const double ptfkit_result = calc_ptf_ferrerjulia2004_campbell_shiozawa(sand, clay); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_campbell_shiozawa_strided_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double clay = *(const double *)(data[1] + index * strides[1]); + const double ptfkit_result = calc_ptf_ferrerjulia2004_campbell_shiozawa(sand, clay); + *(double *)(data[2] + index * strides[2]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_campbell_shiozawa_slots[] = { + {NPY_METH_strided_loop, calc_ptf_ferrerjulia2004_campbell_shiozawa_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_ferrerjulia2004_campbell_shiozawa_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_campbell_shiozawa_spec = { + .name = "calc_ptf_ferrerjulia2004_campbell_shiozawa", + .nin = 2, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_campbell_shiozawa_slots, +}; + +static int calc_ptf_ferrerjulia2004_saxton_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_clay = (const double *)data[1]; + double *out_k_sat = (double *)data[2]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double clay = in_clay[index]; + const double ptfkit_result = calc_ptf_ferrerjulia2004_saxton(sand, clay); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_saxton_strided_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double clay = *(const double *)(data[1] + index * strides[1]); + const double ptfkit_result = calc_ptf_ferrerjulia2004_saxton(sand, clay); + *(double *)(data[2] + index * strides[2]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_saxton_slots[] = { + {NPY_METH_strided_loop, calc_ptf_ferrerjulia2004_saxton_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_ferrerjulia2004_saxton_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_saxton_spec = { + .name = "calc_ptf_ferrerjulia2004_saxton", + .nin = 2, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_saxton_slots, +}; + +static int calc_ptf_ferrerjulia2004_dane_puckett_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, - const npy_intp *steps, - void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double k_sat = 0.814 * exp(0.052 * sand); - *(double *)args[1] = k_sat; - for (int arg = 0; arg < 2; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_ferrerjulia2004_calcaric_fluvisol_sand_functions[] = { - calc_ptf_ferrerjulia2004_calcaric_fluvisol_sand_loop}; -static char calc_ptf_ferrerjulia2004_calcaric_fluvisol_sand_types[] = {NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_calcaric_fluvisol_texture_organic_matter_loop( - char **args, const npy_intp *dimensions, const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double clay = *(const double *)args[1]; - const double organic_matter = *(const double *)args[2]; - const double k_sat = -15.779 + 0.657 * sand - 0.134 * clay - 0.248 * organic_matter; - *(double *)args[3] = k_sat; - for (int arg = 0; arg < 4; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction - calc_ptf_ferrerjulia2004_calcaric_fluvisol_texture_organic_matter_functions[] = { - calc_ptf_ferrerjulia2004_calcaric_fluvisol_texture_organic_matter_loop}; -static char calc_ptf_ferrerjulia2004_calcaric_fluvisol_texture_organic_matter_types[] = { - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_calcic_luvisol_sand_loop(char **args, - const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double k_sat = 0.671 * exp(0.0467 * sand); - *(double *)args[1] = k_sat; - for (int arg = 0; arg < 2; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_ferrerjulia2004_calcic_luvisol_sand_functions[] = { - calc_ptf_ferrerjulia2004_calcic_luvisol_sand_loop}; -static char calc_ptf_ferrerjulia2004_calcic_luvisol_sand_types[] = {NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_calcic_luvisol_texture_organic_matter_loop( - char **args, const npy_intp *dimensions, const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double clay = *(const double *)args[1]; - const double organic_matter = *(const double *)args[2]; - const double k_sat = 5.379 + 0.138 * sand - 0.131 * clay - 0.02832 * organic_matter; - *(double *)args[3] = k_sat; - for (int arg = 0; arg < 4; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction - calc_ptf_ferrerjulia2004_calcic_luvisol_texture_organic_matter_functions[] = { - calc_ptf_ferrerjulia2004_calcic_luvisol_texture_organic_matter_loop}; -static char calc_ptf_ferrerjulia2004_calcic_luvisol_texture_organic_matter_types[] = { - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_chromic_luvisol_sand_loop(char **args, - const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double k_sat = 0.898 * exp(0.0494 * sand); - *(double *)args[1] = k_sat; - for (int arg = 0; arg < 2; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_ferrerjulia2004_chromic_luvisol_sand_functions[] = { - calc_ptf_ferrerjulia2004_chromic_luvisol_sand_loop}; -static char calc_ptf_ferrerjulia2004_chromic_luvisol_sand_types[] = {NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_chromic_luvisol_texture_organic_matter_loop( - char **args, const npy_intp *dimensions, const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double clay = *(const double *)args[1]; - const double organic_matter = *(const double *)args[2]; - const double k_sat = -10.171 + 0.576 * sand - 0.0075 * clay - 0.518 * organic_matter; - *(double *)args[3] = k_sat; - for (int arg = 0; arg < 4; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction - calc_ptf_ferrerjulia2004_chromic_luvisol_texture_organic_matter_functions[] = { - calc_ptf_ferrerjulia2004_chromic_luvisol_texture_organic_matter_loop}; -static char calc_ptf_ferrerjulia2004_chromic_luvisol_texture_organic_matter_types[] = { - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_gleyic_luvisol_sand_loop(char **args, - const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double k_sat = 0.5395 * exp(0.0514 * sand); - *(double *)args[1] = k_sat; - for (int arg = 0; arg < 2; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_ferrerjulia2004_gleyic_luvisol_sand_functions[] = { - calc_ptf_ferrerjulia2004_gleyic_luvisol_sand_loop}; -static char calc_ptf_ferrerjulia2004_gleyic_luvisol_sand_types[] = {NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_gleyic_luvisol_texture_organic_matter_loop( - char **args, const npy_intp *dimensions, const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double clay = *(const double *)args[1]; - const double organic_matter = *(const double *)args[2]; - const double k_sat = 10.28 + 0.449 * sand - 0.507 * clay - 0.202 * organic_matter; - *(double *)args[3] = k_sat; - for (int arg = 0; arg < 4; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction - calc_ptf_ferrerjulia2004_gleyic_luvisol_texture_organic_matter_functions[] = { - calc_ptf_ferrerjulia2004_gleyic_luvisol_texture_organic_matter_loop}; -static char calc_ptf_ferrerjulia2004_gleyic_luvisol_texture_organic_matter_types[] = { - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_orthic_luvisol_sand_loop(char **args, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_clay = (const double *)data[0]; + double *out_k_sat = (double *)data[1]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = in_clay[index]; + const double ptfkit_result = calc_ptf_ferrerjulia2004_dane_puckett(clay); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_dane_puckett_strided_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double k_sat = 1.3958 * exp(0.0431 * sand); - *(double *)args[1] = k_sat; - for (int arg = 0; arg < 2; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_ferrerjulia2004_orthic_luvisol_sand_functions[] = { - calc_ptf_ferrerjulia2004_orthic_luvisol_sand_loop}; -static char calc_ptf_ferrerjulia2004_orthic_luvisol_sand_types[] = {NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_orthic_luvisol_texture_organic_matter_loop( - char **args, const npy_intp *dimensions, const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double clay = *(const double *)args[1]; - const double organic_matter = *(const double *)args[2]; - const double k_sat = 4.829 + 0.499 * sand - 0.332 * clay - 0.0299 * organic_matter; - *(double *)args[3] = k_sat; - for (int arg = 0; arg < 4; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction - calc_ptf_ferrerjulia2004_orthic_luvisol_texture_organic_matter_functions[] = { - calc_ptf_ferrerjulia2004_orthic_luvisol_texture_organic_matter_loop}; -static char calc_ptf_ferrerjulia2004_orthic_luvisol_texture_organic_matter_types[] = { - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_ranker_sand_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double k_sat = 0.9847 * exp(0.0507 * sand); - *(double *)args[1] = k_sat; - for (int arg = 0; arg < 2; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_ferrerjulia2004_ranker_sand_functions[] = { - calc_ptf_ferrerjulia2004_ranker_sand_loop}; -static char calc_ptf_ferrerjulia2004_ranker_sand_types[] = {NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_ranker_texture_organic_matter_loop(char **args, - const npy_intp *dimensions, - const npy_intp *steps, - void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double clay = *(const double *)args[1]; - const double organic_matter = *(const double *)args[2]; - const double k_sat = -8.621 + 0.682 * sand - 0.0771 * clay - 0.44 * organic_matter; - *(double *)args[3] = k_sat; - for (int arg = 0; arg < 4; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_ferrerjulia2004_ranker_texture_organic_matter_functions[] = { - calc_ptf_ferrerjulia2004_ranker_texture_organic_matter_loop}; -static char calc_ptf_ferrerjulia2004_ranker_texture_organic_matter_types[] = { - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_calcaric_regosol_sand_loop(char **args, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = *(const double *)(data[0] + index * strides[0]); + const double ptfkit_result = calc_ptf_ferrerjulia2004_dane_puckett(clay); + *(double *)(data[1] + index * strides[1]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_dane_puckett_slots[] = { + {NPY_METH_strided_loop, calc_ptf_ferrerjulia2004_dane_puckett_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_ferrerjulia2004_dane_puckett_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_dane_puckett_spec = { + .name = "calc_ptf_ferrerjulia2004_dane_puckett", + .nin = 1, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_dane_puckett_slots, +}; + +static int calc_ptf_ferrerjulia2004_puckett_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_clay = (const double *)data[0]; + double *out_k_sat = (double *)data[1]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = in_clay[index]; + const double ptfkit_result = calc_ptf_ferrerjulia2004_puckett(clay); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_puckett_strided_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = *(const double *)(data[0] + index * strides[0]); + const double ptfkit_result = calc_ptf_ferrerjulia2004_puckett(clay); + *(double *)(data[1] + index * strides[1]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_puckett_slots[] = { + {NPY_METH_strided_loop, calc_ptf_ferrerjulia2004_puckett_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_ferrerjulia2004_puckett_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_puckett_spec = { + .name = "calc_ptf_ferrerjulia2004_puckett", + .nin = 1, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_puckett_slots, +}; + +static int calc_ptf_ferrerjulia2004_cosby_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_clay = (const double *)data[1]; + double *out_k_sat = (double *)data[2]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double clay = in_clay[index]; + const double ptfkit_result = calc_ptf_ferrerjulia2004_cosby(sand, clay); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_cosby_strided_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double clay = *(const double *)(data[1] + index * strides[1]); + const double ptfkit_result = calc_ptf_ferrerjulia2004_cosby(sand, clay); + *(double *)(data[2] + index * strides[2]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_cosby_slots[] = { + {NPY_METH_strided_loop, calc_ptf_ferrerjulia2004_cosby_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_ferrerjulia2004_cosby_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_cosby_spec = { + .name = "calc_ptf_ferrerjulia2004_cosby", + .nin = 2, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_cosby_slots, +}; + +static int calc_ptf_ferrerjulia2004_humic_acrisol_sand_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + double *out_k_sat = (double *)data[1]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double ptfkit_result = calc_ptf_ferrerjulia2004_humic_acrisol_sand(sand); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_humic_acrisol_sand_strided_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double ptfkit_result = calc_ptf_ferrerjulia2004_humic_acrisol_sand(sand); + *(double *)(data[1] + index * strides[1]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_humic_acrisol_sand_slots[] = { + {NPY_METH_strided_loop, calc_ptf_ferrerjulia2004_humic_acrisol_sand_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_ferrerjulia2004_humic_acrisol_sand_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_humic_acrisol_sand_spec = { + .name = "calc_ptf_ferrerjulia2004_humic_acrisol_sand", + .nin = 1, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_humic_acrisol_sand_slots, +}; + +static int calc_ptf_ferrerjulia2004_humic_acrisol_texture_organic_matter_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_clay = (const double *)data[1]; + const double *in_organic_matter = (const double *)data[2]; + double *out_k_sat = (double *)data[3]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double clay = in_clay[index]; + const double organic_matter = in_organic_matter[index]; + const double ptfkit_result = calc_ptf_ferrerjulia2004_humic_acrisol_texture_organic_matter( + sand, clay, organic_matter); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_humic_acrisol_texture_organic_matter_strided_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double clay = *(const double *)(data[1] + index * strides[1]); + const double organic_matter = *(const double *)(data[2] + index * strides[2]); + const double ptfkit_result = calc_ptf_ferrerjulia2004_humic_acrisol_texture_organic_matter( + sand, clay, organic_matter); + *(double *)(data[3] + index * strides[3]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_humic_acrisol_texture_organic_matter_slots[] = { + {NPY_METH_strided_loop, + calc_ptf_ferrerjulia2004_humic_acrisol_texture_organic_matter_strided_loop}, + {NPY_METH_contiguous_loop, + calc_ptf_ferrerjulia2004_humic_acrisol_texture_organic_matter_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_humic_acrisol_texture_organic_matter_spec = { + .name = "calc_ptf_ferrerjulia2004_humic_acrisol_texture_organic_matter", + .nin = 3, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_humic_acrisol_texture_organic_matter_slots, +}; + +static int calc_ptf_ferrerjulia2004_calcic_cambisol_sand_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + double *out_k_sat = (double *)data[1]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double ptfkit_result = calc_ptf_ferrerjulia2004_calcic_cambisol_sand(sand); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_calcic_cambisol_sand_strided_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double ptfkit_result = calc_ptf_ferrerjulia2004_calcic_cambisol_sand(sand); + *(double *)(data[1] + index * strides[1]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_calcic_cambisol_sand_slots[] = { + {NPY_METH_strided_loop, calc_ptf_ferrerjulia2004_calcic_cambisol_sand_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_ferrerjulia2004_calcic_cambisol_sand_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_calcic_cambisol_sand_spec = { + .name = "calc_ptf_ferrerjulia2004_calcic_cambisol_sand", + .nin = 1, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_calcic_cambisol_sand_slots, +}; + +static int calc_ptf_ferrerjulia2004_calcic_cambisol_texture_organic_matter_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_clay = (const double *)data[1]; + const double *in_organic_matter = (const double *)data[2]; + double *out_k_sat = (double *)data[3]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double clay = in_clay[index]; + const double organic_matter = in_organic_matter[index]; + const double ptfkit_result = + calc_ptf_ferrerjulia2004_calcic_cambisol_texture_organic_matter(sand, clay, + organic_matter); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_calcic_cambisol_texture_organic_matter_strided_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double clay = *(const double *)(data[1] + index * strides[1]); + const double organic_matter = *(const double *)(data[2] + index * strides[2]); + const double ptfkit_result = + calc_ptf_ferrerjulia2004_calcic_cambisol_texture_organic_matter(sand, clay, + organic_matter); + *(double *)(data[3] + index * strides[3]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_calcic_cambisol_texture_organic_matter_slots[] = { + {NPY_METH_strided_loop, + calc_ptf_ferrerjulia2004_calcic_cambisol_texture_organic_matter_strided_loop}, + {NPY_METH_contiguous_loop, + calc_ptf_ferrerjulia2004_calcic_cambisol_texture_organic_matter_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_calcic_cambisol_texture_organic_matter_spec = { + .name = "calc_ptf_ferrerjulia2004_calcic_cambisol_texture_organic_matter", + .nin = 3, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_calcic_cambisol_texture_organic_matter_slots, +}; + +static int calc_ptf_ferrerjulia2004_dystric_cambisol_sand_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + double *out_k_sat = (double *)data[1]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double ptfkit_result = calc_ptf_ferrerjulia2004_dystric_cambisol_sand(sand); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_dystric_cambisol_sand_strided_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double ptfkit_result = calc_ptf_ferrerjulia2004_dystric_cambisol_sand(sand); + *(double *)(data[1] + index * strides[1]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_dystric_cambisol_sand_slots[] = { + {NPY_METH_strided_loop, calc_ptf_ferrerjulia2004_dystric_cambisol_sand_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_ferrerjulia2004_dystric_cambisol_sand_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_dystric_cambisol_sand_spec = { + .name = "calc_ptf_ferrerjulia2004_dystric_cambisol_sand", + .nin = 1, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_dystric_cambisol_sand_slots, +}; + +static int calc_ptf_ferrerjulia2004_dystric_cambisol_texture_organic_matter_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_clay = (const double *)data[1]; + const double *in_organic_matter = (const double *)data[2]; + double *out_k_sat = (double *)data[3]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double clay = in_clay[index]; + const double organic_matter = in_organic_matter[index]; + const double ptfkit_result = + calc_ptf_ferrerjulia2004_dystric_cambisol_texture_organic_matter(sand, clay, + organic_matter); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_dystric_cambisol_texture_organic_matter_strided_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double clay = *(const double *)(data[1] + index * strides[1]); + const double organic_matter = *(const double *)(data[2] + index * strides[2]); + const double ptfkit_result = + calc_ptf_ferrerjulia2004_dystric_cambisol_texture_organic_matter(sand, clay, + organic_matter); + *(double *)(data[3] + index * strides[3]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_dystric_cambisol_texture_organic_matter_slots[] = { + {NPY_METH_strided_loop, + calc_ptf_ferrerjulia2004_dystric_cambisol_texture_organic_matter_strided_loop}, + {NPY_METH_contiguous_loop, + calc_ptf_ferrerjulia2004_dystric_cambisol_texture_organic_matter_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_dystric_cambisol_texture_organic_matter_spec = { + .name = "calc_ptf_ferrerjulia2004_dystric_cambisol_texture_organic_matter", + .nin = 3, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_dystric_cambisol_texture_organic_matter_slots, +}; + +static int calc_ptf_ferrerjulia2004_eutric_cambisol_sand_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + double *out_k_sat = (double *)data[1]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double ptfkit_result = calc_ptf_ferrerjulia2004_eutric_cambisol_sand(sand); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_eutric_cambisol_sand_strided_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double ptfkit_result = calc_ptf_ferrerjulia2004_eutric_cambisol_sand(sand); + *(double *)(data[1] + index * strides[1]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_eutric_cambisol_sand_slots[] = { + {NPY_METH_strided_loop, calc_ptf_ferrerjulia2004_eutric_cambisol_sand_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_ferrerjulia2004_eutric_cambisol_sand_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_eutric_cambisol_sand_spec = { + .name = "calc_ptf_ferrerjulia2004_eutric_cambisol_sand", + .nin = 1, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_eutric_cambisol_sand_slots, +}; + +static int calc_ptf_ferrerjulia2004_eutric_cambisol_texture_organic_matter_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_clay = (const double *)data[1]; + const double *in_organic_matter = (const double *)data[2]; + double *out_k_sat = (double *)data[3]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double clay = in_clay[index]; + const double organic_matter = in_organic_matter[index]; + const double ptfkit_result = + calc_ptf_ferrerjulia2004_eutric_cambisol_texture_organic_matter(sand, clay, + organic_matter); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_eutric_cambisol_texture_organic_matter_strided_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double clay = *(const double *)(data[1] + index * strides[1]); + const double organic_matter = *(const double *)(data[2] + index * strides[2]); + const double ptfkit_result = + calc_ptf_ferrerjulia2004_eutric_cambisol_texture_organic_matter(sand, clay, + organic_matter); + *(double *)(data[3] + index * strides[3]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_eutric_cambisol_texture_organic_matter_slots[] = { + {NPY_METH_strided_loop, + calc_ptf_ferrerjulia2004_eutric_cambisol_texture_organic_matter_strided_loop}, + {NPY_METH_contiguous_loop, + calc_ptf_ferrerjulia2004_eutric_cambisol_texture_organic_matter_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_eutric_cambisol_texture_organic_matter_spec = { + .name = "calc_ptf_ferrerjulia2004_eutric_cambisol_texture_organic_matter", + .nin = 3, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_eutric_cambisol_texture_organic_matter_slots, +}; + +static int calc_ptf_ferrerjulia2004_gleyic_cambisol_sand_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + double *out_k_sat = (double *)data[1]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double ptfkit_result = calc_ptf_ferrerjulia2004_gleyic_cambisol_sand(sand); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_gleyic_cambisol_sand_strided_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double ptfkit_result = calc_ptf_ferrerjulia2004_gleyic_cambisol_sand(sand); + *(double *)(data[1] + index * strides[1]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_gleyic_cambisol_sand_slots[] = { + {NPY_METH_strided_loop, calc_ptf_ferrerjulia2004_gleyic_cambisol_sand_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_ferrerjulia2004_gleyic_cambisol_sand_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_gleyic_cambisol_sand_spec = { + .name = "calc_ptf_ferrerjulia2004_gleyic_cambisol_sand", + .nin = 1, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_gleyic_cambisol_sand_slots, +}; + +static int calc_ptf_ferrerjulia2004_gleyic_cambisol_texture_organic_matter_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_clay = (const double *)data[1]; + const double *in_organic_matter = (const double *)data[2]; + double *out_k_sat = (double *)data[3]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double clay = in_clay[index]; + const double organic_matter = in_organic_matter[index]; + const double ptfkit_result = + calc_ptf_ferrerjulia2004_gleyic_cambisol_texture_organic_matter(sand, clay, + organic_matter); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_gleyic_cambisol_texture_organic_matter_strided_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double clay = *(const double *)(data[1] + index * strides[1]); + const double organic_matter = *(const double *)(data[2] + index * strides[2]); + const double ptfkit_result = + calc_ptf_ferrerjulia2004_gleyic_cambisol_texture_organic_matter(sand, clay, + organic_matter); + *(double *)(data[3] + index * strides[3]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_gleyic_cambisol_texture_organic_matter_slots[] = { + {NPY_METH_strided_loop, + calc_ptf_ferrerjulia2004_gleyic_cambisol_texture_organic_matter_strided_loop}, + {NPY_METH_contiguous_loop, + calc_ptf_ferrerjulia2004_gleyic_cambisol_texture_organic_matter_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_gleyic_cambisol_texture_organic_matter_spec = { + .name = "calc_ptf_ferrerjulia2004_gleyic_cambisol_texture_organic_matter", + .nin = 3, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_gleyic_cambisol_texture_organic_matter_slots, +}; + +static int calc_ptf_ferrerjulia2004_humic_cambisol_sand_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + double *out_k_sat = (double *)data[1]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double ptfkit_result = calc_ptf_ferrerjulia2004_humic_cambisol_sand(sand); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_humic_cambisol_sand_strided_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double ptfkit_result = calc_ptf_ferrerjulia2004_humic_cambisol_sand(sand); + *(double *)(data[1] + index * strides[1]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_humic_cambisol_sand_slots[] = { + {NPY_METH_strided_loop, calc_ptf_ferrerjulia2004_humic_cambisol_sand_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_ferrerjulia2004_humic_cambisol_sand_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_humic_cambisol_sand_spec = { + .name = "calc_ptf_ferrerjulia2004_humic_cambisol_sand", + .nin = 1, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_humic_cambisol_sand_slots, +}; + +static int calc_ptf_ferrerjulia2004_humic_cambisol_texture_organic_matter_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_clay = (const double *)data[1]; + const double *in_organic_matter = (const double *)data[2]; + double *out_k_sat = (double *)data[3]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double clay = in_clay[index]; + const double organic_matter = in_organic_matter[index]; + const double ptfkit_result = calc_ptf_ferrerjulia2004_humic_cambisol_texture_organic_matter( + sand, clay, organic_matter); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_humic_cambisol_texture_organic_matter_strided_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double clay = *(const double *)(data[1] + index * strides[1]); + const double organic_matter = *(const double *)(data[2] + index * strides[2]); + const double ptfkit_result = calc_ptf_ferrerjulia2004_humic_cambisol_texture_organic_matter( + sand, clay, organic_matter); + *(double *)(data[3] + index * strides[3]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_humic_cambisol_texture_organic_matter_slots[] = { + {NPY_METH_strided_loop, + calc_ptf_ferrerjulia2004_humic_cambisol_texture_organic_matter_strided_loop}, + {NPY_METH_contiguous_loop, + calc_ptf_ferrerjulia2004_humic_cambisol_texture_organic_matter_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_humic_cambisol_texture_organic_matter_spec = { + .name = "calc_ptf_ferrerjulia2004_humic_cambisol_texture_organic_matter", + .nin = 3, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_humic_cambisol_texture_organic_matter_slots, +}; + +static int calc_ptf_ferrerjulia2004_calcaric_fluvisol_sand_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + double *out_k_sat = (double *)data[1]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double ptfkit_result = calc_ptf_ferrerjulia2004_calcaric_fluvisol_sand(sand); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_calcaric_fluvisol_sand_strided_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double ptfkit_result = calc_ptf_ferrerjulia2004_calcaric_fluvisol_sand(sand); + *(double *)(data[1] + index * strides[1]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_calcaric_fluvisol_sand_slots[] = { + {NPY_METH_strided_loop, calc_ptf_ferrerjulia2004_calcaric_fluvisol_sand_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_ferrerjulia2004_calcaric_fluvisol_sand_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_calcaric_fluvisol_sand_spec = { + .name = "calc_ptf_ferrerjulia2004_calcaric_fluvisol_sand", + .nin = 1, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_calcaric_fluvisol_sand_slots, +}; + +static int calc_ptf_ferrerjulia2004_calcaric_fluvisol_texture_organic_matter_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_clay = (const double *)data[1]; + const double *in_organic_matter = (const double *)data[2]; + double *out_k_sat = (double *)data[3]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double clay = in_clay[index]; + const double organic_matter = in_organic_matter[index]; + const double ptfkit_result = + calc_ptf_ferrerjulia2004_calcaric_fluvisol_texture_organic_matter(sand, clay, + organic_matter); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_calcaric_fluvisol_texture_organic_matter_strided_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double clay = *(const double *)(data[1] + index * strides[1]); + const double organic_matter = *(const double *)(data[2] + index * strides[2]); + const double ptfkit_result = + calc_ptf_ferrerjulia2004_calcaric_fluvisol_texture_organic_matter(sand, clay, + organic_matter); + *(double *)(data[3] + index * strides[3]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_calcaric_fluvisol_texture_organic_matter_slots[] = { + {NPY_METH_strided_loop, + calc_ptf_ferrerjulia2004_calcaric_fluvisol_texture_organic_matter_strided_loop}, + {NPY_METH_contiguous_loop, + calc_ptf_ferrerjulia2004_calcaric_fluvisol_texture_organic_matter_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_calcaric_fluvisol_texture_organic_matter_spec = { + .name = "calc_ptf_ferrerjulia2004_calcaric_fluvisol_texture_organic_matter", + .nin = 3, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_calcaric_fluvisol_texture_organic_matter_slots, +}; + +static int calc_ptf_ferrerjulia2004_calcic_luvisol_sand_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + double *out_k_sat = (double *)data[1]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double ptfkit_result = calc_ptf_ferrerjulia2004_calcic_luvisol_sand(sand); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_calcic_luvisol_sand_strided_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double ptfkit_result = calc_ptf_ferrerjulia2004_calcic_luvisol_sand(sand); + *(double *)(data[1] + index * strides[1]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_calcic_luvisol_sand_slots[] = { + {NPY_METH_strided_loop, calc_ptf_ferrerjulia2004_calcic_luvisol_sand_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_ferrerjulia2004_calcic_luvisol_sand_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_calcic_luvisol_sand_spec = { + .name = "calc_ptf_ferrerjulia2004_calcic_luvisol_sand", + .nin = 1, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_calcic_luvisol_sand_slots, +}; + +static int calc_ptf_ferrerjulia2004_calcic_luvisol_texture_organic_matter_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_clay = (const double *)data[1]; + const double *in_organic_matter = (const double *)data[2]; + double *out_k_sat = (double *)data[3]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double clay = in_clay[index]; + const double organic_matter = in_organic_matter[index]; + const double ptfkit_result = calc_ptf_ferrerjulia2004_calcic_luvisol_texture_organic_matter( + sand, clay, organic_matter); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_calcic_luvisol_texture_organic_matter_strided_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double clay = *(const double *)(data[1] + index * strides[1]); + const double organic_matter = *(const double *)(data[2] + index * strides[2]); + const double ptfkit_result = calc_ptf_ferrerjulia2004_calcic_luvisol_texture_organic_matter( + sand, clay, organic_matter); + *(double *)(data[3] + index * strides[3]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_calcic_luvisol_texture_organic_matter_slots[] = { + {NPY_METH_strided_loop, + calc_ptf_ferrerjulia2004_calcic_luvisol_texture_organic_matter_strided_loop}, + {NPY_METH_contiguous_loop, + calc_ptf_ferrerjulia2004_calcic_luvisol_texture_organic_matter_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_calcic_luvisol_texture_organic_matter_spec = { + .name = "calc_ptf_ferrerjulia2004_calcic_luvisol_texture_organic_matter", + .nin = 3, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_calcic_luvisol_texture_organic_matter_slots, +}; + +static int calc_ptf_ferrerjulia2004_chromic_luvisol_sand_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + double *out_k_sat = (double *)data[1]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double ptfkit_result = calc_ptf_ferrerjulia2004_chromic_luvisol_sand(sand); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_chromic_luvisol_sand_strided_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double ptfkit_result = calc_ptf_ferrerjulia2004_chromic_luvisol_sand(sand); + *(double *)(data[1] + index * strides[1]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_chromic_luvisol_sand_slots[] = { + {NPY_METH_strided_loop, calc_ptf_ferrerjulia2004_chromic_luvisol_sand_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_ferrerjulia2004_chromic_luvisol_sand_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_chromic_luvisol_sand_spec = { + .name = "calc_ptf_ferrerjulia2004_chromic_luvisol_sand", + .nin = 1, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_chromic_luvisol_sand_slots, +}; + +static int calc_ptf_ferrerjulia2004_chromic_luvisol_texture_organic_matter_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_clay = (const double *)data[1]; + const double *in_organic_matter = (const double *)data[2]; + double *out_k_sat = (double *)data[3]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double clay = in_clay[index]; + const double organic_matter = in_organic_matter[index]; + const double ptfkit_result = + calc_ptf_ferrerjulia2004_chromic_luvisol_texture_organic_matter(sand, clay, + organic_matter); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_chromic_luvisol_texture_organic_matter_strided_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double clay = *(const double *)(data[1] + index * strides[1]); + const double organic_matter = *(const double *)(data[2] + index * strides[2]); + const double ptfkit_result = + calc_ptf_ferrerjulia2004_chromic_luvisol_texture_organic_matter(sand, clay, + organic_matter); + *(double *)(data[3] + index * strides[3]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_chromic_luvisol_texture_organic_matter_slots[] = { + {NPY_METH_strided_loop, + calc_ptf_ferrerjulia2004_chromic_luvisol_texture_organic_matter_strided_loop}, + {NPY_METH_contiguous_loop, + calc_ptf_ferrerjulia2004_chromic_luvisol_texture_organic_matter_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_chromic_luvisol_texture_organic_matter_spec = { + .name = "calc_ptf_ferrerjulia2004_chromic_luvisol_texture_organic_matter", + .nin = 3, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_chromic_luvisol_texture_organic_matter_slots, +}; + +static int calc_ptf_ferrerjulia2004_gleyic_luvisol_sand_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + double *out_k_sat = (double *)data[1]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double ptfkit_result = calc_ptf_ferrerjulia2004_gleyic_luvisol_sand(sand); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_gleyic_luvisol_sand_strided_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double ptfkit_result = calc_ptf_ferrerjulia2004_gleyic_luvisol_sand(sand); + *(double *)(data[1] + index * strides[1]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_gleyic_luvisol_sand_slots[] = { + {NPY_METH_strided_loop, calc_ptf_ferrerjulia2004_gleyic_luvisol_sand_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_ferrerjulia2004_gleyic_luvisol_sand_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_gleyic_luvisol_sand_spec = { + .name = "calc_ptf_ferrerjulia2004_gleyic_luvisol_sand", + .nin = 1, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_gleyic_luvisol_sand_slots, +}; + +static int calc_ptf_ferrerjulia2004_gleyic_luvisol_texture_organic_matter_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_clay = (const double *)data[1]; + const double *in_organic_matter = (const double *)data[2]; + double *out_k_sat = (double *)data[3]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double clay = in_clay[index]; + const double organic_matter = in_organic_matter[index]; + const double ptfkit_result = calc_ptf_ferrerjulia2004_gleyic_luvisol_texture_organic_matter( + sand, clay, organic_matter); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_gleyic_luvisol_texture_organic_matter_strided_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double clay = *(const double *)(data[1] + index * strides[1]); + const double organic_matter = *(const double *)(data[2] + index * strides[2]); + const double ptfkit_result = calc_ptf_ferrerjulia2004_gleyic_luvisol_texture_organic_matter( + sand, clay, organic_matter); + *(double *)(data[3] + index * strides[3]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_gleyic_luvisol_texture_organic_matter_slots[] = { + {NPY_METH_strided_loop, + calc_ptf_ferrerjulia2004_gleyic_luvisol_texture_organic_matter_strided_loop}, + {NPY_METH_contiguous_loop, + calc_ptf_ferrerjulia2004_gleyic_luvisol_texture_organic_matter_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_gleyic_luvisol_texture_organic_matter_spec = { + .name = "calc_ptf_ferrerjulia2004_gleyic_luvisol_texture_organic_matter", + .nin = 3, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_gleyic_luvisol_texture_organic_matter_slots, +}; + +static int calc_ptf_ferrerjulia2004_orthic_luvisol_sand_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + double *out_k_sat = (double *)data[1]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double ptfkit_result = calc_ptf_ferrerjulia2004_orthic_luvisol_sand(sand); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_orthic_luvisol_sand_strided_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double ptfkit_result = calc_ptf_ferrerjulia2004_orthic_luvisol_sand(sand); + *(double *)(data[1] + index * strides[1]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_orthic_luvisol_sand_slots[] = { + {NPY_METH_strided_loop, calc_ptf_ferrerjulia2004_orthic_luvisol_sand_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_ferrerjulia2004_orthic_luvisol_sand_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_orthic_luvisol_sand_spec = { + .name = "calc_ptf_ferrerjulia2004_orthic_luvisol_sand", + .nin = 1, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_orthic_luvisol_sand_slots, +}; + +static int calc_ptf_ferrerjulia2004_orthic_luvisol_texture_organic_matter_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_clay = (const double *)data[1]; + const double *in_organic_matter = (const double *)data[2]; + double *out_k_sat = (double *)data[3]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double clay = in_clay[index]; + const double organic_matter = in_organic_matter[index]; + const double ptfkit_result = calc_ptf_ferrerjulia2004_orthic_luvisol_texture_organic_matter( + sand, clay, organic_matter); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_orthic_luvisol_texture_organic_matter_strided_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double clay = *(const double *)(data[1] + index * strides[1]); + const double organic_matter = *(const double *)(data[2] + index * strides[2]); + const double ptfkit_result = calc_ptf_ferrerjulia2004_orthic_luvisol_texture_organic_matter( + sand, clay, organic_matter); + *(double *)(data[3] + index * strides[3]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_orthic_luvisol_texture_organic_matter_slots[] = { + {NPY_METH_strided_loop, + calc_ptf_ferrerjulia2004_orthic_luvisol_texture_organic_matter_strided_loop}, + {NPY_METH_contiguous_loop, + calc_ptf_ferrerjulia2004_orthic_luvisol_texture_organic_matter_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_orthic_luvisol_texture_organic_matter_spec = { + .name = "calc_ptf_ferrerjulia2004_orthic_luvisol_texture_organic_matter", + .nin = 3, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_orthic_luvisol_texture_organic_matter_slots, +}; + +static int calc_ptf_ferrerjulia2004_ranker_sand_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double k_sat = 0.8931 * exp(0.0524 * sand); - *(double *)args[1] = k_sat; - for (int arg = 0; arg < 2; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_ferrerjulia2004_calcaric_regosol_sand_functions[] = { - calc_ptf_ferrerjulia2004_calcaric_regosol_sand_loop}; -static char calc_ptf_ferrerjulia2004_calcaric_regosol_sand_types[] = {NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_calcaric_regosol_texture_organic_matter_loop( - char **args, const npy_intp *dimensions, const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double clay = *(const double *)args[1]; - const double organic_matter = *(const double *)args[2]; - const double k_sat = 1.522 + 0.537 * sand - 0.284 * clay - 0.296 * organic_matter; - *(double *)args[3] = k_sat; - for (int arg = 0; arg < 4; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction - calc_ptf_ferrerjulia2004_calcaric_regosol_texture_organic_matter_functions[] = { - calc_ptf_ferrerjulia2004_calcaric_regosol_texture_organic_matter_loop}; -static char calc_ptf_ferrerjulia2004_calcaric_regosol_texture_organic_matter_types[] = { - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_dystric_regosol_sand_loop(char **args, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + double *out_k_sat = (double *)data[1]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double ptfkit_result = calc_ptf_ferrerjulia2004_ranker_sand(sand); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_ranker_sand_strided_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double ptfkit_result = calc_ptf_ferrerjulia2004_ranker_sand(sand); + *(double *)(data[1] + index * strides[1]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_ranker_sand_slots[] = { + {NPY_METH_strided_loop, calc_ptf_ferrerjulia2004_ranker_sand_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_ferrerjulia2004_ranker_sand_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_ranker_sand_spec = { + .name = "calc_ptf_ferrerjulia2004_ranker_sand", + .nin = 1, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_ranker_sand_slots, +}; + +static int calc_ptf_ferrerjulia2004_ranker_texture_organic_matter_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_clay = (const double *)data[1]; + const double *in_organic_matter = (const double *)data[2]; + double *out_k_sat = (double *)data[3]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double clay = in_clay[index]; + const double organic_matter = in_organic_matter[index]; + const double ptfkit_result = + calc_ptf_ferrerjulia2004_ranker_texture_organic_matter(sand, clay, organic_matter); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_ranker_texture_organic_matter_strided_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double clay = *(const double *)(data[1] + index * strides[1]); + const double organic_matter = *(const double *)(data[2] + index * strides[2]); + const double ptfkit_result = + calc_ptf_ferrerjulia2004_ranker_texture_organic_matter(sand, clay, organic_matter); + *(double *)(data[3] + index * strides[3]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_ranker_texture_organic_matter_slots[] = { + {NPY_METH_strided_loop, calc_ptf_ferrerjulia2004_ranker_texture_organic_matter_strided_loop}, + {NPY_METH_contiguous_loop, + calc_ptf_ferrerjulia2004_ranker_texture_organic_matter_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_ranker_texture_organic_matter_spec = { + .name = "calc_ptf_ferrerjulia2004_ranker_texture_organic_matter", + .nin = 3, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_ranker_texture_organic_matter_slots, +}; + +static int calc_ptf_ferrerjulia2004_calcaric_regosol_sand_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + double *out_k_sat = (double *)data[1]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double ptfkit_result = calc_ptf_ferrerjulia2004_calcaric_regosol_sand(sand); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_calcaric_regosol_sand_strided_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double ptfkit_result = calc_ptf_ferrerjulia2004_calcaric_regosol_sand(sand); + *(double *)(data[1] + index * strides[1]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_calcaric_regosol_sand_slots[] = { + {NPY_METH_strided_loop, calc_ptf_ferrerjulia2004_calcaric_regosol_sand_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_ferrerjulia2004_calcaric_regosol_sand_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_calcaric_regosol_sand_spec = { + .name = "calc_ptf_ferrerjulia2004_calcaric_regosol_sand", + .nin = 1, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_calcaric_regosol_sand_slots, +}; + +static int calc_ptf_ferrerjulia2004_calcaric_regosol_texture_organic_matter_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_clay = (const double *)data[1]; + const double *in_organic_matter = (const double *)data[2]; + double *out_k_sat = (double *)data[3]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double clay = in_clay[index]; + const double organic_matter = in_organic_matter[index]; + const double ptfkit_result = + calc_ptf_ferrerjulia2004_calcaric_regosol_texture_organic_matter(sand, clay, + organic_matter); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_calcaric_regosol_texture_organic_matter_strided_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double clay = *(const double *)(data[1] + index * strides[1]); + const double organic_matter = *(const double *)(data[2] + index * strides[2]); + const double ptfkit_result = + calc_ptf_ferrerjulia2004_calcaric_regosol_texture_organic_matter(sand, clay, + organic_matter); + *(double *)(data[3] + index * strides[3]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_calcaric_regosol_texture_organic_matter_slots[] = { + {NPY_METH_strided_loop, + calc_ptf_ferrerjulia2004_calcaric_regosol_texture_organic_matter_strided_loop}, + {NPY_METH_contiguous_loop, + calc_ptf_ferrerjulia2004_calcaric_regosol_texture_organic_matter_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_calcaric_regosol_texture_organic_matter_spec = { + .name = "calc_ptf_ferrerjulia2004_calcaric_regosol_texture_organic_matter", + .nin = 3, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_calcaric_regosol_texture_organic_matter_slots, +}; + +static int calc_ptf_ferrerjulia2004_dystric_regosol_sand_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + double *out_k_sat = (double *)data[1]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double ptfkit_result = calc_ptf_ferrerjulia2004_dystric_regosol_sand(sand); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_dystric_regosol_sand_strided_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double ptfkit_result = calc_ptf_ferrerjulia2004_dystric_regosol_sand(sand); + *(double *)(data[1] + index * strides[1]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_dystric_regosol_sand_slots[] = { + {NPY_METH_strided_loop, calc_ptf_ferrerjulia2004_dystric_regosol_sand_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_ferrerjulia2004_dystric_regosol_sand_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_dystric_regosol_sand_spec = { + .name = "calc_ptf_ferrerjulia2004_dystric_regosol_sand", + .nin = 1, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_dystric_regosol_sand_slots, +}; + +static int calc_ptf_ferrerjulia2004_dystric_regosol_texture_organic_matter_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_clay = (const double *)data[1]; + const double *in_organic_matter = (const double *)data[2]; + double *out_k_sat = (double *)data[3]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double clay = in_clay[index]; + const double organic_matter = in_organic_matter[index]; + const double ptfkit_result = + calc_ptf_ferrerjulia2004_dystric_regosol_texture_organic_matter(sand, clay, + organic_matter); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_dystric_regosol_texture_organic_matter_strided_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double clay = *(const double *)(data[1] + index * strides[1]); + const double organic_matter = *(const double *)(data[2] + index * strides[2]); + const double ptfkit_result = + calc_ptf_ferrerjulia2004_dystric_regosol_texture_organic_matter(sand, clay, + organic_matter); + *(double *)(data[3] + index * strides[3]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_dystric_regosol_texture_organic_matter_slots[] = { + {NPY_METH_strided_loop, + calc_ptf_ferrerjulia2004_dystric_regosol_texture_organic_matter_strided_loop}, + {NPY_METH_contiguous_loop, + calc_ptf_ferrerjulia2004_dystric_regosol_texture_organic_matter_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_dystric_regosol_texture_organic_matter_spec = { + .name = "calc_ptf_ferrerjulia2004_dystric_regosol_texture_organic_matter", + .nin = 3, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_dystric_regosol_texture_organic_matter_slots, +}; + +static int calc_ptf_ferrerjulia2004_eutric_regosol_sand_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + double *out_k_sat = (double *)data[1]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double ptfkit_result = calc_ptf_ferrerjulia2004_eutric_regosol_sand(sand); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_eutric_regosol_sand_strided_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double ptfkit_result = calc_ptf_ferrerjulia2004_eutric_regosol_sand(sand); + *(double *)(data[1] + index * strides[1]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_eutric_regosol_sand_slots[] = { + {NPY_METH_strided_loop, calc_ptf_ferrerjulia2004_eutric_regosol_sand_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_ferrerjulia2004_eutric_regosol_sand_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_eutric_regosol_sand_spec = { + .name = "calc_ptf_ferrerjulia2004_eutric_regosol_sand", + .nin = 1, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_eutric_regosol_sand_slots, +}; + +static int calc_ptf_ferrerjulia2004_eutric_regosol_texture_organic_matter_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_clay = (const double *)data[1]; + const double *in_organic_matter = (const double *)data[2]; + double *out_k_sat = (double *)data[3]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double clay = in_clay[index]; + const double organic_matter = in_organic_matter[index]; + const double ptfkit_result = calc_ptf_ferrerjulia2004_eutric_regosol_texture_organic_matter( + sand, clay, organic_matter); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_eutric_regosol_texture_organic_matter_strided_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double clay = *(const double *)(data[1] + index * strides[1]); + const double organic_matter = *(const double *)(data[2] + index * strides[2]); + const double ptfkit_result = calc_ptf_ferrerjulia2004_eutric_regosol_texture_organic_matter( + sand, clay, organic_matter); + *(double *)(data[3] + index * strides[3]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_eutric_regosol_texture_organic_matter_slots[] = { + {NPY_METH_strided_loop, + calc_ptf_ferrerjulia2004_eutric_regosol_texture_organic_matter_strided_loop}, + {NPY_METH_contiguous_loop, + calc_ptf_ferrerjulia2004_eutric_regosol_texture_organic_matter_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_eutric_regosol_texture_organic_matter_spec = { + .name = "calc_ptf_ferrerjulia2004_eutric_regosol_texture_organic_matter", + .nin = 3, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_eutric_regosol_texture_organic_matter_slots, +}; + +static int calc_ptf_ferrerjulia2004_rendzina_sand_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + double *out_k_sat = (double *)data[1]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double ptfkit_result = calc_ptf_ferrerjulia2004_rendzina_sand(sand); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_rendzina_sand_strided_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double k_sat = 1.096 * exp(0.048 * sand); - *(double *)args[1] = k_sat; - for (int arg = 0; arg < 2; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_ferrerjulia2004_dystric_regosol_sand_functions[] = { - calc_ptf_ferrerjulia2004_dystric_regosol_sand_loop}; -static char calc_ptf_ferrerjulia2004_dystric_regosol_sand_types[] = {NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_dystric_regosol_texture_organic_matter_loop( - char **args, const npy_intp *dimensions, const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double clay = *(const double *)args[1]; - const double organic_matter = *(const double *)args[2]; - const double k_sat = -0.784 + 0.596 * sand - 0.431 * clay - 0.443 * organic_matter; - *(double *)args[3] = k_sat; - for (int arg = 0; arg < 4; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction - calc_ptf_ferrerjulia2004_dystric_regosol_texture_organic_matter_functions[] = { - calc_ptf_ferrerjulia2004_dystric_regosol_texture_organic_matter_loop}; -static char calc_ptf_ferrerjulia2004_dystric_regosol_texture_organic_matter_types[] = { - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_eutric_regosol_sand_loop(char **args, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double ptfkit_result = calc_ptf_ferrerjulia2004_rendzina_sand(sand); + *(double *)(data[1] + index * strides[1]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_rendzina_sand_slots[] = { + {NPY_METH_strided_loop, calc_ptf_ferrerjulia2004_rendzina_sand_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_ferrerjulia2004_rendzina_sand_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_rendzina_sand_spec = { + .name = "calc_ptf_ferrerjulia2004_rendzina_sand", + .nin = 1, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_rendzina_sand_slots, +}; + +static int calc_ptf_ferrerjulia2004_rendzina_texture_organic_matter_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_clay = (const double *)data[1]; + const double *in_organic_matter = (const double *)data[2]; + double *out_k_sat = (double *)data[3]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double clay = in_clay[index]; + const double organic_matter = in_organic_matter[index]; + const double ptfkit_result = + calc_ptf_ferrerjulia2004_rendzina_texture_organic_matter(sand, clay, organic_matter); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_rendzina_texture_organic_matter_strided_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double clay = *(const double *)(data[1] + index * strides[1]); + const double organic_matter = *(const double *)(data[2] + index * strides[2]); + const double ptfkit_result = + calc_ptf_ferrerjulia2004_rendzina_texture_organic_matter(sand, clay, organic_matter); + *(double *)(data[3] + index * strides[3]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_rendzina_texture_organic_matter_slots[] = { + {NPY_METH_strided_loop, calc_ptf_ferrerjulia2004_rendzina_texture_organic_matter_strided_loop}, + {NPY_METH_contiguous_loop, + calc_ptf_ferrerjulia2004_rendzina_texture_organic_matter_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_rendzina_texture_organic_matter_spec = { + .name = "calc_ptf_ferrerjulia2004_rendzina_texture_organic_matter", + .nin = 3, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_rendzina_texture_organic_matter_slots, +}; + +static int calc_ptf_ferrerjulia2004_gleyic_solonchak_sand_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + double *out_k_sat = (double *)data[1]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double ptfkit_result = calc_ptf_ferrerjulia2004_gleyic_solonchak_sand(sand); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_gleyic_solonchak_sand_strided_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double ptfkit_result = calc_ptf_ferrerjulia2004_gleyic_solonchak_sand(sand); + *(double *)(data[1] + index * strides[1]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_gleyic_solonchak_sand_slots[] = { + {NPY_METH_strided_loop, calc_ptf_ferrerjulia2004_gleyic_solonchak_sand_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_ferrerjulia2004_gleyic_solonchak_sand_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_gleyic_solonchak_sand_spec = { + .name = "calc_ptf_ferrerjulia2004_gleyic_solonchak_sand", + .nin = 1, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_gleyic_solonchak_sand_slots, +}; + +static int calc_ptf_ferrerjulia2004_gleyic_solonchak_texture_organic_matter_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_clay = (const double *)data[1]; + const double *in_organic_matter = (const double *)data[2]; + double *out_k_sat = (double *)data[3]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double clay = in_clay[index]; + const double organic_matter = in_organic_matter[index]; + const double ptfkit_result = + calc_ptf_ferrerjulia2004_gleyic_solonchak_texture_organic_matter(sand, clay, + organic_matter); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_gleyic_solonchak_texture_organic_matter_strided_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double clay = *(const double *)(data[1] + index * strides[1]); + const double organic_matter = *(const double *)(data[2] + index * strides[2]); + const double ptfkit_result = + calc_ptf_ferrerjulia2004_gleyic_solonchak_texture_organic_matter(sand, clay, + organic_matter); + *(double *)(data[3] + index * strides[3]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_gleyic_solonchak_texture_organic_matter_slots[] = { + {NPY_METH_strided_loop, + calc_ptf_ferrerjulia2004_gleyic_solonchak_texture_organic_matter_strided_loop}, + {NPY_METH_contiguous_loop, + calc_ptf_ferrerjulia2004_gleyic_solonchak_texture_organic_matter_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_gleyic_solonchak_texture_organic_matter_spec = { + .name = "calc_ptf_ferrerjulia2004_gleyic_solonchak_texture_organic_matter", + .nin = 3, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_gleyic_solonchak_texture_organic_matter_slots, +}; + +static int calc_ptf_ferrerjulia2004_general_sand_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + double *out_k_sat = (double *)data[1]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double ptfkit_result = calc_ptf_ferrerjulia2004_general_sand(sand); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_general_sand_strided_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double k_sat = 1.0005 * exp(0.0523 * sand); - *(double *)args[1] = k_sat; - for (int arg = 0; arg < 2; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_ferrerjulia2004_eutric_regosol_sand_functions[] = { - calc_ptf_ferrerjulia2004_eutric_regosol_sand_loop}; -static char calc_ptf_ferrerjulia2004_eutric_regosol_sand_types[] = {NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_eutric_regosol_texture_organic_matter_loop( - char **args, const npy_intp *dimensions, const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double clay = *(const double *)args[1]; - const double organic_matter = *(const double *)args[2]; - const double k_sat = -5.5 + 0.647 * sand - 0.00325 * clay - 1.082 * organic_matter; - *(double *)args[3] = k_sat; - for (int arg = 0; arg < 4; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction - calc_ptf_ferrerjulia2004_eutric_regosol_texture_organic_matter_functions[] = { - calc_ptf_ferrerjulia2004_eutric_regosol_texture_organic_matter_loop}; -static char calc_ptf_ferrerjulia2004_eutric_regosol_texture_organic_matter_types[] = { - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_rendzina_sand_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double k_sat = 2.4645 * exp(0.0325 * sand); - *(double *)args[1] = k_sat; - for (int arg = 0; arg < 2; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_ferrerjulia2004_rendzina_sand_functions[] = { - calc_ptf_ferrerjulia2004_rendzina_sand_loop}; -static char calc_ptf_ferrerjulia2004_rendzina_sand_types[] = {NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_rendzina_texture_organic_matter_loop( - char **args, const npy_intp *dimensions, const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double clay = *(const double *)args[1]; - const double organic_matter = *(const double *)args[2]; - const double k_sat = 23.288 + 0.175 * sand - 0.602 * clay - 0.279 * organic_matter; - *(double *)args[3] = k_sat; - for (int arg = 0; arg < 4; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_ferrerjulia2004_rendzina_texture_organic_matter_functions[] = - {calc_ptf_ferrerjulia2004_rendzina_texture_organic_matter_loop}; -static char calc_ptf_ferrerjulia2004_rendzina_texture_organic_matter_types[] = { - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_gleyic_solonchak_sand_loop(char **args, - const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double k_sat = 0.7602 * exp(0.0372 * sand); - *(double *)args[1] = k_sat; - for (int arg = 0; arg < 2; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_ferrerjulia2004_gleyic_solonchak_sand_functions[] = { - calc_ptf_ferrerjulia2004_gleyic_solonchak_sand_loop}; -static char calc_ptf_ferrerjulia2004_gleyic_solonchak_sand_types[] = {NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_gleyic_solonchak_texture_organic_matter_loop( - char **args, const npy_intp *dimensions, const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double clay = *(const double *)args[1]; - const double organic_matter = *(const double *)args[2]; - const double k_sat = -0.90917 + 0.328 * sand - 0.173 * clay - 0.252 * organic_matter; - *(double *)args[3] = k_sat; - for (int arg = 0; arg < 4; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction - calc_ptf_ferrerjulia2004_gleyic_solonchak_texture_organic_matter_functions[] = { - calc_ptf_ferrerjulia2004_gleyic_solonchak_texture_organic_matter_loop}; -static char calc_ptf_ferrerjulia2004_gleyic_solonchak_texture_organic_matter_types[] = { - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_general_sand_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double k_sat = 0.920 * exp(0.0491 * sand); - *(double *)args[1] = k_sat; - for (int arg = 0; arg < 2; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_ferrerjulia2004_general_sand_functions[] = { - calc_ptf_ferrerjulia2004_general_sand_loop}; -static char calc_ptf_ferrerjulia2004_general_sand_types[] = {NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_ferrerjulia2004_general_texture_organic_matter_loop(char **args, - const npy_intp *dimensions, - const npy_intp *steps, - void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double clay = *(const double *)args[1]; - const double organic_matter = *(const double *)args[2]; - const double k_sat = -4.994 + 0.56728 * sand - 0.131 * clay - 0.0127 * organic_matter; - *(double *)args[3] = k_sat; - for (int arg = 0; arg < 4; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_ferrerjulia2004_general_texture_organic_matter_functions[] = - {calc_ptf_ferrerjulia2004_general_texture_organic_matter_loop}; -static char calc_ptf_ferrerjulia2004_general_texture_organic_matter_types[] = { - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double ptfkit_result = calc_ptf_ferrerjulia2004_general_sand(sand); + *(double *)(data[1] + index * strides[1]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_general_sand_slots[] = { + {NPY_METH_strided_loop, calc_ptf_ferrerjulia2004_general_sand_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_ferrerjulia2004_general_sand_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_general_sand_spec = { + .name = "calc_ptf_ferrerjulia2004_general_sand", + .nin = 1, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_general_sand_slots, +}; + +static int calc_ptf_ferrerjulia2004_general_texture_organic_matter_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_clay = (const double *)data[1]; + const double *in_organic_matter = (const double *)data[2]; + double *out_k_sat = (double *)data[3]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double clay = in_clay[index]; + const double organic_matter = in_organic_matter[index]; + const double ptfkit_result = + calc_ptf_ferrerjulia2004_general_texture_organic_matter(sand, clay, organic_matter); + out_k_sat[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_ferrerjulia2004_general_texture_organic_matter_strided_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double clay = *(const double *)(data[1] + index * strides[1]); + const double organic_matter = *(const double *)(data[2] + index * strides[2]); + const double ptfkit_result = + calc_ptf_ferrerjulia2004_general_texture_organic_matter(sand, clay, organic_matter); + *(double *)(data[3] + index * strides[3]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_ferrerjulia2004_general_texture_organic_matter_slots[] = { + {NPY_METH_strided_loop, calc_ptf_ferrerjulia2004_general_texture_organic_matter_strided_loop}, + {NPY_METH_contiguous_loop, + calc_ptf_ferrerjulia2004_general_texture_organic_matter_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_ferrerjulia2004_general_texture_organic_matter_spec = { + .name = "calc_ptf_ferrerjulia2004_general_texture_organic_matter", + .nin = 3, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_ferrerjulia2004_general_texture_organic_matter_slots, +}; int ptfkit_register_ferrerjulia2004(PyObject *module) { - if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_campbell_shiozawa", - calc_ptf_ferrerjulia2004_campbell_shiozawa_functions, - calc_ptf_ferrerjulia2004_campbell_shiozawa_types, 2, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_campbell_shiozawa", 2, 1, + &calc_ptf_ferrerjulia2004_campbell_shiozawa_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_saxton", - calc_ptf_ferrerjulia2004_saxton_functions, - calc_ptf_ferrerjulia2004_saxton_types, 2, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_saxton", 2, 1, + &calc_ptf_ferrerjulia2004_saxton_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_dane_puckett", - calc_ptf_ferrerjulia2004_dane_puckett_functions, - calc_ptf_ferrerjulia2004_dane_puckett_types, 1, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_dane_puckett", 1, 1, + &calc_ptf_ferrerjulia2004_dane_puckett_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_puckett", - calc_ptf_ferrerjulia2004_puckett_functions, - calc_ptf_ferrerjulia2004_puckett_types, 1, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_puckett", 1, 1, + &calc_ptf_ferrerjulia2004_puckett_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_cosby", - calc_ptf_ferrerjulia2004_cosby_functions, - calc_ptf_ferrerjulia2004_cosby_types, 2, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_cosby", 2, 1, + &calc_ptf_ferrerjulia2004_cosby_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_humic_acrisol_sand", - calc_ptf_ferrerjulia2004_humic_acrisol_sand_functions, - calc_ptf_ferrerjulia2004_humic_acrisol_sand_types, 1, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_humic_acrisol_sand", 1, 1, + &calc_ptf_ferrerjulia2004_humic_acrisol_sand_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_humic_acrisol_texture_organic_matter", - calc_ptf_ferrerjulia2004_humic_acrisol_texture_organic_matter_functions, - calc_ptf_ferrerjulia2004_humic_acrisol_texture_organic_matter_types, 3, - 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_humic_acrisol_texture_organic_matter", 3, + 1, + &calc_ptf_ferrerjulia2004_humic_acrisol_texture_organic_matter_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_calcic_cambisol_sand", - calc_ptf_ferrerjulia2004_calcic_cambisol_sand_functions, - calc_ptf_ferrerjulia2004_calcic_cambisol_sand_types, 1, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_calcic_cambisol_sand", 1, 1, + &calc_ptf_ferrerjulia2004_calcic_cambisol_sand_spec) < 0) return -1; if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_calcic_cambisol_texture_organic_matter", - calc_ptf_ferrerjulia2004_calcic_cambisol_texture_organic_matter_functions, - calc_ptf_ferrerjulia2004_calcic_cambisol_texture_organic_matter_types, 3, - 1) < 0) + 3, 1, + &calc_ptf_ferrerjulia2004_calcic_cambisol_texture_organic_matter_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_dystric_cambisol_sand", - calc_ptf_ferrerjulia2004_dystric_cambisol_sand_functions, - calc_ptf_ferrerjulia2004_dystric_cambisol_sand_types, 1, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_dystric_cambisol_sand", 1, 1, + &calc_ptf_ferrerjulia2004_dystric_cambisol_sand_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_dystric_cambisol_texture_organic_matter", - calc_ptf_ferrerjulia2004_dystric_cambisol_texture_organic_matter_functions, - calc_ptf_ferrerjulia2004_dystric_cambisol_texture_organic_matter_types, 3, - 1) < 0) + if (ptfkit_add_ufunc( + module, "calc_ptf_ferrerjulia2004_dystric_cambisol_texture_organic_matter", 3, 1, + &calc_ptf_ferrerjulia2004_dystric_cambisol_texture_organic_matter_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_eutric_cambisol_sand", - calc_ptf_ferrerjulia2004_eutric_cambisol_sand_functions, - calc_ptf_ferrerjulia2004_eutric_cambisol_sand_types, 1, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_eutric_cambisol_sand", 1, 1, + &calc_ptf_ferrerjulia2004_eutric_cambisol_sand_spec) < 0) return -1; if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_eutric_cambisol_texture_organic_matter", - calc_ptf_ferrerjulia2004_eutric_cambisol_texture_organic_matter_functions, - calc_ptf_ferrerjulia2004_eutric_cambisol_texture_organic_matter_types, 3, - 1) < 0) + 3, 1, + &calc_ptf_ferrerjulia2004_eutric_cambisol_texture_organic_matter_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_gleyic_cambisol_sand", - calc_ptf_ferrerjulia2004_gleyic_cambisol_sand_functions, - calc_ptf_ferrerjulia2004_gleyic_cambisol_sand_types, 1, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_gleyic_cambisol_sand", 1, 1, + &calc_ptf_ferrerjulia2004_gleyic_cambisol_sand_spec) < 0) return -1; if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_gleyic_cambisol_texture_organic_matter", - calc_ptf_ferrerjulia2004_gleyic_cambisol_texture_organic_matter_functions, - calc_ptf_ferrerjulia2004_gleyic_cambisol_texture_organic_matter_types, 3, - 1) < 0) + 3, 1, + &calc_ptf_ferrerjulia2004_gleyic_cambisol_texture_organic_matter_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_humic_cambisol_sand", - calc_ptf_ferrerjulia2004_humic_cambisol_sand_functions, - calc_ptf_ferrerjulia2004_humic_cambisol_sand_types, 1, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_humic_cambisol_sand", 1, 1, + &calc_ptf_ferrerjulia2004_humic_cambisol_sand_spec) < 0) return -1; if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_humic_cambisol_texture_organic_matter", - calc_ptf_ferrerjulia2004_humic_cambisol_texture_organic_matter_functions, - calc_ptf_ferrerjulia2004_humic_cambisol_texture_organic_matter_types, 3, - 1) < 0) + 3, 1, + &calc_ptf_ferrerjulia2004_humic_cambisol_texture_organic_matter_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_calcaric_fluvisol_sand", - calc_ptf_ferrerjulia2004_calcaric_fluvisol_sand_functions, - calc_ptf_ferrerjulia2004_calcaric_fluvisol_sand_types, 1, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_calcaric_fluvisol_sand", 1, 1, + &calc_ptf_ferrerjulia2004_calcaric_fluvisol_sand_spec) < 0) return -1; if (ptfkit_add_ufunc( - module, "calc_ptf_ferrerjulia2004_calcaric_fluvisol_texture_organic_matter", - calc_ptf_ferrerjulia2004_calcaric_fluvisol_texture_organic_matter_functions, - calc_ptf_ferrerjulia2004_calcaric_fluvisol_texture_organic_matter_types, 3, 1) < 0) + module, "calc_ptf_ferrerjulia2004_calcaric_fluvisol_texture_organic_matter", 3, 1, + &calc_ptf_ferrerjulia2004_calcaric_fluvisol_texture_organic_matter_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_calcic_luvisol_sand", - calc_ptf_ferrerjulia2004_calcic_luvisol_sand_functions, - calc_ptf_ferrerjulia2004_calcic_luvisol_sand_types, 1, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_calcic_luvisol_sand", 1, 1, + &calc_ptf_ferrerjulia2004_calcic_luvisol_sand_spec) < 0) return -1; if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_calcic_luvisol_texture_organic_matter", - calc_ptf_ferrerjulia2004_calcic_luvisol_texture_organic_matter_functions, - calc_ptf_ferrerjulia2004_calcic_luvisol_texture_organic_matter_types, 3, - 1) < 0) + 3, 1, + &calc_ptf_ferrerjulia2004_calcic_luvisol_texture_organic_matter_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_chromic_luvisol_sand", - calc_ptf_ferrerjulia2004_chromic_luvisol_sand_functions, - calc_ptf_ferrerjulia2004_chromic_luvisol_sand_types, 1, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_chromic_luvisol_sand", 1, 1, + &calc_ptf_ferrerjulia2004_chromic_luvisol_sand_spec) < 0) return -1; if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_chromic_luvisol_texture_organic_matter", - calc_ptf_ferrerjulia2004_chromic_luvisol_texture_organic_matter_functions, - calc_ptf_ferrerjulia2004_chromic_luvisol_texture_organic_matter_types, 3, - 1) < 0) + 3, 1, + &calc_ptf_ferrerjulia2004_chromic_luvisol_texture_organic_matter_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_gleyic_luvisol_sand", - calc_ptf_ferrerjulia2004_gleyic_luvisol_sand_functions, - calc_ptf_ferrerjulia2004_gleyic_luvisol_sand_types, 1, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_gleyic_luvisol_sand", 1, 1, + &calc_ptf_ferrerjulia2004_gleyic_luvisol_sand_spec) < 0) return -1; if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_gleyic_luvisol_texture_organic_matter", - calc_ptf_ferrerjulia2004_gleyic_luvisol_texture_organic_matter_functions, - calc_ptf_ferrerjulia2004_gleyic_luvisol_texture_organic_matter_types, 3, - 1) < 0) + 3, 1, + &calc_ptf_ferrerjulia2004_gleyic_luvisol_texture_organic_matter_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_orthic_luvisol_sand", - calc_ptf_ferrerjulia2004_orthic_luvisol_sand_functions, - calc_ptf_ferrerjulia2004_orthic_luvisol_sand_types, 1, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_orthic_luvisol_sand", 1, 1, + &calc_ptf_ferrerjulia2004_orthic_luvisol_sand_spec) < 0) return -1; if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_orthic_luvisol_texture_organic_matter", - calc_ptf_ferrerjulia2004_orthic_luvisol_texture_organic_matter_functions, - calc_ptf_ferrerjulia2004_orthic_luvisol_texture_organic_matter_types, 3, - 1) < 0) + 3, 1, + &calc_ptf_ferrerjulia2004_orthic_luvisol_texture_organic_matter_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_ranker_sand", - calc_ptf_ferrerjulia2004_ranker_sand_functions, - calc_ptf_ferrerjulia2004_ranker_sand_types, 1, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_ranker_sand", 1, 1, + &calc_ptf_ferrerjulia2004_ranker_sand_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_ranker_texture_organic_matter", - calc_ptf_ferrerjulia2004_ranker_texture_organic_matter_functions, - calc_ptf_ferrerjulia2004_ranker_texture_organic_matter_types, 3, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_ranker_texture_organic_matter", 3, 1, + &calc_ptf_ferrerjulia2004_ranker_texture_organic_matter_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_calcaric_regosol_sand", - calc_ptf_ferrerjulia2004_calcaric_regosol_sand_functions, - calc_ptf_ferrerjulia2004_calcaric_regosol_sand_types, 1, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_calcaric_regosol_sand", 1, 1, + &calc_ptf_ferrerjulia2004_calcaric_regosol_sand_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_calcaric_regosol_texture_organic_matter", - calc_ptf_ferrerjulia2004_calcaric_regosol_texture_organic_matter_functions, - calc_ptf_ferrerjulia2004_calcaric_regosol_texture_organic_matter_types, 3, - 1) < 0) + if (ptfkit_add_ufunc( + module, "calc_ptf_ferrerjulia2004_calcaric_regosol_texture_organic_matter", 3, 1, + &calc_ptf_ferrerjulia2004_calcaric_regosol_texture_organic_matter_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_dystric_regosol_sand", - calc_ptf_ferrerjulia2004_dystric_regosol_sand_functions, - calc_ptf_ferrerjulia2004_dystric_regosol_sand_types, 1, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_dystric_regosol_sand", 1, 1, + &calc_ptf_ferrerjulia2004_dystric_regosol_sand_spec) < 0) return -1; if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_dystric_regosol_texture_organic_matter", - calc_ptf_ferrerjulia2004_dystric_regosol_texture_organic_matter_functions, - calc_ptf_ferrerjulia2004_dystric_regosol_texture_organic_matter_types, 3, - 1) < 0) + 3, 1, + &calc_ptf_ferrerjulia2004_dystric_regosol_texture_organic_matter_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_eutric_regosol_sand", - calc_ptf_ferrerjulia2004_eutric_regosol_sand_functions, - calc_ptf_ferrerjulia2004_eutric_regosol_sand_types, 1, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_eutric_regosol_sand", 1, 1, + &calc_ptf_ferrerjulia2004_eutric_regosol_sand_spec) < 0) return -1; if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_eutric_regosol_texture_organic_matter", - calc_ptf_ferrerjulia2004_eutric_regosol_texture_organic_matter_functions, - calc_ptf_ferrerjulia2004_eutric_regosol_texture_organic_matter_types, 3, - 1) < 0) - return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_rendzina_sand", - calc_ptf_ferrerjulia2004_rendzina_sand_functions, - calc_ptf_ferrerjulia2004_rendzina_sand_types, 1, 1) < 0) - return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_rendzina_texture_organic_matter", - calc_ptf_ferrerjulia2004_rendzina_texture_organic_matter_functions, - calc_ptf_ferrerjulia2004_rendzina_texture_organic_matter_types, 3, 1) < 0) - return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_gleyic_solonchak_sand", - calc_ptf_ferrerjulia2004_gleyic_solonchak_sand_functions, - calc_ptf_ferrerjulia2004_gleyic_solonchak_sand_types, 1, 1) < 0) - return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_gleyic_solonchak_texture_organic_matter", - calc_ptf_ferrerjulia2004_gleyic_solonchak_texture_organic_matter_functions, - calc_ptf_ferrerjulia2004_gleyic_solonchak_texture_organic_matter_types, 3, - 1) < 0) - return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_general_sand", - calc_ptf_ferrerjulia2004_general_sand_functions, - calc_ptf_ferrerjulia2004_general_sand_types, 1, 1) < 0) - return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_general_texture_organic_matter", - calc_ptf_ferrerjulia2004_general_texture_organic_matter_functions, - calc_ptf_ferrerjulia2004_general_texture_organic_matter_types, 3, 1) < 0) + 3, 1, + &calc_ptf_ferrerjulia2004_eutric_regosol_texture_organic_matter_spec) < 0) + return -1; + if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_rendzina_sand", 1, 1, + &calc_ptf_ferrerjulia2004_rendzina_sand_spec) < 0) + return -1; + if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_rendzina_texture_organic_matter", 3, 1, + &calc_ptf_ferrerjulia2004_rendzina_texture_organic_matter_spec) < 0) + return -1; + if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_gleyic_solonchak_sand", 1, 1, + &calc_ptf_ferrerjulia2004_gleyic_solonchak_sand_spec) < 0) + return -1; + if (ptfkit_add_ufunc( + module, "calc_ptf_ferrerjulia2004_gleyic_solonchak_texture_organic_matter", 3, 1, + &calc_ptf_ferrerjulia2004_gleyic_solonchak_texture_organic_matter_spec) < 0) + return -1; + if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_general_sand", 1, 1, + &calc_ptf_ferrerjulia2004_general_sand_spec) < 0) + return -1; + if (ptfkit_add_ufunc(module, "calc_ptf_ferrerjulia2004_general_texture_organic_matter", 3, 1, + &calc_ptf_ferrerjulia2004_general_texture_organic_matter_spec) < 0) return -1; return 0; } diff --git a/targets/ptfkit-py/src/ptfkit/ferrerjulia2004.py b/targets/ptfkit-py/src/ptfkit/ferrerjulia2004.py index 00f93cf..a5f1fae 100644 --- a/targets/ptfkit-py/src/ptfkit/ferrerjulia2004.py +++ b/targets/ptfkit-py/src/ptfkit/ferrerjulia2004.py @@ -25,6 +25,7 @@ from typing import TYPE_CHECKING, overload +from ptfkit._dispatch import call as _call from ptfkit._ptfkit import ( calc_ptf_ferrerjulia2004_campbell_shiozawa as _calc_ptf_ferrerjulia2004_campbell_shiozawa, calc_ptf_ferrerjulia2004_saxton as _calc_ptf_ferrerjulia2004_saxton, @@ -156,12 +157,12 @@ def calc_ptf_ferrerjulia2004_campbell_shiozawa( Reproduced in Section 4.2 for comparison with the new Spanish-soil PTFs. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_campbell_shiozawa(sand, clay) - else: - values = _calc_ptf_ferrerjulia2004_campbell_shiozawa(sand, clay, out=out) - - return values + return _call( + _calc_ptf_ferrerjulia2004_campbell_shiozawa, + sand, + clay, + out=out, + ) @overload @@ -205,12 +206,12 @@ def calc_ptf_ferrerjulia2004_saxton( singularity policy. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_saxton(sand, clay) - else: - values = _calc_ptf_ferrerjulia2004_saxton(sand, clay, out=out) - - return values + return _call( + _calc_ptf_ferrerjulia2004_saxton, + sand, + clay, + out=out, + ) @overload @@ -247,12 +248,11 @@ def calc_ptf_ferrerjulia2004_dane_puckett( Reproduced in Section 4.2 for comparison with the new Spanish-soil PTFs. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_dane_puckett(clay) - else: - values = _calc_ptf_ferrerjulia2004_dane_puckett(clay, out=out) - - return values + return _call( + _calc_ptf_ferrerjulia2004_dane_puckett, + clay, + out=out, + ) @overload @@ -289,12 +289,11 @@ def calc_ptf_ferrerjulia2004_puckett( Reproduced in Section 4.2 for comparison with the new Spanish-soil PTFs. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_puckett(clay) - else: - values = _calc_ptf_ferrerjulia2004_puckett(clay, out=out) - - return values + return _call( + _calc_ptf_ferrerjulia2004_puckett, + clay, + out=out, + ) @overload @@ -334,12 +333,12 @@ def calc_ptf_ferrerjulia2004_cosby( Reproduced in Section 4.2 for comparison with the new Spanish-soil PTFs. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_cosby(sand, clay) - else: - values = _calc_ptf_ferrerjulia2004_cosby(sand, clay, out=out) - - return values + return _call( + _calc_ptf_ferrerjulia2004_cosby, + sand, + clay, + out=out, + ) @overload @@ -376,12 +375,11 @@ def calc_ptf_ferrerjulia2004_humic_acrisol_sand( Table 3; R^2 = 0.723. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_humic_acrisol_sand(sand) - else: - values = _calc_ptf_ferrerjulia2004_humic_acrisol_sand(sand, out=out) - - return values + return _call( + _calc_ptf_ferrerjulia2004_humic_acrisol_sand, + sand, + out=out, + ) @overload @@ -426,16 +424,13 @@ def calc_ptf_ferrerjulia2004_humic_acrisol_texture_organic_matter( Table 3; R^2 = 0.701. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_humic_acrisol_texture_organic_matter( - sand, clay, organic_matter - ) - else: - values = _calc_ptf_ferrerjulia2004_humic_acrisol_texture_organic_matter( - sand, clay, organic_matter, out=out - ) - - return values + return _call( + _calc_ptf_ferrerjulia2004_humic_acrisol_texture_organic_matter, + sand, + clay, + organic_matter, + out=out, + ) @overload @@ -472,12 +467,11 @@ def calc_ptf_ferrerjulia2004_calcic_cambisol_sand( Table 3; R^2 = 0.521. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_calcic_cambisol_sand(sand) - else: - values = _calc_ptf_ferrerjulia2004_calcic_cambisol_sand(sand, out=out) - - return values + return _call( + _calc_ptf_ferrerjulia2004_calcic_cambisol_sand, + sand, + out=out, + ) @overload @@ -522,16 +516,13 @@ def calc_ptf_ferrerjulia2004_calcic_cambisol_texture_organic_matter( Table 3; R^2 = 0.468. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_calcic_cambisol_texture_organic_matter( - sand, clay, organic_matter - ) - else: - values = _calc_ptf_ferrerjulia2004_calcic_cambisol_texture_organic_matter( - sand, clay, organic_matter, out=out - ) - - return values + return _call( + _calc_ptf_ferrerjulia2004_calcic_cambisol_texture_organic_matter, + sand, + clay, + organic_matter, + out=out, + ) @overload @@ -568,12 +559,11 @@ def calc_ptf_ferrerjulia2004_dystric_cambisol_sand( Table 3; R^2 = 0.750. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_dystric_cambisol_sand(sand) - else: - values = _calc_ptf_ferrerjulia2004_dystric_cambisol_sand(sand, out=out) - - return values + return _call( + _calc_ptf_ferrerjulia2004_dystric_cambisol_sand, + sand, + out=out, + ) @overload @@ -618,16 +608,13 @@ def calc_ptf_ferrerjulia2004_dystric_cambisol_texture_organic_matter( Table 3; R^2 = 0.779. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_dystric_cambisol_texture_organic_matter( - sand, clay, organic_matter - ) - else: - values = _calc_ptf_ferrerjulia2004_dystric_cambisol_texture_organic_matter( - sand, clay, organic_matter, out=out - ) - - return values + return _call( + _calc_ptf_ferrerjulia2004_dystric_cambisol_texture_organic_matter, + sand, + clay, + organic_matter, + out=out, + ) @overload @@ -664,12 +651,11 @@ def calc_ptf_ferrerjulia2004_eutric_cambisol_sand( Table 3; R^2 = 0.734. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_eutric_cambisol_sand(sand) - else: - values = _calc_ptf_ferrerjulia2004_eutric_cambisol_sand(sand, out=out) - - return values + return _call( + _calc_ptf_ferrerjulia2004_eutric_cambisol_sand, + sand, + out=out, + ) @overload @@ -714,16 +700,13 @@ def calc_ptf_ferrerjulia2004_eutric_cambisol_texture_organic_matter( Table 3; R^2 = 0.686. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_eutric_cambisol_texture_organic_matter( - sand, clay, organic_matter - ) - else: - values = _calc_ptf_ferrerjulia2004_eutric_cambisol_texture_organic_matter( - sand, clay, organic_matter, out=out - ) - - return values + return _call( + _calc_ptf_ferrerjulia2004_eutric_cambisol_texture_organic_matter, + sand, + clay, + organic_matter, + out=out, + ) @overload @@ -760,12 +743,11 @@ def calc_ptf_ferrerjulia2004_gleyic_cambisol_sand( Table 3; R^2 = 0.807. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_gleyic_cambisol_sand(sand) - else: - values = _calc_ptf_ferrerjulia2004_gleyic_cambisol_sand(sand, out=out) - - return values + return _call( + _calc_ptf_ferrerjulia2004_gleyic_cambisol_sand, + sand, + out=out, + ) @overload @@ -810,16 +792,13 @@ def calc_ptf_ferrerjulia2004_gleyic_cambisol_texture_organic_matter( Table 3; R^2 = 0.824. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_gleyic_cambisol_texture_organic_matter( - sand, clay, organic_matter - ) - else: - values = _calc_ptf_ferrerjulia2004_gleyic_cambisol_texture_organic_matter( - sand, clay, organic_matter, out=out - ) - - return values + return _call( + _calc_ptf_ferrerjulia2004_gleyic_cambisol_texture_organic_matter, + sand, + clay, + organic_matter, + out=out, + ) @overload @@ -856,12 +835,11 @@ def calc_ptf_ferrerjulia2004_humic_cambisol_sand( Table 3; R^2 = 0.592. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_humic_cambisol_sand(sand) - else: - values = _calc_ptf_ferrerjulia2004_humic_cambisol_sand(sand, out=out) - - return values + return _call( + _calc_ptf_ferrerjulia2004_humic_cambisol_sand, + sand, + out=out, + ) @overload @@ -906,16 +884,13 @@ def calc_ptf_ferrerjulia2004_humic_cambisol_texture_organic_matter( Table 3; R^2 = 0.632. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_humic_cambisol_texture_organic_matter( - sand, clay, organic_matter - ) - else: - values = _calc_ptf_ferrerjulia2004_humic_cambisol_texture_organic_matter( - sand, clay, organic_matter, out=out - ) - - return values + return _call( + _calc_ptf_ferrerjulia2004_humic_cambisol_texture_organic_matter, + sand, + clay, + organic_matter, + out=out, + ) @overload @@ -952,12 +927,11 @@ def calc_ptf_ferrerjulia2004_calcaric_fluvisol_sand( Table 3; R^2 = 0.772. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_calcaric_fluvisol_sand(sand) - else: - values = _calc_ptf_ferrerjulia2004_calcaric_fluvisol_sand(sand, out=out) - - return values + return _call( + _calc_ptf_ferrerjulia2004_calcaric_fluvisol_sand, + sand, + out=out, + ) @overload @@ -1002,16 +976,13 @@ def calc_ptf_ferrerjulia2004_calcaric_fluvisol_texture_organic_matter( Table 3; R^2 = 0.792. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_calcaric_fluvisol_texture_organic_matter( - sand, clay, organic_matter - ) - else: - values = _calc_ptf_ferrerjulia2004_calcaric_fluvisol_texture_organic_matter( - sand, clay, organic_matter, out=out - ) - - return values + return _call( + _calc_ptf_ferrerjulia2004_calcaric_fluvisol_texture_organic_matter, + sand, + clay, + organic_matter, + out=out, + ) @overload @@ -1051,12 +1022,11 @@ def calc_ptf_ferrerjulia2004_calcic_luvisol_sand( The paper reports weak fit and suggests missing clay-mineralogy information. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_calcic_luvisol_sand(sand) - else: - values = _calc_ptf_ferrerjulia2004_calcic_luvisol_sand(sand, out=out) - - return values + return _call( + _calc_ptf_ferrerjulia2004_calcic_luvisol_sand, + sand, + out=out, + ) @overload @@ -1104,16 +1074,13 @@ def calc_ptf_ferrerjulia2004_calcic_luvisol_texture_organic_matter( The paper reports weak fit and suggests missing clay-mineralogy information. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_calcic_luvisol_texture_organic_matter( - sand, clay, organic_matter - ) - else: - values = _calc_ptf_ferrerjulia2004_calcic_luvisol_texture_organic_matter( - sand, clay, organic_matter, out=out - ) - - return values + return _call( + _calc_ptf_ferrerjulia2004_calcic_luvisol_texture_organic_matter, + sand, + clay, + organic_matter, + out=out, + ) @overload @@ -1150,12 +1117,11 @@ def calc_ptf_ferrerjulia2004_chromic_luvisol_sand( Table 3; R^2 = 0.534. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_chromic_luvisol_sand(sand) - else: - values = _calc_ptf_ferrerjulia2004_chromic_luvisol_sand(sand, out=out) - - return values + return _call( + _calc_ptf_ferrerjulia2004_chromic_luvisol_sand, + sand, + out=out, + ) @overload @@ -1200,16 +1166,13 @@ def calc_ptf_ferrerjulia2004_chromic_luvisol_texture_organic_matter( Table 3; R^2 = 0.557. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_chromic_luvisol_texture_organic_matter( - sand, clay, organic_matter - ) - else: - values = _calc_ptf_ferrerjulia2004_chromic_luvisol_texture_organic_matter( - sand, clay, organic_matter, out=out - ) - - return values + return _call( + _calc_ptf_ferrerjulia2004_chromic_luvisol_texture_organic_matter, + sand, + clay, + organic_matter, + out=out, + ) @overload @@ -1246,12 +1209,11 @@ def calc_ptf_ferrerjulia2004_gleyic_luvisol_sand( Table 3; R^2 = 0.876. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_gleyic_luvisol_sand(sand) - else: - values = _calc_ptf_ferrerjulia2004_gleyic_luvisol_sand(sand, out=out) - - return values + return _call( + _calc_ptf_ferrerjulia2004_gleyic_luvisol_sand, + sand, + out=out, + ) @overload @@ -1296,16 +1258,13 @@ def calc_ptf_ferrerjulia2004_gleyic_luvisol_texture_organic_matter( Table 3; R^2 = 0.917. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_gleyic_luvisol_texture_organic_matter( - sand, clay, organic_matter - ) - else: - values = _calc_ptf_ferrerjulia2004_gleyic_luvisol_texture_organic_matter( - sand, clay, organic_matter, out=out - ) - - return values + return _call( + _calc_ptf_ferrerjulia2004_gleyic_luvisol_texture_organic_matter, + sand, + clay, + organic_matter, + out=out, + ) @overload @@ -1342,12 +1301,11 @@ def calc_ptf_ferrerjulia2004_orthic_luvisol_sand( Table 3; R^2 = 0.676. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_orthic_luvisol_sand(sand) - else: - values = _calc_ptf_ferrerjulia2004_orthic_luvisol_sand(sand, out=out) - - return values + return _call( + _calc_ptf_ferrerjulia2004_orthic_luvisol_sand, + sand, + out=out, + ) @overload @@ -1392,16 +1350,13 @@ def calc_ptf_ferrerjulia2004_orthic_luvisol_texture_organic_matter( Table 3; R^2 = 0.729. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_orthic_luvisol_texture_organic_matter( - sand, clay, organic_matter - ) - else: - values = _calc_ptf_ferrerjulia2004_orthic_luvisol_texture_organic_matter( - sand, clay, organic_matter, out=out - ) - - return values + return _call( + _calc_ptf_ferrerjulia2004_orthic_luvisol_texture_organic_matter, + sand, + clay, + organic_matter, + out=out, + ) @overload @@ -1438,12 +1393,11 @@ def calc_ptf_ferrerjulia2004_ranker_sand( Table 3; R^2 = 0.726. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_ranker_sand(sand) - else: - values = _calc_ptf_ferrerjulia2004_ranker_sand(sand, out=out) - - return values + return _call( + _calc_ptf_ferrerjulia2004_ranker_sand, + sand, + out=out, + ) @overload @@ -1488,14 +1442,13 @@ def calc_ptf_ferrerjulia2004_ranker_texture_organic_matter( Table 3; R^2 = 0.717. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_ranker_texture_organic_matter(sand, clay, organic_matter) - else: - values = _calc_ptf_ferrerjulia2004_ranker_texture_organic_matter( - sand, clay, organic_matter, out=out - ) - - return values + return _call( + _calc_ptf_ferrerjulia2004_ranker_texture_organic_matter, + sand, + clay, + organic_matter, + out=out, + ) @overload @@ -1532,12 +1485,11 @@ def calc_ptf_ferrerjulia2004_calcaric_regosol_sand( Table 3; R^2 = 0.655. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_calcaric_regosol_sand(sand) - else: - values = _calc_ptf_ferrerjulia2004_calcaric_regosol_sand(sand, out=out) - - return values + return _call( + _calc_ptf_ferrerjulia2004_calcaric_regosol_sand, + sand, + out=out, + ) @overload @@ -1582,16 +1534,13 @@ def calc_ptf_ferrerjulia2004_calcaric_regosol_texture_organic_matter( Table 3; R^2 = 0.705. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_calcaric_regosol_texture_organic_matter( - sand, clay, organic_matter - ) - else: - values = _calc_ptf_ferrerjulia2004_calcaric_regosol_texture_organic_matter( - sand, clay, organic_matter, out=out - ) - - return values + return _call( + _calc_ptf_ferrerjulia2004_calcaric_regosol_texture_organic_matter, + sand, + clay, + organic_matter, + out=out, + ) @overload @@ -1628,12 +1577,11 @@ def calc_ptf_ferrerjulia2004_dystric_regosol_sand( Table 3; R^2 = 0.834. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_dystric_regosol_sand(sand) - else: - values = _calc_ptf_ferrerjulia2004_dystric_regosol_sand(sand, out=out) - - return values + return _call( + _calc_ptf_ferrerjulia2004_dystric_regosol_sand, + sand, + out=out, + ) @overload @@ -1678,16 +1626,13 @@ def calc_ptf_ferrerjulia2004_dystric_regosol_texture_organic_matter( Table 3; R^2 = 0.862. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_dystric_regosol_texture_organic_matter( - sand, clay, organic_matter - ) - else: - values = _calc_ptf_ferrerjulia2004_dystric_regosol_texture_organic_matter( - sand, clay, organic_matter, out=out - ) - - return values + return _call( + _calc_ptf_ferrerjulia2004_dystric_regosol_texture_organic_matter, + sand, + clay, + organic_matter, + out=out, + ) @overload @@ -1724,12 +1669,11 @@ def calc_ptf_ferrerjulia2004_eutric_regosol_sand( Table 3; R^2 = 0.824. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_eutric_regosol_sand(sand) - else: - values = _calc_ptf_ferrerjulia2004_eutric_regosol_sand(sand, out=out) - - return values + return _call( + _calc_ptf_ferrerjulia2004_eutric_regosol_sand, + sand, + out=out, + ) @overload @@ -1774,16 +1718,13 @@ def calc_ptf_ferrerjulia2004_eutric_regosol_texture_organic_matter( Table 3; R^2 = 0.702. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_eutric_regosol_texture_organic_matter( - sand, clay, organic_matter - ) - else: - values = _calc_ptf_ferrerjulia2004_eutric_regosol_texture_organic_matter( - sand, clay, organic_matter, out=out - ) - - return values + return _call( + _calc_ptf_ferrerjulia2004_eutric_regosol_texture_organic_matter, + sand, + clay, + organic_matter, + out=out, + ) @overload @@ -1825,12 +1766,11 @@ def calc_ptf_ferrerjulia2004_rendzina_sand( conductivity values. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_rendzina_sand(sand) - else: - values = _calc_ptf_ferrerjulia2004_rendzina_sand(sand, out=out) - - return values + return _call( + _calc_ptf_ferrerjulia2004_rendzina_sand, + sand, + out=out, + ) @overload @@ -1878,16 +1818,13 @@ def calc_ptf_ferrerjulia2004_rendzina_texture_organic_matter( The regression has weak fit and is affected by converted qualitative conductivity values. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_rendzina_texture_organic_matter( - sand, clay, organic_matter - ) - else: - values = _calc_ptf_ferrerjulia2004_rendzina_texture_organic_matter( - sand, clay, organic_matter, out=out - ) - - return values + return _call( + _calc_ptf_ferrerjulia2004_rendzina_texture_organic_matter, + sand, + clay, + organic_matter, + out=out, + ) @overload @@ -1927,12 +1864,11 @@ def calc_ptf_ferrerjulia2004_gleyic_solonchak_sand( The source gives inconsistent R^2 values for this regression. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_gleyic_solonchak_sand(sand) - else: - values = _calc_ptf_ferrerjulia2004_gleyic_solonchak_sand(sand, out=out) - - return values + return _call( + _calc_ptf_ferrerjulia2004_gleyic_solonchak_sand, + sand, + out=out, + ) @overload @@ -1982,16 +1918,13 @@ def calc_ptf_ferrerjulia2004_gleyic_solonchak_texture_organic_matter( which prints the intercept as -90917. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_gleyic_solonchak_texture_organic_matter( - sand, clay, organic_matter - ) - else: - values = _calc_ptf_ferrerjulia2004_gleyic_solonchak_texture_organic_matter( - sand, clay, organic_matter, out=out - ) - - return values + return _call( + _calc_ptf_ferrerjulia2004_gleyic_solonchak_texture_organic_matter, + sand, + clay, + organic_matter, + out=out, + ) @overload @@ -2032,12 +1965,11 @@ def calc_ptf_ferrerjulia2004_general_sand( data. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_general_sand(sand) - else: - values = _calc_ptf_ferrerjulia2004_general_sand(sand, out=out) - - return values + return _call( + _calc_ptf_ferrerjulia2004_general_sand, + sand, + out=out, + ) @overload @@ -2086,13 +2018,10 @@ def calc_ptf_ferrerjulia2004_general_texture_organic_matter( data. """ - if out is None: - values = _calc_ptf_ferrerjulia2004_general_texture_organic_matter( - sand, clay, organic_matter - ) - else: - values = _calc_ptf_ferrerjulia2004_general_texture_organic_matter( - sand, clay, organic_matter, out=out - ) - - return values + return _call( + _calc_ptf_ferrerjulia2004_general_texture_organic_matter, + sand, + clay, + organic_matter, + out=out, + ) diff --git a/targets/ptfkit-py/src/ptfkit/hodnett2002.c b/targets/ptfkit-py/src/ptfkit/hodnett2002.c index 4ad1c9e..08134f0 100644 --- a/targets/ptfkit-py/src/ptfkit/hodnett2002.c +++ b/targets/ptfkit-py/src/ptfkit/hodnett2002.c @@ -1,50 +1,79 @@ /* @generated by ptfkit-codegen; DO NOT EDIT. */ +#include #include "ufunc.h" -static void calc_ptf_hodnett2002_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double silt = *(const double *)args[1]; - const double clay = *(const double *)args[2]; - const double organic_carbon = *(const double *)args[3]; - const double bulk_density = *(const double *)args[4]; - const double cation_exchange_capacity = *(const double *)args[5]; - const double ph = *(const double *)args[6]; - const double clay_squared = clay * clay; - const double ln_alpha = - (-2.294 - 3.526 * silt + 2.440 * organic_carbon - 0.076 * cation_exchange_capacity - - 11.331 * ph + 0.019 * (silt * silt)) / - 100.0; - const double alpha = exp(ln_alpha); - const double ln_n = (62.986 - 0.833 * clay - 0.529 * organic_carbon + 0.593 * ph + - 0.0070 * clay_squared - 0.014 * sand * silt) / - 100.0; - const double n = exp(ln_n); - const double theta_s = - (81.799 + 0.099 * clay - 31.420 * bulk_density + 0.018 * cation_exchange_capacity + - 0.451 * ph - 0.0005 * sand * clay) / - 100.0; - const double theta_r = (22.733 - 0.164 * sand + 0.235 * cation_exchange_capacity - - 0.831 * ph + 0.0018 * clay_squared + 0.0026 * sand * clay) / - 100.0; - *(double *)args[7] = alpha; - *(double *)args[8] = n; - *(double *)args[9] = theta_s; - *(double *)args[10] = theta_r; - for (int arg = 0; arg < 11; arg++) - args[arg] += steps[arg]; +static int calc_ptf_hodnett2002_contiguous_loop(PyArrayMethod_Context *context, char *const *data, + const npy_intp *dimensions, const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_silt = (const double *)data[1]; + const double *in_clay = (const double *)data[2]; + const double *in_organic_carbon = (const double *)data[3]; + const double *in_bulk_density = (const double *)data[4]; + const double *in_cation_exchange_capacity = (const double *)data[5]; + const double *in_ph = (const double *)data[6]; + double *out_alpha = (double *)data[7]; + double *out_n = (double *)data[8]; + double *out_theta_s = (double *)data[9]; + double *out_theta_r = (double *)data[10]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double silt = in_silt[index]; + const double clay = in_clay[index]; + const double organic_carbon = in_organic_carbon[index]; + const double bulk_density = in_bulk_density[index]; + const double cation_exchange_capacity = in_cation_exchange_capacity[index]; + const double ph = in_ph[index]; + const hodnett2002_ptf_result ptfkit_result = calc_ptf_hodnett2002( + sand, silt, clay, organic_carbon, bulk_density, cation_exchange_capacity, ph); + out_alpha[index] = ptfkit_result.alpha; + out_n[index] = ptfkit_result.n; + out_theta_s[index] = ptfkit_result.theta_s; + out_theta_r[index] = ptfkit_result.theta_r; } + return 0; +} + +static int calc_ptf_hodnett2002_strided_loop(PyArrayMethod_Context *context, char *const *data, + const npy_intp *dimensions, const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double silt = *(const double *)(data[1] + index * strides[1]); + const double clay = *(const double *)(data[2] + index * strides[2]); + const double organic_carbon = *(const double *)(data[3] + index * strides[3]); + const double bulk_density = *(const double *)(data[4] + index * strides[4]); + const double cation_exchange_capacity = *(const double *)(data[5] + index * strides[5]); + const double ph = *(const double *)(data[6] + index * strides[6]); + const hodnett2002_ptf_result ptfkit_result = calc_ptf_hodnett2002( + sand, silt, clay, organic_carbon, bulk_density, cation_exchange_capacity, ph); + *(double *)(data[7] + index * strides[7]) = ptfkit_result.alpha; + *(double *)(data[8] + index * strides[8]) = ptfkit_result.n; + *(double *)(data[9] + index * strides[9]) = ptfkit_result.theta_s; + *(double *)(data[10] + index * strides[10]) = ptfkit_result.theta_r; + } + return 0; } -static PyUFuncGenericFunction calc_ptf_hodnett2002_functions[] = {calc_ptf_hodnett2002_loop}; -static char calc_ptf_hodnett2002_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; +static PyType_Slot calc_ptf_hodnett2002_slots[] = { + {NPY_METH_strided_loop, calc_ptf_hodnett2002_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_hodnett2002_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_hodnett2002_spec = { + .name = "calc_ptf_hodnett2002", + .nin = 7, + .nout = 4, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_hodnett2002_slots, +}; int ptfkit_register_hodnett2002(PyObject *module) { - if (ptfkit_add_ufunc(module, "calc_ptf_hodnett2002", calc_ptf_hodnett2002_functions, - calc_ptf_hodnett2002_types, 7, 4) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_hodnett2002", 7, 4, &calc_ptf_hodnett2002_spec) < 0) return -1; return 0; } diff --git a/targets/ptfkit-py/src/ptfkit/hodnett2002.py b/targets/ptfkit-py/src/ptfkit/hodnett2002.py index da7d61d..b6a31e9 100644 --- a/targets/ptfkit-py/src/ptfkit/hodnett2002.py +++ b/targets/ptfkit-py/src/ptfkit/hodnett2002.py @@ -23,6 +23,7 @@ from typing import TYPE_CHECKING, Generic, NamedTuple, TypeVar, overload +from ptfkit._dispatch import call as _call from ptfkit._ptfkit import ( calc_ptf_hodnett2002 as _calc_ptf_hodnett2002, ) @@ -136,20 +137,16 @@ def calc_ptf_hodnett2002( calibration data; mineralogy and structure were not directly represented. """ - if out is None: - values = _calc_ptf_hodnett2002( - sand, silt, clay, organic_carbon, bulk_density, cation_exchange_capacity, ph - ) - else: - values = _calc_ptf_hodnett2002( - sand, - silt, - clay, - organic_carbon, - bulk_density, - cation_exchange_capacity, - ph, - out=tuple(out), - ) + values = _call( + _calc_ptf_hodnett2002, + sand, + silt, + clay, + organic_carbon, + bulk_density, + cation_exchange_capacity, + ph, + out=out, + ) return Hodnett2002PTFResult(*values) diff --git a/targets/ptfkit-py/src/ptfkit/jabro1992.c b/targets/ptfkit-py/src/ptfkit/jabro1992.c index 8d01bc8..6d0bfbc 100644 --- a/targets/ptfkit-py/src/ptfkit/jabro1992.c +++ b/targets/ptfkit-py/src/ptfkit/jabro1992.c @@ -1,27 +1,56 @@ /* @generated by ptfkit-codegen; DO NOT EDIT. */ +#include #include "ufunc.h" -static void calc_ptf_jabro1992_loop(char **args, const npy_intp *dimensions, const npy_intp *steps, - void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double silt = *(const double *)args[0]; - const double clay = *(const double *)args[1]; - const double bulk_density = *(const double *)args[2]; - const double log10_k_sat_cm_per_hour = - 9.56 - 0.81 * log10(silt) - 1.09 * log10(clay) - 4.64 * bulk_density; - const double k_sat = pow(10.0, log10_k_sat_cm_per_hour) * (0.01 / 3600.0); - *(double *)args[3] = k_sat; - for (int arg = 0; arg < 4; arg++) - args[arg] += steps[arg]; +static int calc_ptf_jabro1992_contiguous_loop(PyArrayMethod_Context *context, char *const *data, + const npy_intp *dimensions, const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_silt = (const double *)data[0]; + const double *in_clay = (const double *)data[1]; + const double *in_bulk_density = (const double *)data[2]; + double *out_k_sat = (double *)data[3]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double silt = in_silt[index]; + const double clay = in_clay[index]; + const double bulk_density = in_bulk_density[index]; + const double ptfkit_result = calc_ptf_jabro1992(silt, clay, bulk_density); + out_k_sat[index] = ptfkit_result; } + return 0; +} + +static int calc_ptf_jabro1992_strided_loop(PyArrayMethod_Context *context, char *const *data, + const npy_intp *dimensions, const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double silt = *(const double *)(data[0] + index * strides[0]); + const double clay = *(const double *)(data[1] + index * strides[1]); + const double bulk_density = *(const double *)(data[2] + index * strides[2]); + const double ptfkit_result = calc_ptf_jabro1992(silt, clay, bulk_density); + *(double *)(data[3] + index * strides[3]) = ptfkit_result; + } + return 0; } -static PyUFuncGenericFunction calc_ptf_jabro1992_functions[] = {calc_ptf_jabro1992_loop}; -static char calc_ptf_jabro1992_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; +static PyType_Slot calc_ptf_jabro1992_slots[] = { + {NPY_METH_strided_loop, calc_ptf_jabro1992_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_jabro1992_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_jabro1992_spec = { + .name = "calc_ptf_jabro1992", + .nin = 3, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_jabro1992_slots, +}; int ptfkit_register_jabro1992(PyObject *module) { - if (ptfkit_add_ufunc(module, "calc_ptf_jabro1992", calc_ptf_jabro1992_functions, - calc_ptf_jabro1992_types, 3, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_jabro1992", 3, 1, &calc_ptf_jabro1992_spec) < 0) return -1; return 0; } diff --git a/targets/ptfkit-py/src/ptfkit/jabro1992.py b/targets/ptfkit-py/src/ptfkit/jabro1992.py index 58c4692..6fdf25b 100644 --- a/targets/ptfkit-py/src/ptfkit/jabro1992.py +++ b/targets/ptfkit-py/src/ptfkit/jabro1992.py @@ -22,6 +22,7 @@ from typing import TYPE_CHECKING, overload +from ptfkit._dispatch import call as _call from ptfkit._ptfkit import ( calc_ptf_jabro1992 as _calc_ptf_jabro1992, ) @@ -77,9 +78,10 @@ def calc_ptf_jabro1992( The formula uses base-10 logarithms of silt and clay. """ - if out is None: - values = _calc_ptf_jabro1992(silt, clay, bulk_density) - else: - values = _calc_ptf_jabro1992(silt, clay, bulk_density, out=out) - - return values + return _call( + _calc_ptf_jabro1992, + silt, + clay, + bulk_density, + out=out, + ) diff --git a/targets/ptfkit-py/src/ptfkit/li2007.c b/targets/ptfkit-py/src/ptfkit/li2007.c index ca1c52a..ec5df28 100644 --- a/targets/ptfkit-py/src/ptfkit/li2007.c +++ b/targets/ptfkit-py/src/ptfkit/li2007.c @@ -1,46 +1,73 @@ /* @generated by ptfkit-codegen; DO NOT EDIT. */ +#include #include "ufunc.h" -static void calc_ptf_li2007_loop(char **args, const npy_intp *dimensions, const npy_intp *steps, - void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double silt = *(const double *)args[1]; - const double clay = *(const double *)args[2]; - const double bulk_density = *(const double *)args[3]; - const double soil_organic_matter = *(const double *)args[4]; - const double sand_ln = log(sand); - const double silt_ln = log(silt); - const double clay_ln = log(clay); - const double soil_organic_matter_ln = log(soil_organic_matter); - const double bulk_density_ln = log(bulk_density); - const double theta_s = exp(-1.531 + 0.212 * sand_ln + 0.006 * silt - - 0.051 * soil_organic_matter - 0.566 * bulk_density_ln); - const double a_vg = - exp(-67.408 - 0.040 * silt - 0.670 * silt_ln - 2.189 * soil_organic_matter + - 1.410 * soil_organic_matter_ln + 78.400 * bulk_density - 121.331 * bulk_density_ln); - const double n_vg = 1.488 + 0.002 * silt_ln + 0.013 * clay - 0.248 * clay_ln + - 0.048 * soil_organic_matter_ln + 0.451 * bulk_density_ln; - const double k_sat_cm_per_day = exp(13.262 - 1.914 * sand_ln - 0.974 * silt_ln - - 0.058 * clay - 1.709 * soil_organic_matter_ln + - 2.885 * soil_organic_matter - 8.026 * bulk_density_ln); - const double k_sat = k_sat_cm_per_day * (1.0 / 8640000.0); - *(double *)args[5] = theta_s; - *(double *)args[6] = a_vg; - *(double *)args[7] = n_vg; - *(double *)args[8] = k_sat; - for (int arg = 0; arg < 9; arg++) - args[arg] += steps[arg]; +static int calc_ptf_li2007_contiguous_loop(PyArrayMethod_Context *context, char *const *data, + const npy_intp *dimensions, const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_silt = (const double *)data[1]; + const double *in_clay = (const double *)data[2]; + const double *in_bulk_density = (const double *)data[3]; + const double *in_soil_organic_matter = (const double *)data[4]; + double *out_theta_s = (double *)data[5]; + double *out_a_vg = (double *)data[6]; + double *out_n_vg = (double *)data[7]; + double *out_k_sat = (double *)data[8]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double silt = in_silt[index]; + const double clay = in_clay[index]; + const double bulk_density = in_bulk_density[index]; + const double soil_organic_matter = in_soil_organic_matter[index]; + const li2007_ptf_result ptfkit_result = + calc_ptf_li2007(sand, silt, clay, bulk_density, soil_organic_matter); + out_theta_s[index] = ptfkit_result.theta_s; + out_a_vg[index] = ptfkit_result.a_vg; + out_n_vg[index] = ptfkit_result.n_vg; + out_k_sat[index] = ptfkit_result.k_sat; } + return 0; +} + +static int calc_ptf_li2007_strided_loop(PyArrayMethod_Context *context, char *const *data, + const npy_intp *dimensions, const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double silt = *(const double *)(data[1] + index * strides[1]); + const double clay = *(const double *)(data[2] + index * strides[2]); + const double bulk_density = *(const double *)(data[3] + index * strides[3]); + const double soil_organic_matter = *(const double *)(data[4] + index * strides[4]); + const li2007_ptf_result ptfkit_result = + calc_ptf_li2007(sand, silt, clay, bulk_density, soil_organic_matter); + *(double *)(data[5] + index * strides[5]) = ptfkit_result.theta_s; + *(double *)(data[6] + index * strides[6]) = ptfkit_result.a_vg; + *(double *)(data[7] + index * strides[7]) = ptfkit_result.n_vg; + *(double *)(data[8] + index * strides[8]) = ptfkit_result.k_sat; + } + return 0; } -static PyUFuncGenericFunction calc_ptf_li2007_functions[] = {calc_ptf_li2007_loop}; -static char calc_ptf_li2007_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; +static PyType_Slot calc_ptf_li2007_slots[] = { + {NPY_METH_strided_loop, calc_ptf_li2007_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_li2007_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_li2007_spec = { + .name = "calc_ptf_li2007", + .nin = 5, + .nout = 4, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_li2007_slots, +}; int ptfkit_register_li2007(PyObject *module) { - if (ptfkit_add_ufunc(module, "calc_ptf_li2007", calc_ptf_li2007_functions, - calc_ptf_li2007_types, 5, 4) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_li2007", 5, 4, &calc_ptf_li2007_spec) < 0) return -1; return 0; } diff --git a/targets/ptfkit-py/src/ptfkit/li2007.py b/targets/ptfkit-py/src/ptfkit/li2007.py index cc428a3..4c09815 100644 --- a/targets/ptfkit-py/src/ptfkit/li2007.py +++ b/targets/ptfkit-py/src/ptfkit/li2007.py @@ -23,6 +23,7 @@ from typing import TYPE_CHECKING, Generic, NamedTuple, TypeVar, overload +from ptfkit._dispatch import call as _call from ptfkit._ptfkit import ( calc_ptf_li2007 as _calc_ptf_li2007, ) @@ -109,11 +110,14 @@ def calc_ptf_li2007( The formulas use natural logarithms of selected inputs. """ - if out is None: - values = _calc_ptf_li2007(sand, silt, clay, bulk_density, soil_organic_matter) - else: - values = _calc_ptf_li2007( - sand, silt, clay, bulk_density, soil_organic_matter, out=tuple(out) - ) + values = _call( + _calc_ptf_li2007, + sand, + silt, + clay, + bulk_density, + soil_organic_matter, + out=out, + ) return Li2007PTFResult(*values) diff --git a/targets/ptfkit-py/src/ptfkit/mayr1999.c b/targets/ptfkit-py/src/ptfkit/mayr1999.c index b00530b..0f2ef00 100644 --- a/targets/ptfkit-py/src/ptfkit/mayr1999.c +++ b/targets/ptfkit-py/src/ptfkit/mayr1999.c @@ -1,47 +1,70 @@ /* @generated by ptfkit-codegen; DO NOT EDIT. */ +#include #include "ufunc.h" -static void calc_ptf_mayr1999_loop(char **args, const npy_intp *dimensions, const npy_intp *steps, - void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double silt = *(const double *)args[1]; - const double clay = *(const double *)args[2]; - const double bulk_density = *(const double *)args[3]; - const double organic_carbon = *(const double *)args[4]; - const double silt_squared = silt * silt; - const double sand_squared = sand * sand; - const double organic_carbon_squared = organic_carbon * organic_carbon; - const double log10_a_hc = -4.9840297533 + 0.0509226283 * sand + 0.1575152771 * silt + - 0.1240901644 * bulk_density - 0.1640033143 * organic_carbon - - 0.0021767278 * silt_squared + 1.438224e-5 * (silt * silt * silt) + - 8.040715e-4 * (clay * clay) + - 0.0044067117 * organic_carbon_squared; - const double log10_inv_b_hc = -0.8466880654 - 0.0046806123 * sand + 0.0092463819 * silt - - 0.4542769707 * bulk_density - 0.0497915563 * organic_carbon + - 3.294687e-4 * sand_squared - - 1.689056e-6 * (sand * sand * sand) + - 0.0011225373 * organic_carbon_squared; - const double a_hc = pow(10.0, log10_a_hc); - const double b_hc = pow(10.0, -log10_inv_b_hc); - const double theta_s = 0.2345971971 + 0.0046614221 * sand + 0.0088163314 * silt + - 0.0064338641 * clay - 0.3028160229 * bulk_density + - 1.79762e-5 * sand_squared - 3.134631e-5 * silt_squared; - *(double *)args[5] = a_hc; - *(double *)args[6] = b_hc; - *(double *)args[7] = theta_s; - for (int arg = 0; arg < 8; arg++) - args[arg] += steps[arg]; +static int calc_ptf_mayr1999_contiguous_loop(PyArrayMethod_Context *context, char *const *data, + const npy_intp *dimensions, const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_silt = (const double *)data[1]; + const double *in_clay = (const double *)data[2]; + const double *in_bulk_density = (const double *)data[3]; + const double *in_organic_carbon = (const double *)data[4]; + double *out_a_hc = (double *)data[5]; + double *out_b_hc = (double *)data[6]; + double *out_theta_s = (double *)data[7]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double silt = in_silt[index]; + const double clay = in_clay[index]; + const double bulk_density = in_bulk_density[index]; + const double organic_carbon = in_organic_carbon[index]; + const mayr1999_ptf_result ptfkit_result = + calc_ptf_mayr1999(sand, silt, clay, bulk_density, organic_carbon); + out_a_hc[index] = ptfkit_result.a_hc; + out_b_hc[index] = ptfkit_result.b_hc; + out_theta_s[index] = ptfkit_result.theta_s; } + return 0; +} + +static int calc_ptf_mayr1999_strided_loop(PyArrayMethod_Context *context, char *const *data, + const npy_intp *dimensions, const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double silt = *(const double *)(data[1] + index * strides[1]); + const double clay = *(const double *)(data[2] + index * strides[2]); + const double bulk_density = *(const double *)(data[3] + index * strides[3]); + const double organic_carbon = *(const double *)(data[4] + index * strides[4]); + const mayr1999_ptf_result ptfkit_result = + calc_ptf_mayr1999(sand, silt, clay, bulk_density, organic_carbon); + *(double *)(data[5] + index * strides[5]) = ptfkit_result.a_hc; + *(double *)(data[6] + index * strides[6]) = ptfkit_result.b_hc; + *(double *)(data[7] + index * strides[7]) = ptfkit_result.theta_s; + } + return 0; } -static PyUFuncGenericFunction calc_ptf_mayr1999_functions[] = {calc_ptf_mayr1999_loop}; -static char calc_ptf_mayr1999_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; +static PyType_Slot calc_ptf_mayr1999_slots[] = { + {NPY_METH_strided_loop, calc_ptf_mayr1999_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_mayr1999_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_mayr1999_spec = { + .name = "calc_ptf_mayr1999", + .nin = 5, + .nout = 3, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_mayr1999_slots, +}; int ptfkit_register_mayr1999(PyObject *module) { - if (ptfkit_add_ufunc(module, "calc_ptf_mayr1999", calc_ptf_mayr1999_functions, - calc_ptf_mayr1999_types, 5, 3) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_mayr1999", 5, 3, &calc_ptf_mayr1999_spec) < 0) return -1; return 0; } diff --git a/targets/ptfkit-py/src/ptfkit/mayr1999.py b/targets/ptfkit-py/src/ptfkit/mayr1999.py index 654c77b..e5f3801 100644 --- a/targets/ptfkit-py/src/ptfkit/mayr1999.py +++ b/targets/ptfkit-py/src/ptfkit/mayr1999.py @@ -23,6 +23,7 @@ from typing import TYPE_CHECKING, Generic, NamedTuple, TypeVar, overload +from ptfkit._dispatch import call as _call from ptfkit._ptfkit import ( calc_ptf_mayr1999 as _calc_ptf_mayr1999, ) @@ -115,9 +116,14 @@ def calc_ptf_mayr1999( paper provides that distribution only graphically. """ - if out is None: - values = _calc_ptf_mayr1999(sand, silt, clay, bulk_density, organic_carbon) - else: - values = _calc_ptf_mayr1999(sand, silt, clay, bulk_density, organic_carbon, out=tuple(out)) + values = _call( + _calc_ptf_mayr1999, + sand, + silt, + clay, + bulk_density, + organic_carbon, + out=out, + ) return Mayr1999PTFResult(*values) diff --git a/targets/ptfkit-py/src/ptfkit/oosterveld1980.c b/targets/ptfkit-py/src/ptfkit/oosterveld1980.c index 68be100..5b40009 100644 --- a/targets/ptfkit-py/src/ptfkit/oosterveld1980.c +++ b/targets/ptfkit-py/src/ptfkit/oosterveld1980.c @@ -1,122 +1,274 @@ /* @generated by ptfkit-codegen; DO NOT EDIT. */ +#include #include "ufunc.h" -static void calc_ptf_oosterveld1980_field_capacity_tension_loop(char **args, - const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double clay = *(const double *)args[0]; - const double field_capacity_tension = 5.356 * pow(clay, 0.421); - *(double *)args[1] = field_capacity_tension; - for (int arg = 0; arg < 2; arg++) - args[arg] += steps[arg]; +static int calc_ptf_oosterveld1980_field_capacity_tension_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_clay = (const double *)data[0]; + double *out_field_capacity_tension = (double *)data[1]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = in_clay[index]; + const double ptfkit_result = calc_ptf_oosterveld1980_field_capacity_tension(clay); + out_field_capacity_tension[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_oosterveld1980_field_capacity_tension_strided_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = *(const double *)(data[0] + index * strides[0]); + const double ptfkit_result = calc_ptf_oosterveld1980_field_capacity_tension(clay); + *(double *)(data[1] + index * strides[1]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_oosterveld1980_field_capacity_tension_slots[] = { + {NPY_METH_strided_loop, calc_ptf_oosterveld1980_field_capacity_tension_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_oosterveld1980_field_capacity_tension_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_oosterveld1980_field_capacity_tension_spec = { + .name = "calc_ptf_oosterveld1980_field_capacity_tension", + .nin = 1, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_oosterveld1980_field_capacity_tension_slots, +}; + +static int calc_ptf_oosterveld1980_retention_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_clay = (const double *)data[0]; + const double *in_sand = (const double *)data[1]; + const double *in_mean_depth = (const double *)data[2]; + const double *in_tension = (const double *)data[3]; + double *out_moisture_content = (double *)data[4]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = in_clay[index]; + const double sand = in_sand[index]; + const double mean_depth = in_mean_depth[index]; + const double tension = in_tension[index]; + const double ptfkit_result = + calc_ptf_oosterveld1980_retention(clay, sand, mean_depth, tension); + out_moisture_content[index] = ptfkit_result; } + return 0; } -static PyUFuncGenericFunction calc_ptf_oosterveld1980_field_capacity_tension_functions[] = { - calc_ptf_oosterveld1980_field_capacity_tension_loop}; -static char calc_ptf_oosterveld1980_field_capacity_tension_types[] = {NPY_DOUBLE, NPY_DOUBLE}; -static void calc_ptf_oosterveld1980_retention_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double clay = *(const double *)args[0]; - const double sand = *(const double *)args[1]; - const double mean_depth = *(const double *)args[2]; - const double tension = *(const double *)args[3]; - const double moisture_content = - (35.367 + 0.644 * clay - 0.251 * sand - 0.045 * mean_depth) * pow(tension, -0.190); - *(double *)args[4] = moisture_content; - for (int arg = 0; arg < 5; arg++) - args[arg] += steps[arg]; +static int calc_ptf_oosterveld1980_retention_strided_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = *(const double *)(data[0] + index * strides[0]); + const double sand = *(const double *)(data[1] + index * strides[1]); + const double mean_depth = *(const double *)(data[2] + index * strides[2]); + const double tension = *(const double *)(data[3] + index * strides[3]); + const double ptfkit_result = + calc_ptf_oosterveld1980_retention(clay, sand, mean_depth, tension); + *(double *)(data[4] + index * strides[4]) = ptfkit_result; } + return 0; } -static PyUFuncGenericFunction calc_ptf_oosterveld1980_retention_functions[] = { - calc_ptf_oosterveld1980_retention_loop}; -static char calc_ptf_oosterveld1980_retention_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE, NPY_DOUBLE}; +static PyType_Slot calc_ptf_oosterveld1980_retention_slots[] = { + {NPY_METH_strided_loop, calc_ptf_oosterveld1980_retention_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_oosterveld1980_retention_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_oosterveld1980_retention_spec = { + .name = "calc_ptf_oosterveld1980_retention", + .nin = 4, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_oosterveld1980_retention_slots, +}; -static void calc_ptf_oosterveld1980_field_capacity_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double clay = *(const double *)args[0]; - const double sand = *(const double *)args[1]; - const double mean_depth = *(const double *)args[2]; - const double field_capacity_moisture = - (25.713 + 0.469 * clay - 0.184 * sand - 0.0329 * mean_depth) * pow(clay, -0.080); - *(double *)args[3] = field_capacity_moisture; - for (int arg = 0; arg < 4; arg++) - args[arg] += steps[arg]; +static int calc_ptf_oosterveld1980_field_capacity_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_clay = (const double *)data[0]; + const double *in_sand = (const double *)data[1]; + const double *in_mean_depth = (const double *)data[2]; + double *out_field_capacity_moisture = (double *)data[3]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = in_clay[index]; + const double sand = in_sand[index]; + const double mean_depth = in_mean_depth[index]; + const double ptfkit_result = calc_ptf_oosterveld1980_field_capacity(clay, sand, mean_depth); + out_field_capacity_moisture[index] = ptfkit_result; } + return 0; } -static PyUFuncGenericFunction calc_ptf_oosterveld1980_field_capacity_functions[] = { - calc_ptf_oosterveld1980_field_capacity_loop}; -static char calc_ptf_oosterveld1980_field_capacity_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE}; -static void calc_ptf_oosterveld1980_wilting_point_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double clay = *(const double *)args[0]; - const double sand = *(const double *)args[1]; - const double mean_depth = *(const double *)args[2]; - const double wilting_point_moisture = - 4.035 + 0.299 * clay - 0.034 * sand - 0.016 * mean_depth; - *(double *)args[3] = wilting_point_moisture; - for (int arg = 0; arg < 4; arg++) - args[arg] += steps[arg]; +static int calc_ptf_oosterveld1980_field_capacity_strided_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = *(const double *)(data[0] + index * strides[0]); + const double sand = *(const double *)(data[1] + index * strides[1]); + const double mean_depth = *(const double *)(data[2] + index * strides[2]); + const double ptfkit_result = calc_ptf_oosterveld1980_field_capacity(clay, sand, mean_depth); + *(double *)(data[3] + index * strides[3]) = ptfkit_result; } + return 0; } -static PyUFuncGenericFunction calc_ptf_oosterveld1980_wilting_point_functions[] = { - calc_ptf_oosterveld1980_wilting_point_loop}; -static char calc_ptf_oosterveld1980_wilting_point_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE}; +static PyType_Slot calc_ptf_oosterveld1980_field_capacity_slots[] = { + {NPY_METH_strided_loop, calc_ptf_oosterveld1980_field_capacity_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_oosterveld1980_field_capacity_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_oosterveld1980_field_capacity_spec = { + .name = "calc_ptf_oosterveld1980_field_capacity", + .nin = 3, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_oosterveld1980_field_capacity_slots, +}; -static void calc_ptf_oosterveld1980_available_water_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double clay = *(const double *)args[0]; - const double sand = *(const double *)args[1]; - const double mean_depth = *(const double *)args[2]; - const double field_capacity_moisture = - (25.713 + 0.469 * clay - 0.184 * sand - 0.0329 * mean_depth) * pow(clay, -0.080); - const double wilting_point_moisture = - 4.035 + 0.299 * clay - 0.034 * sand - 0.016 * mean_depth; - const double available_moisture = field_capacity_moisture - wilting_point_moisture; - *(double *)args[3] = available_moisture; - for (int arg = 0; arg < 4; arg++) - args[arg] += steps[arg]; +static int calc_ptf_oosterveld1980_wilting_point_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_clay = (const double *)data[0]; + const double *in_sand = (const double *)data[1]; + const double *in_mean_depth = (const double *)data[2]; + double *out_wilting_point_moisture = (double *)data[3]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = in_clay[index]; + const double sand = in_sand[index]; + const double mean_depth = in_mean_depth[index]; + const double ptfkit_result = calc_ptf_oosterveld1980_wilting_point(clay, sand, mean_depth); + out_wilting_point_moisture[index] = ptfkit_result; } + return 0; +} + +static int calc_ptf_oosterveld1980_wilting_point_strided_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = *(const double *)(data[0] + index * strides[0]); + const double sand = *(const double *)(data[1] + index * strides[1]); + const double mean_depth = *(const double *)(data[2] + index * strides[2]); + const double ptfkit_result = calc_ptf_oosterveld1980_wilting_point(clay, sand, mean_depth); + *(double *)(data[3] + index * strides[3]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_oosterveld1980_wilting_point_slots[] = { + {NPY_METH_strided_loop, calc_ptf_oosterveld1980_wilting_point_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_oosterveld1980_wilting_point_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_oosterveld1980_wilting_point_spec = { + .name = "calc_ptf_oosterveld1980_wilting_point", + .nin = 3, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_oosterveld1980_wilting_point_slots, +}; + +static int calc_ptf_oosterveld1980_available_water_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_clay = (const double *)data[0]; + const double *in_sand = (const double *)data[1]; + const double *in_mean_depth = (const double *)data[2]; + double *out_available_moisture = (double *)data[3]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = in_clay[index]; + const double sand = in_sand[index]; + const double mean_depth = in_mean_depth[index]; + const double ptfkit_result = + calc_ptf_oosterveld1980_available_water(clay, sand, mean_depth); + out_available_moisture[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_oosterveld1980_available_water_strided_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = *(const double *)(data[0] + index * strides[0]); + const double sand = *(const double *)(data[1] + index * strides[1]); + const double mean_depth = *(const double *)(data[2] + index * strides[2]); + const double ptfkit_result = + calc_ptf_oosterveld1980_available_water(clay, sand, mean_depth); + *(double *)(data[3] + index * strides[3]) = ptfkit_result; + } + return 0; } -static PyUFuncGenericFunction calc_ptf_oosterveld1980_available_water_functions[] = { - calc_ptf_oosterveld1980_available_water_loop}; -static char calc_ptf_oosterveld1980_available_water_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE}; +static PyType_Slot calc_ptf_oosterveld1980_available_water_slots[] = { + {NPY_METH_strided_loop, calc_ptf_oosterveld1980_available_water_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_oosterveld1980_available_water_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_oosterveld1980_available_water_spec = { + .name = "calc_ptf_oosterveld1980_available_water", + .nin = 3, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_oosterveld1980_available_water_slots, +}; int ptfkit_register_oosterveld1980(PyObject *module) { - if (ptfkit_add_ufunc(module, "calc_ptf_oosterveld1980_field_capacity_tension", - calc_ptf_oosterveld1980_field_capacity_tension_functions, - calc_ptf_oosterveld1980_field_capacity_tension_types, 1, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_oosterveld1980_field_capacity_tension", 1, 1, + &calc_ptf_oosterveld1980_field_capacity_tension_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_oosterveld1980_retention", - calc_ptf_oosterveld1980_retention_functions, - calc_ptf_oosterveld1980_retention_types, 4, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_oosterveld1980_retention", 4, 1, + &calc_ptf_oosterveld1980_retention_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_oosterveld1980_field_capacity", - calc_ptf_oosterveld1980_field_capacity_functions, - calc_ptf_oosterveld1980_field_capacity_types, 3, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_oosterveld1980_field_capacity", 3, 1, + &calc_ptf_oosterveld1980_field_capacity_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_oosterveld1980_wilting_point", - calc_ptf_oosterveld1980_wilting_point_functions, - calc_ptf_oosterveld1980_wilting_point_types, 3, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_oosterveld1980_wilting_point", 3, 1, + &calc_ptf_oosterveld1980_wilting_point_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_oosterveld1980_available_water", - calc_ptf_oosterveld1980_available_water_functions, - calc_ptf_oosterveld1980_available_water_types, 3, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_oosterveld1980_available_water", 3, 1, + &calc_ptf_oosterveld1980_available_water_spec) < 0) return -1; return 0; } diff --git a/targets/ptfkit-py/src/ptfkit/oosterveld1980.py b/targets/ptfkit-py/src/ptfkit/oosterveld1980.py index cf75ca1..db11cd0 100644 --- a/targets/ptfkit-py/src/ptfkit/oosterveld1980.py +++ b/targets/ptfkit-py/src/ptfkit/oosterveld1980.py @@ -23,6 +23,7 @@ from typing import TYPE_CHECKING, overload +from ptfkit._dispatch import call as _call from ptfkit._ptfkit import ( calc_ptf_oosterveld1980_field_capacity_tension as _calc_ptf_oosterveld1980_field_capacity_tension, calc_ptf_oosterveld1980_retention as _calc_ptf_oosterveld1980_retention, @@ -82,12 +83,11 @@ def calc_ptf_oosterveld1980_field_capacity_tension( Equation 1 reports r = 0.67 and n = 134. """ - if out is None: - values = _calc_ptf_oosterveld1980_field_capacity_tension(clay) - else: - values = _calc_ptf_oosterveld1980_field_capacity_tension(clay, out=out) - - return values + return _call( + _calc_ptf_oosterveld1980_field_capacity_tension, + clay, + out=out, + ) @overload @@ -138,12 +138,14 @@ def calc_ptf_oosterveld1980_retention( The paper reports slight inaccuracy at very high clay content and high tension. """ - if out is None: - values = _calc_ptf_oosterveld1980_retention(clay, sand, mean_depth, tension) - else: - values = _calc_ptf_oosterveld1980_retention(clay, sand, mean_depth, tension, out=out) - - return values + return _call( + _calc_ptf_oosterveld1980_retention, + clay, + sand, + mean_depth, + tension, + out=out, + ) @overload @@ -191,12 +193,13 @@ def calc_ptf_oosterveld1980_field_capacity( 2. """ - if out is None: - values = _calc_ptf_oosterveld1980_field_capacity(clay, sand, mean_depth) - else: - values = _calc_ptf_oosterveld1980_field_capacity(clay, sand, mean_depth, out=out) - - return values + return _call( + _calc_ptf_oosterveld1980_field_capacity, + clay, + sand, + mean_depth, + out=out, + ) @overload @@ -243,12 +246,13 @@ def calc_ptf_oosterveld1980_wilting_point( The paper takes moisture content at 1500 kPa as the wilting point. """ - if out is None: - values = _calc_ptf_oosterveld1980_wilting_point(clay, sand, mean_depth) - else: - values = _calc_ptf_oosterveld1980_wilting_point(clay, sand, mean_depth, out=out) - - return values + return _call( + _calc_ptf_oosterveld1980_wilting_point, + clay, + sand, + mean_depth, + out=out, + ) @overload @@ -296,9 +300,10 @@ def calc_ptf_oosterveld1980_available_water( The paper defines available soil water by subtracting Equation 4 from Equation 3. """ - if out is None: - values = _calc_ptf_oosterveld1980_available_water(clay, sand, mean_depth) - else: - values = _calc_ptf_oosterveld1980_available_water(clay, sand, mean_depth, out=out) - - return values + return _call( + _calc_ptf_oosterveld1980_available_water, + clay, + sand, + mean_depth, + out=out, + ) diff --git a/targets/ptfkit-py/src/ptfkit/pidgeon1972.c b/targets/ptfkit-py/src/ptfkit/pidgeon1972.c index 42b8f08..1da5ed8 100644 --- a/targets/ptfkit-py/src/ptfkit/pidgeon1972.c +++ b/targets/ptfkit-py/src/ptfkit/pidgeon1972.c @@ -1,360 +1,847 @@ /* @generated by ptfkit-codegen; DO NOT EDIT. */ +#include #include "ufunc.h" -static void calc_ptf_pidgeon1972_fc_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double silt = *(const double *)args[0]; - const double clay = *(const double *)args[1]; - const double organic_matter = *(const double *)args[2]; - const double field_capacity = 7.38 + 0.16 * silt + 0.30 * clay + 1.54 * organic_matter; - *(double *)args[3] = field_capacity; - for (int arg = 0; arg < 4; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_pidgeon1972_fc_functions[] = {calc_ptf_pidgeon1972_fc_loop}; -static char calc_ptf_pidgeon1972_fc_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_pidgeon1972_fc_sand_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double field_capacity = 36.16 - 0.25 * sand; - *(double *)args[1] = field_capacity; - for (int arg = 0; arg < 2; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_pidgeon1972_fc_sand_functions[] = { - calc_ptf_pidgeon1972_fc_sand_loop}; -static char calc_ptf_pidgeon1972_fc_sand_types[] = {NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_pidgeon1972_fc_sand_organic_matter_loop(char **args, +static int calc_ptf_pidgeon1972_fc_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_silt = (const double *)data[0]; + const double *in_clay = (const double *)data[1]; + const double *in_organic_matter = (const double *)data[2]; + double *out_field_capacity = (double *)data[3]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double silt = in_silt[index]; + const double clay = in_clay[index]; + const double organic_matter = in_organic_matter[index]; + const double ptfkit_result = calc_ptf_pidgeon1972_fc(silt, clay, organic_matter); + out_field_capacity[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_pidgeon1972_fc_strided_loop(PyArrayMethod_Context *context, char *const *data, + const npy_intp *dimensions, const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double silt = *(const double *)(data[0] + index * strides[0]); + const double clay = *(const double *)(data[1] + index * strides[1]); + const double organic_matter = *(const double *)(data[2] + index * strides[2]); + const double ptfkit_result = calc_ptf_pidgeon1972_fc(silt, clay, organic_matter); + *(double *)(data[3] + index * strides[3]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_pidgeon1972_fc_slots[] = { + {NPY_METH_strided_loop, calc_ptf_pidgeon1972_fc_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_pidgeon1972_fc_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_pidgeon1972_fc_spec = { + .name = "calc_ptf_pidgeon1972_fc", + .nin = 3, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_pidgeon1972_fc_slots, +}; + +static int calc_ptf_pidgeon1972_fc_sand_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + double *out_field_capacity = (double *)data[1]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double ptfkit_result = calc_ptf_pidgeon1972_fc_sand(sand); + out_field_capacity[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_pidgeon1972_fc_sand_strided_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double ptfkit_result = calc_ptf_pidgeon1972_fc_sand(sand); + *(double *)(data[1] + index * strides[1]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_pidgeon1972_fc_sand_slots[] = { + {NPY_METH_strided_loop, calc_ptf_pidgeon1972_fc_sand_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_pidgeon1972_fc_sand_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_pidgeon1972_fc_sand_spec = { + .name = "calc_ptf_pidgeon1972_fc_sand", + .nin = 1, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_pidgeon1972_fc_sand_slots, +}; + +static int calc_ptf_pidgeon1972_fc_sand_organic_matter_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_organic_matter = (const double *)data[1]; + double *out_field_capacity = (double *)data[2]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double organic_matter = in_organic_matter[index]; + const double ptfkit_result = + calc_ptf_pidgeon1972_fc_sand_organic_matter(sand, organic_matter); + out_field_capacity[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_pidgeon1972_fc_sand_organic_matter_strided_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double organic_matter = *(const double *)(data[1] + index * strides[1]); + const double ptfkit_result = + calc_ptf_pidgeon1972_fc_sand_organic_matter(sand, organic_matter); + *(double *)(data[2] + index * strides[2]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_pidgeon1972_fc_sand_organic_matter_slots[] = { + {NPY_METH_strided_loop, calc_ptf_pidgeon1972_fc_sand_organic_matter_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_pidgeon1972_fc_sand_organic_matter_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_pidgeon1972_fc_sand_organic_matter_spec = { + .name = "calc_ptf_pidgeon1972_fc_sand_organic_matter", + .nin = 2, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_pidgeon1972_fc_sand_organic_matter_slots, +}; + +static int calc_ptf_pidgeon1972_fc_vol_sand_organic_matter_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_organic_matter = (const double *)data[1]; + double *out_field_capacity = (double *)data[2]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double organic_matter = in_organic_matter[index]; + const double ptfkit_result = + calc_ptf_pidgeon1972_fc_vol_sand_organic_matter(sand, organic_matter); + out_field_capacity[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_pidgeon1972_fc_vol_sand_organic_matter_strided_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double organic_matter = *(const double *)(data[1] + index * strides[1]); + const double ptfkit_result = + calc_ptf_pidgeon1972_fc_vol_sand_organic_matter(sand, organic_matter); + *(double *)(data[2] + index * strides[2]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_pidgeon1972_fc_vol_sand_organic_matter_slots[] = { + {NPY_METH_strided_loop, calc_ptf_pidgeon1972_fc_vol_sand_organic_matter_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_pidgeon1972_fc_vol_sand_organic_matter_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_pidgeon1972_fc_vol_sand_organic_matter_spec = { + .name = "calc_ptf_pidgeon1972_fc_vol_sand_organic_matter", + .nin = 2, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_pidgeon1972_fc_vol_sand_organic_matter_slots, +}; + +static int calc_ptf_pidgeon1972_pwp_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_silt = (const double *)data[0]; + const double *in_clay = (const double *)data[1]; + const double *in_organic_matter = (const double *)data[2]; + double *out_permanent_wilting_point = (double *)data[3]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double silt = in_silt[index]; + const double clay = in_clay[index]; + const double organic_matter = in_organic_matter[index]; + const double ptfkit_result = calc_ptf_pidgeon1972_pwp(silt, clay, organic_matter); + out_permanent_wilting_point[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_pidgeon1972_pwp_strided_loop(PyArrayMethod_Context *context, char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double silt = *(const double *)(data[0] + index * strides[0]); + const double clay = *(const double *)(data[1] + index * strides[1]); + const double organic_matter = *(const double *)(data[2] + index * strides[2]); + const double ptfkit_result = calc_ptf_pidgeon1972_pwp(silt, clay, organic_matter); + *(double *)(data[3] + index * strides[3]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_pidgeon1972_pwp_slots[] = { + {NPY_METH_strided_loop, calc_ptf_pidgeon1972_pwp_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_pidgeon1972_pwp_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_pidgeon1972_pwp_spec = { + .name = "calc_ptf_pidgeon1972_pwp", + .nin = 3, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_pidgeon1972_pwp_slots, +}; + +static int calc_ptf_pidgeon1972_pwp_sand_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + double *out_permanent_wilting_point = (double *)data[1]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double ptfkit_result = calc_ptf_pidgeon1972_pwp_sand(sand); + out_permanent_wilting_point[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_pidgeon1972_pwp_sand_strided_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double ptfkit_result = calc_ptf_pidgeon1972_pwp_sand(sand); + *(double *)(data[1] + index * strides[1]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_pidgeon1972_pwp_sand_slots[] = { + {NPY_METH_strided_loop, calc_ptf_pidgeon1972_pwp_sand_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_pidgeon1972_pwp_sand_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_pidgeon1972_pwp_sand_spec = { + .name = "calc_ptf_pidgeon1972_pwp_sand", + .nin = 1, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_pidgeon1972_pwp_sand_slots, +}; + +static int calc_ptf_pidgeon1972_pwp_sand_organic_matter_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_organic_matter = (const double *)data[1]; + double *out_permanent_wilting_point = (double *)data[2]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double organic_matter = in_organic_matter[index]; + const double ptfkit_result = + calc_ptf_pidgeon1972_pwp_sand_organic_matter(sand, organic_matter); + out_permanent_wilting_point[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_pidgeon1972_pwp_sand_organic_matter_strided_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double organic_matter = *(const double *)(data[1] + index * strides[1]); + const double ptfkit_result = + calc_ptf_pidgeon1972_pwp_sand_organic_matter(sand, organic_matter); + *(double *)(data[2] + index * strides[2]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_pidgeon1972_pwp_sand_organic_matter_slots[] = { + {NPY_METH_strided_loop, calc_ptf_pidgeon1972_pwp_sand_organic_matter_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_pidgeon1972_pwp_sand_organic_matter_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_pidgeon1972_pwp_sand_organic_matter_spec = { + .name = "calc_ptf_pidgeon1972_pwp_sand_organic_matter", + .nin = 2, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_pidgeon1972_pwp_sand_organic_matter_slots, +}; + +static int calc_ptf_pidgeon1972_awc_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_clay = (const double *)data[0]; + const double *in_organic_matter = (const double *)data[1]; + double *out_available_water_capacity = (double *)data[2]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = in_clay[index]; + const double organic_matter = in_organic_matter[index]; + const double ptfkit_result = calc_ptf_pidgeon1972_awc(clay, organic_matter); + out_available_water_capacity[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_pidgeon1972_awc_strided_loop(PyArrayMethod_Context *context, char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = *(const double *)(data[0] + index * strides[0]); + const double organic_matter = *(const double *)(data[1] + index * strides[1]); + const double ptfkit_result = calc_ptf_pidgeon1972_awc(clay, organic_matter); + *(double *)(data[2] + index * strides[2]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_pidgeon1972_awc_slots[] = { + {NPY_METH_strided_loop, calc_ptf_pidgeon1972_awc_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_pidgeon1972_awc_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_pidgeon1972_awc_spec = { + .name = "calc_ptf_pidgeon1972_awc", + .nin = 2, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_pidgeon1972_awc_slots, +}; + +static int calc_ptf_pidgeon1972_awc_sand_organic_matter_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_organic_matter = (const double *)data[1]; + double *out_available_water_capacity = (double *)data[2]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double organic_matter = in_organic_matter[index]; + const double ptfkit_result = + calc_ptf_pidgeon1972_awc_sand_organic_matter(sand, organic_matter); + out_available_water_capacity[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_pidgeon1972_awc_sand_organic_matter_strided_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double organic_matter = *(const double *)(data[1] + index * strides[1]); + const double ptfkit_result = + calc_ptf_pidgeon1972_awc_sand_organic_matter(sand, organic_matter); + *(double *)(data[2] + index * strides[2]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_pidgeon1972_awc_sand_organic_matter_slots[] = { + {NPY_METH_strided_loop, calc_ptf_pidgeon1972_awc_sand_organic_matter_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_pidgeon1972_awc_sand_organic_matter_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_pidgeon1972_awc_sand_organic_matter_spec = { + .name = "calc_ptf_pidgeon1972_awc_sand_organic_matter", + .nin = 2, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_pidgeon1972_awc_sand_organic_matter_slots, +}; + +static int calc_ptf_pidgeon1972_awc_coarse_sand_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_coarse_sand = (const double *)data[0]; + double *out_available_water_capacity = (double *)data[1]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double coarse_sand = in_coarse_sand[index]; + const double ptfkit_result = calc_ptf_pidgeon1972_awc_coarse_sand(coarse_sand); + out_available_water_capacity[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_pidgeon1972_awc_coarse_sand_strided_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double organic_matter = *(const double *)args[1]; - const double field_capacity = 34.27 - 0.27 * sand + 1.25 * organic_matter; - *(double *)args[2] = field_capacity; - for (int arg = 0; arg < 3; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_pidgeon1972_fc_sand_organic_matter_functions[] = { - calc_ptf_pidgeon1972_fc_sand_organic_matter_loop}; -static char calc_ptf_pidgeon1972_fc_sand_organic_matter_types[] = {NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE}; - -static void calc_ptf_pidgeon1972_fc_vol_sand_organic_matter_loop(char **args, - const npy_intp *dimensions, - const npy_intp *steps, - void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double organic_matter = *(const double *)args[1]; - const double field_capacity = 38.15 - 0.17 * sand + 0.77 * organic_matter; - *(double *)args[2] = field_capacity; - for (int arg = 0; arg < 3; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_pidgeon1972_fc_vol_sand_organic_matter_functions[] = { - calc_ptf_pidgeon1972_fc_vol_sand_organic_matter_loop}; -static char calc_ptf_pidgeon1972_fc_vol_sand_organic_matter_types[] = {NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE}; - -static void calc_ptf_pidgeon1972_pwp_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double silt = *(const double *)args[0]; - const double clay = *(const double *)args[1]; - const double organic_matter = *(const double *)args[2]; - const double permanent_wilting_point = - -4.19 + 0.19 * silt + 0.39 * clay + 0.90 * organic_matter; - *(double *)args[3] = permanent_wilting_point; - for (int arg = 0; arg < 4; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_pidgeon1972_pwp_functions[] = { - calc_ptf_pidgeon1972_pwp_loop}; -static char calc_ptf_pidgeon1972_pwp_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_pidgeon1972_pwp_sand_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double permanent_wilting_point = 28.41 - 0.29 * sand; - *(double *)args[1] = permanent_wilting_point; - for (int arg = 0; arg < 2; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_pidgeon1972_pwp_sand_functions[] = { - calc_ptf_pidgeon1972_pwp_sand_loop}; -static char calc_ptf_pidgeon1972_pwp_sand_types[] = {NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_pidgeon1972_pwp_sand_organic_matter_loop(char **args, - const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double organic_matter = *(const double *)args[1]; - const double permanent_wilting_point = 32.90 - 0.37 * sand + 0.44 * organic_matter; - *(double *)args[2] = permanent_wilting_point; - for (int arg = 0; arg < 3; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_pidgeon1972_pwp_sand_organic_matter_functions[] = { - calc_ptf_pidgeon1972_pwp_sand_organic_matter_loop}; -static char calc_ptf_pidgeon1972_pwp_sand_organic_matter_types[] = {NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE}; - -static void calc_ptf_pidgeon1972_awc_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double clay = *(const double *)args[0]; - const double organic_matter = *(const double *)args[1]; - const double available_water_capacity = 169.3 - 1.50 * clay + 6.09 * organic_matter; - *(double *)args[2] = available_water_capacity; - for (int arg = 0; arg < 3; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_pidgeon1972_awc_functions[] = { - calc_ptf_pidgeon1972_awc_loop}; -static char calc_ptf_pidgeon1972_awc_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_pidgeon1972_awc_sand_organic_matter_loop(char **args, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double coarse_sand = *(const double *)(data[0] + index * strides[0]); + const double ptfkit_result = calc_ptf_pidgeon1972_awc_coarse_sand(coarse_sand); + *(double *)(data[1] + index * strides[1]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_pidgeon1972_awc_coarse_sand_slots[] = { + {NPY_METH_strided_loop, calc_ptf_pidgeon1972_awc_coarse_sand_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_pidgeon1972_awc_coarse_sand_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_pidgeon1972_awc_coarse_sand_spec = { + .name = "calc_ptf_pidgeon1972_awc_coarse_sand", + .nin = 1, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_pidgeon1972_awc_coarse_sand_slots, +}; + +static int calc_ptf_pidgeon1972_awc_fine_sand_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double organic_matter = *(const double *)args[1]; - const double available_water_capacity = 1.0 + 1.84 * sand + 8.12 * organic_matter; - *(double *)args[2] = available_water_capacity; - for (int arg = 0; arg < 3; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_pidgeon1972_awc_sand_organic_matter_functions[] = { - calc_ptf_pidgeon1972_awc_sand_organic_matter_loop}; -static char calc_ptf_pidgeon1972_awc_sand_organic_matter_types[] = {NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE}; - -static void calc_ptf_pidgeon1972_awc_coarse_sand_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double coarse_sand = *(const double *)args[0]; - const double available_water_capacity = 68.5 + 2.33 * coarse_sand; - *(double *)args[1] = available_water_capacity; - for (int arg = 0; arg < 2; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_pidgeon1972_awc_coarse_sand_functions[] = { - calc_ptf_pidgeon1972_awc_coarse_sand_loop}; -static char calc_ptf_pidgeon1972_awc_coarse_sand_types[] = {NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_pidgeon1972_awc_fine_sand_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double fine_sand = *(const double *)args[0]; - const double available_water_capacity = 66.7 + 2.66 * fine_sand; - *(double *)args[1] = available_water_capacity; - for (int arg = 0; arg < 2; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_pidgeon1972_awc_fine_sand_functions[] = { - calc_ptf_pidgeon1972_awc_fine_sand_loop}; -static char calc_ptf_pidgeon1972_awc_fine_sand_types[] = {NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_pidgeon1972_awc_very_fine_sand_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double very_fine_sand = *(const double *)args[0]; - const double available_water_capacity = 66.9 + 4.58 * very_fine_sand; - *(double *)args[1] = available_water_capacity; - for (int arg = 0; arg < 2; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_pidgeon1972_awc_very_fine_sand_functions[] = { - calc_ptf_pidgeon1972_awc_very_fine_sand_loop}; -static char calc_ptf_pidgeon1972_awc_very_fine_sand_types[] = {NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_pidgeon1972_eawc_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double silt = *(const double *)args[0]; - const double clay = *(const double *)args[1]; - const double organic_matter = *(const double *)args[2]; - const double extended_available_water_capacity = - 121.1 - 3.03 * silt - 1.38 * clay + 6.76 * organic_matter; - *(double *)args[3] = extended_available_water_capacity; - for (int arg = 0; arg < 4; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_pidgeon1972_eawc_functions[] = { - calc_ptf_pidgeon1972_eawc_loop}; -static char calc_ptf_pidgeon1972_eawc_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_pidgeon1972_eawc_sand_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double extended_available_water_capacity = -25.8 + 1.55 * sand; - *(double *)args[1] = extended_available_water_capacity; - for (int arg = 0; arg < 2; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_pidgeon1972_eawc_sand_functions[] = { - calc_ptf_pidgeon1972_eawc_sand_loop}; -static char calc_ptf_pidgeon1972_eawc_sand_types[] = {NPY_DOUBLE, NPY_DOUBLE}; - -static void calc_ptf_pidgeon1972_eawc_sand_organic_matter_loop(char **args, - const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double organic_matter = *(const double *)args[1]; - const double extended_available_water_capacity = - -10.8 + 1.15 * sand + 4.78 * organic_matter; - *(double *)args[2] = extended_available_water_capacity; - for (int arg = 0; arg < 3; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_pidgeon1972_eawc_sand_organic_matter_functions[] = { - calc_ptf_pidgeon1972_eawc_sand_organic_matter_loop}; -static char calc_ptf_pidgeon1972_eawc_sand_organic_matter_types[] = {NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE}; - -static void calc_ptf_pidgeon1972_eawc_coarse_sand_organic_matter_loop(char **args, - const npy_intp *dimensions, - const npy_intp *steps, - void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double coarse_sand = *(const double *)args[0]; - const double organic_matter = *(const double *)args[1]; - const double extended_available_water_capacity = - -7.4 + 2.37 * coarse_sand + 6.86 * organic_matter; - *(double *)args[2] = extended_available_water_capacity; - for (int arg = 0; arg < 3; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_pidgeon1972_eawc_coarse_sand_organic_matter_functions[] = { - calc_ptf_pidgeon1972_eawc_coarse_sand_organic_matter_loop}; -static char calc_ptf_pidgeon1972_eawc_coarse_sand_organic_matter_types[] = {NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE}; - -static void calc_ptf_pidgeon1972_eawc_fine_sand_organic_matter_loop(char **args, - const npy_intp *dimensions, - const npy_intp *steps, - void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double fine_sand = *(const double *)args[0]; - const double organic_matter = *(const double *)args[1]; - const double extended_available_water_capacity = - -18.0 + 3.11 * fine_sand + 7.69 * organic_matter; - *(double *)args[2] = extended_available_water_capacity; - for (int arg = 0; arg < 3; arg++) - args[arg] += steps[arg]; - } -} -static PyUFuncGenericFunction calc_ptf_pidgeon1972_eawc_fine_sand_organic_matter_functions[] = { - calc_ptf_pidgeon1972_eawc_fine_sand_organic_matter_loop}; -static char calc_ptf_pidgeon1972_eawc_fine_sand_organic_matter_types[] = {NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE}; + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_fine_sand = (const double *)data[0]; + double *out_available_water_capacity = (double *)data[1]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double fine_sand = in_fine_sand[index]; + const double ptfkit_result = calc_ptf_pidgeon1972_awc_fine_sand(fine_sand); + out_available_water_capacity[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_pidgeon1972_awc_fine_sand_strided_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double fine_sand = *(const double *)(data[0] + index * strides[0]); + const double ptfkit_result = calc_ptf_pidgeon1972_awc_fine_sand(fine_sand); + *(double *)(data[1] + index * strides[1]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_pidgeon1972_awc_fine_sand_slots[] = { + {NPY_METH_strided_loop, calc_ptf_pidgeon1972_awc_fine_sand_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_pidgeon1972_awc_fine_sand_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_pidgeon1972_awc_fine_sand_spec = { + .name = "calc_ptf_pidgeon1972_awc_fine_sand", + .nin = 1, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_pidgeon1972_awc_fine_sand_slots, +}; + +static int calc_ptf_pidgeon1972_awc_very_fine_sand_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_very_fine_sand = (const double *)data[0]; + double *out_available_water_capacity = (double *)data[1]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double very_fine_sand = in_very_fine_sand[index]; + const double ptfkit_result = calc_ptf_pidgeon1972_awc_very_fine_sand(very_fine_sand); + out_available_water_capacity[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_pidgeon1972_awc_very_fine_sand_strided_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double very_fine_sand = *(const double *)(data[0] + index * strides[0]); + const double ptfkit_result = calc_ptf_pidgeon1972_awc_very_fine_sand(very_fine_sand); + *(double *)(data[1] + index * strides[1]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_pidgeon1972_awc_very_fine_sand_slots[] = { + {NPY_METH_strided_loop, calc_ptf_pidgeon1972_awc_very_fine_sand_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_pidgeon1972_awc_very_fine_sand_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_pidgeon1972_awc_very_fine_sand_spec = { + .name = "calc_ptf_pidgeon1972_awc_very_fine_sand", + .nin = 1, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_pidgeon1972_awc_very_fine_sand_slots, +}; + +static int calc_ptf_pidgeon1972_eawc_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_silt = (const double *)data[0]; + const double *in_clay = (const double *)data[1]; + const double *in_organic_matter = (const double *)data[2]; + double *out_extended_available_water_capacity = (double *)data[3]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double silt = in_silt[index]; + const double clay = in_clay[index]; + const double organic_matter = in_organic_matter[index]; + const double ptfkit_result = calc_ptf_pidgeon1972_eawc(silt, clay, organic_matter); + out_extended_available_water_capacity[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_pidgeon1972_eawc_strided_loop(PyArrayMethod_Context *context, char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double silt = *(const double *)(data[0] + index * strides[0]); + const double clay = *(const double *)(data[1] + index * strides[1]); + const double organic_matter = *(const double *)(data[2] + index * strides[2]); + const double ptfkit_result = calc_ptf_pidgeon1972_eawc(silt, clay, organic_matter); + *(double *)(data[3] + index * strides[3]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_pidgeon1972_eawc_slots[] = { + {NPY_METH_strided_loop, calc_ptf_pidgeon1972_eawc_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_pidgeon1972_eawc_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_pidgeon1972_eawc_spec = { + .name = "calc_ptf_pidgeon1972_eawc", + .nin = 3, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_pidgeon1972_eawc_slots, +}; + +static int calc_ptf_pidgeon1972_eawc_sand_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + double *out_extended_available_water_capacity = (double *)data[1]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double ptfkit_result = calc_ptf_pidgeon1972_eawc_sand(sand); + out_extended_available_water_capacity[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_pidgeon1972_eawc_sand_strided_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double ptfkit_result = calc_ptf_pidgeon1972_eawc_sand(sand); + *(double *)(data[1] + index * strides[1]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_pidgeon1972_eawc_sand_slots[] = { + {NPY_METH_strided_loop, calc_ptf_pidgeon1972_eawc_sand_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_pidgeon1972_eawc_sand_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_pidgeon1972_eawc_sand_spec = { + .name = "calc_ptf_pidgeon1972_eawc_sand", + .nin = 1, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_pidgeon1972_eawc_sand_slots, +}; + +static int calc_ptf_pidgeon1972_eawc_sand_organic_matter_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_organic_matter = (const double *)data[1]; + double *out_extended_available_water_capacity = (double *)data[2]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double organic_matter = in_organic_matter[index]; + const double ptfkit_result = + calc_ptf_pidgeon1972_eawc_sand_organic_matter(sand, organic_matter); + out_extended_available_water_capacity[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_pidgeon1972_eawc_sand_organic_matter_strided_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double organic_matter = *(const double *)(data[1] + index * strides[1]); + const double ptfkit_result = + calc_ptf_pidgeon1972_eawc_sand_organic_matter(sand, organic_matter); + *(double *)(data[2] + index * strides[2]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_pidgeon1972_eawc_sand_organic_matter_slots[] = { + {NPY_METH_strided_loop, calc_ptf_pidgeon1972_eawc_sand_organic_matter_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_pidgeon1972_eawc_sand_organic_matter_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_pidgeon1972_eawc_sand_organic_matter_spec = { + .name = "calc_ptf_pidgeon1972_eawc_sand_organic_matter", + .nin = 2, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_pidgeon1972_eawc_sand_organic_matter_slots, +}; + +static int calc_ptf_pidgeon1972_eawc_coarse_sand_organic_matter_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_coarse_sand = (const double *)data[0]; + const double *in_organic_matter = (const double *)data[1]; + double *out_extended_available_water_capacity = (double *)data[2]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double coarse_sand = in_coarse_sand[index]; + const double organic_matter = in_organic_matter[index]; + const double ptfkit_result = + calc_ptf_pidgeon1972_eawc_coarse_sand_organic_matter(coarse_sand, organic_matter); + out_extended_available_water_capacity[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_pidgeon1972_eawc_coarse_sand_organic_matter_strided_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double coarse_sand = *(const double *)(data[0] + index * strides[0]); + const double organic_matter = *(const double *)(data[1] + index * strides[1]); + const double ptfkit_result = + calc_ptf_pidgeon1972_eawc_coarse_sand_organic_matter(coarse_sand, organic_matter); + *(double *)(data[2] + index * strides[2]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_pidgeon1972_eawc_coarse_sand_organic_matter_slots[] = { + {NPY_METH_strided_loop, calc_ptf_pidgeon1972_eawc_coarse_sand_organic_matter_strided_loop}, + {NPY_METH_contiguous_loop, + calc_ptf_pidgeon1972_eawc_coarse_sand_organic_matter_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_pidgeon1972_eawc_coarse_sand_organic_matter_spec = { + .name = "calc_ptf_pidgeon1972_eawc_coarse_sand_organic_matter", + .nin = 2, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_pidgeon1972_eawc_coarse_sand_organic_matter_slots, +}; + +static int calc_ptf_pidgeon1972_eawc_fine_sand_organic_matter_contiguous_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_fine_sand = (const double *)data[0]; + const double *in_organic_matter = (const double *)data[1]; + double *out_extended_available_water_capacity = (double *)data[2]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double fine_sand = in_fine_sand[index]; + const double organic_matter = in_organic_matter[index]; + const double ptfkit_result = + calc_ptf_pidgeon1972_eawc_fine_sand_organic_matter(fine_sand, organic_matter); + out_extended_available_water_capacity[index] = ptfkit_result; + } + return 0; +} + +static int calc_ptf_pidgeon1972_eawc_fine_sand_organic_matter_strided_loop( + PyArrayMethod_Context *context, char *const *data, const npy_intp *dimensions, + const npy_intp *strides, NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double fine_sand = *(const double *)(data[0] + index * strides[0]); + const double organic_matter = *(const double *)(data[1] + index * strides[1]); + const double ptfkit_result = + calc_ptf_pidgeon1972_eawc_fine_sand_organic_matter(fine_sand, organic_matter); + *(double *)(data[2] + index * strides[2]) = ptfkit_result; + } + return 0; +} +static PyType_Slot calc_ptf_pidgeon1972_eawc_fine_sand_organic_matter_slots[] = { + {NPY_METH_strided_loop, calc_ptf_pidgeon1972_eawc_fine_sand_organic_matter_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_pidgeon1972_eawc_fine_sand_organic_matter_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_pidgeon1972_eawc_fine_sand_organic_matter_spec = { + .name = "calc_ptf_pidgeon1972_eawc_fine_sand_organic_matter", + .nin = 2, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_pidgeon1972_eawc_fine_sand_organic_matter_slots, +}; int ptfkit_register_pidgeon1972(PyObject *module) { - if (ptfkit_add_ufunc(module, "calc_ptf_pidgeon1972_fc", calc_ptf_pidgeon1972_fc_functions, - calc_ptf_pidgeon1972_fc_types, 3, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_pidgeon1972_fc", 3, 1, &calc_ptf_pidgeon1972_fc_spec) < + 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_pidgeon1972_fc_sand", - calc_ptf_pidgeon1972_fc_sand_functions, calc_ptf_pidgeon1972_fc_sand_types, - 1, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_pidgeon1972_fc_sand", 1, 1, + &calc_ptf_pidgeon1972_fc_sand_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_pidgeon1972_fc_sand_organic_matter", - calc_ptf_pidgeon1972_fc_sand_organic_matter_functions, - calc_ptf_pidgeon1972_fc_sand_organic_matter_types, 2, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_pidgeon1972_fc_sand_organic_matter", 2, 1, + &calc_ptf_pidgeon1972_fc_sand_organic_matter_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_pidgeon1972_fc_vol_sand_organic_matter", - calc_ptf_pidgeon1972_fc_vol_sand_organic_matter_functions, - calc_ptf_pidgeon1972_fc_vol_sand_organic_matter_types, 2, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_pidgeon1972_fc_vol_sand_organic_matter", 2, 1, + &calc_ptf_pidgeon1972_fc_vol_sand_organic_matter_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_pidgeon1972_pwp", calc_ptf_pidgeon1972_pwp_functions, - calc_ptf_pidgeon1972_pwp_types, 3, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_pidgeon1972_pwp", 3, 1, &calc_ptf_pidgeon1972_pwp_spec) < + 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_pidgeon1972_pwp_sand", - calc_ptf_pidgeon1972_pwp_sand_functions, - calc_ptf_pidgeon1972_pwp_sand_types, 1, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_pidgeon1972_pwp_sand", 1, 1, + &calc_ptf_pidgeon1972_pwp_sand_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_pidgeon1972_pwp_sand_organic_matter", - calc_ptf_pidgeon1972_pwp_sand_organic_matter_functions, - calc_ptf_pidgeon1972_pwp_sand_organic_matter_types, 2, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_pidgeon1972_pwp_sand_organic_matter", 2, 1, + &calc_ptf_pidgeon1972_pwp_sand_organic_matter_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_pidgeon1972_awc", calc_ptf_pidgeon1972_awc_functions, - calc_ptf_pidgeon1972_awc_types, 2, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_pidgeon1972_awc", 2, 1, &calc_ptf_pidgeon1972_awc_spec) < + 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_pidgeon1972_awc_sand_organic_matter", - calc_ptf_pidgeon1972_awc_sand_organic_matter_functions, - calc_ptf_pidgeon1972_awc_sand_organic_matter_types, 2, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_pidgeon1972_awc_sand_organic_matter", 2, 1, + &calc_ptf_pidgeon1972_awc_sand_organic_matter_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_pidgeon1972_awc_coarse_sand", - calc_ptf_pidgeon1972_awc_coarse_sand_functions, - calc_ptf_pidgeon1972_awc_coarse_sand_types, 1, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_pidgeon1972_awc_coarse_sand", 1, 1, + &calc_ptf_pidgeon1972_awc_coarse_sand_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_pidgeon1972_awc_fine_sand", - calc_ptf_pidgeon1972_awc_fine_sand_functions, - calc_ptf_pidgeon1972_awc_fine_sand_types, 1, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_pidgeon1972_awc_fine_sand", 1, 1, + &calc_ptf_pidgeon1972_awc_fine_sand_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_pidgeon1972_awc_very_fine_sand", - calc_ptf_pidgeon1972_awc_very_fine_sand_functions, - calc_ptf_pidgeon1972_awc_very_fine_sand_types, 1, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_pidgeon1972_awc_very_fine_sand", 1, 1, + &calc_ptf_pidgeon1972_awc_very_fine_sand_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_pidgeon1972_eawc", calc_ptf_pidgeon1972_eawc_functions, - calc_ptf_pidgeon1972_eawc_types, 3, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_pidgeon1972_eawc", 3, 1, + &calc_ptf_pidgeon1972_eawc_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_pidgeon1972_eawc_sand", - calc_ptf_pidgeon1972_eawc_sand_functions, - calc_ptf_pidgeon1972_eawc_sand_types, 1, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_pidgeon1972_eawc_sand", 1, 1, + &calc_ptf_pidgeon1972_eawc_sand_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_pidgeon1972_eawc_sand_organic_matter", - calc_ptf_pidgeon1972_eawc_sand_organic_matter_functions, - calc_ptf_pidgeon1972_eawc_sand_organic_matter_types, 2, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_pidgeon1972_eawc_sand_organic_matter", 2, 1, + &calc_ptf_pidgeon1972_eawc_sand_organic_matter_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_pidgeon1972_eawc_coarse_sand_organic_matter", - calc_ptf_pidgeon1972_eawc_coarse_sand_organic_matter_functions, - calc_ptf_pidgeon1972_eawc_coarse_sand_organic_matter_types, 2, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_pidgeon1972_eawc_coarse_sand_organic_matter", 2, 1, + &calc_ptf_pidgeon1972_eawc_coarse_sand_organic_matter_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_pidgeon1972_eawc_fine_sand_organic_matter", - calc_ptf_pidgeon1972_eawc_fine_sand_organic_matter_functions, - calc_ptf_pidgeon1972_eawc_fine_sand_organic_matter_types, 2, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_pidgeon1972_eawc_fine_sand_organic_matter", 2, 1, + &calc_ptf_pidgeon1972_eawc_fine_sand_organic_matter_spec) < 0) return -1; return 0; } diff --git a/targets/ptfkit-py/src/ptfkit/pidgeon1972.py b/targets/ptfkit-py/src/ptfkit/pidgeon1972.py index 89d8933..4e235db 100644 --- a/targets/ptfkit-py/src/ptfkit/pidgeon1972.py +++ b/targets/ptfkit-py/src/ptfkit/pidgeon1972.py @@ -23,6 +23,7 @@ from typing import TYPE_CHECKING, overload +from ptfkit._dispatch import call as _call from ptfkit._ptfkit import ( calc_ptf_pidgeon1972_fc as _calc_ptf_pidgeon1972_fc, calc_ptf_pidgeon1972_fc_sand as _calc_ptf_pidgeon1972_fc_sand, @@ -109,12 +110,13 @@ def calc_ptf_pidgeon1972_fc( The reviewed organic-matter coefficient is 1.54. """ - if out is None: - values = _calc_ptf_pidgeon1972_fc(silt, clay, organic_matter) - else: - values = _calc_ptf_pidgeon1972_fc(silt, clay, organic_matter, out=out) - - return values + return _call( + _calc_ptf_pidgeon1972_fc, + silt, + clay, + organic_matter, + out=out, + ) @overload @@ -150,12 +152,11 @@ def calc_ptf_pidgeon1972_fc_sand( Prediction target: Gravimetric field capacity """ - if out is None: - values = _calc_ptf_pidgeon1972_fc_sand(sand) - else: - values = _calc_ptf_pidgeon1972_fc_sand(sand, out=out) - - return values + return _call( + _calc_ptf_pidgeon1972_fc_sand, + sand, + out=out, + ) @overload @@ -196,12 +197,12 @@ def calc_ptf_pidgeon1972_fc_sand_organic_matter( Prediction target: Gravimetric field capacity """ - if out is None: - values = _calc_ptf_pidgeon1972_fc_sand_organic_matter(sand, organic_matter) - else: - values = _calc_ptf_pidgeon1972_fc_sand_organic_matter(sand, organic_matter, out=out) - - return values + return _call( + _calc_ptf_pidgeon1972_fc_sand_organic_matter, + sand, + organic_matter, + out=out, + ) @overload @@ -242,12 +243,12 @@ def calc_ptf_pidgeon1972_fc_vol_sand_organic_matter( Prediction target: Volumetric field capacity """ - if out is None: - values = _calc_ptf_pidgeon1972_fc_vol_sand_organic_matter(sand, organic_matter) - else: - values = _calc_ptf_pidgeon1972_fc_vol_sand_organic_matter(sand, organic_matter, out=out) - - return values + return _call( + _calc_ptf_pidgeon1972_fc_vol_sand_organic_matter, + sand, + organic_matter, + out=out, + ) @overload @@ -289,12 +290,13 @@ def calc_ptf_pidgeon1972_pwp( Prediction target: Gravimetric permanent wilting point """ - if out is None: - values = _calc_ptf_pidgeon1972_pwp(silt, clay, organic_matter) - else: - values = _calc_ptf_pidgeon1972_pwp(silt, clay, organic_matter, out=out) - - return values + return _call( + _calc_ptf_pidgeon1972_pwp, + silt, + clay, + organic_matter, + out=out, + ) @overload @@ -330,12 +332,11 @@ def calc_ptf_pidgeon1972_pwp_sand( Prediction target: Gravimetric permanent wilting point """ - if out is None: - values = _calc_ptf_pidgeon1972_pwp_sand(sand) - else: - values = _calc_ptf_pidgeon1972_pwp_sand(sand, out=out) - - return values + return _call( + _calc_ptf_pidgeon1972_pwp_sand, + sand, + out=out, + ) @overload @@ -376,12 +377,12 @@ def calc_ptf_pidgeon1972_pwp_sand_organic_matter( Prediction target: Gravimetric permanent wilting point """ - if out is None: - values = _calc_ptf_pidgeon1972_pwp_sand_organic_matter(sand, organic_matter) - else: - values = _calc_ptf_pidgeon1972_pwp_sand_organic_matter(sand, organic_matter, out=out) - - return values + return _call( + _calc_ptf_pidgeon1972_pwp_sand_organic_matter, + sand, + organic_matter, + out=out, + ) @overload @@ -420,12 +421,12 @@ def calc_ptf_pidgeon1972_awc( Prediction target: Available water capacity """ - if out is None: - values = _calc_ptf_pidgeon1972_awc(clay, organic_matter) - else: - values = _calc_ptf_pidgeon1972_awc(clay, organic_matter, out=out) - - return values + return _call( + _calc_ptf_pidgeon1972_awc, + clay, + organic_matter, + out=out, + ) @overload @@ -466,12 +467,12 @@ def calc_ptf_pidgeon1972_awc_sand_organic_matter( Prediction target: Available water capacity """ - if out is None: - values = _calc_ptf_pidgeon1972_awc_sand_organic_matter(sand, organic_matter) - else: - values = _calc_ptf_pidgeon1972_awc_sand_organic_matter(sand, organic_matter, out=out) - - return values + return _call( + _calc_ptf_pidgeon1972_awc_sand_organic_matter, + sand, + organic_matter, + out=out, + ) @overload @@ -507,12 +508,11 @@ def calc_ptf_pidgeon1972_awc_coarse_sand( Prediction target: Available water capacity """ - if out is None: - values = _calc_ptf_pidgeon1972_awc_coarse_sand(coarse_sand) - else: - values = _calc_ptf_pidgeon1972_awc_coarse_sand(coarse_sand, out=out) - - return values + return _call( + _calc_ptf_pidgeon1972_awc_coarse_sand, + coarse_sand, + out=out, + ) @overload @@ -548,12 +548,11 @@ def calc_ptf_pidgeon1972_awc_fine_sand( Prediction target: Available water capacity """ - if out is None: - values = _calc_ptf_pidgeon1972_awc_fine_sand(fine_sand) - else: - values = _calc_ptf_pidgeon1972_awc_fine_sand(fine_sand, out=out) - - return values + return _call( + _calc_ptf_pidgeon1972_awc_fine_sand, + fine_sand, + out=out, + ) @overload @@ -589,12 +588,11 @@ def calc_ptf_pidgeon1972_awc_very_fine_sand( Prediction target: Available water capacity """ - if out is None: - values = _calc_ptf_pidgeon1972_awc_very_fine_sand(very_fine_sand) - else: - values = _calc_ptf_pidgeon1972_awc_very_fine_sand(very_fine_sand, out=out) - - return values + return _call( + _calc_ptf_pidgeon1972_awc_very_fine_sand, + very_fine_sand, + out=out, + ) @overload @@ -636,12 +634,13 @@ def calc_ptf_pidgeon1972_eawc( Prediction target: Extended available water capacity """ - if out is None: - values = _calc_ptf_pidgeon1972_eawc(silt, clay, organic_matter) - else: - values = _calc_ptf_pidgeon1972_eawc(silt, clay, organic_matter, out=out) - - return values + return _call( + _calc_ptf_pidgeon1972_eawc, + silt, + clay, + organic_matter, + out=out, + ) @overload @@ -677,12 +676,11 @@ def calc_ptf_pidgeon1972_eawc_sand( Prediction target: Extended available water capacity """ - if out is None: - values = _calc_ptf_pidgeon1972_eawc_sand(sand) - else: - values = _calc_ptf_pidgeon1972_eawc_sand(sand, out=out) - - return values + return _call( + _calc_ptf_pidgeon1972_eawc_sand, + sand, + out=out, + ) @overload @@ -723,12 +721,12 @@ def calc_ptf_pidgeon1972_eawc_sand_organic_matter( Prediction target: Extended available water capacity """ - if out is None: - values = _calc_ptf_pidgeon1972_eawc_sand_organic_matter(sand, organic_matter) - else: - values = _calc_ptf_pidgeon1972_eawc_sand_organic_matter(sand, organic_matter, out=out) - - return values + return _call( + _calc_ptf_pidgeon1972_eawc_sand_organic_matter, + sand, + organic_matter, + out=out, + ) @overload @@ -769,14 +767,12 @@ def calc_ptf_pidgeon1972_eawc_coarse_sand_organic_matter( Prediction target: Extended available water capacity """ - if out is None: - values = _calc_ptf_pidgeon1972_eawc_coarse_sand_organic_matter(coarse_sand, organic_matter) - else: - values = _calc_ptf_pidgeon1972_eawc_coarse_sand_organic_matter( - coarse_sand, organic_matter, out=out - ) - - return values + return _call( + _calc_ptf_pidgeon1972_eawc_coarse_sand_organic_matter, + coarse_sand, + organic_matter, + out=out, + ) @overload @@ -817,11 +813,9 @@ def calc_ptf_pidgeon1972_eawc_fine_sand_organic_matter( Prediction target: Extended available water capacity """ - if out is None: - values = _calc_ptf_pidgeon1972_eawc_fine_sand_organic_matter(fine_sand, organic_matter) - else: - values = _calc_ptf_pidgeon1972_eawc_fine_sand_organic_matter( - fine_sand, organic_matter, out=out - ) - - return values + return _call( + _calc_ptf_pidgeon1972_eawc_fine_sand_organic_matter, + fine_sand, + organic_matter, + out=out, + ) diff --git a/targets/ptfkit-py/src/ptfkit/ptfkit.c b/targets/ptfkit-py/src/ptfkit/ptfkit.c index 69a0f94..e687583 100644 --- a/targets/ptfkit-py/src/ptfkit/ptfkit.c +++ b/targets/ptfkit-py/src/ptfkit/ptfkit.c @@ -1,6 +1,7 @@ /* @generated by ptfkit-codegen; DO NOT EDIT. */ #define PY_SSIZE_T_CLEAN #define PY_ARRAY_UNIQUE_SYMBOL PTFKIT_ARRAY_API +#define NPY_TARGET_VERSION NPY_2_0_API_VERSION #include #include #include diff --git a/targets/ptfkit-py/src/ptfkit/puckett1985.c b/targets/ptfkit-py/src/ptfkit/puckett1985.c index 9b7698b..91b42b7 100644 --- a/targets/ptfkit-py/src/ptfkit/puckett1985.c +++ b/targets/ptfkit-py/src/ptfkit/puckett1985.c @@ -1,49 +1,94 @@ /* @generated by ptfkit-codegen; DO NOT EDIT. */ +#include #include "ufunc.h" -static void calc_ptf_puckett1985_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double fine_sand = *(const double *)args[1]; - const double clay = *(const double *)args[2]; - const double bulk_density = *(const double *)args[3]; - const double porosity = *(const double *)args[4]; - const double theta_0 = 0.264 * bulk_density + 1.60 * porosity - 0.706; - const double theta_1 = 318.0 / 1000.0 * bulk_density + 1.69 * porosity - 0.834; - const double theta_5 = 0.0001930 * fine_sand - 0.000357 * sand + 0.000182 * clay + 0.410; - const double theta_10 = 0.0000712 * fine_sand - 0.000383 * sand + 0.000243 * clay + 0.415; - const double theta_30 = 0.0000059 * fine_sand - 0.000348 * sand + 0.000321 * clay + 0.365; - const double theta_60 = 0.0000003 * fine_sand - 0.000319 * sand + 0.000351 * clay + 0.330; - const double theta_100 = 0.0000019 * fine_sand - 0.000302 * sand + 0.000362 * clay + 0.310; - const double theta_500 = 0.0000140 * fine_sand - 0.000262 * sand + 0.000375 * clay + 0.265; - const double theta_1000 = 0.0000197 * fine_sand - 0.000244 * sand + 0.000378 * clay + 0.264; - const double theta_1500 = 0.0000254 * fine_sand - 0.000239 * sand + 0.000380 * clay + 0.239; - const double k_sat = 4.36e-5 * exp(-0.1975 * clay); - *(double *)args[5] = theta_0; - *(double *)args[6] = theta_1; - *(double *)args[7] = theta_5; - *(double *)args[8] = theta_10; - *(double *)args[9] = theta_30; - *(double *)args[10] = theta_60; - *(double *)args[11] = theta_100; - *(double *)args[12] = theta_500; - *(double *)args[13] = theta_1000; - *(double *)args[14] = theta_1500; - *(double *)args[15] = k_sat; - for (int arg = 0; arg < 16; arg++) - args[arg] += steps[arg]; +static int calc_ptf_puckett1985_contiguous_loop(PyArrayMethod_Context *context, char *const *data, + const npy_intp *dimensions, const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_fine_sand = (const double *)data[1]; + const double *in_clay = (const double *)data[2]; + const double *in_bulk_density = (const double *)data[3]; + const double *in_porosity = (const double *)data[4]; + double *out_theta_0 = (double *)data[5]; + double *out_theta_1 = (double *)data[6]; + double *out_theta_5 = (double *)data[7]; + double *out_theta_10 = (double *)data[8]; + double *out_theta_30 = (double *)data[9]; + double *out_theta_60 = (double *)data[10]; + double *out_theta_100 = (double *)data[11]; + double *out_theta_500 = (double *)data[12]; + double *out_theta_1000 = (double *)data[13]; + double *out_theta_1500 = (double *)data[14]; + double *out_k_sat = (double *)data[15]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double fine_sand = in_fine_sand[index]; + const double clay = in_clay[index]; + const double bulk_density = in_bulk_density[index]; + const double porosity = in_porosity[index]; + const puckett1985_ptf_result ptfkit_result = + calc_ptf_puckett1985(sand, fine_sand, clay, bulk_density, porosity); + out_theta_0[index] = ptfkit_result.theta_0; + out_theta_1[index] = ptfkit_result.theta_1; + out_theta_5[index] = ptfkit_result.theta_5; + out_theta_10[index] = ptfkit_result.theta_10; + out_theta_30[index] = ptfkit_result.theta_30; + out_theta_60[index] = ptfkit_result.theta_60; + out_theta_100[index] = ptfkit_result.theta_100; + out_theta_500[index] = ptfkit_result.theta_500; + out_theta_1000[index] = ptfkit_result.theta_1000; + out_theta_1500[index] = ptfkit_result.theta_1500; + out_k_sat[index] = ptfkit_result.k_sat; } + return 0; +} + +static int calc_ptf_puckett1985_strided_loop(PyArrayMethod_Context *context, char *const *data, + const npy_intp *dimensions, const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double fine_sand = *(const double *)(data[1] + index * strides[1]); + const double clay = *(const double *)(data[2] + index * strides[2]); + const double bulk_density = *(const double *)(data[3] + index * strides[3]); + const double porosity = *(const double *)(data[4] + index * strides[4]); + const puckett1985_ptf_result ptfkit_result = + calc_ptf_puckett1985(sand, fine_sand, clay, bulk_density, porosity); + *(double *)(data[5] + index * strides[5]) = ptfkit_result.theta_0; + *(double *)(data[6] + index * strides[6]) = ptfkit_result.theta_1; + *(double *)(data[7] + index * strides[7]) = ptfkit_result.theta_5; + *(double *)(data[8] + index * strides[8]) = ptfkit_result.theta_10; + *(double *)(data[9] + index * strides[9]) = ptfkit_result.theta_30; + *(double *)(data[10] + index * strides[10]) = ptfkit_result.theta_60; + *(double *)(data[11] + index * strides[11]) = ptfkit_result.theta_100; + *(double *)(data[12] + index * strides[12]) = ptfkit_result.theta_500; + *(double *)(data[13] + index * strides[13]) = ptfkit_result.theta_1000; + *(double *)(data[14] + index * strides[14]) = ptfkit_result.theta_1500; + *(double *)(data[15] + index * strides[15]) = ptfkit_result.k_sat; + } + return 0; } -static PyUFuncGenericFunction calc_ptf_puckett1985_functions[] = {calc_ptf_puckett1985_loop}; -static char calc_ptf_puckett1985_types[] = { - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; +static PyType_Slot calc_ptf_puckett1985_slots[] = { + {NPY_METH_strided_loop, calc_ptf_puckett1985_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_puckett1985_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_puckett1985_spec = { + .name = "calc_ptf_puckett1985", + .nin = 5, + .nout = 11, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_puckett1985_slots, +}; int ptfkit_register_puckett1985(PyObject *module) { - if (ptfkit_add_ufunc(module, "calc_ptf_puckett1985", calc_ptf_puckett1985_functions, - calc_ptf_puckett1985_types, 5, 11) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_puckett1985", 5, 11, &calc_ptf_puckett1985_spec) < 0) return -1; return 0; } diff --git a/targets/ptfkit-py/src/ptfkit/puckett1985.py b/targets/ptfkit-py/src/ptfkit/puckett1985.py index 6acaddf..dbd64ec 100644 --- a/targets/ptfkit-py/src/ptfkit/puckett1985.py +++ b/targets/ptfkit-py/src/ptfkit/puckett1985.py @@ -21,6 +21,7 @@ from typing import TYPE_CHECKING, Generic, NamedTuple, TypeVar, overload +from ptfkit._dispatch import call as _call from ptfkit._ptfkit import ( calc_ptf_puckett1985 as _calc_ptf_puckett1985, ) @@ -120,11 +121,14 @@ def calc_ptf_puckett1985( Use outside Lower Coastal Plain Ultisols requires independent validation. """ - if out is None: - values = _calc_ptf_puckett1985(sand, fine_sand, clay, bulk_density, porosity) - else: - values = _calc_ptf_puckett1985( - sand, fine_sand, clay, bulk_density, porosity, out=tuple(out) - ) + values = _call( + _calc_ptf_puckett1985, + sand, + fine_sand, + clay, + bulk_density, + porosity, + out=out, + ) return Puckett1985PTFResult(*values) diff --git a/targets/ptfkit-py/src/ptfkit/rawls1982.c b/targets/ptfkit-py/src/ptfkit/rawls1982.c index c4e932e..7553ad1 100644 --- a/targets/ptfkit-py/src/ptfkit/rawls1982.c +++ b/targets/ptfkit-py/src/ptfkit/rawls1982.c @@ -1,103 +1,204 @@ /* @generated by ptfkit-codegen; DO NOT EDIT. */ +#include #include "ufunc.h" -static void calc_ptf_rawls1982_theta_1500_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double clay = *(const double *)args[0]; - const double organic_matter = *(const double *)args[1]; - const double theta_1500 = 0.0260 + 0.0050 * clay + 0.0158 * organic_matter; - *(double *)args[2] = theta_1500; - for (int arg = 0; arg < 3; arg++) - args[arg] += steps[arg]; +static int calc_ptf_rawls1982_theta_1500_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_clay = (const double *)data[0]; + const double *in_organic_matter = (const double *)data[1]; + double *out_theta_1500 = (double *)data[2]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = in_clay[index]; + const double organic_matter = in_organic_matter[index]; + const double ptfkit_result = calc_ptf_rawls1982_theta_1500(clay, organic_matter); + out_theta_1500[index] = ptfkit_result; } + return 0; +} + +static int calc_ptf_rawls1982_theta_1500_strided_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = *(const double *)(data[0] + index * strides[0]); + const double organic_matter = *(const double *)(data[1] + index * strides[1]); + const double ptfkit_result = calc_ptf_rawls1982_theta_1500(clay, organic_matter); + *(double *)(data[2] + index * strides[2]) = ptfkit_result; + } + return 0; } -static PyUFuncGenericFunction calc_ptf_rawls1982_theta_1500_functions[] = { - calc_ptf_rawls1982_theta_1500_loop}; -static char calc_ptf_rawls1982_theta_1500_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; +static PyType_Slot calc_ptf_rawls1982_theta_1500_slots[] = { + {NPY_METH_strided_loop, calc_ptf_rawls1982_theta_1500_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_rawls1982_theta_1500_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_rawls1982_theta_1500_spec = { + .name = "calc_ptf_rawls1982_theta_1500", + .nin = 2, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_rawls1982_theta_1500_slots, +}; -static void calc_ptf_rawls1982_theta_33_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double organic_matter = *(const double *)args[1]; - const double theta_1500 = *(const double *)args[2]; - const double theta_33 = - 0.2391 - 0.0019 * sand + 0.0210 * organic_matter + 0.72 * theta_1500; - *(double *)args[3] = theta_33; - for (int arg = 0; arg < 4; arg++) - args[arg] += steps[arg]; +static int calc_ptf_rawls1982_theta_33_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_organic_matter = (const double *)data[1]; + const double *in_theta_1500 = (const double *)data[2]; + double *out_theta_33 = (double *)data[3]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double organic_matter = in_organic_matter[index]; + const double theta_1500 = in_theta_1500[index]; + const double ptfkit_result = calc_ptf_rawls1982_theta_33(sand, organic_matter, theta_1500); + out_theta_33[index] = ptfkit_result; } + return 0; } -static PyUFuncGenericFunction calc_ptf_rawls1982_theta_33_functions[] = { - calc_ptf_rawls1982_theta_33_loop}; -static char calc_ptf_rawls1982_theta_33_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; -static void calc_ptf_rawls1982_full_wrc_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double organic_matter = *(const double *)args[1]; - const double bulk_density = *(const double *)args[2]; - const double theta_33 = *(const double *)args[3]; - const double theta_1500 = *(const double *)args[4]; - const double theta_4 = 0.1829 - 0.0246 * organic_matter - 0.0376 * bulk_density + - 1.89 * theta_33 - 1.38 * theta_1500; - const double theta_7 = - 0.8888 - 0.0003 * sand - 0.0107 * organic_matter + 1.53 * theta_33 - 0.81 * theta_1500; - const double theta_10 = - 0.0619 - 0.0002 * sand - 0.0067 * organic_matter + 1.34 * theta_33 - 0.51 * theta_1500; - const double theta_20 = 0.0319 - 0.0002 * sand + 1.01 * theta_33 - 0.06 * theta_1500; - const double theta_60 = - 0.0136 - 0.0091 * bulk_density + 0.66 * theta_33 + 0.39 * theta_1500; - const double theta_100 = - -0.0034 + 0.0022 * organic_matter + 0.52 * theta_33 + 0.54 * theta_1500; - const double theta_200 = - -0.0043 + 0.0026 * organic_matter + 0.36 * theta_33 + 0.69 * theta_1500; - const double theta_400 = - -0.0038 + 0.0026 * organic_matter + 0.24 * theta_33 + 0.79 * theta_1500; - const double theta_700 = - -0.0027 + 0.0024 * organic_matter + 0.16 * theta_33 + 0.86 * theta_1500; - const double theta_1000 = - -0.0019 + 0.0022 * organic_matter + 0.11 * theta_33 + 0.89 * theta_1500; - *(double *)args[5] = theta_4; - *(double *)args[6] = theta_7; - *(double *)args[7] = theta_10; - *(double *)args[8] = theta_20; - *(double *)args[9] = theta_33; - *(double *)args[10] = theta_60; - *(double *)args[11] = theta_100; - *(double *)args[12] = theta_200; - *(double *)args[13] = theta_400; - *(double *)args[14] = theta_700; - *(double *)args[15] = theta_1000; - *(double *)args[16] = theta_1500; - for (int arg = 0; arg < 17; arg++) - args[arg] += steps[arg]; +static int calc_ptf_rawls1982_theta_33_strided_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double organic_matter = *(const double *)(data[1] + index * strides[1]); + const double theta_1500 = *(const double *)(data[2] + index * strides[2]); + const double ptfkit_result = calc_ptf_rawls1982_theta_33(sand, organic_matter, theta_1500); + *(double *)(data[3] + index * strides[3]) = ptfkit_result; } + return 0; +} +static PyType_Slot calc_ptf_rawls1982_theta_33_slots[] = { + {NPY_METH_strided_loop, calc_ptf_rawls1982_theta_33_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_rawls1982_theta_33_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_rawls1982_theta_33_spec = { + .name = "calc_ptf_rawls1982_theta_33", + .nin = 3, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_rawls1982_theta_33_slots, +}; + +static int calc_ptf_rawls1982_full_wrc_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_organic_matter = (const double *)data[1]; + const double *in_bulk_density = (const double *)data[2]; + const double *in_theta_33 = (const double *)data[3]; + const double *in_theta_1500 = (const double *)data[4]; + double *out_theta_4 = (double *)data[5]; + double *out_theta_7 = (double *)data[6]; + double *out_theta_10 = (double *)data[7]; + double *out_theta_20 = (double *)data[8]; + double *out_theta_33 = (double *)data[9]; + double *out_theta_60 = (double *)data[10]; + double *out_theta_100 = (double *)data[11]; + double *out_theta_200 = (double *)data[12]; + double *out_theta_400 = (double *)data[13]; + double *out_theta_700 = (double *)data[14]; + double *out_theta_1000 = (double *)data[15]; + double *out_theta_1500 = (double *)data[16]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double organic_matter = in_organic_matter[index]; + const double bulk_density = in_bulk_density[index]; + const double theta_33 = in_theta_33[index]; + const double theta_1500 = in_theta_1500[index]; + const rawls1982_ptf_result ptfkit_result = + calc_ptf_rawls1982_full_wrc(sand, organic_matter, bulk_density, theta_33, theta_1500); + out_theta_4[index] = ptfkit_result.theta_4; + out_theta_7[index] = ptfkit_result.theta_7; + out_theta_10[index] = ptfkit_result.theta_10; + out_theta_20[index] = ptfkit_result.theta_20; + out_theta_33[index] = ptfkit_result.theta_33; + out_theta_60[index] = ptfkit_result.theta_60; + out_theta_100[index] = ptfkit_result.theta_100; + out_theta_200[index] = ptfkit_result.theta_200; + out_theta_400[index] = ptfkit_result.theta_400; + out_theta_700[index] = ptfkit_result.theta_700; + out_theta_1000[index] = ptfkit_result.theta_1000; + out_theta_1500[index] = ptfkit_result.theta_1500; + } + return 0; +} + +static int calc_ptf_rawls1982_full_wrc_strided_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double organic_matter = *(const double *)(data[1] + index * strides[1]); + const double bulk_density = *(const double *)(data[2] + index * strides[2]); + const double theta_33 = *(const double *)(data[3] + index * strides[3]); + const double theta_1500 = *(const double *)(data[4] + index * strides[4]); + const rawls1982_ptf_result ptfkit_result = + calc_ptf_rawls1982_full_wrc(sand, organic_matter, bulk_density, theta_33, theta_1500); + *(double *)(data[5] + index * strides[5]) = ptfkit_result.theta_4; + *(double *)(data[6] + index * strides[6]) = ptfkit_result.theta_7; + *(double *)(data[7] + index * strides[7]) = ptfkit_result.theta_10; + *(double *)(data[8] + index * strides[8]) = ptfkit_result.theta_20; + *(double *)(data[9] + index * strides[9]) = ptfkit_result.theta_33; + *(double *)(data[10] + index * strides[10]) = ptfkit_result.theta_60; + *(double *)(data[11] + index * strides[11]) = ptfkit_result.theta_100; + *(double *)(data[12] + index * strides[12]) = ptfkit_result.theta_200; + *(double *)(data[13] + index * strides[13]) = ptfkit_result.theta_400; + *(double *)(data[14] + index * strides[14]) = ptfkit_result.theta_700; + *(double *)(data[15] + index * strides[15]) = ptfkit_result.theta_1000; + *(double *)(data[16] + index * strides[16]) = ptfkit_result.theta_1500; + } + return 0; } -static PyUFuncGenericFunction calc_ptf_rawls1982_full_wrc_functions[] = { - calc_ptf_rawls1982_full_wrc_loop}; -static char calc_ptf_rawls1982_full_wrc_types[] = { - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; +static PyType_Slot calc_ptf_rawls1982_full_wrc_slots[] = { + {NPY_METH_strided_loop, calc_ptf_rawls1982_full_wrc_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_rawls1982_full_wrc_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_rawls1982_full_wrc_spec = { + .name = "calc_ptf_rawls1982_full_wrc", + .nin = 5, + .nout = 12, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_rawls1982_full_wrc_slots, +}; int ptfkit_register_rawls1982(PyObject *module) { - if (ptfkit_add_ufunc(module, "calc_ptf_rawls1982_theta_1500", - calc_ptf_rawls1982_theta_1500_functions, - calc_ptf_rawls1982_theta_1500_types, 2, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_rawls1982_theta_1500", 2, 1, + &calc_ptf_rawls1982_theta_1500_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_rawls1982_theta_33", - calc_ptf_rawls1982_theta_33_functions, calc_ptf_rawls1982_theta_33_types, - 3, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_rawls1982_theta_33", 3, 1, + &calc_ptf_rawls1982_theta_33_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_rawls1982_full_wrc", - calc_ptf_rawls1982_full_wrc_functions, calc_ptf_rawls1982_full_wrc_types, - 5, 12) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_rawls1982_full_wrc", 5, 12, + &calc_ptf_rawls1982_full_wrc_spec) < 0) return -1; return 0; } diff --git a/targets/ptfkit-py/src/ptfkit/rawls1982.py b/targets/ptfkit-py/src/ptfkit/rawls1982.py index 9d616f3..9f7fcf1 100644 --- a/targets/ptfkit-py/src/ptfkit/rawls1982.py +++ b/targets/ptfkit-py/src/ptfkit/rawls1982.py @@ -22,6 +22,7 @@ from typing import TYPE_CHECKING, Generic, NamedTuple, TypeVar, overload +from ptfkit._dispatch import call as _call from ptfkit._ptfkit import ( calc_ptf_rawls1982_theta_1500 as _calc_ptf_rawls1982_theta_1500, calc_ptf_rawls1982_theta_33 as _calc_ptf_rawls1982_theta_33, @@ -113,12 +114,12 @@ def calc_theta_1500_rawls1982( Prediction target: Volumetric soil water content at -1500 kPa. """ - if out is None: - values = _calc_ptf_rawls1982_theta_1500(clay, organic_matter) - else: - values = _calc_ptf_rawls1982_theta_1500(clay, organic_matter, out=out) - - return values + return _call( + _calc_ptf_rawls1982_theta_1500, + clay, + organic_matter, + out=out, + ) @overload @@ -162,12 +163,13 @@ def calc_theta_33_rawls1982( Prediction target: Volumetric soil water content at -33 kPa. """ - if out is None: - values = _calc_ptf_rawls1982_theta_33(sand, organic_matter, theta_1500) - else: - values = _calc_ptf_rawls1982_theta_33(sand, organic_matter, theta_1500, out=out) - - return values + return _call( + _calc_ptf_rawls1982_theta_33, + sand, + organic_matter, + theta_1500, + out=out, + ) @overload @@ -222,13 +224,14 @@ def calc_full_wrc_rawls1982( The source value 0.8888 is retained literally for the theta_7 intercept. """ - if out is None: - values = _calc_ptf_rawls1982_full_wrc( - sand, organic_matter, bulk_density, theta_33, theta_1500 - ) - else: - values = _calc_ptf_rawls1982_full_wrc( - sand, organic_matter, bulk_density, theta_33, theta_1500, out=tuple(out) - ) + values = _call( + _calc_ptf_rawls1982_full_wrc, + sand, + organic_matter, + bulk_density, + theta_33, + theta_1500, + out=out, + ) return Rawls1982PTFResult(*values) diff --git a/targets/ptfkit-py/src/ptfkit/saxton2006.c b/targets/ptfkit-py/src/ptfkit/saxton2006.c index 3d10fa0..52a9415 100644 --- a/targets/ptfkit-py/src/ptfkit/saxton2006.c +++ b/targets/ptfkit-py/src/ptfkit/saxton2006.c @@ -1,230 +1,446 @@ /* @generated by ptfkit-codegen; DO NOT EDIT. */ +#include #include "ufunc.h" -static void calc_ptf_saxton2006_loop(char **args, const npy_intp *dimensions, const npy_intp *steps, - void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double clay = *(const double *)args[1]; - const double organic_matter = *(const double *)args[2]; - const double clay_organic_matter_term = 0.027 * clay * organic_matter; - const double theta_1500_preliminary = - -0.024 * sand + 0.487 * clay + 0.006 * organic_matter + 0.005 * sand * organic_matter - - 0.013 * clay * organic_matter + 0.068 * sand * clay + 0.031; - const double theta_1500 = theta_1500_preliminary + 0.14 * theta_1500_preliminary - 0.02; - const double theta_33_preliminary = -0.251 * sand + 0.195 * clay + 0.011 * organic_matter + - 0.006 * sand * organic_matter - - clay_organic_matter_term + 0.452 * sand * clay + 0.299; - const double theta_33 = theta_33_preliminary + - 1.283 * (theta_33_preliminary * theta_33_preliminary) - - 0.374 * theta_33_preliminary - 0.015; - const double theta_s_minus_33_preliminary = - 0.278 * sand + 0.034 * clay + 0.022 * organic_matter - 0.018 * sand * organic_matter - - clay_organic_matter_term - 0.584 * sand * clay + 0.078; - const double theta_s_minus_33 = - theta_s_minus_33_preliminary + 0.636 * theta_s_minus_33_preliminary - 0.107; - const double theta_s = theta_33 + theta_s_minus_33 - 0.097 * sand + 0.043; - const double plant_available_water = theta_33 - theta_1500; - const double air_entry_preliminary = - -21.67 * sand - 27.93 * clay - 81.97 * theta_s_minus_33_preliminary + - 71.12 * sand * theta_s_minus_33_preliminary + - 8.29 * clay * theta_s_minus_33_preliminary + 14.05 * sand * clay + 27.16; - const double air_entry_tension = air_entry_preliminary + - 0.02 * (air_entry_preliminary * air_entry_preliminary) - - 0.113 * air_entry_preliminary - 0.70; - const double ln_33 = log(33.0); - const double ln_theta_33 = log(theta_33); - const double retention_b = (log(1500.0) - ln_33) / (ln_theta_33 - log(theta_1500)); - const double retention_a = exp(ln_33 + retention_b * ln_theta_33); - const double conductivity_lambda = 1.0 / retention_b; - const double saturated_conductivity = - 1930.0 * pow(theta_s - theta_33, 3.0 - conductivity_lambda); - const double normal_density = (1.0 - theta_s) * 2.65; - *(double *)args[3] = theta_1500; - *(double *)args[4] = theta_33; - *(double *)args[5] = theta_s; - *(double *)args[6] = plant_available_water; - *(double *)args[7] = air_entry_tension; - *(double *)args[8] = retention_a; - *(double *)args[9] = retention_b; - *(double *)args[10] = conductivity_lambda; - *(double *)args[11] = saturated_conductivity; - *(double *)args[12] = normal_density; - for (int arg = 0; arg < 13; arg++) - args[arg] += steps[arg]; +static int calc_ptf_saxton2006_contiguous_loop(PyArrayMethod_Context *context, char *const *data, + const npy_intp *dimensions, const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_clay = (const double *)data[1]; + const double *in_organic_matter = (const double *)data[2]; + double *out_theta_1500 = (double *)data[3]; + double *out_theta_33 = (double *)data[4]; + double *out_theta_s = (double *)data[5]; + double *out_plant_available_water = (double *)data[6]; + double *out_air_entry_tension = (double *)data[7]; + double *out_retention_a = (double *)data[8]; + double *out_retention_b = (double *)data[9]; + double *out_conductivity_lambda = (double *)data[10]; + double *out_saturated_conductivity = (double *)data[11]; + double *out_normal_density = (double *)data[12]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double clay = in_clay[index]; + const double organic_matter = in_organic_matter[index]; + const saxton2006_ptf_result ptfkit_result = calc_ptf_saxton2006(sand, clay, organic_matter); + out_theta_1500[index] = ptfkit_result.theta_1500; + out_theta_33[index] = ptfkit_result.theta_33; + out_theta_s[index] = ptfkit_result.theta_s; + out_plant_available_water[index] = ptfkit_result.plant_available_water; + out_air_entry_tension[index] = ptfkit_result.air_entry_tension; + out_retention_a[index] = ptfkit_result.retention_a; + out_retention_b[index] = ptfkit_result.retention_b; + out_conductivity_lambda[index] = ptfkit_result.conductivity_lambda; + out_saturated_conductivity[index] = ptfkit_result.saturated_conductivity; + out_normal_density[index] = ptfkit_result.normal_density; } + return 0; +} + +static int calc_ptf_saxton2006_strided_loop(PyArrayMethod_Context *context, char *const *data, + const npy_intp *dimensions, const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double clay = *(const double *)(data[1] + index * strides[1]); + const double organic_matter = *(const double *)(data[2] + index * strides[2]); + const saxton2006_ptf_result ptfkit_result = calc_ptf_saxton2006(sand, clay, organic_matter); + *(double *)(data[3] + index * strides[3]) = ptfkit_result.theta_1500; + *(double *)(data[4] + index * strides[4]) = ptfkit_result.theta_33; + *(double *)(data[5] + index * strides[5]) = ptfkit_result.theta_s; + *(double *)(data[6] + index * strides[6]) = ptfkit_result.plant_available_water; + *(double *)(data[7] + index * strides[7]) = ptfkit_result.air_entry_tension; + *(double *)(data[8] + index * strides[8]) = ptfkit_result.retention_a; + *(double *)(data[9] + index * strides[9]) = ptfkit_result.retention_b; + *(double *)(data[10] + index * strides[10]) = ptfkit_result.conductivity_lambda; + *(double *)(data[11] + index * strides[11]) = ptfkit_result.saturated_conductivity; + *(double *)(data[12] + index * strides[12]) = ptfkit_result.normal_density; + } + return 0; +} +static PyType_Slot calc_ptf_saxton2006_slots[] = { + {NPY_METH_strided_loop, calc_ptf_saxton2006_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_saxton2006_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_saxton2006_spec = { + .name = "calc_ptf_saxton2006", + .nin = 3, + .nout = 10, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_saxton2006_slots, +}; + +static int calc_ptf_saxton2006_density_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_normal_density = (const double *)data[0]; + const double *in_theta_s = (const double *)data[1]; + const double *in_theta_33 = (const double *)data[2]; + const double *in_density_factor = (const double *)data[3]; + double *out_adjusted_density = (double *)data[4]; + double *out_adjusted_theta_s = (double *)data[5]; + double *out_adjusted_theta_33 = (double *)data[6]; + double *out_adjusted_theta_s_minus_33 = (double *)data[7]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double normal_density = in_normal_density[index]; + const double theta_s = in_theta_s[index]; + const double theta_33 = in_theta_33[index]; + const double density_factor = in_density_factor[index]; + const saxton2006_density_result ptfkit_result = + calc_ptf_saxton2006_density(normal_density, theta_s, theta_33, density_factor); + out_adjusted_density[index] = ptfkit_result.adjusted_density; + out_adjusted_theta_s[index] = ptfkit_result.adjusted_theta_s; + out_adjusted_theta_33[index] = ptfkit_result.adjusted_theta_33; + out_adjusted_theta_s_minus_33[index] = ptfkit_result.adjusted_theta_s_minus_33; + } + return 0; } -static PyUFuncGenericFunction calc_ptf_saxton2006_functions[] = {calc_ptf_saxton2006_loop}; -static char calc_ptf_saxton2006_types[] = { - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; -static void calc_ptf_saxton2006_density_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double normal_density = *(const double *)args[0]; - const double theta_s = *(const double *)args[1]; - const double theta_33 = *(const double *)args[2]; - const double density_factor = *(const double *)args[3]; - const double adjusted_density = normal_density * density_factor; - const double adjusted_theta_s = 1.0 - adjusted_density / 2.65; - const double adjusted_theta_33 = theta_33 - 0.2 * (theta_s - adjusted_theta_s); - const double adjusted_theta_s_minus_33 = fmax(adjusted_theta_s - adjusted_theta_33, 0.005); - *(double *)args[4] = adjusted_density; - *(double *)args[5] = adjusted_theta_s; - *(double *)args[6] = adjusted_theta_33; - *(double *)args[7] = adjusted_theta_s_minus_33; - for (int arg = 0; arg < 8; arg++) - args[arg] += steps[arg]; +static int calc_ptf_saxton2006_density_strided_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double normal_density = *(const double *)(data[0] + index * strides[0]); + const double theta_s = *(const double *)(data[1] + index * strides[1]); + const double theta_33 = *(const double *)(data[2] + index * strides[2]); + const double density_factor = *(const double *)(data[3] + index * strides[3]); + const saxton2006_density_result ptfkit_result = + calc_ptf_saxton2006_density(normal_density, theta_s, theta_33, density_factor); + *(double *)(data[4] + index * strides[4]) = ptfkit_result.adjusted_density; + *(double *)(data[5] + index * strides[5]) = ptfkit_result.adjusted_theta_s; + *(double *)(data[6] + index * strides[6]) = ptfkit_result.adjusted_theta_33; + *(double *)(data[7] + index * strides[7]) = ptfkit_result.adjusted_theta_s_minus_33; } + return 0; } -static PyUFuncGenericFunction calc_ptf_saxton2006_density_functions[] = { - calc_ptf_saxton2006_density_loop}; -static char calc_ptf_saxton2006_density_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; +static PyType_Slot calc_ptf_saxton2006_density_slots[] = { + {NPY_METH_strided_loop, calc_ptf_saxton2006_density_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_saxton2006_density_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_saxton2006_density_spec = { + .name = "calc_ptf_saxton2006_density", + .nin = 4, + .nout = 4, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_saxton2006_density_slots, +}; -static void calc_ptf_saxton2006_tension_dry_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double theta = *(const double *)args[0]; - const double theta_1500 = *(const double *)args[1]; - const double theta_33 = *(const double *)args[2]; - const double ln_33 = log(33.0); - const double ln_theta_33 = log(theta_33); - const double retention_b = (log(1500.0) - ln_33) / (ln_theta_33 - log(theta_1500)); - const double retention_a = exp(ln_33 + retention_b * ln_theta_33); - const double tension = retention_a * pow(theta, -retention_b); - *(double *)args[3] = tension; - for (int arg = 0; arg < 4; arg++) - args[arg] += steps[arg]; +static int calc_ptf_saxton2006_tension_dry_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_theta = (const double *)data[0]; + const double *in_theta_1500 = (const double *)data[1]; + const double *in_theta_33 = (const double *)data[2]; + double *out_tension = (double *)data[3]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double theta = in_theta[index]; + const double theta_1500 = in_theta_1500[index]; + const double theta_33 = in_theta_33[index]; + const double ptfkit_result = calc_ptf_saxton2006_tension_dry(theta, theta_1500, theta_33); + out_tension[index] = ptfkit_result; } + return 0; } -static PyUFuncGenericFunction calc_ptf_saxton2006_tension_dry_functions[] = { - calc_ptf_saxton2006_tension_dry_loop}; -static char calc_ptf_saxton2006_tension_dry_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE}; -static void calc_ptf_saxton2006_tension_wet_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double theta = *(const double *)args[0]; - const double theta_33 = *(const double *)args[1]; - const double theta_s = *(const double *)args[2]; - const double air_entry_tension = *(const double *)args[3]; - const double tension = - 33.0 - (theta - theta_33) * (33.0 - air_entry_tension) / (theta_s - theta_33); - *(double *)args[4] = tension; - for (int arg = 0; arg < 5; arg++) - args[arg] += steps[arg]; +static int calc_ptf_saxton2006_tension_dry_strided_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double theta = *(const double *)(data[0] + index * strides[0]); + const double theta_1500 = *(const double *)(data[1] + index * strides[1]); + const double theta_33 = *(const double *)(data[2] + index * strides[2]); + const double ptfkit_result = calc_ptf_saxton2006_tension_dry(theta, theta_1500, theta_33); + *(double *)(data[3] + index * strides[3]) = ptfkit_result; } + return 0; } -static PyUFuncGenericFunction calc_ptf_saxton2006_tension_wet_functions[] = { - calc_ptf_saxton2006_tension_wet_loop}; -static char calc_ptf_saxton2006_tension_wet_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE, NPY_DOUBLE}; +static PyType_Slot calc_ptf_saxton2006_tension_dry_slots[] = { + {NPY_METH_strided_loop, calc_ptf_saxton2006_tension_dry_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_saxton2006_tension_dry_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_saxton2006_tension_dry_spec = { + .name = "calc_ptf_saxton2006_tension_dry", + .nin = 3, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_saxton2006_tension_dry_slots, +}; -static void calc_ptf_saxton2006_conductivity_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double theta = *(const double *)args[0]; - const double theta_s = *(const double *)args[1]; - const double saturated_conductivity = *(const double *)args[2]; - const double conductivity_lambda = *(const double *)args[3]; - const double conductivity = - saturated_conductivity * pow(theta / theta_s, 3.0 + 2.0 / conductivity_lambda); - *(double *)args[4] = conductivity; - for (int arg = 0; arg < 5; arg++) - args[arg] += steps[arg]; +static int calc_ptf_saxton2006_tension_wet_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_theta = (const double *)data[0]; + const double *in_theta_33 = (const double *)data[1]; + const double *in_theta_s = (const double *)data[2]; + const double *in_air_entry_tension = (const double *)data[3]; + double *out_tension = (double *)data[4]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double theta = in_theta[index]; + const double theta_33 = in_theta_33[index]; + const double theta_s = in_theta_s[index]; + const double air_entry_tension = in_air_entry_tension[index]; + const double ptfkit_result = + calc_ptf_saxton2006_tension_wet(theta, theta_33, theta_s, air_entry_tension); + out_tension[index] = ptfkit_result; } + return 0; } -static PyUFuncGenericFunction calc_ptf_saxton2006_conductivity_functions[] = { - calc_ptf_saxton2006_conductivity_loop}; -static char calc_ptf_saxton2006_conductivity_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE, NPY_DOUBLE}; -static void calc_ptf_saxton2006_gravel_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double gravel_weight_fraction = *(const double *)args[0]; - const double matric_density = *(const double *)args[1]; - const double plant_available_water = *(const double *)args[2]; - const double saturated_conductivity = *(const double *)args[3]; - const double density_ratio = matric_density / 2.65; - const double gravel_volume_fraction = - density_ratio * gravel_weight_fraction / - (1.0 - gravel_weight_fraction * (1.0 - density_ratio)); - const double bulk_density = - matric_density * (1.0 - gravel_volume_fraction) + gravel_volume_fraction * 2.65; - const double bulk_plant_available_water = - plant_available_water * (1.0 - gravel_volume_fraction); - const double bulk_saturated_conductivity = - saturated_conductivity * (1.0 - gravel_volume_fraction) / - (1.0 - gravel_volume_fraction * (1.0 - 3.0 * density_ratio / 2.0)); - *(double *)args[4] = gravel_volume_fraction; - *(double *)args[5] = bulk_density; - *(double *)args[6] = bulk_plant_available_water; - *(double *)args[7] = bulk_saturated_conductivity; - for (int arg = 0; arg < 8; arg++) - args[arg] += steps[arg]; +static int calc_ptf_saxton2006_tension_wet_strided_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double theta = *(const double *)(data[0] + index * strides[0]); + const double theta_33 = *(const double *)(data[1] + index * strides[1]); + const double theta_s = *(const double *)(data[2] + index * strides[2]); + const double air_entry_tension = *(const double *)(data[3] + index * strides[3]); + const double ptfkit_result = + calc_ptf_saxton2006_tension_wet(theta, theta_33, theta_s, air_entry_tension); + *(double *)(data[4] + index * strides[4]) = ptfkit_result; } + return 0; +} +static PyType_Slot calc_ptf_saxton2006_tension_wet_slots[] = { + {NPY_METH_strided_loop, calc_ptf_saxton2006_tension_wet_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_saxton2006_tension_wet_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_saxton2006_tension_wet_spec = { + .name = "calc_ptf_saxton2006_tension_wet", + .nin = 4, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_saxton2006_tension_wet_slots, +}; + +static int calc_ptf_saxton2006_conductivity_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_theta = (const double *)data[0]; + const double *in_theta_s = (const double *)data[1]; + const double *in_saturated_conductivity = (const double *)data[2]; + const double *in_conductivity_lambda = (const double *)data[3]; + double *out_conductivity = (double *)data[4]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double theta = in_theta[index]; + const double theta_s = in_theta_s[index]; + const double saturated_conductivity = in_saturated_conductivity[index]; + const double conductivity_lambda = in_conductivity_lambda[index]; + const double ptfkit_result = calc_ptf_saxton2006_conductivity( + theta, theta_s, saturated_conductivity, conductivity_lambda); + out_conductivity[index] = ptfkit_result; + } + return 0; } -static PyUFuncGenericFunction calc_ptf_saxton2006_gravel_functions[] = { - calc_ptf_saxton2006_gravel_loop}; -static char calc_ptf_saxton2006_gravel_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; -static void calc_ptf_saxton2006_salinity_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double electrical_conductivity = *(const double *)args[0]; - const double theta = *(const double *)args[1]; - const double theta_s = *(const double *)args[2]; - const double saturated_osmotic_potential = 36.0 * electrical_conductivity; - const double osmotic_potential = theta_s / theta * saturated_osmotic_potential; - *(double *)args[3] = saturated_osmotic_potential; - *(double *)args[4] = osmotic_potential; - for (int arg = 0; arg < 5; arg++) - args[arg] += steps[arg]; +static int calc_ptf_saxton2006_conductivity_strided_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double theta = *(const double *)(data[0] + index * strides[0]); + const double theta_s = *(const double *)(data[1] + index * strides[1]); + const double saturated_conductivity = *(const double *)(data[2] + index * strides[2]); + const double conductivity_lambda = *(const double *)(data[3] + index * strides[3]); + const double ptfkit_result = calc_ptf_saxton2006_conductivity( + theta, theta_s, saturated_conductivity, conductivity_lambda); + *(double *)(data[4] + index * strides[4]) = ptfkit_result; } + return 0; +} +static PyType_Slot calc_ptf_saxton2006_conductivity_slots[] = { + {NPY_METH_strided_loop, calc_ptf_saxton2006_conductivity_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_saxton2006_conductivity_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_saxton2006_conductivity_spec = { + .name = "calc_ptf_saxton2006_conductivity", + .nin = 4, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_saxton2006_conductivity_slots, +}; + +static int calc_ptf_saxton2006_gravel_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_gravel_weight_fraction = (const double *)data[0]; + const double *in_matric_density = (const double *)data[1]; + const double *in_plant_available_water = (const double *)data[2]; + const double *in_saturated_conductivity = (const double *)data[3]; + double *out_gravel_volume_fraction = (double *)data[4]; + double *out_bulk_density = (double *)data[5]; + double *out_bulk_plant_available_water = (double *)data[6]; + double *out_bulk_saturated_conductivity = (double *)data[7]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double gravel_weight_fraction = in_gravel_weight_fraction[index]; + const double matric_density = in_matric_density[index]; + const double plant_available_water = in_plant_available_water[index]; + const double saturated_conductivity = in_saturated_conductivity[index]; + const saxton2006_gravel_result ptfkit_result = calc_ptf_saxton2006_gravel( + gravel_weight_fraction, matric_density, plant_available_water, saturated_conductivity); + out_gravel_volume_fraction[index] = ptfkit_result.gravel_volume_fraction; + out_bulk_density[index] = ptfkit_result.bulk_density; + out_bulk_plant_available_water[index] = ptfkit_result.bulk_plant_available_water; + out_bulk_saturated_conductivity[index] = ptfkit_result.bulk_saturated_conductivity; + } + return 0; +} + +static int calc_ptf_saxton2006_gravel_strided_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double gravel_weight_fraction = *(const double *)(data[0] + index * strides[0]); + const double matric_density = *(const double *)(data[1] + index * strides[1]); + const double plant_available_water = *(const double *)(data[2] + index * strides[2]); + const double saturated_conductivity = *(const double *)(data[3] + index * strides[3]); + const saxton2006_gravel_result ptfkit_result = calc_ptf_saxton2006_gravel( + gravel_weight_fraction, matric_density, plant_available_water, saturated_conductivity); + *(double *)(data[4] + index * strides[4]) = ptfkit_result.gravel_volume_fraction; + *(double *)(data[5] + index * strides[5]) = ptfkit_result.bulk_density; + *(double *)(data[6] + index * strides[6]) = ptfkit_result.bulk_plant_available_water; + *(double *)(data[7] + index * strides[7]) = ptfkit_result.bulk_saturated_conductivity; + } + return 0; +} +static PyType_Slot calc_ptf_saxton2006_gravel_slots[] = { + {NPY_METH_strided_loop, calc_ptf_saxton2006_gravel_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_saxton2006_gravel_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_saxton2006_gravel_spec = { + .name = "calc_ptf_saxton2006_gravel", + .nin = 4, + .nout = 4, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_saxton2006_gravel_slots, +}; + +static int calc_ptf_saxton2006_salinity_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_electrical_conductivity = (const double *)data[0]; + const double *in_theta = (const double *)data[1]; + const double *in_theta_s = (const double *)data[2]; + double *out_saturated_osmotic_potential = (double *)data[3]; + double *out_osmotic_potential = (double *)data[4]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double electrical_conductivity = in_electrical_conductivity[index]; + const double theta = in_theta[index]; + const double theta_s = in_theta_s[index]; + const saxton2006_salinity_result ptfkit_result = + calc_ptf_saxton2006_salinity(electrical_conductivity, theta, theta_s); + out_saturated_osmotic_potential[index] = ptfkit_result.saturated_osmotic_potential; + out_osmotic_potential[index] = ptfkit_result.osmotic_potential; + } + return 0; +} + +static int calc_ptf_saxton2006_salinity_strided_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double electrical_conductivity = *(const double *)(data[0] + index * strides[0]); + const double theta = *(const double *)(data[1] + index * strides[1]); + const double theta_s = *(const double *)(data[2] + index * strides[2]); + const saxton2006_salinity_result ptfkit_result = + calc_ptf_saxton2006_salinity(electrical_conductivity, theta, theta_s); + *(double *)(data[3] + index * strides[3]) = ptfkit_result.saturated_osmotic_potential; + *(double *)(data[4] + index * strides[4]) = ptfkit_result.osmotic_potential; + } + return 0; } -static PyUFuncGenericFunction calc_ptf_saxton2006_salinity_functions[] = { - calc_ptf_saxton2006_salinity_loop}; -static char calc_ptf_saxton2006_salinity_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE}; +static PyType_Slot calc_ptf_saxton2006_salinity_slots[] = { + {NPY_METH_strided_loop, calc_ptf_saxton2006_salinity_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_saxton2006_salinity_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_saxton2006_salinity_spec = { + .name = "calc_ptf_saxton2006_salinity", + .nin = 3, + .nout = 2, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_saxton2006_salinity_slots, +}; int ptfkit_register_saxton2006(PyObject *module) { - if (ptfkit_add_ufunc(module, "calc_ptf_saxton2006", calc_ptf_saxton2006_functions, - calc_ptf_saxton2006_types, 3, 10) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_saxton2006", 3, 10, &calc_ptf_saxton2006_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_saxton2006_density", - calc_ptf_saxton2006_density_functions, calc_ptf_saxton2006_density_types, - 4, 4) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_saxton2006_density", 4, 4, + &calc_ptf_saxton2006_density_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_saxton2006_tension_dry", - calc_ptf_saxton2006_tension_dry_functions, - calc_ptf_saxton2006_tension_dry_types, 3, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_saxton2006_tension_dry", 3, 1, + &calc_ptf_saxton2006_tension_dry_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_saxton2006_tension_wet", - calc_ptf_saxton2006_tension_wet_functions, - calc_ptf_saxton2006_tension_wet_types, 4, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_saxton2006_tension_wet", 4, 1, + &calc_ptf_saxton2006_tension_wet_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_saxton2006_conductivity", - calc_ptf_saxton2006_conductivity_functions, - calc_ptf_saxton2006_conductivity_types, 4, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_saxton2006_conductivity", 4, 1, + &calc_ptf_saxton2006_conductivity_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_saxton2006_gravel", calc_ptf_saxton2006_gravel_functions, - calc_ptf_saxton2006_gravel_types, 4, 4) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_saxton2006_gravel", 4, 4, + &calc_ptf_saxton2006_gravel_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_saxton2006_salinity", - calc_ptf_saxton2006_salinity_functions, calc_ptf_saxton2006_salinity_types, - 3, 2) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_saxton2006_salinity", 3, 2, + &calc_ptf_saxton2006_salinity_spec) < 0) return -1; return 0; } diff --git a/targets/ptfkit-py/src/ptfkit/saxton2006.py b/targets/ptfkit-py/src/ptfkit/saxton2006.py index 5102ba0..d256f1f 100644 --- a/targets/ptfkit-py/src/ptfkit/saxton2006.py +++ b/targets/ptfkit-py/src/ptfkit/saxton2006.py @@ -24,6 +24,7 @@ from typing import TYPE_CHECKING, Generic, NamedTuple, TypeVar, overload +from ptfkit._dispatch import call as _call from ptfkit._ptfkit import ( calc_ptf_saxton2006 as _calc_ptf_saxton2006, calc_ptf_saxton2006_density as _calc_ptf_saxton2006_density, @@ -185,10 +186,13 @@ def calc_ptf_saxton2006( available. """ - if out is None: - values = _calc_ptf_saxton2006(sand, clay, organic_matter) - else: - values = _calc_ptf_saxton2006(sand, clay, organic_matter, out=tuple(out)) + values = _call( + _calc_ptf_saxton2006, + sand, + clay, + organic_matter, + out=out, + ) return Saxton2006PTFResult(*values) @@ -241,12 +245,14 @@ def calc_density_adjustment_saxton2006( The source recommends density factors only from 0.9 to 1.3. """ - if out is None: - values = _calc_ptf_saxton2006_density(normal_density, theta_s, theta_33, density_factor) - else: - values = _calc_ptf_saxton2006_density( - normal_density, theta_s, theta_33, density_factor, out=tuple(out) - ) + values = _call( + _calc_ptf_saxton2006_density, + normal_density, + theta_s, + theta_33, + density_factor, + out=out, + ) return Saxton2006DensityResult(*values) @@ -295,12 +301,13 @@ def calc_tension_dry_saxton2006( Use only for the 1500 to 33 kPa segment defined by the source. """ - if out is None: - values = _calc_ptf_saxton2006_tension_dry(theta, theta_1500, theta_33) - else: - values = _calc_ptf_saxton2006_tension_dry(theta, theta_1500, theta_33, out=out) - - return values + return _call( + _calc_ptf_saxton2006_tension_dry, + theta, + theta_1500, + theta_33, + out=out, + ) @overload @@ -351,14 +358,14 @@ def calc_tension_wet_saxton2006( Use only for the 33 kPa to air-entry segment defined by the source. """ - if out is None: - values = _calc_ptf_saxton2006_tension_wet(theta, theta_33, theta_s, air_entry_tension) - else: - values = _calc_ptf_saxton2006_tension_wet( - theta, theta_33, theta_s, air_entry_tension, out=out - ) - - return values + return _call( + _calc_ptf_saxton2006_tension_wet, + theta, + theta_33, + theta_s, + air_entry_tension, + out=out, + ) @overload @@ -408,16 +415,14 @@ def calc_conductivity_saxton2006( The equation does not include residual water content. """ - if out is None: - values = _calc_ptf_saxton2006_conductivity( - theta, theta_s, saturated_conductivity, conductivity_lambda - ) - else: - values = _calc_ptf_saxton2006_conductivity( - theta, theta_s, saturated_conductivity, conductivity_lambda, out=out - ) - - return values + return _call( + _calc_ptf_saxton2006_conductivity, + theta, + theta_s, + saturated_conductivity, + conductivity_lambda, + out=out, + ) @overload @@ -475,18 +480,14 @@ def calc_gravel_adjustment_saxton2006( soils. """ - if out is None: - values = _calc_ptf_saxton2006_gravel( - gravel_weight_fraction, matric_density, plant_available_water, saturated_conductivity - ) - else: - values = _calc_ptf_saxton2006_gravel( - gravel_weight_fraction, - matric_density, - plant_available_water, - saturated_conductivity, - out=tuple(out), - ) + values = _call( + _calc_ptf_saxton2006_gravel, + gravel_weight_fraction, + matric_density, + plant_available_water, + saturated_conductivity, + out=out, + ) return Saxton2006GravelResult(*values) @@ -537,11 +538,12 @@ def calc_osmotic_potential_saxton2006( Precipitation, bonding, ionic nutrition, and toxicity can modify actual salinity effects. """ - if out is None: - values = _calc_ptf_saxton2006_salinity(electrical_conductivity, theta, theta_s) - else: - values = _calc_ptf_saxton2006_salinity( - electrical_conductivity, theta, theta_s, out=tuple(out) - ) + values = _call( + _calc_ptf_saxton2006_salinity, + electrical_conductivity, + theta, + theta_s, + out=out, + ) return Saxton2006SalinityResult(*values) diff --git a/targets/ptfkit-py/src/ptfkit/tiwary2014.c b/targets/ptfkit-py/src/ptfkit/tiwary2014.c index 01c362c..a39603f 100644 --- a/targets/ptfkit-py/src/ptfkit/tiwary2014.c +++ b/targets/ptfkit-py/src/ptfkit/tiwary2014.c @@ -1,57 +1,129 @@ /* @generated by ptfkit-codegen; DO NOT EDIT. */ +#include #include "ufunc.h" -static void calc_ptf_tiwary2014_igp_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double bulk_density = *(const double *)args[1]; - const double esp = *(const double *)args[2]; - const double k_sat_mm_per_hour = 4.079 + 0.047 * sand - 0.054 * esp - 2.238 * bulk_density; - const double k_sat = k_sat_mm_per_hour / 3600000.0; - *(double *)args[3] = k_sat; - for (int arg = 0; arg < 4; arg++) - args[arg] += steps[arg]; +static int calc_ptf_tiwary2014_igp_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_bulk_density = (const double *)data[1]; + const double *in_esp = (const double *)data[2]; + double *out_k_sat = (double *)data[3]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double bulk_density = in_bulk_density[index]; + const double esp = in_esp[index]; + const double ptfkit_result = calc_ptf_tiwary2014_igp(sand, bulk_density, esp); + out_k_sat[index] = ptfkit_result; } + return 0; +} + +static int calc_ptf_tiwary2014_igp_strided_loop(PyArrayMethod_Context *context, char *const *data, + const npy_intp *dimensions, const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double bulk_density = *(const double *)(data[1] + index * strides[1]); + const double esp = *(const double *)(data[2] + index * strides[2]); + const double ptfkit_result = calc_ptf_tiwary2014_igp(sand, bulk_density, esp); + *(double *)(data[3] + index * strides[3]) = ptfkit_result; + } + return 0; } -static PyUFuncGenericFunction calc_ptf_tiwary2014_igp_functions[] = {calc_ptf_tiwary2014_igp_loop}; -static char calc_ptf_tiwary2014_igp_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; +static PyType_Slot calc_ptf_tiwary2014_igp_slots[] = { + {NPY_METH_strided_loop, calc_ptf_tiwary2014_igp_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_tiwary2014_igp_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_tiwary2014_igp_spec = { + .name = "calc_ptf_tiwary2014_igp", + .nin = 3, + .nout = 1, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_tiwary2014_igp_slots, +}; -static void calc_ptf_tiwary2014_bsr_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double clay = *(const double *)args[0]; - const double ph = *(const double *)args[1]; - const double cation_exchange_capacity = *(const double *)args[2]; - const double esp = *(const double *)args[3]; - const double emp = *(const double *)args[4]; - const double excm = *(const double *)args[5]; - const double w_33 = 2.583 + 0.346 * cation_exchange_capacity + 0.249 * clay + 0.494 * esp; - const double w_100 = -1.918 + 0.383 * cation_exchange_capacity + 0.228 * clay + 0.361 * esp; - const double w_1500 = 0.541 + 0.306 * cation_exchange_capacity + 0.146 * esp + 0.058 * emp; - const double k_sat_mm_per_hour = 120.637 - 13.094 * ph - 0.102 * clay + 1.151 * excm; - const double k_sat = k_sat_mm_per_hour / 3600000.0; - *(double *)args[6] = w_33; - *(double *)args[7] = w_100; - *(double *)args[8] = w_1500; - *(double *)args[9] = k_sat; - for (int arg = 0; arg < 10; arg++) - args[arg] += steps[arg]; +static int calc_ptf_tiwary2014_bsr_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_clay = (const double *)data[0]; + const double *in_ph = (const double *)data[1]; + const double *in_cation_exchange_capacity = (const double *)data[2]; + const double *in_esp = (const double *)data[3]; + const double *in_emp = (const double *)data[4]; + const double *in_excm = (const double *)data[5]; + double *out_w_33 = (double *)data[6]; + double *out_w_100 = (double *)data[7]; + double *out_w_1500 = (double *)data[8]; + double *out_k_sat = (double *)data[9]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = in_clay[index]; + const double ph = in_ph[index]; + const double cation_exchange_capacity = in_cation_exchange_capacity[index]; + const double esp = in_esp[index]; + const double emp = in_emp[index]; + const double excm = in_excm[index]; + const tiwary2014_ptf_result ptfkit_result = + calc_ptf_tiwary2014_bsr(clay, ph, cation_exchange_capacity, esp, emp, excm); + out_w_33[index] = ptfkit_result.w_33; + out_w_100[index] = ptfkit_result.w_100; + out_w_1500[index] = ptfkit_result.w_1500; + out_k_sat[index] = ptfkit_result.k_sat; } + return 0; +} + +static int calc_ptf_tiwary2014_bsr_strided_loop(PyArrayMethod_Context *context, char *const *data, + const npy_intp *dimensions, const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double clay = *(const double *)(data[0] + index * strides[0]); + const double ph = *(const double *)(data[1] + index * strides[1]); + const double cation_exchange_capacity = *(const double *)(data[2] + index * strides[2]); + const double esp = *(const double *)(data[3] + index * strides[3]); + const double emp = *(const double *)(data[4] + index * strides[4]); + const double excm = *(const double *)(data[5] + index * strides[5]); + const tiwary2014_ptf_result ptfkit_result = + calc_ptf_tiwary2014_bsr(clay, ph, cation_exchange_capacity, esp, emp, excm); + *(double *)(data[6] + index * strides[6]) = ptfkit_result.w_33; + *(double *)(data[7] + index * strides[7]) = ptfkit_result.w_100; + *(double *)(data[8] + index * strides[8]) = ptfkit_result.w_1500; + *(double *)(data[9] + index * strides[9]) = ptfkit_result.k_sat; + } + return 0; } -static PyUFuncGenericFunction calc_ptf_tiwary2014_bsr_functions[] = {calc_ptf_tiwary2014_bsr_loop}; -static char calc_ptf_tiwary2014_bsr_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE, NPY_DOUBLE}; +static PyType_Slot calc_ptf_tiwary2014_bsr_slots[] = { + {NPY_METH_strided_loop, calc_ptf_tiwary2014_bsr_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_tiwary2014_bsr_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_tiwary2014_bsr_spec = { + .name = "calc_ptf_tiwary2014_bsr", + .nin = 6, + .nout = 4, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_tiwary2014_bsr_slots, +}; int ptfkit_register_tiwary2014(PyObject *module) { - if (ptfkit_add_ufunc(module, "calc_ptf_tiwary2014_igp", calc_ptf_tiwary2014_igp_functions, - calc_ptf_tiwary2014_igp_types, 3, 1) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_tiwary2014_igp", 3, 1, &calc_ptf_tiwary2014_igp_spec) < + 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_tiwary2014_bsr", calc_ptf_tiwary2014_bsr_functions, - calc_ptf_tiwary2014_bsr_types, 6, 4) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_tiwary2014_bsr", 6, 4, &calc_ptf_tiwary2014_bsr_spec) < + 0) return -1; return 0; } diff --git a/targets/ptfkit-py/src/ptfkit/tiwary2014.py b/targets/ptfkit-py/src/ptfkit/tiwary2014.py index 1edaca9..2f1551c 100644 --- a/targets/ptfkit-py/src/ptfkit/tiwary2014.py +++ b/targets/ptfkit-py/src/ptfkit/tiwary2014.py @@ -24,6 +24,7 @@ from typing import TYPE_CHECKING, Generic, NamedTuple, TypeVar, overload +from ptfkit._dispatch import call as _call from ptfkit._ptfkit import ( calc_ptf_tiwary2014_igp as _calc_ptf_tiwary2014_igp, calc_ptf_tiwary2014_bsr as _calc_ptf_tiwary2014_bsr, @@ -101,12 +102,13 @@ def calc_ptf_tiwary2014_igp( defines them only for BSR soils. """ - if out is None: - values = _calc_ptf_tiwary2014_igp(sand, bulk_density, esp) - else: - values = _calc_ptf_tiwary2014_igp(sand, bulk_density, esp, out=out) - - return values + return _call( + _calc_ptf_tiwary2014_igp, + sand, + bulk_density, + esp, + out=out, + ) @overload @@ -163,11 +165,15 @@ def calc_ptf_tiwary2014_bsr( 46 profiles. """ - if out is None: - values = _calc_ptf_tiwary2014_bsr(clay, ph, cation_exchange_capacity, esp, emp, excm) - else: - values = _calc_ptf_tiwary2014_bsr( - clay, ph, cation_exchange_capacity, esp, emp, excm, out=tuple(out) - ) + values = _call( + _calc_ptf_tiwary2014_bsr, + clay, + ph, + cation_exchange_capacity, + esp, + emp, + excm, + out=out, + ) return Tiwary2014PTFResult(*values) diff --git a/targets/ptfkit-py/src/ptfkit/ufunc.h b/targets/ptfkit-py/src/ptfkit/ufunc.h index e03b839..b694d7c 100644 --- a/targets/ptfkit-py/src/ptfkit/ufunc.h +++ b/targets/ptfkit-py/src/ptfkit/ufunc.h @@ -7,12 +7,19 @@ static inline double ptfkit_pow4(double value) { return square * square; } -static inline int ptfkit_add_ufunc(PyObject *module, const char *name, - PyUFuncGenericFunction *functions, char *types, int nin, - int nout) { +static inline int ptfkit_add_ufunc(PyObject *module, const char *name, int nin, int nout, + PyArrayMethod_Spec *spec) { + PyArray_DTypeMeta *dtypes[NPY_MAXARGS]; + for (int argument = 0; argument < nin + nout; argument++) + dtypes[argument] = &PyArray_DoubleDType; + spec->dtypes = dtypes; PyObject *ufunc = - PyUFunc_FromFuncAndData(functions, NULL, types, 1, nin, nout, PyUFunc_None, name, NULL, 0); + PyUFunc_FromFuncAndData(NULL, NULL, NULL, 0, nin, nout, PyUFunc_None, name, NULL, 0); if (ufunc == NULL) return -1; + if (PyUFunc_AddLoopFromSpec(ufunc, spec) < 0) { + Py_DECREF(ufunc); + return -1; + } return PyModule_AddObject(module, name, ufunc); } diff --git a/targets/ptfkit-py/src/ptfkit/varallyai1982.c b/targets/ptfkit-py/src/ptfkit/varallyai1982.c index b7f656f..3e6b8ea 100644 --- a/targets/ptfkit-py/src/ptfkit/varallyai1982.c +++ b/targets/ptfkit-py/src/ptfkit/varallyai1982.c @@ -1,112 +1,245 @@ /* @generated by ptfkit-codegen; DO NOT EDIT. */ +#include #include "ufunc.h" -static void calc_ptf_varallyai1982_meadow_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double bulk_density = *(const double *)args[0]; - const double fine_sand_fraction = *(const double *)args[1]; - const double fine_fraction = *(const double *)args[2]; - const double theta_0 = - -8.78 * (bulk_density * bulk_density) + 14.46 * (fine_fraction * fine_fraction) + 62.85; - const double m = 0.576 * (fine_sand_fraction * fine_sand_fraction) - - 1.434 * fine_sand_fraction * fine_fraction + 0.156; - const double pf_star = - -1.702 * fine_sand_fraction + 1.103 * bulk_density * fine_fraction + 3.749; - *(double *)args[3] = theta_0; - *(double *)args[4] = m; - *(double *)args[5] = pf_star; - for (int arg = 0; arg < 6; arg++) - args[arg] += steps[arg]; +static int calc_ptf_varallyai1982_meadow_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_bulk_density = (const double *)data[0]; + const double *in_fine_sand_fraction = (const double *)data[1]; + const double *in_fine_fraction = (const double *)data[2]; + double *out_theta_0 = (double *)data[3]; + double *out_m = (double *)data[4]; + double *out_pf_star = (double *)data[5]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double bulk_density = in_bulk_density[index]; + const double fine_sand_fraction = in_fine_sand_fraction[index]; + const double fine_fraction = in_fine_fraction[index]; + const varallyai1982_parameters ptfkit_result = + calc_ptf_varallyai1982_meadow(bulk_density, fine_sand_fraction, fine_fraction); + out_theta_0[index] = ptfkit_result.theta_0; + out_m[index] = ptfkit_result.m; + out_pf_star[index] = ptfkit_result.pf_star; } + return 0; +} + +static int calc_ptf_varallyai1982_meadow_strided_loop(PyArrayMethod_Context *context, + char *const *data, const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double bulk_density = *(const double *)(data[0] + index * strides[0]); + const double fine_sand_fraction = *(const double *)(data[1] + index * strides[1]); + const double fine_fraction = *(const double *)(data[2] + index * strides[2]); + const varallyai1982_parameters ptfkit_result = + calc_ptf_varallyai1982_meadow(bulk_density, fine_sand_fraction, fine_fraction); + *(double *)(data[3] + index * strides[3]) = ptfkit_result.theta_0; + *(double *)(data[4] + index * strides[4]) = ptfkit_result.m; + *(double *)(data[5] + index * strides[5]) = ptfkit_result.pf_star; + } + return 0; +} +static PyType_Slot calc_ptf_varallyai1982_meadow_slots[] = { + {NPY_METH_strided_loop, calc_ptf_varallyai1982_meadow_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_varallyai1982_meadow_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_varallyai1982_meadow_spec = { + .name = "calc_ptf_varallyai1982_meadow", + .nin = 3, + .nout = 3, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_varallyai1982_meadow_slots, +}; + +static int calc_ptf_varallyai1982_chernozem_a_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_bulk_density = (const double *)data[0]; + const double *in_fine_fraction = (const double *)data[1]; + double *out_theta_0 = (double *)data[2]; + double *out_m = (double *)data[3]; + double *out_pf_star = (double *)data[4]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double bulk_density = in_bulk_density[index]; + const double fine_fraction = in_fine_fraction[index]; + const varallyai1982_parameters ptfkit_result = + calc_ptf_varallyai1982_chernozem_a(bulk_density, fine_fraction); + out_theta_0[index] = ptfkit_result.theta_0; + out_m[index] = ptfkit_result.m; + out_pf_star[index] = ptfkit_result.pf_star; + } + return 0; +} + +static int calc_ptf_varallyai1982_chernozem_a_strided_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double bulk_density = *(const double *)(data[0] + index * strides[0]); + const double fine_fraction = *(const double *)(data[1] + index * strides[1]); + const varallyai1982_parameters ptfkit_result = + calc_ptf_varallyai1982_chernozem_a(bulk_density, fine_fraction); + *(double *)(data[2] + index * strides[2]) = ptfkit_result.theta_0; + *(double *)(data[3] + index * strides[3]) = ptfkit_result.m; + *(double *)(data[4] + index * strides[4]) = ptfkit_result.pf_star; + } + return 0; +} +static PyType_Slot calc_ptf_varallyai1982_chernozem_a_slots[] = { + {NPY_METH_strided_loop, calc_ptf_varallyai1982_chernozem_a_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_varallyai1982_chernozem_a_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_varallyai1982_chernozem_a_spec = { + .name = "calc_ptf_varallyai1982_chernozem_a", + .nin = 2, + .nout = 3, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_varallyai1982_chernozem_a_slots, +}; + +static int calc_ptf_varallyai1982_chernozem_b_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_bulk_density = (const double *)data[0]; + const double *in_fine_fraction = (const double *)data[1]; + double *out_theta_0 = (double *)data[2]; + double *out_m = (double *)data[3]; + double *out_pf_star = (double *)data[4]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double bulk_density = in_bulk_density[index]; + const double fine_fraction = in_fine_fraction[index]; + const varallyai1982_parameters ptfkit_result = + calc_ptf_varallyai1982_chernozem_b(bulk_density, fine_fraction); + out_theta_0[index] = ptfkit_result.theta_0; + out_m[index] = ptfkit_result.m; + out_pf_star[index] = ptfkit_result.pf_star; + } + return 0; } -static PyUFuncGenericFunction calc_ptf_varallyai1982_meadow_functions[] = { - calc_ptf_varallyai1982_meadow_loop}; -static char calc_ptf_varallyai1982_meadow_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; -static void calc_ptf_varallyai1982_chernozem_a_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double bulk_density = *(const double *)args[0]; - const double fine_fraction = *(const double *)args[1]; - const double theta_0 = -56.40 * bulk_density + 20.50 * fine_fraction + 123.79; - const double m = 0.336 * bulk_density - 0.053; - const double pf_star = 4.701 * bulk_density * fine_fraction + 1.513 * bulk_density - 0.417; - *(double *)args[2] = theta_0; - *(double *)args[3] = m; - *(double *)args[4] = pf_star; - for (int arg = 0; arg < 5; arg++) - args[arg] += steps[arg]; +static int calc_ptf_varallyai1982_chernozem_b_strided_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double bulk_density = *(const double *)(data[0] + index * strides[0]); + const double fine_fraction = *(const double *)(data[1] + index * strides[1]); + const varallyai1982_parameters ptfkit_result = + calc_ptf_varallyai1982_chernozem_b(bulk_density, fine_fraction); + *(double *)(data[2] + index * strides[2]) = ptfkit_result.theta_0; + *(double *)(data[3] + index * strides[3]) = ptfkit_result.m; + *(double *)(data[4] + index * strides[4]) = ptfkit_result.pf_star; } + return 0; } -static PyUFuncGenericFunction calc_ptf_varallyai1982_chernozem_a_functions[] = { - calc_ptf_varallyai1982_chernozem_a_loop}; -static char calc_ptf_varallyai1982_chernozem_a_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE, NPY_DOUBLE}; +static PyType_Slot calc_ptf_varallyai1982_chernozem_b_slots[] = { + {NPY_METH_strided_loop, calc_ptf_varallyai1982_chernozem_b_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_varallyai1982_chernozem_b_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_varallyai1982_chernozem_b_spec = { + .name = "calc_ptf_varallyai1982_chernozem_b", + .nin = 2, + .nout = 3, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_varallyai1982_chernozem_b_slots, +}; -static void calc_ptf_varallyai1982_chernozem_b_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double bulk_density = *(const double *)args[0]; - const double fine_fraction = *(const double *)args[1]; - const double theta_0 = - -62.20 * bulk_density - 49.14 * (fine_fraction * fine_fraction) + 140.70; - const double m = 0.635 * bulk_density - 0.482; - const double pf_star = 4.270 * bulk_density * fine_fraction + 3.509 * bulk_density - 3.075; - *(double *)args[2] = theta_0; - *(double *)args[3] = m; - *(double *)args[4] = pf_star; - for (int arg = 0; arg < 5; arg++) - args[arg] += steps[arg]; +static int calc_ptf_varallyai1982_chernozem_c_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_bulk_density = (const double *)data[0]; + const double *in_fine_fraction = (const double *)data[1]; + double *out_theta_0 = (double *)data[2]; + double *out_m = (double *)data[3]; + double *out_pf_star = (double *)data[4]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double bulk_density = in_bulk_density[index]; + const double fine_fraction = in_fine_fraction[index]; + const varallyai1982_parameters ptfkit_result = + calc_ptf_varallyai1982_chernozem_c(bulk_density, fine_fraction); + out_theta_0[index] = ptfkit_result.theta_0; + out_m[index] = ptfkit_result.m; + out_pf_star[index] = ptfkit_result.pf_star; } + return 0; } -static PyUFuncGenericFunction calc_ptf_varallyai1982_chernozem_b_functions[] = { - calc_ptf_varallyai1982_chernozem_b_loop}; -static char calc_ptf_varallyai1982_chernozem_b_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE, NPY_DOUBLE}; -static void calc_ptf_varallyai1982_chernozem_c_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double bulk_density = *(const double *)args[0]; - const double fine_fraction = *(const double *)args[1]; - const double theta_0 = -46.80 * bulk_density + 115.39; - const double m = 0.439 * bulk_density * fine_fraction + 0.625; - const double pf_star = - 3.268 * bulk_density * fine_fraction + 0.865 * (bulk_density * bulk_density) + 0.301; - *(double *)args[2] = theta_0; - *(double *)args[3] = m; - *(double *)args[4] = pf_star; - for (int arg = 0; arg < 5; arg++) - args[arg] += steps[arg]; +static int calc_ptf_varallyai1982_chernozem_c_strided_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double bulk_density = *(const double *)(data[0] + index * strides[0]); + const double fine_fraction = *(const double *)(data[1] + index * strides[1]); + const varallyai1982_parameters ptfkit_result = + calc_ptf_varallyai1982_chernozem_c(bulk_density, fine_fraction); + *(double *)(data[2] + index * strides[2]) = ptfkit_result.theta_0; + *(double *)(data[3] + index * strides[3]) = ptfkit_result.m; + *(double *)(data[4] + index * strides[4]) = ptfkit_result.pf_star; } + return 0; } -static PyUFuncGenericFunction calc_ptf_varallyai1982_chernozem_c_functions[] = { - calc_ptf_varallyai1982_chernozem_c_loop}; -static char calc_ptf_varallyai1982_chernozem_c_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE, NPY_DOUBLE}; +static PyType_Slot calc_ptf_varallyai1982_chernozem_c_slots[] = { + {NPY_METH_strided_loop, calc_ptf_varallyai1982_chernozem_c_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_varallyai1982_chernozem_c_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_varallyai1982_chernozem_c_spec = { + .name = "calc_ptf_varallyai1982_chernozem_c", + .nin = 2, + .nout = 3, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_varallyai1982_chernozem_c_slots, +}; int ptfkit_register_varallyai1982(PyObject *module) { - if (ptfkit_add_ufunc(module, "calc_ptf_varallyai1982_meadow", - calc_ptf_varallyai1982_meadow_functions, - calc_ptf_varallyai1982_meadow_types, 3, 3) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_varallyai1982_meadow", 3, 3, + &calc_ptf_varallyai1982_meadow_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_varallyai1982_chernozem_a", - calc_ptf_varallyai1982_chernozem_a_functions, - calc_ptf_varallyai1982_chernozem_a_types, 2, 3) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_varallyai1982_chernozem_a", 2, 3, + &calc_ptf_varallyai1982_chernozem_a_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_varallyai1982_chernozem_b", - calc_ptf_varallyai1982_chernozem_b_functions, - calc_ptf_varallyai1982_chernozem_b_types, 2, 3) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_varallyai1982_chernozem_b", 2, 3, + &calc_ptf_varallyai1982_chernozem_b_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_varallyai1982_chernozem_c", - calc_ptf_varallyai1982_chernozem_c_functions, - calc_ptf_varallyai1982_chernozem_c_types, 2, 3) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_varallyai1982_chernozem_c", 2, 3, + &calc_ptf_varallyai1982_chernozem_c_spec) < 0) return -1; return 0; } diff --git a/targets/ptfkit-py/src/ptfkit/varallyai1982.py b/targets/ptfkit-py/src/ptfkit/varallyai1982.py index 61c023b..b8fbb68 100644 --- a/targets/ptfkit-py/src/ptfkit/varallyai1982.py +++ b/targets/ptfkit-py/src/ptfkit/varallyai1982.py @@ -24,6 +24,7 @@ from typing import TYPE_CHECKING, Generic, NamedTuple, TypeVar, overload +from ptfkit._dispatch import call as _call from ptfkit._ptfkit import ( calc_ptf_varallyai1982_meadow as _calc_ptf_varallyai1982_meadow, calc_ptf_varallyai1982_chernozem_a as _calc_ptf_varallyai1982_chernozem_a, @@ -117,12 +118,13 @@ def calc_ptf_varallyai1982_meadow( Hungarian meadow-series soils. """ - if out is None: - values = _calc_ptf_varallyai1982_meadow(bulk_density, fine_sand_fraction, fine_fraction) - else: - values = _calc_ptf_varallyai1982_meadow( - bulk_density, fine_sand_fraction, fine_fraction, out=tuple(out) - ) + values = _call( + _calc_ptf_varallyai1982_meadow, + bulk_density, + fine_sand_fraction, + fine_fraction, + out=out, + ) return Varallyai1982Parameters(*values) @@ -177,10 +179,12 @@ def calc_ptf_varallyai1982_chernozem_a( Hungarian chernozem A horizons. """ - if out is None: - values = _calc_ptf_varallyai1982_chernozem_a(bulk_density, fine_fraction) - else: - values = _calc_ptf_varallyai1982_chernozem_a(bulk_density, fine_fraction, out=tuple(out)) + values = _call( + _calc_ptf_varallyai1982_chernozem_a, + bulk_density, + fine_fraction, + out=out, + ) return Varallyai1982Parameters(*values) @@ -235,10 +239,12 @@ def calc_ptf_varallyai1982_chernozem_b( Hungarian chernozem B horizons. """ - if out is None: - values = _calc_ptf_varallyai1982_chernozem_b(bulk_density, fine_fraction) - else: - values = _calc_ptf_varallyai1982_chernozem_b(bulk_density, fine_fraction, out=tuple(out)) + values = _call( + _calc_ptf_varallyai1982_chernozem_b, + bulk_density, + fine_fraction, + out=out, + ) return Varallyai1982Parameters(*values) @@ -293,9 +299,11 @@ def calc_ptf_varallyai1982_chernozem_c( Hungarian chernozem C horizons. """ - if out is None: - values = _calc_ptf_varallyai1982_chernozem_c(bulk_density, fine_fraction) - else: - values = _calc_ptf_varallyai1982_chernozem_c(bulk_density, fine_fraction, out=tuple(out)) + values = _call( + _calc_ptf_varallyai1982_chernozem_c, + bulk_density, + fine_fraction, + out=out, + ) return Varallyai1982Parameters(*values) diff --git a/targets/ptfkit-py/src/ptfkit/vereecken1989.c b/targets/ptfkit-py/src/ptfkit/vereecken1989.c index fc3415f..d531cbf 100644 --- a/targets/ptfkit-py/src/ptfkit/vereecken1989.c +++ b/targets/ptfkit-py/src/ptfkit/vereecken1989.c @@ -1,93 +1,171 @@ /* @generated by ptfkit-codegen; DO NOT EDIT. */ +#include #include "ufunc.h" -static void calc_ptf_vereecken1989_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double clay = *(const double *)args[1]; - const double carbon = *(const double *)args[2]; - const double bulk_density = *(const double *)args[3]; - const double theta_r = 0.015 + 0.005 * clay + 0.014 * carbon; - const double theta_s = 0.81 - 0.283 * bulk_density + 0.001 * clay; - const double ln_alpha = - -2.486 + 0.025 * sand - 0.351 * carbon - 2.617 * bulk_density - 0.023 * clay; - const double alpha = exp(ln_alpha); - const double ln_n = 0.053 - 0.009 * sand - 0.013 * clay + 0.00015 * sand * sand; - const double n = exp(ln_n); - *(double *)args[4] = theta_r; - *(double *)args[5] = theta_s; - *(double *)args[6] = alpha; - *(double *)args[7] = n; - for (int arg = 0; arg < 8; arg++) - args[arg] += steps[arg]; +static int calc_ptf_vereecken1989_contiguous_loop(PyArrayMethod_Context *context, char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_clay = (const double *)data[1]; + const double *in_carbon = (const double *)data[2]; + const double *in_bulk_density = (const double *)data[3]; + double *out_theta_r = (double *)data[4]; + double *out_theta_s = (double *)data[5]; + double *out_alpha = (double *)data[6]; + double *out_n = (double *)data[7]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double clay = in_clay[index]; + const double carbon = in_carbon[index]; + const double bulk_density = in_bulk_density[index]; + const vereecken1989_ptf_result ptfkit_result = + calc_ptf_vereecken1989(sand, clay, carbon, bulk_density); + out_theta_r[index] = ptfkit_result.theta_r; + out_theta_s[index] = ptfkit_result.theta_s; + out_alpha[index] = ptfkit_result.alpha; + out_n[index] = ptfkit_result.n; } + return 0; +} + +static int calc_ptf_vereecken1989_strided_loop(PyArrayMethod_Context *context, char *const *data, + const npy_intp *dimensions, const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double clay = *(const double *)(data[1] + index * strides[1]); + const double carbon = *(const double *)(data[2] + index * strides[2]); + const double bulk_density = *(const double *)(data[3] + index * strides[3]); + const vereecken1989_ptf_result ptfkit_result = + calc_ptf_vereecken1989(sand, clay, carbon, bulk_density); + *(double *)(data[4] + index * strides[4]) = ptfkit_result.theta_r; + *(double *)(data[5] + index * strides[5]) = ptfkit_result.theta_s; + *(double *)(data[6] + index * strides[6]) = ptfkit_result.alpha; + *(double *)(data[7] + index * strides[7]) = ptfkit_result.n; + } + return 0; } -static PyUFuncGenericFunction calc_ptf_vereecken1989_functions[] = {calc_ptf_vereecken1989_loop}; -static char calc_ptf_vereecken1989_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; +static PyType_Slot calc_ptf_vereecken1989_slots[] = { + {NPY_METH_strided_loop, calc_ptf_vereecken1989_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_vereecken1989_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_vereecken1989_spec = { + .name = "calc_ptf_vereecken1989", + .nin = 4, + .nout = 4, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_vereecken1989_slots, +}; -static void calc_ptf_vereecken1989_detailed_loop(char **args, const npy_intp *dimensions, - const npy_intp *steps, void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double particle_2000_1000 = *(const double *)args[0]; - const double particle_1000_500 = *(const double *)args[1]; - const double particle_500_200 = *(const double *)args[2]; - const double particle_200_100 = *(const double *)args[3]; - const double particle_100_50 = *(const double *)args[4]; - const double particle_50_20 = *(const double *)args[5]; - const double particle_20_10 = *(const double *)args[6]; - const double particle_10_2 = *(const double *)args[7]; - const double clay = *(const double *)args[8]; - const double geometric_mean_particle_size = *(const double *)args[9]; - const double geometric_standard_deviation = *(const double *)args[10]; - const double carbon = *(const double *)args[11]; - const double bulk_density = *(const double *)args[12]; - const double theta_r = 0.027 + 0.0094 * particle_2000_1000 - 0.0035 * particle_1000_500 - - 0.0004 * particle_500_200 - 0.0002 * particle_200_100 - - 0.0001 * particle_100_50 - 0.00028 * particle_50_20 - - 0.00006 * particle_20_10 + 0.0001 * particle_10_2 + 0.0037 * clay - - 0.045 * geometric_mean_particle_size + - 0.00538 * geometric_standard_deviation + 0.015 * carbon; - const double theta_s = 0.81 - 0.283 * bulk_density + 0.001 * clay; - const double ln_alpha = - 1.245 + 0.178 * particle_2000_1000 + 0.173 * particle_1000_500 + - 0.0292 * particle_500_200 + 0.0135 * particle_200_100 + 0.105 * particle_100_50 - - 0.0149 * particle_50_20 - 0.118 * particle_20_10 - 0.042 * particle_10_2 - - 0.0218 * clay - 14.73 * geometric_mean_particle_size - - 0.179 * geometric_standard_deviation - 0.416 * carbon - 2.507 * bulk_density; - const double alpha = exp(ln_alpha); - const double ln_n = -0.0066 - 0.0147 * particle_2000_1000 + 0.0404 * particle_1000_500 + - 0.00234 * particle_500_200 + 0.0047 * particle_200_100 - - 0.0414 * particle_100_50 - 0.007 * particle_50_20 + - 0.0300 * particle_20_10 - 0.0380 * particle_10_2 - 0.0042 * clay + - 1.0322 * geometric_mean_particle_size - - 0.0019 * geometric_standard_deviation; - const double n = exp(ln_n); - *(double *)args[13] = theta_r; - *(double *)args[14] = theta_s; - *(double *)args[15] = alpha; - *(double *)args[16] = n; - for (int arg = 0; arg < 17; arg++) - args[arg] += steps[arg]; +static int calc_ptf_vereecken1989_detailed_contiguous_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_particle_2000_1000 = (const double *)data[0]; + const double *in_particle_1000_500 = (const double *)data[1]; + const double *in_particle_500_200 = (const double *)data[2]; + const double *in_particle_200_100 = (const double *)data[3]; + const double *in_particle_100_50 = (const double *)data[4]; + const double *in_particle_50_20 = (const double *)data[5]; + const double *in_particle_20_10 = (const double *)data[6]; + const double *in_particle_10_2 = (const double *)data[7]; + const double *in_clay = (const double *)data[8]; + const double *in_geometric_mean_particle_size = (const double *)data[9]; + const double *in_geometric_standard_deviation = (const double *)data[10]; + const double *in_carbon = (const double *)data[11]; + const double *in_bulk_density = (const double *)data[12]; + double *out_theta_r = (double *)data[13]; + double *out_theta_s = (double *)data[14]; + double *out_alpha = (double *)data[15]; + double *out_n = (double *)data[16]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double particle_2000_1000 = in_particle_2000_1000[index]; + const double particle_1000_500 = in_particle_1000_500[index]; + const double particle_500_200 = in_particle_500_200[index]; + const double particle_200_100 = in_particle_200_100[index]; + const double particle_100_50 = in_particle_100_50[index]; + const double particle_50_20 = in_particle_50_20[index]; + const double particle_20_10 = in_particle_20_10[index]; + const double particle_10_2 = in_particle_10_2[index]; + const double clay = in_clay[index]; + const double geometric_mean_particle_size = in_geometric_mean_particle_size[index]; + const double geometric_standard_deviation = in_geometric_standard_deviation[index]; + const double carbon = in_carbon[index]; + const double bulk_density = in_bulk_density[index]; + const vereecken1989_detailed_ptf_result ptfkit_result = calc_ptf_vereecken1989_detailed( + particle_2000_1000, particle_1000_500, particle_500_200, particle_200_100, + particle_100_50, particle_50_20, particle_20_10, particle_10_2, clay, + geometric_mean_particle_size, geometric_standard_deviation, carbon, bulk_density); + out_theta_r[index] = ptfkit_result.theta_r; + out_theta_s[index] = ptfkit_result.theta_s; + out_alpha[index] = ptfkit_result.alpha; + out_n[index] = ptfkit_result.n; } + return 0; +} + +static int calc_ptf_vereecken1989_detailed_strided_loop(PyArrayMethod_Context *context, + char *const *data, + const npy_intp *dimensions, + const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double particle_2000_1000 = *(const double *)(data[0] + index * strides[0]); + const double particle_1000_500 = *(const double *)(data[1] + index * strides[1]); + const double particle_500_200 = *(const double *)(data[2] + index * strides[2]); + const double particle_200_100 = *(const double *)(data[3] + index * strides[3]); + const double particle_100_50 = *(const double *)(data[4] + index * strides[4]); + const double particle_50_20 = *(const double *)(data[5] + index * strides[5]); + const double particle_20_10 = *(const double *)(data[6] + index * strides[6]); + const double particle_10_2 = *(const double *)(data[7] + index * strides[7]); + const double clay = *(const double *)(data[8] + index * strides[8]); + const double geometric_mean_particle_size = *(const double *)(data[9] + index * strides[9]); + const double geometric_standard_deviation = + *(const double *)(data[10] + index * strides[10]); + const double carbon = *(const double *)(data[11] + index * strides[11]); + const double bulk_density = *(const double *)(data[12] + index * strides[12]); + const vereecken1989_detailed_ptf_result ptfkit_result = calc_ptf_vereecken1989_detailed( + particle_2000_1000, particle_1000_500, particle_500_200, particle_200_100, + particle_100_50, particle_50_20, particle_20_10, particle_10_2, clay, + geometric_mean_particle_size, geometric_standard_deviation, carbon, bulk_density); + *(double *)(data[13] + index * strides[13]) = ptfkit_result.theta_r; + *(double *)(data[14] + index * strides[14]) = ptfkit_result.theta_s; + *(double *)(data[15] + index * strides[15]) = ptfkit_result.alpha; + *(double *)(data[16] + index * strides[16]) = ptfkit_result.n; + } + return 0; } -static PyUFuncGenericFunction calc_ptf_vereecken1989_detailed_functions[] = { - calc_ptf_vereecken1989_detailed_loop}; -static char calc_ptf_vereecken1989_detailed_types[] = { - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; +static PyType_Slot calc_ptf_vereecken1989_detailed_slots[] = { + {NPY_METH_strided_loop, calc_ptf_vereecken1989_detailed_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_vereecken1989_detailed_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_vereecken1989_detailed_spec = { + .name = "calc_ptf_vereecken1989_detailed", + .nin = 13, + .nout = 4, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_vereecken1989_detailed_slots, +}; int ptfkit_register_vereecken1989(PyObject *module) { - if (ptfkit_add_ufunc(module, "calc_ptf_vereecken1989", calc_ptf_vereecken1989_functions, - calc_ptf_vereecken1989_types, 4, 4) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_vereecken1989", 4, 4, &calc_ptf_vereecken1989_spec) < 0) return -1; - if (ptfkit_add_ufunc(module, "calc_ptf_vereecken1989_detailed", - calc_ptf_vereecken1989_detailed_functions, - calc_ptf_vereecken1989_detailed_types, 13, 4) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_vereecken1989_detailed", 13, 4, + &calc_ptf_vereecken1989_detailed_spec) < 0) return -1; return 0; } diff --git a/targets/ptfkit-py/src/ptfkit/vereecken1989.py b/targets/ptfkit-py/src/ptfkit/vereecken1989.py index eb4eb12..e7aed32 100644 --- a/targets/ptfkit-py/src/ptfkit/vereecken1989.py +++ b/targets/ptfkit-py/src/ptfkit/vereecken1989.py @@ -24,6 +24,7 @@ from typing import TYPE_CHECKING, Generic, NamedTuple, TypeVar, overload +from ptfkit._dispatch import call as _call from ptfkit._ptfkit import ( calc_ptf_vereecken1989 as _calc_ptf_vereecken1989, calc_ptf_vereecken1989_detailed as _calc_ptf_vereecken1989_detailed, @@ -136,10 +137,14 @@ def calc_ptf_vereecken1989( 1.230 value is inconsistent with the reported mean. """ - if out is None: - values = _calc_ptf_vereecken1989(sand, clay, carbon, bulk_density) - else: - values = _calc_ptf_vereecken1989(sand, clay, carbon, bulk_density, out=tuple(out)) + values = _call( + _calc_ptf_vereecken1989, + sand, + clay, + carbon, + bulk_density, + out=out, + ) return Vereecken1989PTFResult(*values) @@ -245,38 +250,22 @@ def calc_ptf_vereecken1989_detailed( 1.230 value is inconsistent with the reported mean. """ - if out is None: - values = _calc_ptf_vereecken1989_detailed( - particle_2000_1000, - particle_1000_500, - particle_500_200, - particle_200_100, - particle_100_50, - particle_50_20, - particle_20_10, - particle_10_2, - clay, - geometric_mean_particle_size, - geometric_standard_deviation, - carbon, - bulk_density, - ) - else: - values = _calc_ptf_vereecken1989_detailed( - particle_2000_1000, - particle_1000_500, - particle_500_200, - particle_200_100, - particle_100_50, - particle_50_20, - particle_20_10, - particle_10_2, - clay, - geometric_mean_particle_size, - geometric_standard_deviation, - carbon, - bulk_density, - out=tuple(out), - ) + values = _call( + _calc_ptf_vereecken1989_detailed, + particle_2000_1000, + particle_1000_500, + particle_500_200, + particle_200_100, + particle_100_50, + particle_50_20, + particle_20_10, + particle_10_2, + clay, + geometric_mean_particle_size, + geometric_standard_deviation, + carbon, + bulk_density, + out=out, + ) return Vereecken1989DetailedPTFResult(*values) diff --git a/targets/ptfkit-py/src/ptfkit/wang2012.c b/targets/ptfkit-py/src/ptfkit/wang2012.c index c49dc78..7b7bd5d 100644 --- a/targets/ptfkit-py/src/ptfkit/wang2012.c +++ b/targets/ptfkit-py/src/ptfkit/wang2012.c @@ -1,49 +1,73 @@ /* @generated by ptfkit-codegen; DO NOT EDIT. */ +#include #include "ufunc.h" -static void calc_ptf_wang2012_loop(char **args, const npy_intp *dimensions, const npy_intp *steps, - void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double sand = *(const double *)args[0]; - const double silt = *(const double *)args[1]; - const double clay = *(const double *)args[2]; - const double bulk_density = *(const double *)args[3]; - const double soil_organic_carbon = *(const double *)args[4]; - const double altitude = *(const double *)args[5]; - const double soil_organic_carbon_g_per_kg = 10.0 * soil_organic_carbon; - const double bulk_density_squared = bulk_density * bulk_density; - const double log10_sand = log10(sand); - const double log10_k_sat_cm_per_day = 1.173 + 0.038 * silt + 0.690 * log10_sand + - 0.865 / sand - 0.030 * bulk_density * silt - - 0.00000995 * soil_organic_carbon_g_per_kg * altitude; - const double k_sat_cm_per_day = pow(10.0, log10_k_sat_cm_per_day); - const double fc_percent = - 46.481 - 4.757 * soil_organic_carbon_g_per_kg - 14.028 * log10(clay) - - 13.991 * log10_sand + 42.261 * log10(soil_organic_carbon_g_per_kg) - 11.763 / sand + - 19.198 / soil_organic_carbon_g_per_kg - 5.448 * bulk_density_squared + - 0.044 * (soil_organic_carbon_g_per_kg * soil_organic_carbon_g_per_kg) + - 1.975 * bulk_density * soil_organic_carbon_g_per_kg; - const double sswc_percent = 98.813 - 21.555 / bulk_density - 39.735 / silt - 2.091 / sand + - 3.247 / soil_organic_carbon_g_per_kg - - 17.096 * bulk_density_squared; - const double theta_s = sswc_percent / 100.0; - const double theta_fc = fc_percent / 100.0; - const double k_sat = k_sat_cm_per_day / 8640000.0; - *(double *)args[6] = theta_s; - *(double *)args[7] = theta_fc; - *(double *)args[8] = k_sat; - for (int arg = 0; arg < 9; arg++) - args[arg] += steps[arg]; +static int calc_ptf_wang2012_contiguous_loop(PyArrayMethod_Context *context, char *const *data, + const npy_intp *dimensions, const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_sand = (const double *)data[0]; + const double *in_silt = (const double *)data[1]; + const double *in_clay = (const double *)data[2]; + const double *in_bulk_density = (const double *)data[3]; + const double *in_soil_organic_carbon = (const double *)data[4]; + const double *in_altitude = (const double *)data[5]; + double *out_theta_s = (double *)data[6]; + double *out_theta_fc = (double *)data[7]; + double *out_k_sat = (double *)data[8]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = in_sand[index]; + const double silt = in_silt[index]; + const double clay = in_clay[index]; + const double bulk_density = in_bulk_density[index]; + const double soil_organic_carbon = in_soil_organic_carbon[index]; + const double altitude = in_altitude[index]; + const wang2012_ptf_result ptfkit_result = + calc_ptf_wang2012(sand, silt, clay, bulk_density, soil_organic_carbon, altitude); + out_theta_s[index] = ptfkit_result.theta_s; + out_theta_fc[index] = ptfkit_result.theta_fc; + out_k_sat[index] = ptfkit_result.k_sat; } + return 0; +} + +static int calc_ptf_wang2012_strided_loop(PyArrayMethod_Context *context, char *const *data, + const npy_intp *dimensions, const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double sand = *(const double *)(data[0] + index * strides[0]); + const double silt = *(const double *)(data[1] + index * strides[1]); + const double clay = *(const double *)(data[2] + index * strides[2]); + const double bulk_density = *(const double *)(data[3] + index * strides[3]); + const double soil_organic_carbon = *(const double *)(data[4] + index * strides[4]); + const double altitude = *(const double *)(data[5] + index * strides[5]); + const wang2012_ptf_result ptfkit_result = + calc_ptf_wang2012(sand, silt, clay, bulk_density, soil_organic_carbon, altitude); + *(double *)(data[6] + index * strides[6]) = ptfkit_result.theta_s; + *(double *)(data[7] + index * strides[7]) = ptfkit_result.theta_fc; + *(double *)(data[8] + index * strides[8]) = ptfkit_result.k_sat; + } + return 0; } -static PyUFuncGenericFunction calc_ptf_wang2012_functions[] = {calc_ptf_wang2012_loop}; -static char calc_ptf_wang2012_types[] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; +static PyType_Slot calc_ptf_wang2012_slots[] = { + {NPY_METH_strided_loop, calc_ptf_wang2012_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_wang2012_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_wang2012_spec = { + .name = "calc_ptf_wang2012", + .nin = 6, + .nout = 3, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_wang2012_slots, +}; int ptfkit_register_wang2012(PyObject *module) { - if (ptfkit_add_ufunc(module, "calc_ptf_wang2012", calc_ptf_wang2012_functions, - calc_ptf_wang2012_types, 6, 3) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_wang2012", 6, 3, &calc_ptf_wang2012_spec) < 0) return -1; return 0; } diff --git a/targets/ptfkit-py/src/ptfkit/wang2012.py b/targets/ptfkit-py/src/ptfkit/wang2012.py index 03848fc..2f64664 100644 --- a/targets/ptfkit-py/src/ptfkit/wang2012.py +++ b/targets/ptfkit-py/src/ptfkit/wang2012.py @@ -21,6 +21,7 @@ from typing import TYPE_CHECKING, Generic, NamedTuple, TypeVar, overload +from ptfkit._dispatch import call as _call from ptfkit._ptfkit import ( calc_ptf_wang2012 as _calc_ptf_wang2012, ) @@ -119,11 +120,15 @@ def calc_ptf_wang2012( 100. """ - if out is None: - values = _calc_ptf_wang2012(sand, silt, clay, bulk_density, soil_organic_carbon, altitude) - else: - values = _calc_ptf_wang2012( - sand, silt, clay, bulk_density, soil_organic_carbon, altitude, out=tuple(out) - ) + values = _call( + _calc_ptf_wang2012, + sand, + silt, + clay, + bulk_density, + soil_organic_carbon, + altitude, + out=out, + ) return Wang2012PTFResult(*values) diff --git a/targets/ptfkit-py/src/ptfkit/weber2020.c b/targets/ptfkit-py/src/ptfkit/weber2020.c index b4203b1..baf5518 100644 --- a/targets/ptfkit-py/src/ptfkit/weber2020.c +++ b/targets/ptfkit-py/src/ptfkit/weber2020.c @@ -1,44 +1,85 @@ /* @generated by ptfkit-codegen; DO NOT EDIT. */ +#include #include "ufunc.h" -static void calc_ptf_weber2020_loop(char **args, const npy_intp *dimensions, const npy_intp *steps, - void *data) { - npy_intp index; - for (index = 0; index < dimensions[0]; index++) { - const double theta_r_vgm = *(const double *)args[0]; - const double theta_s_vgm = *(const double *)args[1]; - const double alpha_vgm = *(const double *)args[2]; - const double n_vgm = *(const double *)args[3]; - const double tau_vgm = *(const double *)args[4]; - const double k_s_vgm = *(const double *)args[5]; - const double theta_snc_bw = -1.58e-3 + 1.285 * theta_r_vgm; - const double theta_s_bw = 1.89e-3 + 0.993 * theta_s_vgm; - const double theta_sc_bw = theta_s_bw - theta_snc_bw; - const double alpha_bw = pow(10.0, -2.06e-2 + 0.986 * log10(alpha_vgm)); - const double n_bw = 1.0 + pow(10.0, 6.42e-2 + 0.933 * log10(n_vgm - 1.0)); - const double tau_vgm_constrained = fmin(tau_vgm, 0.0); - const double tau_bw = 2.95e-2 + 1.833 * tau_vgm_constrained; - const double k_sc_bw = pow(10.0, 1.16e-1 + 1.060 * log10(k_s_vgm)); - const double k_snc_bw = pow(10.0, -1.72); - *(double *)args[6] = theta_snc_bw; - *(double *)args[7] = theta_sc_bw; - *(double *)args[8] = alpha_bw; - *(double *)args[9] = n_bw; - *(double *)args[10] = tau_bw; - *(double *)args[11] = k_sc_bw; - *(double *)args[12] = k_snc_bw; - for (int arg = 0; arg < 13; arg++) - args[arg] += steps[arg]; +static int calc_ptf_weber2020_contiguous_loop(PyArrayMethod_Context *context, char *const *data, + const npy_intp *dimensions, const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)strides; + (void)transferdata; + const double *in_theta_r_vgm = (const double *)data[0]; + const double *in_theta_s_vgm = (const double *)data[1]; + const double *in_alpha_vgm = (const double *)data[2]; + const double *in_n_vgm = (const double *)data[3]; + const double *in_tau_vgm = (const double *)data[4]; + const double *in_k_s_vgm = (const double *)data[5]; + double *out_theta_snc_bw = (double *)data[6]; + double *out_theta_sc_bw = (double *)data[7]; + double *out_alpha_bw = (double *)data[8]; + double *out_n_bw = (double *)data[9]; + double *out_tau_bw = (double *)data[10]; + double *out_k_sc_bw = (double *)data[11]; + double *out_k_snc_bw = (double *)data[12]; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double theta_r_vgm = in_theta_r_vgm[index]; + const double theta_s_vgm = in_theta_s_vgm[index]; + const double alpha_vgm = in_alpha_vgm[index]; + const double n_vgm = in_n_vgm[index]; + const double tau_vgm = in_tau_vgm[index]; + const double k_s_vgm = in_k_s_vgm[index]; + const weber2020_ptf_result ptfkit_result = + calc_ptf_weber2020(theta_r_vgm, theta_s_vgm, alpha_vgm, n_vgm, tau_vgm, k_s_vgm); + out_theta_snc_bw[index] = ptfkit_result.theta_snc_bw; + out_theta_sc_bw[index] = ptfkit_result.theta_sc_bw; + out_alpha_bw[index] = ptfkit_result.alpha_bw; + out_n_bw[index] = ptfkit_result.n_bw; + out_tau_bw[index] = ptfkit_result.tau_bw; + out_k_sc_bw[index] = ptfkit_result.k_sc_bw; + out_k_snc_bw[index] = ptfkit_result.k_snc_bw; } + return 0; +} + +static int calc_ptf_weber2020_strided_loop(PyArrayMethod_Context *context, char *const *data, + const npy_intp *dimensions, const npy_intp *strides, + NpyAuxData *transferdata) { + (void)context; + (void)transferdata; + for (npy_intp index = 0; index < dimensions[0]; index++) { + const double theta_r_vgm = *(const double *)(data[0] + index * strides[0]); + const double theta_s_vgm = *(const double *)(data[1] + index * strides[1]); + const double alpha_vgm = *(const double *)(data[2] + index * strides[2]); + const double n_vgm = *(const double *)(data[3] + index * strides[3]); + const double tau_vgm = *(const double *)(data[4] + index * strides[4]); + const double k_s_vgm = *(const double *)(data[5] + index * strides[5]); + const weber2020_ptf_result ptfkit_result = + calc_ptf_weber2020(theta_r_vgm, theta_s_vgm, alpha_vgm, n_vgm, tau_vgm, k_s_vgm); + *(double *)(data[6] + index * strides[6]) = ptfkit_result.theta_snc_bw; + *(double *)(data[7] + index * strides[7]) = ptfkit_result.theta_sc_bw; + *(double *)(data[8] + index * strides[8]) = ptfkit_result.alpha_bw; + *(double *)(data[9] + index * strides[9]) = ptfkit_result.n_bw; + *(double *)(data[10] + index * strides[10]) = ptfkit_result.tau_bw; + *(double *)(data[11] + index * strides[11]) = ptfkit_result.k_sc_bw; + *(double *)(data[12] + index * strides[12]) = ptfkit_result.k_snc_bw; + } + return 0; } -static PyUFuncGenericFunction calc_ptf_weber2020_functions[] = {calc_ptf_weber2020_loop}; -static char calc_ptf_weber2020_types[] = { - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, - NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; +static PyType_Slot calc_ptf_weber2020_slots[] = { + {NPY_METH_strided_loop, calc_ptf_weber2020_strided_loop}, + {NPY_METH_contiguous_loop, calc_ptf_weber2020_contiguous_loop}, + {0, NULL}, +}; +static PyArrayMethod_Spec calc_ptf_weber2020_spec = { + .name = "calc_ptf_weber2020", + .nin = 6, + .nout = 7, + .casting = NPY_SAME_KIND_CASTING, + .slots = calc_ptf_weber2020_slots, +}; int ptfkit_register_weber2020(PyObject *module) { - if (ptfkit_add_ufunc(module, "calc_ptf_weber2020", calc_ptf_weber2020_functions, - calc_ptf_weber2020_types, 6, 7) < 0) + if (ptfkit_add_ufunc(module, "calc_ptf_weber2020", 6, 7, &calc_ptf_weber2020_spec) < 0) return -1; return 0; } diff --git a/targets/ptfkit-py/src/ptfkit/weber2020.py b/targets/ptfkit-py/src/ptfkit/weber2020.py index 09f1568..f2f38b0 100644 --- a/targets/ptfkit-py/src/ptfkit/weber2020.py +++ b/targets/ptfkit-py/src/ptfkit/weber2020.py @@ -24,6 +24,7 @@ from typing import TYPE_CHECKING, Generic, NamedTuple, TypeVar, overload +from ptfkit._dispatch import call as _call from ptfkit._ptfkit import ( calc_ptf_weber2020 as _calc_ptf_weber2020, ) @@ -131,11 +132,15 @@ def calc_ptf_weber2020( interpreted as being based on nonpositive tau_vgm values. """ - if out is None: - values = _calc_ptf_weber2020(theta_r_vgm, theta_s_vgm, alpha_vgm, n_vgm, tau_vgm, k_s_vgm) - else: - values = _calc_ptf_weber2020( - theta_r_vgm, theta_s_vgm, alpha_vgm, n_vgm, tau_vgm, k_s_vgm, out=tuple(out) - ) + values = _call( + _calc_ptf_weber2020, + theta_r_vgm, + theta_s_vgm, + alpha_vgm, + n_vgm, + tau_vgm, + k_s_vgm, + out=out, + ) return Weber2020PTFResult(*values)