Skip to content
cardilloPublic

About

modern c++ library for the efficient execution of dependency graphs

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

dangle

C++ single-header graph computation library with:

  • a compile-time static DAG builder: dangle::start(...)
  • a mutable reactive graph API: dangle::val<T> + dangle::graph

Header: src/dangle.hpp

static layer

Directed acyclic computation graph; nodes are pure functions.

  • input types are inferred from the first function signature
  • intermediate and output values are referenced by typed node_handle<T, idx> values
  • slot indices are compile-time constants

building a graph

auto [bid, ask, mid, b0] = dangle::start(
    [](double b, double a) { return (b + a) / 2.0; }
);

auto [spread, b1] = b0.compute(
    [](double b, double a) { return a - b; }, bid, ask
);
auto [norm, b2] = b1.compute(
    [](double s, double m) { return s / m; }, spread, mid
);

auto spec = b2.build(mid, spread, norm);
  • start(fn) returns input handles, the first output handle, and a builder
  • builder.compute(fn, handles...) appends a node and returns (new_handle, new_builder)
  • builder.build(handles...) selects outputs and returns a spec

evaluating a graph

auto [m, s, n] = spec.evaluate(99.5, 100.5);
  • spec.evaluate(...) is stateless and re-entrant
  • input types must exactly match the declared input types
  • execution order is registration order

reactive layer

dangle::val<T> and dangle::graph provide a persistent, lazy-evaluated reactive graph. Updating an input marks the graph dirty; reading a value reruns the graph only when needed.

dangle::val<double> x = 3.0;
dangle::graph g;

auto& sq = g.bind([](double v) { return v * v; }, x);
auto& cube = g.bind(
    [](double s, double v) { return s * v; }, sq, x
);

*cube;   // 27.0
x = 4.0;
*cube;   // 64.0

You can also bind from an existing graph-owned value:

auto& fourth = sq.bind([](double v) { return v * v; }, sq);
  • graph::bind(fn, val...) -> val<R>& registers a node and stores the output inside the graph
  • val<T>::bind(fn, val...) -> val<R>& forwards to the owning graph
  • val<T>::operator= marks the graph dirty
  • val<T>::operator* triggers run_if_dirty() and returns the current value

examples

examples/bsm.cpp

  • Black-Scholes pricing and greeks using dangle::graph
  • updates dangle::val<double> inputs between scenarios
  • prints scenario comparisons and an options chain

examples/loan.cpp

  • amortization schedule using the same reactive graph
  • reuses the graph across multiple loan scenarios by reassigning inputs

build and run

make         # build tests and examples into ./bld
make test    # build and run doctest suite
make lint    # run clang-tidy checks
./bld/bsm    # run Black-Scholes example
./bld/loan   # run loan schedule example

About

modern c++ library for the efficient execution of dependency graphs

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages