From 8b7923f81ee229b9833d561a84774928e29d839c Mon Sep 17 00:00:00 2001 From: Petr Tsymbarovich Date: Tue, 25 Aug 2026 17:21:18 +0300 Subject: [PATCH] feat(python): add NumPy ArrayMethod float64 loops Use native ptfkit headers for generated ufunc kernels and register contiguous and strided float64 ArrayMethod loops. Package the native headers in source distributions, preserve scalar wrapper behaviour through a shared private dispatch helper, and keep generated wrappers focused on argument wiring and result construction. --- codegen/src/targets/python/extension.rs | 122 +- codegen/src/targets/python/wrapper.rs | 40 +- targets/ptfkit-py/CMakeLists.txt | 7 +- targets/ptfkit-py/pyproject.toml | 3 + targets/ptfkit-py/src/ptfkit/_dispatch.py | 14 + targets/ptfkit-py/src/ptfkit/ahuja1984.c | 69 +- targets/ptfkit-py/src/ptfkit/ahuja1984.py | 15 +- targets/ptfkit-py/src/ptfkit/aimrun2009.c | 70 +- targets/ptfkit-py/src/ptfkit/aimrun2009.py | 15 +- targets/ptfkit-py/src/ptfkit/beniaich2023.c | 799 +++-- targets/ptfkit-py/src/ptfkit/beniaich2023.py | 109 +- .../ptfkit-py/src/ptfkit/chakraborty2011.c | 528 ++- .../ptfkit-py/src/ptfkit/chakraborty2011.py | 70 +- targets/ptfkit-py/src/ptfkit/cosby1984.c | 101 +- targets/ptfkit-py/src/ptfkit/cosby1984.py | 12 +- .../ptfkit-py/src/ptfkit/dharumarajan2019.c | 353 +- .../ptfkit-py/src/ptfkit/dharumarajan2019.py | 58 +- .../ptfkit-py/src/ptfkit/ferrerjulia2004.c | 2852 ++++++++++++----- .../ptfkit-py/src/ptfkit/ferrerjulia2004.py | 561 ++-- targets/ptfkit-py/src/ptfkit/hodnett2002.c | 109 +- targets/ptfkit-py/src/ptfkit/hodnett2002.py | 27 +- targets/ptfkit-py/src/ptfkit/jabro1992.c | 63 +- targets/ptfkit-py/src/ptfkit/jabro1992.py | 14 +- targets/ptfkit-py/src/ptfkit/li2007.c | 99 +- targets/ptfkit-py/src/ptfkit/li2007.py | 16 +- targets/ptfkit-py/src/ptfkit/mayr1999.c | 97 +- targets/ptfkit-py/src/ptfkit/mayr1999.py | 14 +- targets/ptfkit-py/src/ptfkit/oosterveld1980.c | 344 +- .../ptfkit-py/src/ptfkit/oosterveld1980.py | 65 +- targets/ptfkit-py/src/ptfkit/pidgeon1972.c | 1155 +++++-- targets/ptfkit-py/src/ptfkit/pidgeon1972.py | 206 +- targets/ptfkit-py/src/ptfkit/ptfkit.c | 1 + targets/ptfkit-py/src/ptfkit/puckett1985.c | 123 +- targets/ptfkit-py/src/ptfkit/puckett1985.py | 16 +- targets/ptfkit-py/src/ptfkit/rawls1982.c | 271 +- targets/ptfkit-py/src/ptfkit/rawls1982.py | 43 +- targets/ptfkit-py/src/ptfkit/saxton2006.c | 608 ++-- targets/ptfkit-py/src/ptfkit/saxton2006.py | 106 +- targets/ptfkit-py/src/ptfkit/tiwary2014.c | 158 +- targets/ptfkit-py/src/ptfkit/tiwary2014.py | 30 +- targets/ptfkit-py/src/ptfkit/ufunc.h | 15 +- targets/ptfkit-py/src/ptfkit/varallyai1982.c | 313 +- targets/ptfkit-py/src/ptfkit/varallyai1982.py | 44 +- targets/ptfkit-py/src/ptfkit/vereecken1989.c | 236 +- targets/ptfkit-py/src/ptfkit/vereecken1989.py | 63 +- targets/ptfkit-py/src/ptfkit/wang2012.c | 102 +- targets/ptfkit-py/src/ptfkit/wang2012.py | 17 +- targets/ptfkit-py/src/ptfkit/weber2020.c | 109 +- targets/ptfkit-py/src/ptfkit/weber2020.py | 17 +- 49 files changed, 6897 insertions(+), 3382 deletions(-) create mode 100644 targets/ptfkit-py/src/ptfkit/_dispatch.py 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)