Block type: atan2
| Parameter | Description |
|---|---|
| input ports | 2 input port(s) declared. |
| Parameter | Description |
|---|---|
| output ports | 1 output port(s) declared. |
Four-quadrant arctangent of the two inputs.
| Module |
nflow_blocks
|
| Library | Math blocks |
| Type |
atan2
|
| Label | Atan2 |
Description
Computes atan2(y, x) element-wise, with y on input port 1 and x on input port 2.
The result is the angle in radians in the range (-pi, pi]. Vector signals are processed element by element with scalar expansion.
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/atan2.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
//=============================================================================
// atan2: four-quadrant arctangent, out = atan2(y, x) with y on input port 0
// and x on input port 1. Element-wise with scalar expansion.
//=============================================================================
#include "SimEngineTypes.hpp"
#include "BlockRegistry.hpp"
#include "FieldNames.hpp"
#include "NFlowBlockDescriptor.hpp"
#include "math_blocks.hpp"
#include <cmath>
//=============================================================================
bool
Nelson::NFlow::handleAtan2(SimCtx& ctx, const Block& b, Phase phase)
{
if (phase != Phase::ALGEBRAIC) {
return false;
}
if (!hasInput(ctx, b.nid, 0) || !hasInput(ctx, b.nid, 1)) {
return false;
}
SigView y = getInputSig(ctx, b.nid, 0);
SigView x = getInputSig(ctx, b.nid, 1);
return emitElementwise(ctx, b.nid, [&](int i) { return std::atan2(sigAt(y, i), sigAt(x, i)); });
}
//=============================================================================
Nelson::NFlow::BlockCodegenTemplate
Nelson::NFlow::getCodeGenCAtan2()
{
BlockCodegenTemplate t;
t.step = "out_{id} = atan2({in0}, {in1});";
return t;
}
//=============================================================================
Nelson::NFlow::BlockCodegenTemplate
Nelson::NFlow::getCodeGenRustAtan2()
{
BlockCodegenTemplate t;
t.step = "out_{id} = libm::atan2({in0}, {in1});";
return t;
}
//=============================================================================
| Version | Description |
|---|---|
| 1.0.0 | initial version |