interpolationPrelookup
Interpolates a static Table from a prelookup [k, f] pair.
📝Syntax
Block type: interpolationPrelookup
📥Input Arguments
Parameter Description
input ports 1 input port(s) declared.
📤Output Arguments
Parameter Description
output ports 1 output port(s) declared.
📄Description

Interpolates a static Table from a prelookup [k, f] pair.

Module nflow_blocks
Library Lookup Tables
Type interpolationPrelookup
Label Interpolation Using Prelookup

Description

Interpolates the static Table using the index/fraction pair produced by a prelookup block. Input port 0 is the 2-element vector [k, f]; the output is tbl[k] + f * (tbl[k+1] - tbl[k]), i.e. linear interpolation at the shared interval. k is clamped to a valid table index. Sharing one prelookup across several of these blocks avoids repeating the interval search per table.

Native runtime (the 2-vector input is a follow-up for code generation).

Ports

Input(s)

Port Role Side Position
Port_1 Numeric signal read by the block. left x=0, y=40

Output(s)

Port Role Side Position
Port_1 Numeric signal produced by the block. right x=90, y=40

Parameters

Parameter Default value
Table [0 1 4 9 16]

Block Characteristics

Block type interpolationPrelookup
Family Lookup Tables
Rendered size 90 x 80
Phases ALGEBRAIC
Internal state or history no
Signal data type double numeric values

Algorithms

Equation or Rule

$$y = t_k + f\,(t_{k+1} - t_k)$$

Extended Capabilities

Code generation: supported for C and Rust.

Implementation Sources

