Native bindings and RBC vectors

The public Tcl procedures retain their argument parsing, aliases, help and existing list/dictionary result shapes. Numerical array conversion, allocation, evaluation loops and cleanup now run in C. SWIG is no longer required. The old SWIG pointer commands and internal array-conversion helpers have been removed.

RBC support is optional:

./configure --with-tcl=/path/to/tcl/lib --with-rbc=/path/to/rbc-tk9
make

--with-rbc accepts an RBC source tree, installed public-header directory, or installation prefix containing rbcVector.h, rbcDecls.h and rbcStubLib.c. The portable RBC stub client is compiled into tclinterp; the RBC shared library is not linked directly. Tcl 9 is required. A compatible rbc::vector package (version 0.8.1 or later) must be available at runtime for vector operations. List-only calls do not load RBC or Tk. Without --with-rbc, list operations work normally and vector requests return an explanatory error.

Every interpolation and approximation procedure accepts these additional options:

Option

Meaning

-input list

Default. All array arguments are Tcl lists.

-input vector

All array arguments are names of real RBC vectors. Scalar options remain scalar.

-output list

Default. Preserve existing list/dictionary results.

-output vector

Replace each numeric result list with its fully qualified RBC vector name.

-namespace name

Vector destination namespace; relative to the caller, created with missing parents.

-name name

Name of the primary yi output vector.

-names dictionary

Destination names for individual output fields (table below).

-ifexists error

Default. Reject existing vector or command names.

-ifexists replace

Update existing real RBC vectors; unrelated commands and complex destinations are rejected.

Input and output modes are independent: list-to-vector and vector-to-list calls are supported. Array inputs within a call use the same input mode. Omitted least-squares weights are generated internally, including in vector input mode. Vector index offsets do not affect sample alignment. Complex vectors and non-finite input samples/scalar parameters are rejected.

Input vector names resolve in the public caller’s namespace. Outputs use -namespace, or the caller’s namespace when omitted. Relative namespace options resolve against the caller; missing parents are created. Empty namespace names are rejected, and the option requires -output vector. Fully qualified output names override this selection; their parent namespace must already exist. Omitted output names, including fields omitted from -names, and a final #auto component use RBC’s own automatic naming in the selected namespace. auto without # is an ordinary name. Returned names are fully qualified. These options do not change input lookup or collision policy. Output vectors survive the interpolation call; destroy them with ::rbc::vector destroy $name, or delete their namespace when appropriate.

package require tclinterp
namespace import ::tclinterp::interpolation::*

# Existing list interface remains unchanged.
set values [lin1d -x {0 1 2} -y {0 2 4} -xi {.5 1.5}]

# List input, automatically named vector output.
set result [lin1d -x {0 1 2} -y {0 2 4} -xi {.5 1.5} -output vector]
puts [$result index :]
::rbc::vector destroy $result

# Vector input and named output, resolved in this namespace.
package require rbc::vector
::rbc::vector create x y xi -variable {}
x set {0 1 2}
y set {0 2 4}
xi set {.5 1.5}
set result [lin1d -input vector -x x -y y -xi xi -output vector -name interpolated]

For multi-output operations, the returned dictionary has the same structure as in list mode. Unspecified fields receive automatic names. -name is shorthand for the yi entry of -names; supplying both for yi is an error.

Operation/options

Keys accepted by -names

Any single-result operation

yi

genBezier

xi, yi

least1d -coeffs

yi, coeffs.b, coeffs.c, coeffs.d

least1dDer

yi, yiDer

least1dDer -coeffs

yi, yiDer, coeffs.b, coeffs.c, coeffs.d

divDif1d -coeffs

yi, coeffs

cubicSpline1d -deriv

yi, yder1, yder2

hermiteSpline1d -deriv

yi, yder1

set result [cubicSpline1d -t {0 1 2} -y {0 1 4} -ti {.5 1.5} -deriv -output vector -names {yi fit yder1 slope yder2 curvature}]
puts [[dict get $result yder1] index :]

Unknown output keys and duplicate explicit destinations are rejected. Results are computed before publishing any output, so an input vector can also be a destination with -ifexists replace. Explicit destinations are checked before publication; new vectors are removed if a later publication step fails. Updates to existing vectors are not rolled back if application callbacks cause a publication error. Do not delete or replace destinations from notification callbacks during publication.

The C binding validates sizes, lengths, required knot ordering, distinct polynomial abscissas, least-squares weights and boundary conditions before entering the legacy numerical routines. Linear/spline operations need at least two knots; not-a-knot cubic boundaries require at least four. Degree-zero Bezier curves are supported. The native boundary also fixes the right-only not-a-knot boundary selection in the underlying cubic routine. The numerical kernels still use their existing algorithms.

Run tests using make test with argparse, Tcllib and (for vector tests) rbc::vector on TCLLIBPATH. No display server or Tk initialization is required for vector tests.

Read-only vectors

RBC-enabled builds require RBC 0.8.1 or newer headers and runtime. Read-only vectors are valid inputs to every interpolation and approximation operation. Input state and data are not changed. Existing output vectors must be writable even with -ifexists replace. All explicit destinations are checked before publishing any results; a locked destination fails with RBC VECTOR READONLY. Unlock it explicitly or select a different name / #auto. New outputs are writable. Permission is checked again before each write because application callbacks may change later destinations during publication.

Package defaults

Set representation and collision defaults once after loading the package:

package require tclinterp
::tclinterp::configure -input vector -output vector -ifexists replace

Subsequent interpolation calls inherit omitted -input, -output and -ifexists options. Explicit per-call options win.

Use ::tclinterp::configure to query all settings, or ::tclinterp::configure -output to query one. The all-settings dictionary can be restored with ::tclinterp::configure {*}$saved. Initial representation defaults remain list; the initial -ifexists policy is error. Invalid requests and unavailable vector support leave settings unchanged. Configuration belongs to the current Tcl interpreter. The command is public but not namespace-exported, so wildcard imports cannot introduce a configure collision. Namespace selection and naming are unchanged. -ifexists replace still requires a compatible, writable destination. The collision setting affects vector output only and can be configured even in a build without RBC.


Copyright (c) George Yashin