Propagate Function
Name
UxHwDoublePropagateFunction, UxHwFloatPropagateFunction — Propagate a distribution through a user-defined function.
Synopsis
#include <stddef.h>
#include <uxhw.h>
void
UxHwDoublePropagateFunction(
void (*functionToPropagate)(void *, double *, size_t, double *, size_t),
void * functionArgs,
uncertain double * inputDistributionArray,
size_t numberOfInputDistributions,
uncertain double * outputDistributionArray,
size_t numberOfOutputDistributions);
void
UxHwFloatPropagateFunction(
void (*functionToPropagate)(void *, float *, size_t, float *, size_t),
void * functionArgs,
uncertain float * inputDistributionArray,
size_t numberOfInputDistributions,
uncertain float * outputDistributionArray,
size_t numberOfOutputDistributions);
Description
UxHw-enabled hardware natively supports arithmetic and common unary and binary mathematical functions for distributional values. Users that require custom functionality that is not supported by the default operations can use UxHw<Double/Float>PropagateFunction to run them with distributional-valued variables.
UxHw<Double/Float>PropagateFunction, on architectures that associate distributions with floating-point values, evaluates a user-defined functionToPropagate over a distribution array inputDistributionArray, with length numberOfInputDistributions, and writes the resulting distribution array into outputDistributionArray, with length numberOfOutputDistributions.
Computationally, this implies evaluating functionToPropagate over the inputDistributionArray joint distribution. In mathematical terms, this function evaluates the push-forward of the aforementioned joint distribution :
where is the functionToPropagate, is the functionArgs, is the inputDistributionArray, numberOfInputDistributions, is the outputDistributionArray and numberOfOutputDistributions.
Notes
- Joint distribution creation, preceding function evaluation is core-dependent. Dependency-tracking cores (e.g., Jupiter) internally track the dependencies and their outputs do not lose dependency from the inputs.
PropagateFunctiondoes not filter forNaNorInfinput values. Non-finite value behavior should be addressed infunctionToPropagate.
Parameters
(*functionToPropagate)(void *, <double/float> *, size_t, <double/float> *, size_t)— The user-defined function pointer for distribution propagation. IfNULL, the function prints a warning and the function returns immediately.functionArgs— Opaque pointer with user-defined function parameters. Non-distributional variables and constants should be added here.inputDistributionArray— Array of distributions taken byfunctionToPropagate. IfNULL, the function prints a warning and the function returns immediately.numberOfInputDistributions— Number of elements ininputDistributionArray. If0, the function prints a warning and the function returns immediately.outputDistributionArray— Array of distributions returned byfunctionToPropagate. IfNULL, the function prints a warning and the function returns immediately.numberOfOutputDistributions— Number of elements inoutputDistributionArray. If0, the function prints a warning and the function returns immediately.
Return values
UxHw<Double/Float>PropagateFunction returns void.
Suggested usage
UxHw<Double/Float>PropagateFunction is especially useful when evaluating mathematical functions that contain control flow expressions, such as conditional and ternary operators. Likewise, mathematical functions defined in non-UxHw-compiled libraries must also be called through UxHw<Double/Float>PropagateFunction, as they do not natively support distributional values.
Examples
Absolute value through PropagateFunction vs fabs native libm function
#include <stdio.h>
#include <uxhw.h>
#include<math.h>
enum
{
kExampleInputCount = 1,
kExampleOutputCount = 1,
};
static void
absoluteValueKernel(void * arguments, double * inputs, size_t inputCount, double * outputs, size_t outputCount)
{
(void) arguments;
(void) inputCount;
(void) outputCount;
if (inputs[0] < 0.0)
{
outputs[0] = -inputs[0];
}
else
{
outputs[0] = inputs[0];
}
return;
}
int
main(void)
{
double x = UxHwDoubleGaussDist(0.0, 1.0);
double absoluteValue = 0.0;
UxHwDoublePropagateFunction(absoluteValueKernel, NULL, &x, kExampleInputCount, &absoluteValue, kExampleOutputCount);
printf(
"|x| (via PropagateFunction) = %lf\n"
"|x| (via native libm func.) = %lf\n",
absoluteValue,
fabs(x)
);
return 0;
}
Custom parametric function
#include <stdio.h>
#include <uxhw.h>
/* Called once per joint input row: in[0..nIn), out[0..nOut) are plain doubles. */
static void
f(void *args, double *in, size_t nIn, double *out, size_t nOut)
{
double k = *(double *)args;
out[0] = k * in[0] + in[1]; /* linear */
out[1] = in[0] * in[1]; /* nonlinear */
}
int
main(void)
{
double k = 2.0;
double in[2] = {UxHwDoubleGaussDist(1.0, 0.1), UxHwDoubleUniformDist(0.0, 1.0)};
double out[2];
UxHwDoublePropagateFunction(f, &k, in, 2, out, 2);
printf("out[0] = %lf\n", out[0]);
printf("out[1] = %lf\n", out[1]);
return 0;
}