Manifestmodules/nflow_blocks/libraries/lookup/library.json
{
  "id": "builtin.lookup",
  "title": "Lookup Tables",
  "version": "0.1.0",
  "format": "nflow-2",
  "builtin": true,
  "blocks": [
    {
      "type": "lookup1D",
      "label": "1-D Lookup Table",
      "icon": "lookup1D.svg",
      "phases": [
        "ALGEBRAIC"
      ],
      "width": 90,
      "height": 80,
      "inputs": [
        {
          "x": 0,
          "y": 40,
          "side": "left"
        }
      ],
      "outputs": [
        {
          "x": 90,
          "y": 40,
          "side": "right"
        }
      ],
      "defaultParams": {
        "BreakpointsForDimension1": [
          0,
          1,
          2,
          3,
          4
        ],
        "Table": [
          0,
          1,
          4,
          9,
          16
        ],
        "InterpMethod": "Linear point-slope",
        "ExtrapMethod": "Linear"
      },
      "render": {
        "type": "image",
        "src": "exports/lookup1D.svg",
        "svgMode": "element",
        "preserveAspectRatio": "none",
        "x": 0,
        "y": 0,
        "width": 90,
        "height": 80
      }
    },
    {
      "type": "lookup2D",
      "label": "2-D Lookup Table",
      "icon": "lookup2D.svg",
      "phases": [
        "ALGEBRAIC"
      ],
      "width": 90,
      "height": 80,
      "inputs": [
        {
          "x": 0,
          "y": 30,
          "side": "left"
        },
        {
          "x": 0,
          "y": 50,
          "side": "left"
        }
      ],
      "outputs": [
        {
          "x": 90,
          "y": 40,
          "side": "right"
        }
      ],
      "defaultParams": {
        "BreakpointsForDimension1": [
          1,
          2,
          3
        ],
        "BreakpointsForDimension2": [
          1,
          2,
          3
        ],
        "Table": [
          4,
          5,
          6,
          5,
          7,
          8,
          6,
          8,
          10
        ],
        "InterpMethod": "Linear point-slope",
        "ExtrapMethod": "Linear"
      },
      "render": {
        "type": "image",
        "src": "exports/lookup2D.svg",
        "svgMode": "element",
        "preserveAspectRatio": "none",
        "x": 0,
        "y": 0,
        "width": 90,
        "height": 80
      }
    },
    {
      "type": "lookupND",
      "label": "n-D Lookup Table",
      "icon": "lookupND.svg",
      "phases": [
        "ALGEBRAIC"
      ],
      "width": 90,
      "height": 80,
      "inputs": [
        {
          "x": 0,
          "y": 30,
          "side": "left"
        },
        {
          "x": 0,
          "y": 50,
          "side": "left"
        }
      ],
      "outputs": [
        {
          "x": 90,
          "y": 40,
          "side": "right"
        }
      ],
      "defaultParams": {
        "NumberOfTableDimensions": 2,
        "BreakpointsForDimension1": [
          1,
          2,
          3
        ],
        "BreakpointsForDimension2": [
          1,
          2,
          3
        ],
        "Table": [
          4,
          5,
          6,
          5,
          7,
          8,
          6,
          8,
          10
        ],
        "InterpMethod": "Linear point-slope",
        "ExtrapMethod": "Linear"
      },
      "render": {
        "type": "image",
        "src": "exports/lookupND.svg",
        "svgMode": "element",
        "preserveAspectRatio": "none",
        "x": 0,
        "y": 0,
        "width": 90,
        "height": 80
      }
    },
    {
      "type": "directLookup",
      "label": "Direct Lookup Table (n-D)",
      "icon": "directLookup.svg",
      "phases": [
        "ALGEBRAIC"
      ],
      "width": 90,
      "height": 80,
      "inputs": [
        {
          "x": 0,
          "y": 30,
          "side": "left"
        },
        {
          "x": 0,
          "y": 50,
          "side": "left"
        }
      ],
      "outputs": [
        {
          "x": 90,
          "y": 40,
          "side": "right"
        }
      ],
      "defaultParams": {
        "NumberOfTableDimensions": 2,
        "TableDimensions": [
          2,
          3
        ],
        "Table": [
          0,
          1,
          10,
          11,
          20,
          21
        ]
      },
      "render": {
        "type": "image",
        "src": "exports/directLookup.svg",
        "svgMode": "element",
        "preserveAspectRatio": "none",
        "x": 0,
        "y": 0,
        "width": 90,
        "height": 80
      }
    },
    {
      "type": "prelookup",
      "label": "Prelookup",
      "icon": "prelookup.svg",
      "phases": [
        "ALGEBRAIC"
      ],
      "width": 90,
      "height": 80,
      "inputs": [
        {
          "x": 0,
          "y": 40,
          "side": "left"
        }
      ],
      "outputs": [
        {
          "x": 90,
          "y": 30,
          "side": "right"
        },
        {
          "x": 90,
          "y": 50,
          "side": "right"
        }
      ],
      "defaultParams": {
        "BreakpointsForDimension1": [
          0,
          1,
          2,
          3,
          4
        ]
      },
      "render": {
        "type": "image",
        "src": "exports/prelookup.svg",
        "svgMode": "element",
        "preserveAspectRatio": "none",
        "x": 0,
        "y": 0,
        "width": 90,
        "height": 80
      }
    },
    {
      "type": "interpolationPrelookup",
      "label": "Interpolation Using Prelookup",
      "icon": "interpolationPrelookup.svg",
      "phases": [
        "ALGEBRAIC"
      ],
      "width": 90,
      "height": 80,
      "inputs": [
        {
          "x": 0,
          "y": 30,
          "side": "left"
        },
        {
          "x": 0,
          "y": 50,
          "side": "left"
        }
      ],
      "outputs": [
        {
          "x": 90,
          "y": 40,
          "side": "right"
        }
      ],
      "defaultParams": {
        "Table": [
          0,
          1,
          4,
          9,
          16
        ]
      },
      "render": {
        "type": "image",
        "src": "exports/interpolationPrelookup.svg",
        "svgMode": "element",
        "preserveAspectRatio": "none",
        "x": 0,
        "y": 0,
        "width": 90,
        "height": 80
      }
    },
    {
      "type": "lookupDynamic",
      "label": "Lookup Table Dynamic",
      "icon": "lookupDynamic.svg",
      "phases": [
        "ALGEBRAIC"
      ],
      "width": 90,
      "height": 80,
      "inputs": [
        {
          "x": 0,
          "y": 20,
          "side": "left"
        },
        {
          "x": 0,
          "y": 40,
          "side": "left"
        },
        {
          "x": 0,
          "y": 60,
          "side": "left"
        }
      ],
      "outputs": [
        {
          "x": 90,
          "y": 40,
          "side": "right"
        }
      ],
      "defaultParams": {},
      "render": {
        "type": "image",
        "src": "exports/lookupDynamic.svg",
        "svgMode": "element",
        "preserveAspectRatio": "none",
        "x": 0,
        "y": 0,
        "width": 90,
        "height": 80
      }
    }
  ]
}
Runtimemodules/nflow_blocks/src/cpp/lookup/interpolationPrelookup.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
//=============================================================================
// interpolationPrelookup (Interpolation Using Prelookup): interpolates a static
// Table using a precomputed index/fraction pair produced by a prelookup block.
// Input port 0 is the 2-element vector [k, f]; the output is
//   tbl[k] + f * (tbl[k+1] - tbl[k]),
// i.e. linear interpolation over the Table at the shared interval. k is clamped
// to a valid table index. Sharing one prelookup across several of these blocks
// avoids repeating the interval search per table. Feedthrough (ALGEBRAIC), real
// double, scalar output. Native runtime (the 2-vector input is a follow-up for
// code generation).
//=============================================================================
#include "SimEngineTypes.hpp"
#include "BlockRegistry.hpp"
#include "FieldNames.hpp"
#include "NFlowBlockDescriptor.hpp"
#include "lookup_blocks.hpp"
#include <string>
#include <vector>
#include <cmath>
//=============================================================================
namespace Nelson {
namespace NFlow {
    //=============================================================================
    bool
    handleInterpolationPrelookup(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::vector<double> tbl = bd.paramList("Table");
        const int m = (int)tbl.size();
        // Index on port 0, fraction on port 1 - the two ports a prelookup
        // produces. A single two-wide input is still read the old way, so a
        // diagram wired before the split keeps working.
        SigView u = getInputSig(ctx, b.nid, 0);
        double kd = sigAt(u, 0);
        double f = 0.0;
        if (numInputs(ctx, b.nid) > 1 && hasInput(ctx, b.nid, 1)) {
            f = getInput(ctx, b.nid, 1, 0.0);
        } else if (u.width > 1) {
            f = sigAt(u, 1);
        }
        double out = 0.0;
        if (m == 1) {
            out = tbl[0];
        } else if (m >= 2) {
            int k = (int)std::floor(kd + 0.5);
            if (k < 0) {
                k = 0;
            }
            if (k > m - 2) {
                k = m - 2;
            }
            out = tbl[k] + f * (tbl[k + 1] - tbl[k]);
        }
        setOutput(ctx, b.nid, out);
        return false;
    }
    //=============================================================================
    // Index and fraction in; scalar out.
    bool
    resolveInterpolationPrelookupDims(const Block& b, const ValMap& vars,
        const std::vector<PortSig>&, std::vector<PortSig>& outSigs, std::string& err)
    {
        nflow::BlockDescriptor bd(b, vars);
        const std::vector<double> tbl = bd.paramList("Table");
        if (tbl.empty()) {
            err = "interpolationPrelookup requires a non-empty Table";
            return false;
        }
        outSigs[0].setVector(1);
        outSigs[0].type = SigType::Double;
        return true;
    }
    //=============================================================================
} // namespace NFlow
} // namespace Nelson
//=============================================================================
💡Examples
See the prelookup example, which wires prelookup into this block.
% See the prelookup example for a complete Prelookup -> Interpolation wiring.
🔗See Also
prelookuplookup1D
🕔Version History
Version Description
1.0.0 initial version
Edit this page on GitHub