lumiera_/doc/technical/howto/crackNuts.txt
Ichthyostega 26bf32525b Invocation: build test-data manipulation function
* based on reproducible data in `TestFrame`
 * using Murmur64A hash-chaining to »mark« with a parameter

This emulates the simplest case of 1:1 processing and can also be applied ''in-place''
2024-11-21 00:50:39 +01:00

117 lines
5.3 KiB
Text

how to crack nut #47
====================
:toc:
.collection of successfully employed technical solutions
Some nasty problems are recurring time and again. Maybe a trick could be found somewhere
in the net, and a library function was created to settle this damn topic once and for all.
Maybe even a nice test and demo is provided. And then the whole story will be forgotten.
_Sounds familiar?_ => ☹☻☺ ~[red]#then please leave a note here...#~
Methods
-------
Mathematics
~~~~~~~~~~~
- some basic descriptive statistics computation are defined in 'lib/stat/statistic.hpp'
- the simple case for _linear regression_ is also implemented there
- Gnuplot provides also common statistics functions, which may come in handy when the
goal is anyway to create a visualisation (-> see <<investigation,below>>)
Situations
----------
Investigation
~~~~~~~~~~~~~
summary test::
Reformulate the research and the findings into a test, which can be read top-down like a novel.
Start with documenting the basics, package helpers into a tool class, or package setup into a
workbench-style class, with individual tool modules. Provide a short version of this test with
the basic demo, which should be able to run with the regular test suite. Extended long-running
tests can be started conditionally with commandline-arguments. See 'scheduler-stress-test.cpp'
visualisation::
Use code generation to visualise data structures or functions and observation statistics.
Typically these generation statements can be packaged into an invocation helper and included
into a relevant test, but commented-out there.
+
- generate Graphviz diagrams: 'lib/dot-gen.hpp' provides a simple DSL. See 'test-chain-load-test.cpp'
- generate Gnuplot scripts: use the Text-Template engine to fill in data, possibly from a data table
* 'lib/gnuplot-gen.hpp' provides some pre-canned scripts for statistics plots
* used by the 'stress-test-rig.cpp', in combination with 'data.hpp' to collect measurement results
Common Tasks
------------
Data handling
~~~~~~~~~~~~~
persistent data set::
use the `lib::stat::DataTable` ('data.hpp') with CSV rendering -> see 'data-csv-test.cpp'
Formatting
~~~~~~~~~~
- implement a conversion-to-string operator.
- include the C++ IOStreams via 'lib/format-cout.hpp' -> this magically uses the `util::toString()`
- for testing, temporarily include 'lib/test/diagnostic-output' and use the `SHOW_EXPR` macro.
- use 'util::join' ('lib/format-util.hpp') to join arbitrary elements with `util::toString()` conversion
- use _printf-style formatters_ from Boost-format. We provide a light-weight front-end via 'lib/format-string.hpp'
* the heavyweight boost-format include is only required once, for 'lib/format-string.cpp'.
* the templated front-end passes-through most basic types and types with string-conversion
* all invocations are strictly error safe (never throw) and can thus be used from catch-handlers
- use the *Text-Template* engine. See 'text-template-test.cpp'. Can be used with simple map bindings,
but also from a `lib::GenNode` tree, or with a custom defined `DataSource` template
Language constructs
-------------------
Templates
~~~~~~~~~
build-from-anything::
use a templated constructor, possibly even with varargs
+
- use a _deduction guide_ to pick the right ctor and arguments -> see
* `ThreadJoinable` in 'thread.hpp', 698
* `DataSource<string>` specialisation only when argument can be converted to string,
in 'text-template.hpp', 745
- prevent shadowing of _automatically generated copy operations._
See https://issues.lumiera.org/ticket/963[#963]. Based on the ``disable if'' SFINAE technique.
A ready-made templated typedef `lib::metadisable_if_self` can be found in 'lib/meta/util.hpp'
Varargs
~~~~~~~
pick and manipulate individually::
The key trick is to define an _index sequence template,_ which can then be matched against
a processing template for a single argument; and the latter can have partial specialisations
+
- see 'variadic-argument-picker-test.cpp'
- but sometimes it is easier to use the tried and true technique of the Loki-Typelists, which
can be programmed recursively, similar to LISP. The »bridge« is to unpack the variadic argument pack
into the `lib::meta::Types<ARGS...>` ([yellow-background]#⚠ still broken in 2024#
see https://issues.lumiera.org/ticket/987[#987], use `lib::meta::TySeq` from 'variadic-helper.hpp' as workaround...
+
apply functor to each::
A common trick is to use `std::apply` in combination with a _fold-expression_
+
- provided as `lib::meta::forEach` in 'lib/meta/util.hpp
- The design of the `DataTable` with CSV-Formatting is based on this technique, see 'lib/stat/data.hpp'
- 'test-rand-ontology.cpp' uses this in `manipulateFrame()` to accept an arbitrary number of input chains
+
unpack iterator into tuple::
Under controlled conditions this is possible (even while it seems like time travel from the runtime into
the compile-time domain). The number of results to extract from the iterator must be known at compile time,
and the possible result types must be limited, so that a visitor can be used for double-dispatch.
+
- see tuple-record-init-test.cpp
- used in 'command-simple-closure.hpp' to receive parameter values sent via UI-Bus and package them
into a tuple for invocation of a Steam-Layer command.