Introduction
Those of you that have not read my rather cryptic software development tutorial on Data Flow Modelling please do so now. Those of you that have read it and think I have 'lost my marbles' please follow this example carefully.
This tutorial shows the first forty-five Fibonacci numbers being computed and displayed but using a very fringe modelling and programming technique I formulated some twenty years ago (and yes, my bosses and colleagues thought I was well and truly mental even back then).
The Data Flow Base Class
The base class for all the objects used in this example is known as df_base. This simply provides a mechanism for setting the next object that will be executed in the chain, as well as ensuring that all objects derived from it either override the execute method or use it's own method implementation (which does nothing except return the next object in the chain).
The Zero Class
This class has no inputs and provides a zero output when executed (rather like a constant in conventional paradigms). As this object will only be executed once, and the first Fibonacci number is zero, the execute method prints a zero to the console after setting it's output.
The One Class
This class has no inputs and provides a one output when executed (rather like a constant in conventional paradigms). As this object will only be executed once, and the second Fibonacci number is one, the execute method prints a one to the console after setting it's output.
The Mux Class
This class has two inputs and provides a one output when executed. The execution logic of this object has been set such that the first time the execution method is called, the output is set to the value of port A. Subsequent calls to the execute method set the output to the value on port B.
The Splitter Class
This class has one input and provides two outputs when executed. It may be viewed as a helper class permitting the input to be output to two different objects.
The Adder Class
This class has two input and provides one output when executed. Execution involves adding the port A and port B values together and setting it's output to the result of that addition.
#include <stdio.h>
class df_base {
protected:
df_base * next;
public:
df_base() : next(NULL) { };
void set_chain_forward(df_base * forward) { next = forward; };
virtual df_base * execute() { return next; };
};
class ZERO : public df_base {
private:
int * output;
public:
ZERO() { };
void set_output(int *address) { output = address; };
df_base * execute() { *output = 0; printf("%d\n", *output); return next; };
};
class ONE : public df_base {
private:
int * output;
public:
ONE() { };
void set_output(int *address) { output = address; };
df_base * execute() { *output = 1; printf("%d\n", *output); return next; };
};
class MUX : public df_base {
private:
int port_A;
int port_B;
int * output;
bool state;
public:
MUX() : state(false) { };
int * address_port_A() { return &port_A; };
int * address_port_B() { return &port_B; };
void set_output(int *address) { output = address; };
df_base * execute() { state==false ? *output = port_A : *output = port_B; state = true; return next; };
};
class SPLITTER : public df_base {
private:
int port_A;
int * output_A;
int * output_B;
public:
SPLITTER() { };
int * address_port_A() { return &port_A; };
void set_output_A(int *address) { output_A = address; };
void set_output_B(int *address) { output_B = address; };
df_base * execute() { *output_A = port_A; *output_B = port_A; return next; };
} ;
class ADDER : public df_base {
private:
int port_A;
int port_B;
int * output;
public:
ADDER() { };
int * address_port_A() { return &port_A; };
int * address_port_B() { return &port_B; };
void set_output(int *address) { output = address; };
df_base * execute() { *output = port_A + port_B; printf("%d\n", *output); return next; };
} ;
int main(int argc, char ** argv) {
ZERO zero;
ONE one;
MUX mux_1;
MUX mux_2;
SPLITTER splitter;
ADDER adder;
df_base * next = &zero;
zero.set_chain_forward(&one);
// zero output into mux 1 port A
zero.set_output(mux_1.address_port_A());
one.set_chain_forward(&mux_1);
// one output into mux 2 port A
one.set_output(mux_2.address_port_A());
mux_1.set_chain_forward(&mux_2);
// mux 1 output into adder port A
mux_1.set_output(adder.address_port_A());
mux_2.set_chain_forward(&splitter);
// mux 2 output into splitter port A
mux_2.set_output(splitter.address_port_A());
splitter.set_chain_forward(&adder);
// splitter output into mux 1 port B and adder port B
splitter.set_output_A(mux_1.address_port_B());
splitter.set_output_B(adder.address_port_B());
adder.set_chain_forward(&mux_1);
// adder output into mux 2 port B
adder.set_output(mux_2.address_port_B());
for ( int x = 0; x < (45*4)+2; x++ ) next = next->execute();
}
You will notice that the number of times executed seems a little strange. This is because the first two Fibonacci numbers are output by the zero and one objects respectively, and then the remaining four objects are the only ones that executed as part of the 'tick cycle'. As the maximum positive value that an integer can contain is 2147483648, the loop needs to be restricted to 47.





MultiQuote





|