Block type: roundingFunction
| Parameter | Description |
|---|---|
| input ports | 1 input port(s) declared. |
| Parameter | Description |
|---|---|
| output ports | 1 output port(s) declared. |
Rounds the input to an integer value.
| Module |
nflow_blocks
|
| Library | Math blocks |
| Type |
roundingFunction
|
| Label | Rounding Function |
Description
Applies the rounding mode selected by the Operator parameter, element-wise, with scalar expansion for vector signals.
Operator
floor: round toward minus infinity.
ceil: round toward plus infinity.
round: round to the nearest integer, ties away from zero.
fix: truncate toward zero.
This page describes the native runtime behavior observed in the module C++ sources. Declared phases indicate when the simulation engine calls the block.
Code generation: supported for C and Rust.
Implementation Sources
modules/nflow_blocks/libraries/math/library.json{
"id": "builtin.math",
"title": "Math",
"version": "1.0.0",
"format": "nflow-2",
"metadata": {
"author": "Allan CORNET",
"created": "2026-03-21",
"tool": "Nelson nflow"
},
"builtin": true,
"comment": "Basic math blocks",
"license": "LGPL-3.0",
"blocks": [
{
"type": "matmul",
"label": "MatMul",
"icon": "matmul.svg",
"phases": [
"ALGEBRAIC"
],
"width": 60,
"height": 60,
"inputs": [
{
"x": 0,
"y": 20,
"side": "left"
},
{
"x": 0,
"y": 40,
"side": "left"
}
],
"outputs": [
{
"x": 60,
"y": 30,
"side": "right"
}
],
"defaultParams": {
"MultiplicationRule": "matrix"
}
},
{
"type": "sumElements",
"label": "Sum of Elements",
"icon": "sumElements.svg",
"phases": [
"ALGEBRAIC"
],
"width": 80,
"height": 80,
"inputs": [
{
"x": 0,
"y": 40,
"side": "left"
}
],
"outputs": [
{
"x": 80,
"y": 40,
"side": "right"
}
],
"defaultParams": {},
"render": {
"type": "image",
"src": "exports/sumElements.svg",
"svgMode": "element",
"preserveAspectRatio": "none",
"x": 0,
"y": 0,
"width": 80,
"height": 80
}
},
{
"type": "productOfElements",
"label": "Product of Elements",
"icon": "productOfElements.svg",
"phases": [
"ALGEBRAIC"
],
"width": 80,
"height": 80,
"inputs": [
{
"x": 0,
"y": 40,
"side": "left"
}
],
"outputs": [
{
"x": 80,
"y": 40,
"side": "right"
}
],
"defaultParams": {},
"render": {
"type": "image",
"src": "exports/productOfElements.svg",
"svgMode": "element",
"preserveAspectRatio": "none",
"x": 0,
"y": 0,
"width": 80,
"height": 80
}
},
{
"type": "dotProduct",
"label": "Dot Product",
"icon": "dotProduct.svg",
"phases": [
"ALGEBRAIC"
],
"width": 80,
"height": 80,
"inputs": [
{
"x": 0,
"y": 30,
"side": "left"
},
{
"x": 0,
"y": 50,
"side": "left"
}
],
"outputs": [
{
"x": 80,
"y": 40,
"side": "right"
}
],
"defaultParams": {},
"render": {
"type": "image",
"src": "exports/dotProduct.svg",
"svgMode": "element",
"preserveAspectRatio": "none",
"x": 0,
"y": 0,
"width": 80,
"height": 80
}
},
{
"type": "crossProduct",
"label": "Cross Product",
"icon": "crossProduct.svg",
"phases": [
"ALGEBRAIC"
],
"width": 80,
"height": 80,
"inputs": [
{
"x": 0,
"y": 30,
"side": "left"
},
{
"x": 0,
"y": 50,
"side": "left"
}
],
"outputs": [
{
"x": 80,
"y": 40,
"side": "right"
}
],
"defaultParams": {},
"render": {
"type": "image",
"src": "exports/crossProduct.svg",
"svgMode": "element",
"preserveAspectRatio": "none",
"x": 0,
"y": 0,
"width": 80,
"height": 80
}
},
{
"type": "gain",
"label": "Gain",
"icon": "gain.svg",
"phases": [
"ALGEBRAIC"
],
"width": 100,
"height": 80,
"inputs": [
{
"x": 0,
"y": 40,
"side": "left"
}
],
"outputs": [
{
"x": 100,
"y": 40,
"side": "right"
}
],
"defaultParams": {
"Gain": 2
},
"render": {
"type": "math",
"formula": "{params.Gain}",
"mathGroupClass": "gain-math",
"textSize": "16px",
"width": 100,
"height": 80
}
},
{
"type": "sum",
"label": "Sum",
"icon": "sum.svg",
"phases": [
"ALGEBRAIC"
],
"width": 20,
"height": 20,
"inputs": [
{
"x": -30,
"y": 10,
"side": "left",
"wireX": -10,
"wireY": 10
},
{
"x": 10,
"y": -30,
"side": "top",
"wireX": 10,
"wireY": -10
},
{
"x": 10,
"y": 50,
"side": "bottom",
"wireX": 10,
"wireY": 30
}
],
"outputs": [
{
"x": 50,
"y": 10,
"side": "right",
"wireX": 30,
"wireY": 10
}
],
"defaultParams": {
"Inputs": "+++"
},
"render": {
"type": "math",
"formula": "\\oplus",
"mathGroupClass": "sum-math",
"textSize": "16px",
"width": 20,
"height": 20
}
},
{
"type": "mult",
"label": "Mult",
"icon": "mult.svg",
"phases": [
"ALGEBRAIC"
],
"width": 20,
"height": 20,
"inputs": [
{
"x": -30,
"y": 10,
"side": "left",
"wireX": -10,
"wireY": 10
},
{
"x": 10,
"y": -30,
"side": "top",
"wireX": 10,
"wireY": -10
},
{
"x": 10,
"y": 50,
"side": "bottom",
"wireX": 10,
"wireY": 30
}
],
"outputs": [
{
"x": 50,
"y": 10,
"side": "right",
"wireX": 30,
"wireY": 10
}
],
"defaultParams": {},
"render": {
"type": "math",
"formula": "\\otimes",
"mathGroupClass": "mult-math",
"textSize": "16px",
"width": 20,
"height": 20
}
},
{
"type": "abs",
"label": "Abs",
"icon": "abs.svg",
"phases": [
"ALGEBRAIC"
],
"width": 80,
"height": 80,
"inputs": [
{
"x": 0,
"y": 40,
"side": "left"
}
],
"outputs": [
{
"x": 80,
"y": 40,
"side": "right"
}
],
"defaultParams": {},
"render": {
"type": "math",
"formula": "|x|",
"mathGroupClass": "abs-math",
"textSize": "16px",
"width": 80,
"height": 80
}
},
{
"type": "mathFunction",
"label": "Math Function",
"icon": "mathFunction.svg",
"phases": [
"ALGEBRAIC"
],
"width": 80,
"height": 80,
"inputs": [
{
"x": 0,
"y": 40,
"side": "left"
}
],
"outputs": [
{
"x": 80,
"y": 40,
"side": "right"
}
],
"defaultParams": {
"Function": "exp"
},
"render": {
"type": "image",
"src": "exports/mathFunction.svg",
"svgMode": "element",
"preserveAspectRatio": "none",
"x": 0,
"y": 0,
"width": 80,
"height": 80
}
},
{
"type": "trigFunction",
"label": "Trigonometric Function",
"icon": "trigFunction.svg",
"phases": [
"ALGEBRAIC"
],
"width": 80,
"height": 80,
"inputs": [
{
"x": 0,
"y": 40,
"side": "left"
}
],
"outputs": [
{
"x": 80,
"y": 40,
"side": "right"
}
],
"defaultParams": {
"Function": "sin"
},
"render": {
"type": "image",
"src": "exports/trigFunction.svg",
"svgMode": "element",
"preserveAspectRatio": "none",
"x": 0,
"y": 0,
"width": 80,
"height": 80
}
},
{
"type": "roundingFunction",
"label": "Rounding Function",
"icon": "roundingFunction.svg",
"phases": [
"ALGEBRAIC"
],
"width": 80,
"height": 80,
"inputs": [
{
"x": 0,
"y": 40,
"side": "left"
}
],
"outputs": [
{
"x": 80,
"y": 40,
"side": "right"
}
],
"defaultParams": {
"Operator": "floor"
},
"render": {
"type": "image",
"src": "exports/roundingFunction.svg",
"svgMode": "element",
"preserveAspectRatio": "none",
"x": 0,
"y": 0,
"width": 80,
"height": 80
}
},
{
"type": "sign",
"label": "Sign",
"icon": "sign.svg",
"phases": [
"ALGEBRAIC"
],
"width": 80,
"height": 80,
"inputs": [
{
"x": 0,
"y": 40,
"side": "left"
}
],
"outputs": [
{
"x": 80,
"y": 40,
"side": "right"
}
],
"defaultParams": {},
"render": {
"type": "image",
"src": "exports/sign.svg",
"svgMode": "element",
"preserveAspectRatio": "none",
"x": 0,
"y": 0,
"width": 80,
"height": 80
}
},
{
"type": "sqrt",
"label": "Sqrt",
"icon": "sqrt.svg",
"phases": [
"ALGEBRAIC"
],
"width": 80,
"height": 80,
"inputs": [
{
"x": 0,
"y": 40,
"side": "left"
}
],
"outputs": [
{
"x": 80,
"y": 40,
"side": "right"
}
],
"defaultParams": {
"Function": "sqrt"
},
"render": {
"type": "image",
"src": "exports/sqrt.svg",
"svgMode": "element",
"preserveAspectRatio": "none",
"x": 0,
"y": 0,
"width": 80,
"height": 80
}
},
{
"type": "divide",
"label": "Divide",
"icon": "divide.svg",
"phases": [
"ALGEBRAIC"
],
"width": 80,
"height": 80,
"inputs": [
{
"x": 0,
"y": 30,
"side": "left"
},
{
"x": 0,
"y": 50,
"side": "left"
}
],
"outputs": [
{
"x": 80,
"y": 40,
"side": "right"
}
],
"defaultParams": {},
"render": {
"type": "image",
"src": "exports/divide.svg",
"svgMode": "element",
"preserveAspectRatio": "none",
"x": 0,
"y": 0,
"width": 80,
"height": 80
}
},
{
"type": "negate",
"label": "Negate",
"icon": "negate.svg",
"phases": [
"ALGEBRAIC"
],
"width": 80,
"height": 80,
"inputs": [
{
"x": 0,
"y": 40,
"side": "left"
}
],
"outputs": [
{
"x": 80,
"y": 40,
"side": "right"
}
],
"defaultParams": {},
"render": {
"type": "image",
"src": "exports/negate.svg",
"svgMode": "element",
"preserveAspectRatio": "none",
"x": 0,
"y": 0,
"width": 80,
"height": 80
}
},
{
"type": "bias",
"label": "Bias",
"icon": "bias.svg",
"phases": [
"ALGEBRAIC"
],
"width": 80,
"height": 80,
"inputs": [
{
"x": 0,
"y": 40,
"side": "left"
}
],
"outputs": [
{
"x": 80,
"y": 40,
"side": "right"
}
],
"defaultParams": {
"Bias": 1
},
"render": {
"type": "image",
"src": "exports/bias.svg",
"svgMode": "element",
"preserveAspectRatio": "none",
"x": 0,
"y": 0,
"width": 80,
"height": 80
}
},
{
"type": "min",
"label": "Min",
"icon": "min.svg",
"phases": [
"ALGEBRAIC"
],
"width": 80,
"height": 80,
"inputs": [
{
"x": 0,
"y": 30,
"side": "left"
},
{
"x": 0,
"y": 50,
"side": "left"
}
],
"outputs": [
{
"x": 80,
"y": 40,
"side": "right"
}
],
"defaultParams": {},
"render": {
"type": "math",
"formula": "min(x,y)",
"mathGroupClass": "min-math",
"textSize": "16px",
"width": 80,
"height": 80
}
},
{
"type": "max",
"label": "Max",
"icon": "max.svg",
"phases": [
"ALGEBRAIC"
],
"width": 80,
"height": 80,
"inputs": [
{
"x": 0,
"y": 30,
"side": "left"
},
{
"x": 0,
"y": 50,
"side": "left"
}
],
"outputs": [
{
"x": 80,
"y": 40,
"side": "right"
}
],
"defaultParams": {},
"render": {
"type": "math",
"formula": "max(x,y)",
"mathGroupClass": "max-math",
"textSize": "16px",
"width": 80,
"height": 80
}
},
{
"type": "realImagToComplex",
"label": "Re-Im to Complex",
"icon": "realImagToComplex.svg",
"phases": [
"ALGEBRAIC"
],
"width": 60,
"height": 60,
"inputs": [
{
"x": 0,
"y": 20,
"side": "left"
},
{
"x": 0,
"y": 40,
"side": "left"
}
],
"outputs": [
{
"x": 60,
"y": 30,
"side": "right"
}
],
"defaultParams": {}
},
{
"type": "complexToRealImag",
"label": "Complex to Re-Im",
"icon": "complexToRealImag.svg",
"phases": [
"ALGEBRAIC"
],
"width": 60,
"height": 60,
"inputs": [
{
"x": 0,
"y": 30,
"side": "left"
}
],
"outputs": [
{
"x": 60,
"y": 20,
"side": "right"
},
{
"x": 60,
"y": 40,
"side": "right"
}
],
"defaultParams": {}
},
{
"type": "magnitudeAngleToComplex",
"label": "Mag-Angle to Complex",
"icon": "magnitudeAngleToComplex.svg",
"phases": [
"ALGEBRAIC"
],
"width": 60,
"height": 60,
"inputs": [
{
"x": 0,
"y": 20,
"side": "left"
},
{
"x": 0,
"y": 40,
"side": "left"
}
],
"outputs": [
{
"x": 60,
"y": 30,
"side": "right"
}
],
"defaultParams": {}
},
{
"type": "complexToMagnitudeAngle",
"label": "Complex to Mag-Angle",
"icon": "complexToMagnitudeAngle.svg",
"phases": [
"ALGEBRAIC"
],
"width": 60,
"height": 60,
"inputs": [
{
"x": 0,
"y": 30,
"side": "left"
}
],
"outputs": [
{
"x": 60,
"y": 20,
"side": "right"
},
{
"x": 60,
"y": 40,
"side": "right"
}
],
"defaultParams": {}
},
{
"type": "conjugate",
"label": "Conjugate",
"icon": "conjugate.svg",
"phases": [
"ALGEBRAIC"
],
"width": 60,
"height": 60,
"inputs": [
{
"x": 0,
"y": 30,
"side": "left"
}
],
"outputs": [
{
"x": 60,
"y": 30,
"side": "right"
}
],
"defaultParams": {}
},
{
"type": "atan2",
"label": "Atan2",
"icon": "atan2.svg",
"phases": [
"ALGEBRAIC"
],
"width": 60,
"height": 60,
"inputs": [
{
"x": 0,
"y": 20,
"side": "left"
},
{
"x": 0,
"y": 40,
"side": "left"
}
],
"outputs": [
{
"x": 60,
"y": 30,
"side": "right"
}
],
"defaultParams": {}
},
{
"type": "wrapToZero",
"label": "Wrap To Zero",
"icon": "wrapToZero.svg",
"phases": [
"ALGEBRAIC"
],
"width": 80,
"height": 80,
"inputs": [
{
"x": 0,
"y": 40,
"side": "left"
}
],
"outputs": [
{
"x": 80,
"y": 40,
"side": "right"
}
],
"defaultParams": {
"Threshold": 255
},
"render": {
"type": "image",
"src": "exports/wrapToZero.svg",
"svgMode": "element",
"preserveAspectRatio": "none",
"x": 0,
"y": 0,
"width": 80,
"height": 80
}
},
{
"type": "polynomial",
"label": "Polynomial",
"icon": "polynomial.svg",
"phases": [
"ALGEBRAIC"
],
"width": 80,
"height": 80,
"inputs": [
{
"x": 0,
"y": 40,
"side": "left"
}
],
"outputs": [
{
"x": 80,
"y": 40,
"side": "right"
}
],
"defaultParams": {
"Coefficients": [
1,
0,
0
]
},
"render": {
"type": "image",
"src": "exports/polynomial.svg",
"svgMode": "element",
"preserveAspectRatio": "none",
"x": 0,
"y": 0,
"width": 80,
"height": 80
}
}
]
}
modules/nflow_blocks/src/cpp/math/roundingFunction.cpp//=============================================================================
// Copyright (c) 2016-present Allan CORNET (Nelson)
//=============================================================================
// This file is part of Nelson.
//=============================================================================
// LICENCE_BLOCK_BEGIN
// SPDX-License-Identifier: LGPL-3.0-or-later
// LICENCE_BLOCK_END
//=============================================================================
// roundingFunction: element-wise rounding block whose params.Operator selects
// the rounding mode (floor/ceil/round/fix). Feedthrough (ALGEBRAIC), real
// double signals, vector element-wise; has C / Rust code generation.
// floor -> toward -inf ceil -> toward +inf
// round -> nearest, ties away from zero fix -> truncate toward zero
//=============================================================================
#include "SimEngineTypes.hpp"
#include "BlockRegistry.hpp"
#include "FieldNames.hpp"
#include "NFlowBlockDescriptor.hpp"
#include "math_blocks.hpp"
#include <cmath>
#include <string>
//=============================================================================
namespace Nelson {
namespace NFlow {
//=============================================================================
namespace {
double
applyRounding(const std::string& op, double x)
{
if (op == "ceil") {
return std::ceil(x);
}
if (op == "round") {
return std::round(x); // ties away from zero
}
if (op == "fix") {
return std::trunc(x); // toward zero
}
return std::floor(x); // "floor" (default)
}
// C / Rust intrinsic name for the selected operator.
std::string
roundingFn(const std::string& op, bool rust)
{
const std::string p = rust ? "libm::" : "";
if (op == "ceil") {
return p + "ceil";
}
if (op == "round") {
return p + "round";
}
if (op == "fix") {
return p + "trunc";
}
return p + "floor";
}
BlockCodegenTemplate
makeCodegen(bool rust)
{
BlockCodegenTemplate t;
t.emitStep = [rust](const BlockCodegenArgs& a) {
nflow::BlockDescriptor bd(*a.block, *a.variables);
const std::string op = bd.paramStr("Operator", "floor");
a.line("out_" + a.id + " = " + roundingFn(op, rust) + "(" + a.in[0] + ");");
};
return t;
}
} // namespace
//=============================================================================
bool
handleRoundingFunction(SimCtx& ctx, const Block& b, Phase phase)
{
if (phase != Phase::ALGEBRAIC) {
return false;
}
if (!hasInput(ctx, b.nid, 0)) {
return false;
}
nflow::BlockDescriptor bd(b, ctx.variables);
const std::string op = bd.paramStr("Operator", "floor");
SigView u = getInputSig(ctx, b.nid, 0);
return emitElementwise(ctx, b.nid, [&](int i) { return applyRounding(op, sigAt(u, i)); });
}
//=============================================================================
BlockCodegenTemplate
getCodeGenCRoundingFunction()
{
return makeCodegen(false);
}
//=============================================================================
BlockCodegenTemplate
getCodeGenRustRoundingFunction()
{
return makeCodegen(true);
}
//=============================================================================
} // namespace NFlow
} // namespace Nelson
//=============================================================================
| Version | Description |
|---|---|
| 1.0.0 | initial version |