luis 7 năm trước cách đây
commit
88cd0e7f8c

+ 90 - 0
README.md

@@ -0,0 +1,90 @@
+Extensible Flow Engine
+===========================
+
+Features
+---------------
+
+- Develop new Operators
+- Serialize graph of operations
+- Distribute operations to serveral workers/servers
+- HTTP Graphical UI Editor
+- Serve http or grpc API
+- Chain flow operators   -- No needed since we can build operations,
+  might be possible to build entires/methods from operators
+- System containing more than one flow
+- Define stages of the system
+
+Special operators
+--------------------
+
+```go
+f := flow.New(f);
+v := f.Variable([]float32{1,2,3}) // Init value
+```
+
+### New version
+Simplified flow even more maintaining a func
+
+
+### flowt2
+
+Flow will create an array of operators with references as inputs
+the builder will create the Graph
+
+We should not allow user to directly pass Operation to the `flow.Op` method,
+since the serialization will be hard then
+
+define future inputs for operation groups
+
+```go
+g.Run([]O{op1,op2},1,2,3)
+```
+
+
+
+
+
+
+
+
+
+Serialize
+--------------------
+
+Grab all operators in a list
+create a reference lookup table
+
+System
+---------------
+
+system combine several flows 
+
+Idea:
+
+Develop and combine operators to create a function, 
+
+### Components
+using ECS (entity component system) to extend each Operator, so if we have
+UI we store UI information in UI component
+
+### Describe components via code or serialization
+Each node has components
+create multiple channels to each node
+
+CNN - combines convolution matrixes with images then sends to a regular
+neural network
+
+a Node could have input and properties?
+
+## Backfetch:
+ perpare linkages as AddSource(node)
+ every time we call, it will call the results
+
+```go
+// Prototype
+n := flow.AddNode(&node)
+n.AddSource(&otherNode)
+
+
+```
+

+ 48 - 0
benchmark_test.go

@@ -0,0 +1,48 @@
+package flow_test
+
+import (
+	"math/rand"
+	"os"
+	"strconv"
+	"testing"
+
+	"dev.hexasoftware.com/x/flow"
+)
+
+var (
+	vecsize = 10
+)
+
+func init() {
+	var err error
+	vecsizeEnv := os.Getenv("VECSIZE")
+	if vecsizeEnv != "" {
+		vecsize, err = strconv.Atoi(vecsizeEnv)
+		if err != nil {
+			panic(err)
+		}
+
+	}
+}
+
+func BenchmarkMul(b *testing.B) {
+	f := flow.New()
+
+	v1 := f.Variable(randvec())
+	v2 := f.Variable(randvec())
+
+	mulop := f.Op("vecmul", v1, v2)
+	for i := 0; i < b.N; i++ {
+		f.Run(mulop)
+	}
+
+}
+
+func randvec() []float32 {
+	r := make([]float32, vecsize)
+
+	for i := range r {
+		r[i] = rand.Float32()
+	}
+	return r
+}

+ 11 - 0
errors.go

@@ -0,0 +1,11 @@
+package flow
+
+import "errors"
+
+// flow Errors
+var (
+	ErrNotFound  = errors.New("Entry not found")
+	ErrNotAFunc  = errors.New("Is not a function")
+	ErrOutput    = errors.New("Invalid output")
+	ErrOperation = errors.New("Invalid operation")
+)

+ 171 - 0
flow.go

@@ -0,0 +1,171 @@
+package flow
+
+import (
+	"bytes"
+	"encoding/json"
+	"fmt"
+)
+
+// Data interface
+type Data = interface{}
+type opEntry struct {
+	name     string
+	inputs   []operation // still figuring, might be operation
+	executor interface{}
+}
+
+// Flow structure
+// We could Create a single array of operations
+// refs would only mean id, types would be embed in operation
+type Flow struct {
+	registry   *Registry
+	consts     []Data
+	data       []Data
+	operations []opEntry
+	err        error
+}
+
+// New create a new flow
+func New() *Flow {
+	return &Flow{
+		registry:   globalRegistry,
+		consts:     []Data{},
+		data:       []Data{},
+		operations: []opEntry{},
+	}
+}
+
+// OpFunc return
+func (f *Flow) Op(name string, params ...interface{}) operation {
+	inputs := make([]operation, len(params))
+	for i, p := range params {
+		switch v := p.(type) {
+		case operation:
+			inputs[i] = v
+		default:
+			inputs[i] = f.Const(v)
+		}
+	}
+
+	// Grab executor here
+	executor, err := f.registry.Get(name)
+	if err != nil {
+		f.err = err
+		return OpFunc{}
+	}
+	f.operations = append(f.operations, opEntry{name, inputs, executor})
+	refID := len(f.operations) - 1
+	// Initialize opfunc maybe
+	return OpFunc{ref{f, refID}}
+
+}
+
+// Const returns a const operation
+func (f *Flow) Const(value interface{}) OpConst {
+	f.consts = append(f.consts, value)
+	refID := len(f.consts) - 1
+	return OpConst{ref{f, refID}}
+}
+
+// Variable operation
+func (f *Flow) Variable(value interface{}) OpVar {
+	f.data = append(f.consts, value)
+	refID := len(f.data) - 1
+	return OpVar{ref{f, refID}}
+}
+func (f *Flow) In(paramId int) OpIn {
+	return OpIn{ref{f, paramId}}
+}
+
+// Run a batch of operation
+func (f *Flow) Run(ops ...operation) ([]Data, error) {
+	if f.err != nil {
+		return nil, f.err
+	}
+	res := []Data{}
+
+	for _, o := range ops {
+		res = append(res, o.Process())
+	}
+
+	return res, nil
+}
+
+// Analyse every operations
+func (f *Flow) Analyse(params ...Data) string {
+	ret := bytes.NewBuffer(nil)
+	fmt.Fprintf(ret, "Flow analysis:\n")
+
+	for i, op := range f.operations {
+		fmt.Fprintf(ret, "  [%d] %s(", i, op.name)
+		for j, in := range op.inputs {
+			ref := in.fref()
+			if j != 0 {
+				fmt.Fprintf(ret, ", ")
+			}
+			ires := in.Process(params...)
+			fmt.Fprintf(ret, "%s@%d(%v)", typeName(in), ref.ID, ires)
+		}
+		fmt.Fprintf(ret, ") - ")
+		// Create OpProcessor and execute
+		//
+		opfn := OpFunc{ref{f, i}}
+		res := opfn.Process(params...)
+		fmt.Fprintf(ret, "%v\n", res)
+	}
+	return ret.String()
+}
+
+func (f *Flow) String() string {
+	ret := bytes.NewBuffer(nil)
+	// consts
+	fmt.Fprintf(ret, "consts:\n")
+	for i, v := range f.consts {
+		fmt.Fprintf(ret, "  [%d] %v\n", i, v)
+	}
+	fmt.Fprintf(ret, "data:\n") // Or variable
+	for i, v := range f.data {
+		fmt.Fprintf(ret, "  [%d] %v\n", i, v)
+	}
+
+	fmt.Fprintf(ret, "operations:\n")
+	for i, v := range f.operations {
+		fmt.Fprintf(ret, "  [%d] %s(", i, v.name)
+		for j, in := range v.inputs {
+			ref := in.fref()
+			if j != 0 {
+				fmt.Fprintf(ret, ", ")
+			}
+			fmt.Fprintf(ret, "%s@%d", typeName(in), ref.ID)
+		}
+		fmt.Fprintf(ret, ")\n")
+	}
+
+	return ret.String()
+}
+
+// Ref?
+
+func (f *Flow) MarshalJSON() ([]byte, error) {
+	data := map[string]interface{}{}
+	type opMarshal struct {
+		Name  string
+		Input []map[string]interface{}
+	}
+	operations := make([]opMarshal, len(f.operations))
+	for i, o := range f.operations {
+		refs := []map[string]interface{}{}
+		for _, in := range o.inputs { // Switch type?
+			refs = append(refs, map[string]interface{}{
+				"type": typeName(in),
+				"id":   in.fref().ID,
+			})
+		}
+		operations[i] = opMarshal{o.name, refs}
+	}
+	data["operations"] = operations
+	data["data"] = f.data
+	data["consts"] = f.consts
+
+	return json.Marshal(data)
+}

+ 164 - 0
flow_test.go

@@ -0,0 +1,164 @@
+package flow_test
+
+import (
+	"bytes"
+	"encoding/json"
+	"log"
+	"reflect"
+	"testing"
+
+	"dev.hexasoftware.com/x/flow"
+	vecasm "github.com/gohxs/vec-benchmark/asm"
+)
+
+func TestSerialize(t *testing.T) {
+	f := flow.New()
+	var1 := f.Variable([]float32{4, 4, 4})
+
+	c1 := f.Const([]float32{1, 2, 3})
+	c2 := f.Const([]float32{2, 2, 2})
+
+	op1 := f.Op("vecmul", // op:0 - expected: [12,16,20,24]
+		f.Variable([]float32{4, 4, 4, 4}),
+		f.Op("vecadd", // op:1 - expected: [3,4,5,6]
+			f.Const([]float32{1, 2, 3, 4}),
+			f.Const([]float32{2, 2, 2, 2}),
+		),
+	)
+	mul1 := f.Op("vecmul", c1, op1)       // op:2 - expected 12, 32, 60, 0
+	mul2 := f.Op("vecmul", mul1, var1)    // op:3 - expected 48, 128, 240, 0
+	mul3 := f.Op("vecmul", c2, mul2)      // op:4 - expected 96, 256, 480, 0
+	mul4 := f.Op("vecmul", mul3, f.In(0)) // op:5 - expected 96, 512, 1440,0
+
+	t.Log(f.Analyse([]float32{1, 2, 3, 4}))
+	res := mul4.Process([]float32{1, 2, 3, 4})
+
+	t.Log("Res:", res)
+	t.Log("Flow:\n", f)
+
+	ret := bytes.NewBuffer(nil)
+	e := json.NewEncoder(ret)
+	e.Encode(f)
+
+	t.Log("Flow:", ret)
+
+}
+
+func TestFlow(t *testing.T) {
+	f := flow.New()
+	a := f.Const([]float32{1, 2, 3})
+	b := f.Const([]float32{2, 2, 2})
+	f.Op("mul", a, b)
+
+	log.Println(f)
+}
+func TestBuild(t *testing.T) {
+	var err error
+	err = flow.Register("vecmul", vecmul)
+	if err != nil {
+		t.Fatal(err)
+	}
+	err = flow.Register("vecadd", vecadd)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	f := flow.New()
+
+	a := f.Const([]float32{1, 2, 3})
+	b := f.Const([]float32{2, 2, 2})
+	m := f.Op("vecmul", []float32{1, 2, 3}, b)
+	lastOp := f.Op("vecadd", a, m)
+
+	{
+		res, err := f.Run(m, lastOp)
+		errcheck(t, err)
+
+		test := []interface{}{
+			[]float32{2, 4, 6},
+			[]float32{3, 6, 9},
+		}
+		if !reflect.DeepEqual(test, res) {
+			t.Fatal("Arrays does not match:", test, res)
+		}
+		t.Log("Result:", res)
+	}
+}
+func TestImplementation(t *testing.T) {
+	f := flow.New()
+
+	in := f.Variable([]float32{2, 2, 2, 2})
+
+	v1 := f.Const([]float32{1, 2, 3, 4})
+
+	op1 := f.Op("vecmul", v1, v1)  // 1 2 9 16
+	op2 := f.Op("vecmul", in, op1) // 2 4 18 32
+
+	res, err := f.Run(op1, op2)
+	errcheck(t, err)
+	t.Log("Res:", res)
+
+	test := []interface{}{
+		[]float32{1, 4, 9, 16},
+		[]float32{2, 8, 18, 32},
+	}
+	if !reflect.DeepEqual(test, res) {
+		t.Fatal("Arrays does not match:", test, res)
+	}
+}
+
+func TestVariable(t *testing.T) {
+	f := flow.New()
+	v := f.Variable(1)
+
+	res, _ := f.Run(v)
+	t.Log("res", res)
+	if !reflect.DeepEqual(res, []interface{}{1}) {
+		t.Fatal("Result mismatch")
+	}
+
+	v.Set(2)
+	res, _ = f.Run(v)
+	t.Log("res", res)
+	if !reflect.DeepEqual(res, []interface{}{2}) {
+		t.Fatal("Result mismatch")
+	}
+}
+
+func init() {
+	flow.Register("vecmul", vecmul)
+	flow.Register("vecadd", vecadd)
+}
+
+// Some funcs
+func vecmul(a, b []float32) []float32 {
+
+	sz := min(len(a), len(b))
+
+	out := make([]float32, sz)
+	vecasm.VecMulf32x8(a, b, out)
+	return out
+}
+func vecadd(a, b []float32) []float32 {
+	sz := min(len(a), len(b))
+	out := make([]float32, sz)
+	for i := 0; i < sz; i++ {
+		out[i] = a[i] + b[i]
+	}
+	return out
+}
+
+func min(p ...int) int {
+	min := p[0]
+	for _, v := range p[1:] {
+		if min < v {
+			min = v
+		}
+	}
+	return min
+}
+func errcheck(t *testing.T, err error) {
+	if err != nil {
+		t.Fatal(err)
+	}
+}

+ 75 - 0
operation.go

@@ -0,0 +1,75 @@
+// Find a way to improve this mess
+package flow
+
+import (
+	"errors"
+	"reflect"
+)
+
+type operation interface {
+	fref() ref
+	Process(params ...Data) Data
+}
+
+// Ref and cacher?
+// common operation
+type ref struct {
+	flow *Flow
+	// Type? serializable
+	ID int `json:"id"`
+}
+
+// ref ref ref
+func (r ref) fref() ref {
+	return r
+}
+
+func typeName(o operation) string {
+	switch o.(type) {
+	case OpIn:
+		return "in"
+	case OpVar:
+		return "data"
+	case OpConst:
+		return "const"
+	case OpFunc:
+		return "func"
+	}
+	return ""
+}
+
+type OpIn struct{ ref }
+type OpVar struct{ ref }
+type OpConst struct{ ref }
+type OpFunc struct{ ref }
+
+func (o OpIn) Process(p ...Data) Data {
+	if o.ID >= len(p) || o.ID < 0 {
+		o.flow.err = errors.New("Invalid input")
+		return nil
+	}
+	return p[o.ID]
+}
+
+func (o OpVar) Process(...Data) Data { return o.flow.data[o.ID] } // Get
+// Set variable set
+func (o OpVar) Set(value Data) { o.flow.data[o.ID] = value }
+
+// OpConst const operator
+func (o OpConst) Process(...Data) Data { return o.flow.consts[o.ID] } // Get
+
+// Make this else where?
+func (o OpFunc) Process(params ...Data) Data {
+	op := o.flow.operations[o.ID]
+	// Grab operation inputs from flow
+	callParam := make([]reflect.Value, len(op.inputs))
+	for i, in := range op.inputs {
+		switch v := in.(type) {
+		case operation:
+			callParam[i] = reflect.ValueOf(v.Process(params...))
+		default: // {lpf} Analyse this
+			panic(errors.New("Is not operation"))
+		}
+	}
+	return reflect.ValueOf(op.executor).Call(callParam)[0].Interface()
+}

+ 113 - 0
registry.go

@@ -0,0 +1,113 @@
+package flow
+
+import "reflect"
+
+// Global
+var (
+	globalRegistry = NewRegistry()
+	Register       = globalRegistry.Register
+)
+
+// Registry function registry
+type Registry struct {
+	data map[string]interface{}
+}
+
+// NewRegistry creates a new registry
+func NewRegistry() *Registry {
+	return &Registry{map[string]interface{}{}}
+}
+
+//Register should be a func only register
+func (r *Registry) Register(name string, v interface{}) error {
+	fntyp := reflect.TypeOf(v)
+	if fntyp.Kind() != reflect.Func {
+		return ErrNotAFunc
+	}
+	if fntyp.NumOut() == 0 {
+		return ErrOutput
+	}
+
+	r.data[name] = v
+	return nil
+}
+
+// Get an entry
+func (r *Registry) Get(name string, params ...interface{}) (interface{}, error) {
+	v, ok := r.data[name]
+	if !ok {
+		return nil, ErrNotFound
+	}
+
+	// We already know this is a function
+	// and that returns 1 or more values
+	vtyp := reflect.TypeOf(v)
+	if vtyp.Out(0).Kind() == reflect.Func {
+		fparam := make([]reflect.Value, len(params))
+		for i := range params {
+			fparam[i] = reflect.ValueOf(params[i])
+		}
+		// Call the func and return the thing
+		v = reflect.ValueOf(v).Call(fparam)[0].Interface()
+	}
+
+	return v, nil
+}
+
+// opFunc creator
+/*type opFactory func() *opFunc
+
+// Registry of operator factory functions
+type Registry struct {
+	opFactory map[string]opFactory
+}
+
+// NewRegistry Creates a new registry
+func NewRegistry() *Registry {
+	r := &Registry{
+		map[string]opFactory{},
+	}
+	return r
+}
+
+// Register a new operator
+func (r *Registry) Register(name string, fn interface{}) error {
+
+	fntyp := reflect.TypeOf(fn)
+	if fntyp.Kind() != reflect.Func {
+		return ErrNotFunc
+	}
+	if fntyp.NumOut() == 0 {
+		return ErrOutput
+	}
+
+	// Directly add this factory?
+	if f, ok := fn.(opFactory); ok {
+		r.opFactory[name] = f
+	}
+
+	// Constructor for func
+	// opFunc creator?
+	cfn := func() *opFunc {
+		op := &opFunc{
+			executor: fn,
+		}
+		return op
+	}
+
+	// Create function factory for function?
+
+	//Create factory from func
+	r.opFactory[name] = cfn
+	//return nil
+	return nil
+}
+
+//Get a New Operation
+func (r *Registry) Get(name string) (*opFunc, error) {
+	createOP, ok := r.opFactory[name]
+	if !ok {
+		return nil, errors.New("Does not exists")
+	}
+	return createOP(), nil
+}*/

+ 4 - 0
x/backfetch/README.md

@@ -0,0 +1,4 @@
+passing a single func
+==================
+
+Node several inputs to one output

+ 28 - 0
x/backfetch/flow.go

@@ -0,0 +1,28 @@
+package backfetch
+
+import "fmt"
+
+// Flow data
+type Flow struct {
+	Err      error
+	registry *Registry
+
+	nodes []Node
+}
+
+// NewFlow creates new flow
+func NewFlow(r *Registry) *Flow {
+	return &Flow{nil, r, []Node{}}
+}
+
+// Get node to flow
+func (f *Flow) Get(name string, params ...interface{}) Node {
+	if f.Err != nil {
+		return nil
+	}
+	n, err := f.registry.Create(name, params...)
+	if err != nil {
+		f.Err = fmt.Errorf("Node: %s %s", name, err)
+	}
+	return n
+}

+ 133 - 0
x/backfetch/node.go

@@ -0,0 +1,133 @@
+package backfetch
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"reflect"
+)
+
+// Data data type alias
+type Data = interface{}
+
+// Node returns data,
+// parameters would be prepared
+type Node interface { // We don't need this
+	Process() Data      // dataProcessor
+	Type() reflect.Type // output type
+}
+
+// NodeFunc creates a Node from a function
+type NodeFunc struct {
+	name     string
+	input    []Node       // Serializable
+	executor interface{}  // the func
+	typ      reflect.Type // just do the thing
+
+	cached func() Data
+}
+
+// Create executor from function
+//
+
+// CreateNodeFactory creates a node constructor from function
+func CreateNodeFactory(name string, fn interface{}) NodeFactory {
+	fntyp := reflect.TypeOf(fn)
+	// Not func? err
+	return func(params ...Node) (Node, error) {
+		if fntyp.NumIn() != len(params) {
+			return nil, errors.New("Invalid number of params")
+		}
+		if fntyp.NumOut() == 0 {
+			return nil, errors.New("Func it should have at least 1 output")
+		}
+		// Allow any type to pass
+		/*for i, p := range params {
+			log.Println("Matching types:", p, fntyp.In(i))
+			if p.Type().Kind() == reflect.Interface {
+				fntyp.In(i).Implements(p.Type())
+			}
+			if !p.Type().Implements(fntyp.In(i)) {
+				return nil, fmt.Errorf("Type mismatch: '%s' != '%s' ", p.Type().Name(), fntyp.In(i).Name())
+			}
+		}*/
+		// Here
+		node := &NodeFunc{
+			name:     name,
+			input:    params,
+			executor: fn,
+			typ:      fntyp.Out(0), // First output
+		}
+		return node, nil
+	}
+}
+
+//Process calls the function
+func (ne *NodeFunc) Process() Data {
+	if ne.cached != nil {
+		return ne.cached() // cached func
+	}
+	// Fetch inputs first
+	inList := []reflect.Value{}
+	for _, in := range ne.input {
+		inList = append(inList, reflect.ValueOf(in.Process()))
+	}
+
+	// :/
+	out := reflect.ValueOf(ne.executor).Call(inList)
+
+	return out[0].Interface()
+}
+
+//Type returns output type
+func (ne *NodeFunc) Type() reflect.Type {
+	return ne.typ
+}
+
+func (ne *NodeFunc) String() string {
+	ret := bytes.NewBuffer(nil)
+
+	fmt.Fprintf(ret, "[ %s:", ne.name)
+
+	if len(ne.input) > 0 {
+		fmt.Fprintf(ret, "Inputs: ")
+	}
+
+	for i, in := range ne.input {
+		if i != 0 {
+			fmt.Fprintf(ret, ", ")
+		}
+		fmt.Fprintf(ret, "%v", in)
+	}
+	fmt.Fprintf(ret, "Output: %v ]", ne.typ)
+	return ret.String()
+}
+
+///////////////////////// SPECIAL CONST ////////////////////
+func Const(a interface{}) *NodeFunc {
+	return &NodeFunc{
+		name:     "const",
+		executor: func() interface{} { return a },
+		typ:      reflect.TypeOf(a),
+	}
+}
+
+// ConstNode basic node
+/*type ConstNode struct {
+	val interface{}
+	typ reflect.Type
+}
+
+func Const(a interface{}) Node {
+	return &ConstNode{
+		val: a,
+		typ: reflect.TypeOf(a),
+	}
+}
+
+func (n *ConstNode) Process() Data {
+	return n.val
+}
+func (n *ConstNode) Type() reflect.Type {
+	return n.typ
+}*/

+ 102 - 0
x/backfetch/node_test.go

@@ -0,0 +1,102 @@
+package backfetch_test
+
+import (
+	"flow/x/backfetch"
+	"log"
+	"reflect"
+	"testing"
+
+	vecasm "github.com/gohxs/vec-benchmark/asm"
+)
+
+func TestDev(t *testing.T) {
+	// App initialization register all the named funcs
+	reg := backfetch.NewRegistry()
+	reg.Register("mul", vecMul) // Create Nodes
+	reg.Register("ptr", ptr)
+
+	f := backfetch.NewFlow(reg)
+	{
+
+		arr := []float32{1, 2, 3, 4}
+		p := f.Get("ptr", &arr)
+		n := f.Get("mul", []float32{1, 2, 3}, p)
+		n2 := f.Get("mul", n, []float32{3, 3, 3})
+		n3 := f.Get("mul", arr, arr)
+		if f.Err != nil {
+			t.Fatal("Error getting nodes", f.Err)
+		}
+		log.Println("Result:", p.Process(), n.Process(), n2.Process(), n3.Process())
+		log.Println("node:", n3)
+	}
+	{
+		// Manual nodes
+		p := f.Get("mul", []float32{1, 2, 3}, &NodeManual{})
+		log.Println("Res:", p)
+
+	}
+
+}
+
+// Prepare an node with 2 inputs one output?
+func vecMul(a, b []float32) []float32 {
+	sz := len(a)
+	if bsz := len(b); bsz < sz {
+		sz = bsz
+	}
+	out := make([]float32, sz)
+	vecasm.VecMulf32x8(a, b, out)
+	return out
+}
+
+func ptr(a interface{}) interface{} {
+	return reflect.ValueOf(a).Elem().Interface()
+}
+
+type NodeManual struct {
+	/*whatever*/
+}
+
+func (n *NodeManual) Process() backfetch.Data {
+	return []float32{1, 2, 3}
+}
+func (n *NodeManual) Type() reflect.Type {
+	return reflect.TypeOf(([]float32)(nil))
+}
+
+/*
+func TestMain(t *testing.T) {
+	// Register all node factories
+	reg := backfetch.NewRegistry()
+
+	// Register step only registers a func with a name
+	reg.Register("ptr", backfetch.NewPtr)
+	reg.Register("const", backfetch.NewConstNode)
+	reg.Register("mul", vecMul)
+
+	// Get step prepares function with input
+	// which makes verifications
+	f := backfetch.NewFlow(reg)
+
+	arr := []float32{1, 2, 3} // Ptr
+	a := f.Get("ptr", &arr)
+	b := f.Get("const", []float32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})
+	m1 := f.Get("mul", a, b)
+	m2 := f.Get("mul", m1, b)
+	if f.Err != nil {
+		t.Fatal(f.Err)
+	}
+	res := m1.Process()
+	log.Println(res)
+
+	t.Log("Adding element to ptr array")
+	arr = append(arr, 4)
+	log.Println("m1:", m1.Process())
+
+	t.Log("Testing m2:", m2.Process())
+
+}
+
+func TestStruct(t *testing.T) {
+
+}*/

+ 63 - 0
x/backfetch/registry.go

@@ -0,0 +1,63 @@
+package backfetch
+
+import (
+	"errors"
+	"reflect"
+)
+
+//NodeFactory type of func
+// Prepares a node with specifics sources
+type NodeFactory func(sources ...Node) (Node, error)
+
+//Registry node registry
+type Registry struct {
+	// Still nodes
+	nodeFactory map[string]NodeFactory
+}
+
+//NewRegistry creates newRegistry
+func NewRegistry() *Registry {
+	return &Registry{
+		map[string]NodeFactory{},
+	}
+}
+
+// Register a nodeFactory
+func (r *Registry) Register(name string, fn interface{}) error {
+	// do a precheck if it is a func
+	//
+	if reflect.TypeOf(fn).Kind() != reflect.Func {
+		return errors.New("Should be a func?")
+	}
+
+	// It is already a factory
+	if factory, ok := fn.(NodeFactory); ok {
+		r.nodeFactory[name] = factory
+		return nil
+	}
+	//Create node factory here
+	r.nodeFactory[name] = CreateNodeFactory(name, fn)
+	return nil
+}
+
+// Create a node with given inputs
+func (r *Registry) Create(name string, params ...interface{}) (Node, error) {
+	createNode, ok := r.nodeFactory[name]
+	if !ok {
+		return nil, errors.New("Does not exists")
+	}
+	// Create Node list for param
+	nodeParam := []Node{}
+	for _, p := range params {
+		switch v := p.(type) {
+		// if node executor
+		case Node:
+			nodeParam = append(nodeParam, v)
+		default: // Check if pointer too
+			nodeParam = append(nodeParam, Const(v))
+			//return nil, fmt.Errorf("Unimplemented")
+		}
+	}
+	return createNode(nodeParam...)
+
+}

+ 200 - 0
x/flowt1/flow.go

@@ -0,0 +1,200 @@
+package flow
+
+import (
+	"bytes"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"reflect"
+)
+
+// Flow engine
+type Flow struct {
+	name   string
+	reg    *Registry
+	params map[string]interface{}
+	// Will run on process
+	op     Operation
+	lastOp Operation
+	Err    error
+
+	runID int
+}
+
+// New Creates a new Flow app
+func New(name string) *Flow {
+	return &Flow{
+		name:   name,
+		reg:    nil, // should be internall
+		params: map[string]interface{}{},
+		op:     nil,
+		lastOp: nil,
+		Err:    nil,
+		runID:  0,
+	}
+}
+
+// SetRegistry sets the flow registry
+func (f *Flow) SetRegistry(r *Registry) {
+	if f.lastOp != nil {
+		panic("Cannot set registry after operation added")
+	}
+	f.reg = r
+}
+
+//Op creates a new Operation
+func (f *Flow) Op(name string, params ...interface{}) Operation {
+	if f.Err != nil { // do nothing
+		return nil
+	}
+	// Func to solve this aswell
+	registry := f.reg
+	if registry == nil {
+		registry = globalRegistry
+	}
+
+	// Create
+	op, err := registry.Get(name, f, params...)
+	if err != nil {
+		f.Err = fmt.Errorf("Creating: %s - %v", name, err)
+	}
+	f.lastOp = op
+	return op
+}
+
+// SetParam sets a flow Param
+func (f *Flow) SetParam(name string, value interface{}) {
+	f.params[name] = value
+}
+
+// SetOutput this flow output
+func (f *Flow) SetOutput(o Operation) {
+	f.op = o
+}
+
+// Param return a Operation parameter
+func (f *Flow) Param(name string) Operation {
+	// Create a local param
+	// and return operation ptr?
+	return &opHandler{
+		opSpec: func() OpSpec {
+			return OpSpec{
+				Name:       "param[" + name + "]",
+				OutputType: reflect.TypeOf(f.params[name]),
+			}
+		},
+		flow:     f,
+		executor: func() Data { return f.params[name] },
+		// Type?
+	}
+}
+
+// Run several operations
+// if operations is not specified
+// we run the flow main output
+func (f *Flow) Run(operations ...Operation) []Data {
+	f.runID++
+
+	if len(operations) == 0 {
+		return []Data{f.Process()}
+	}
+
+	res := make([]Data, len(operations))
+	for i, o := range operations {
+		res[i] = o.Process() // Internal
+	}
+	return res
+}
+
+// Name Returns the flow name
+func (f *Flow) Name() string {
+	return f.name + "_flow"
+}
+
+// Process process the flow
+func (f *Flow) Process() Data {
+	// create Func to Solve operation
+	op := f.op
+	if op == nil {
+		op = f.lastOp
+	}
+	if op == nil {
+		f.Err = errors.New("Empty operation")
+		return nil
+	}
+
+	return op.Process()
+}
+
+func (f *Flow) Spec() OpSpec {
+	op := f.op
+	if op == nil {
+		op = f.lastOp
+	}
+	if op == nil {
+		f.Err = errors.New("Empty operation")
+		return OpSpec{}
+	}
+
+	return OpSpec{
+		Name:       "flow",
+		OutputType: op.Spec().OutputType,
+	}
+}
+
+// try to serialize
+func (f *Flow) String() string {
+	ret := bytes.NewBuffer(nil)
+
+	// Print flow parameters
+	for k, v := range f.params {
+		fmt.Fprintf(ret, "%s.Param[%s] - %v\n", f.name, k, v)
+	}
+	var printop func(o interface{}, prefix string)
+	printop = func(o interface{}, prefix string) {
+		if op, ok := o.(Operation); ok {
+			spec := op.Spec()
+			fmt.Fprintf(ret, "%s <- Name: %s (output: %v) (inputs: %v)\n", prefix, spec.Name, spec.OutputType, spec.InputType)
+			switch op := o.(type) {
+			case *opHandler:
+				for _, in := range op.inputs {
+					printop(in, prefix+"  ")
+				}
+			case *Flow:
+				printop(op.op, prefix+"  ")
+			}
+			return
+		}
+		fmt.Fprintf(ret, "%s <- Constant: %v\n", prefix, o)
+	}
+
+	printop(f.op, "")
+
+	return ret.String()
+}
+
+// Should appear something like
+// {
+//   'flowid': [
+//			{
+//			name:"vec",
+//			inputs: [
+//				{
+//					name: "vec",
+//					const: []float32{1,2,3},
+//
+//
+//			]
+//   ]
+// }
+func (f *Flow) ToJSON() string {
+	s := &Serialize{[]Operation{}, map[int]opData{}}
+	s.serialize(f.op)
+
+	ret := bytes.NewBuffer(nil)
+	e := json.NewEncoder(ret)
+	e.SetIndent("", " ")
+	e.Encode(s.dataOps)
+
+	return ret.String()
+}

+ 187 - 0
x/flowt1/flow_test.go

@@ -0,0 +1,187 @@
+package flow_test
+
+import (
+	flow "flow/x/flowt1"
+	"log"
+	"reflect"
+	"testing"
+
+	vecasm "github.com/gohxs/vec-benchmark/asm"
+)
+
+// Global registry
+
+func vecmul(a []float32, b []float32) []float32 {
+	sz := len(a)
+	if sz < len(b) {
+		sz = len(b)
+	}
+	out := make([]float32, sz)
+
+	vecasm.VecMulf32x8(a, b, out)
+
+	return out
+}
+
+type Iterate struct {
+	i float32
+}
+
+func (it *Iterate) generate() []float32 {
+	it.i++
+	return []float32{it.i, it.i}
+}
+
+func init() {
+	it := &Iterate{}
+
+	flow.Register("vecmul", vecmul)
+	flow.Register("iter", it.generate)
+}
+
+func TestImplementation(t *testing.T) {
+	f := flow.New("myapp")
+	f.SetParam("in", []float32{2, 2, 2, 2})
+
+	op1 := f.Op("vecmul", []float32{1, 2, 3, 4}, []float32{1, 2, 3, 4})
+	op2 := f.Op("vecmul", f.Param("in"), op1)
+
+	res := f.Run(op1, op2)
+	t.Log("Res:", res)
+
+	test := []interface{}{
+		[]float32{1, 4, 9, 16},
+		[]float32{2, 8, 18, 32},
+	}
+	if !reflect.DeepEqual(test, res) {
+		t.Fatal("Arrays does not match:", test, res)
+	}
+}
+
+func TestChaining(t *testing.T) {
+	f1 := flow.New("flow1")
+	// Set the main output to operation
+	// Simple 2 const arrays
+	f1.SetOutput(f1.Op("vecmul", []float32{1, 2, 3}, []float32{1, 2, 3}))
+
+	f2 := flow.New("flow2")
+	f2.SetParam("p1", []float32{0.5, 0.5, 0.5})
+
+	// Multiply flow1 with flow2 parameter 'p1'
+	op := f2.Op("vecmul", f1, f2.Param("p1"))
+	res := f2.Run(op)
+
+	test := []interface{}{
+		[]float32{0.5, 2, 4.5},
+	}
+	if !reflect.DeepEqual(test, res) {
+		t.Fatal("Arrays does not match:", test, res)
+
+	}
+	t.Log("Multiplied 2 flows", res)
+}
+
+func TestParam(t *testing.T) {
+	f := flow.New("flow1")
+	f.SetOutput(f.Op("vecmul", f.Param("in"), []float32{1, 2, 3}))
+
+	{
+		f.SetParam("in", []float32{2, 2, 2})
+		res := f.Run()
+		t.Log("Result:", res)
+		test := []interface{}{
+			[]float32{2, 4, 6},
+		}
+		if !reflect.DeepEqual(res, test) {
+			t.Fatal("Result mismatch")
+		}
+	}
+	{
+		f.SetParam("in", []float32{0.5, 0.5, 0.5})
+		res := f.Run()
+		t.Log("Result2:", res)
+
+		test := []interface{}{
+			[]float32{0.5, 1.0, 1.5},
+		}
+		if !reflect.DeepEqual(res, test) {
+			t.Fatal("Result mismatch")
+		}
+	}
+}
+
+func TestIterate(t *testing.T) {
+	f := flow.New("Myapp")
+	it := f.Op("iter")
+	f.SetOutput(f.Op("vecmul", f.Op("vecmul", it, it), it))
+	res := f.Run()
+	t.Log("Res:", res)
+	res = f.Run()
+	t.Log("Res2:", res)
+
+}
+
+/*func TestRecurse(t *testing.T) {
+	f := flow.New("flow1")
+	f.Op("vecmul", f, []float32{1, 2, 3, 4})
+	t.Log("F result:", f.Run())
+}*/
+
+func TestString(t *testing.T) {
+	f := flow.New("Myapp")
+	f.SetParam("vec1", []float32{1, 2, 3})
+
+	f2 := flow.New("flow2")
+	f2.SetParam("vec2", []float32{2, 2, 2})
+
+	m := f.Op("vecmul", []float32{1, 2, 3}, f.Param("vec1")) // Result 1,4,9
+	f.SetOutput(f.Op("vecmul", m, []float32{2, 2, 2}))       // Result 2,8,18
+
+	f2.SetOutput(
+		f2.Op("vecmul", f2.Param("vec2"), f), // Result 4,16,36
+	)
+
+	res := f2.Run()
+	t.Log("Result:", res)
+	t.Log("Flow:\n", f2)
+}
+
+func TestSerialize(t *testing.T) {
+	f := flow.New("Myapp")
+
+	//v := f.Variable([]float32{1})
+
+	f.SetParam("vec1", []float32{1, 2, 3})
+
+	c := f.Op("const", []float32{3, 3, 3})
+
+	m1 := f.Op("vecmul", []float32{2, 2, 2}, f.Param("vec1"))
+
+	// Two operations
+	v1 := f.Op("vecmul", c, m1)
+	v2 := f.Op("vecmul", c, m1)
+
+	l := f.Op("vecmul", v2, v1)
+
+	f.SetOutput(l)
+	if f.Err != nil {
+		t.Fatal("Err:", f.Err)
+	}
+
+	log.Println("json:", f.ToJSON())
+
+	/*f2 := flow.New("flow2")
+	f2.SetParam("vec2", []float32{2, 2, 2})
+
+	m := f.Op("vecmul", []float32{1, 2, 3}, f.Param("vec1")) // Result 1,4,9
+	f.SetOutput(f.Op("vecmul", m, []float32{2, 2, 2}))       // Result 2,8,18
+
+	f2.SetOutput(
+		f2.Op("vecmul", f2.Param("vec2"), f), // Result 4,16,36
+	)
+
+	r := f2.ToJSON()
+
+	t.Log("T:\n", r)*/
+
+}

+ 25 - 0
x/flowt1/opconst.go

@@ -0,0 +1,25 @@
+package flow
+
+import "reflect"
+
+// Serializable
+type opConst struct {
+	value Data
+}
+
+func (o *opConst) Process() Data {
+	return o.value
+}
+
+func (o *opConst) Spec() OpSpec {
+	return OpSpec{ // No inputs
+		Name:       "const",
+		OutputType: reflect.TypeOf(o.value),
+	}
+}
+
+func Const(v Data) Operation {
+	return &opConst{
+		value: v,
+	}
+}

+ 97 - 0
x/flowt1/operation.go

@@ -0,0 +1,97 @@
+package flow
+
+import (
+	"errors"
+	"fmt"
+	"reflect"
+)
+
+type Type = reflect.Type
+type Data = interface{}
+
+// Maybe we can set input type
+type OpSpec struct {
+	Name       string
+	InputType  []Type
+	OutputType Type // For dynamics
+}
+
+// Operator
+type Operation interface {
+	Spec() OpSpec
+	Init(params ...interface{}) error
+	Process() Data // Or Value()
+}
+
+// Operation controller
+type opHandler struct {
+	flow   *Flow // use parent flow for certain things
+	opSpec func() OpSpec
+	inputs []Operation // should be an operation
+
+	executor interface{} // Function that executes
+
+	runID int
+	cache interface{}
+
+	// maybe cache
+}
+
+// Processes or fetches data
+func (o *opHandler) Process() Data {
+	if o.flow.runID == o.runID && o.cache != nil {
+		return o.cache
+	}
+
+	callParam := make([]reflect.Value, len(o.inputs))
+	for i, in := range o.inputs {
+		switch ind := in.(type) {
+		case Operation:
+			callParam[i] = reflect.ValueOf(ind.Process())
+		default:
+			callParam[i] = reflect.ValueOf(ind)
+		}
+	}
+
+	o.runID = o.flow.runID
+	o.cache = reflect.ValueOf(o.executor).Call(callParam)[0].Interface()
+	return o.cache
+}
+func (o *opHandler) Spec() OpSpec {
+	return o.opSpec()
+}
+
+// Create a constructor for a func
+func fromFunc(name string, fn interface{}) opFactory {
+	fntyp := reflect.TypeOf(fn)
+
+	// Constructor for func
+	return func(flow *Flow, params ...Operation) (Operation, error) {
+		// Do some checking first
+		if fntyp.NumIn() != len(params) {
+			return nil, fmt.Errorf("Invalid number of params expected: %d got %d", fntyp.NumIn(), len(params))
+		}
+		if fntyp.NumOut() == 0 {
+			return nil, errors.New("Func it should have at least 1 output")
+		}
+		inputTypes := make([]Type, fntyp.NumIn())
+		for i := 0; i < fntyp.NumIn(); i++ {
+			inputTypes[i] = fntyp.In(i)
+		}
+
+		// Here
+		op := &opHandler{
+			opSpec: func() OpSpec {
+				return OpSpec{
+					InputType:  inputTypes,
+					Name:       name,
+					OutputType: fntyp.Out(0), // First output
+				}
+			},
+			flow:     flow,
+			inputs:   params,
+			executor: fn,
+		}
+		return op, nil
+	}
+}

+ 77 - 0
x/flowt1/registry.go

@@ -0,0 +1,77 @@
+package flow
+
+import (
+	"errors"
+	"reflect"
+)
+
+// Errors
+var (
+	ErrNotFunc       = errors.New("Is not a function")
+	ErrInvalidOutput = errors.New("Invalid output")
+
+	globalRegistry = NewRegistry()
+	Register       = globalRegistry.Register
+)
+
+type opFactory func(flow *Flow, source ...Operation) (Operation, error)
+
+// Registry of operations
+type Registry struct {
+	opFactory map[string]opFactory
+}
+
+//NewRegistry creates a new Registry
+func NewRegistry() *Registry {
+	r := &Registry{
+		map[string]opFactory{},
+	}
+	// Register defaults
+
+	//r.Register("const")
+
+	return r
+}
+
+//Register register a new operator
+func (r *Registry) Register(name string, fn interface{}) error {
+	fntyp := reflect.TypeOf(fn)
+
+	if fntyp.Kind() != reflect.Func {
+		return ErrNotFunc
+	}
+	if fntyp.NumOut() == 0 {
+		return ErrInvalidOutput
+	}
+	// Need to have one output
+	//
+	// Directly add this factory?
+	if f, ok := fn.(opFactory); ok {
+		r.opFactory[name] = f
+	}
+
+	//Create factory from func
+	r.opFactory[name] = fromFunc(name, fn)
+	return nil
+}
+
+//Get a New Operation
+func (r *Registry) Get(name string, flow *Flow, params ...interface{}) (Operation, error) {
+	createOP, ok := r.opFactory[name]
+	if !ok {
+		return nil, errors.New("Does not exists")
+	}
+	// Create Node list for param
+	opParam := make([]Operation, len(params))
+	for i, p := range params {
+		switch v := p.(type) {
+		// if node executor
+		case Operation:
+			opParam[i] = v
+		default: // Check if pointer too
+			opParam[i] = Const(v) // Or the simple value?
+		}
+	}
+	return createOP(flow, opParam...)
+
+}

+ 113 - 0
x/flowt1/serializer.go

@@ -0,0 +1,113 @@
+package flow
+
+import "log"
+
+type Serialize struct {
+	ops     []Operation    // Temp ops
+	dataOps map[int]opData // Serialize this
+}
+
+type opData struct {
+	Name  string      `json:"name"`
+	In    []int       `json:"in,omitempty"`
+	Value interface{} `json:"value,omitempty"`
+}
+
+// Fill up ops structure
+func (s *Serialize) serialize(op Operation) int {
+	// Recurse operations into an array
+	// Find operationID
+	if op == nil {
+		log.Println("Op is nil")
+		return -1
+	}
+
+	opId := -1
+	for i, o := range s.ops {
+		if o == op {
+			opId = i
+			break
+		}
+	}
+	if opId == -1 {
+		s.ops = append(s.ops, op)
+		opId = len(s.ops) - 1
+	}
+
+	ret := opId
+	od := opData{In: []int{}, Name: op.Spec().Name}
+
+	switch o := op.(type) {
+	case *opHandler:
+		for _, in := range o.inputs {
+			od.In = append(od.In, s.serialize(in))
+		}
+		break
+	case *opConst:
+		od.Value = o.value
+		break
+
+	}
+	// Store in dataOps
+	s.dataOps[ret] = od
+	return ret
+}
+
+/*type Serialize struct {
+	flows map[string]flowData
+}
+type opData struct {
+	Name   string      `json:",omitempty"`
+	Inputs []opData    `json:",omitempty"`
+	Value  interface{} `json:",omitempty"`
+}
+
+type flowData struct {
+	Param    map[string]interface{}
+	Operator opData
+}
+
+func (s *Serialize) serialize(v interface{}) opData {
+	//Create ID
+	o, ok := v.(Operation)
+	if !ok {
+		return opData{Name: "const", Value: v}
+	}
+	// If it is a flow
+	ret := opData{
+		Name: o.Spec().Name,
+	}
+	// If flow
+	if h, ok := o.(*opHandler); ok {
+		for _, in := range h.inputs {
+			r := s.serialize(in)
+			if f, ok := in.(*Flow); ok {
+				ret.Inputs = append(ret.Inputs, opData{Name: "@" + f.name})
+			} else {
+				ret.Inputs = append(ret.Inputs, r)
+			}
+		}
+	}
+	if f, ok := v.(*Flow); ok {
+
+		fd := flowData{Param: map[string]interface{}{}, Operator: s.serialize(f.op)}
+		for k, p := range f.params {
+			fd.Param[k] = p
+		}
+		s.flows[f.name] = fd
+	}
+
+	return ret
+}
+
+func (s *Serialize) Serialize(f *Flow) string {
+	s.serialize(f)
+
+	ret := bytes.NewBuffer(nil)
+
+	e := json.NewEncoder(ret)
+	e.SetIndent("", " ")
+	e.Encode(s.flows)
+
+	return ret.String()
+}*/

+ 11 - 0
x/flowt2/errors.go

@@ -0,0 +1,11 @@
+package flow
+
+import "errors"
+
+// flow Errors
+var (
+	ErrNotFound  = errors.New("Entry not found")
+	ErrNotAFunc  = errors.New("Is not a function")
+	ErrOutput    = errors.New("Invalid output")
+	ErrOperation = errors.New("Invalid operation")
+)

+ 104 - 0
x/flowt2/flow.go

@@ -0,0 +1,104 @@
+package flow
+
+// Data basic data interface
+type Data = interface{}
+
+// Operation data entry
+type opEntry struct {
+	name  string // Constructor name
+	input []Ref  // Reference to input
+}
+
+// Flow structure
+type Flow struct {
+	registry   *Registry
+	consts     []Data
+	data       []Data
+	operations []opEntry // Registered operations
+
+	// Could be same with some indicator
+}
+
+// New create new flow
+func New() *Flow {
+	return &Flow{
+		registry: globalRegistry,
+
+		// Serializable
+		operations: []opEntry{},
+		data:       []Data{},
+		consts:     []Data{},
+	}
+}
+
+// SetRegistry sets the registry for this flow
+func (f *Flow) SetRegistry(r *Registry) {
+	f.registry = r
+}
+
+// Op add a new operation
+func (f *Flow) Op(name string, params ...interface{}) Ref {
+	refParams := make([]Ref, len(params))
+	for i, p := range params {
+		switch v := p.(type) {
+		case Ref:
+			refParams[i] = v
+		default:
+			refParams[i] = f.Const(v) // Should be a simple value and not a pointer
+		}
+	}
+	f.operations = append(f.operations, opEntry{name, refParams})
+	refID := len(f.operations) - 1
+	return RefFunc{ref{f, refID}}
+}
+
+// Build the flow into a graph
+func (f *Flow) Build() (*Graph, error) {
+	g := &Graph{flow: f, operations: []operation{}}
+
+	// Add operations to operator
+	for _, op := range f.operations {
+		fn, err := f.registry.Get(op.name)
+		if err != nil {
+			return nil, err
+		}
+		// If executor returns a function we can call it to instantiate
+		// Create wrapper here
+		newOp := &opFunc{flow: f, executor: fn}
+		g.operations = append(g.operations, newOp)
+		// Check what is the fn
+		param := []interface{}{}
+		for _, in := range op.input {
+			switch ref := in.(type) {
+			case RefFunc:
+				param = append(param, g.operations[ref.id]) // operation already registered
+			case RefConst:
+				param = append(param, &opConst{f.consts[ref.id]})
+			case RefVar:
+				param = append(param, &opVar{flow: f, id: ref.id})
+			}
+		}
+
+		err = newOp.Init(param...)
+		if err != nil {
+			return nil, err
+		}
+	}
+	return g, nil
+}
+
+// Const new constant
+func (f *Flow) Const(v interface{}) Ref {
+	// Add a ref
+	f.consts = append(f.consts, v)
+	refID := len(f.consts) - 1
+	return RefConst{ref{f, refID}}
+}
+
+// Variable new variable with initial value
+func (f *Flow) Variable(initial interface{}) RefVar {
+	// Add a ref
+	f.data = append(f.data, initial)
+	refID := len(f.data) - 1
+	return RefVar{ref{f, refID}}
+}

+ 128 - 0
x/flowt2/flow_test.go

@@ -0,0 +1,128 @@
+package flow_test
+
+import (
+	flow "flow/x/flowt2"
+	"log"
+	"reflect"
+	"testing"
+
+	vecasm "github.com/gohxs/vec-benchmark/asm"
+)
+
+func TestFlow(t *testing.T) {
+	f := flow.New()
+	a := f.Const([]float32{1, 2, 3})
+	b := f.Const([]float32{2, 2, 2})
+	f.Op("mul", a, b)
+
+	log.Println(f)
+}
+func TestBuild(t *testing.T) {
+	var err error
+	err = flow.Register("vecmul", vecmul)
+	if err != nil {
+		t.Fatal(err)
+	}
+	err = flow.Register("vecadd", vecadd)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	f := flow.New()
+
+	a := f.Const([]float32{1, 2, 3})
+	b := f.Const([]float32{2, 2, 2})
+	m := f.Op("vecmul", []float32{1, 2, 3}, b)
+	lastOp := f.Op("vecadd", a, m)
+
+	{
+		g, err := f.Build()
+		if err != nil {
+			t.Fatal(err)
+		}
+		res, err := g.Run(m, lastOp)
+
+		test := []interface{}{
+			[]float32{2, 4, 6},
+			[]float32{3, 6, 9},
+		}
+		if !reflect.DeepEqual(test, res) {
+			t.Fatal("Arrays does not match:", test, res)
+		}
+		t.Log("Result:", res)
+	}
+}
+func TestImplementation(t *testing.T) {
+	f := flow.New()
+
+	in := f.Variable([]float32{2, 2, 2, 2})
+
+	v1 := f.Const([]float32{1, 2, 3, 4})
+
+	op1 := f.Op("vecmul", v1, v1)  // 1 2 9 16
+	op2 := f.Op("vecmul", in, op1) // 2 4 18 32
+
+	g, err := f.Build()
+	if err != nil {
+		t.Fatal(err)
+	}
+	res, err := g.Run(op1, op2)
+	t.Log("Res:", res)
+
+	test := []interface{}{
+		[]float32{1, 4, 9, 16},
+		[]float32{2, 8, 18, 32},
+	}
+	if !reflect.DeepEqual(test, res) {
+		t.Fatal("Arrays does not match:", test, res)
+	}
+}
+
+func TestVariable(t *testing.T) {
+	f := flow.New()
+	v := f.Variable([]float32{1, 2, 3})
+
+	g, err := f.Build()
+	if err != nil {
+		t.Fatal(err)
+	}
+	res, _ := g.Run(v)
+	log.Println("res", res)
+	v.Set([]float32{4, 5, 6})
+	res, _ = g.Run(v)
+	log.Println("res", res)
+}
+
+func init() {
+	flow.Register("vecmul", vecmul)
+	flow.Register("vecadd", vecadd)
+}
+
+// Some funcs
+func vecmul(a, b []float32) []float32 {
+
+	sz := min(len(a), len(b))
+
+	out := make([]float32, sz)
+	vecasm.VecMulf32x8(a, b, out)
+	log.Println("Mul:", a, b, "=", out)
+	return out
+}
+func vecadd(a, b []float32) []float32 {
+	sz := min(len(a), len(b))
+	out := make([]float32, sz)
+	for i := 0; i < sz; i++ {
+		out[i] = a[i] + b[i]
+	}
+	return out
+}
+
+func min(p ...int) int {
+	min := p[0]
+	for _, v := range p[1:] {
+		if min < v {
+			min = v
+		}
+	}
+	return min
+}

+ 28 - 0
x/flowt2/graph.go

@@ -0,0 +1,28 @@
+package flow
+
+// Graph the graph of operations
+type Graph struct {
+	flow *Flow
+	// built operations
+	// Caching operation
+	operations []operation
+}
+
+// Run functions
+func (g *Graph) Run(refs ...Ref) ([]Data, error) {
+	res := []Data{}
+	for _, r := range refs {
+		switch ref := r.(type) {
+		case RefConst:
+			res = append(res, g.flow.consts[ref.id])
+		case RefVar:
+			res = append(res, g.flow.data[ref.id])
+		case RefFunc:
+			res = append(res, g.operations[ref.id].Process())
+		default:
+			// Invalid operation
+			return nil, ErrOperation
+		}
+	}
+	return res, nil
+}

+ 79 - 0
x/flowt2/operation.go

@@ -0,0 +1,79 @@
+package flow
+
+import "reflect"
+
+// Operation interface
+type operation interface {
+	// Set inputs?
+	//Init(inputs ...interface{}) error
+	Process() Data
+}
+
+////////////////////////////////////////////
+// OP CONST
+//////////////////////////////////////////
+
+// Const should point to flow somehow?
+/*type opConst struct {
+	// Flow ref?
+	value Data
+}
+
+func (o *opConst) Process() Data { return o.value }*/
+
+/////////////////////////////////
+// OP VARIABLE
+///////////////////////////////////
+type opVar struct {
+	flow *Flow
+	id   int
+}
+
+func (o *opVar) Process() Data {
+	return o.flow.data[o.id]
+}
+
+///////////////////////////////////////////
+// function operation
+///////////////////////////
+
+// Operation controller
+// Operator for thing
+type opFunc struct {
+	flow     *Flow
+	inputs   []operation // should be an operation
+	executor interface{} // Function that executes, something like func(...inputs)
+	// maybe cache
+}
+
+func (o *opFunc) Init(params ...interface{}) error {
+	// Create Node list for param
+	o.inputs = make([]operation, len(params))
+	for i, p := range params {
+		switch v := p.(type) {
+		// if node executor
+		case operation:
+			o.inputs[i] = v
+		default: // Check if pointer too
+			//opParam[i] = Const(v) // Or the simple value?
+		}
+	}
+	// Do checks here
+	return nil
+}
+
+func (o *opFunc) Process() Data {
+	// Cache control?
+	callParam := make([]reflect.Value, len(o.inputs))
+	for i, in := range o.inputs {
+		switch v := in.(type) {
+		case operation:
+			callParam[i] = reflect.ValueOf(v.Process())
+		default: // {lpf} Analyse this
+			callParam[i] = reflect.ValueOf(v)
+		}
+	}
+
+	return reflect.ValueOf(o.executor).Call(callParam)[0].Interface()
+
+}

+ 37 - 0
x/flowt2/ref.go

@@ -0,0 +1,37 @@
+package flow
+
+// RefType data type
+//type RefType int
+
+// Reference types
+const (
+//RefConst = RefType(1) + iota
+//RefData
+//RefFunc
+//RefAttr
+)
+
+// Referer interface
+type Ref interface {
+	_ref() ref
+}
+
+// Ref flow object reference
+type ref struct {
+	flow *Flow
+	id   int // ref index
+}
+
+// Return self for interface
+// ref ref ref ref ref
+func (r ref) _ref() ref {
+	return r
+}
+
+type RefFunc struct{ ref }
+type RefConst struct{ ref }
+type RefVar struct{ ref }
+
+func (r RefVar) Set(value interface{}) {
+	r.flow.data[r.id] = value
+}

+ 113 - 0
x/flowt2/registry.go

@@ -0,0 +1,113 @@
+package flow
+
+import "reflect"
+
+// Global
+var (
+	globalRegistry = NewRegistry()
+	Register       = globalRegistry.Register
+)
+
+// Registry function registry
+type Registry struct {
+	data map[string]interface{}
+}
+
+// NewRegistry creates a new registry
+func NewRegistry() *Registry {
+	return &Registry{map[string]interface{}{}}
+}
+
+//Register should be a func only register
+func (r *Registry) Register(name string, v interface{}) error {
+	fntyp := reflect.TypeOf(v)
+	if fntyp.Kind() != reflect.Func {
+		return ErrNotAFunc
+	}
+	if fntyp.NumOut() == 0 {
+		return ErrOutput
+	}
+
+	r.data[name] = v
+	return nil
+}
+
+// Get an entry
+func (r *Registry) Get(name string, params ...interface{}) (interface{}, error) {
+	v, ok := r.data[name]
+	if !ok {
+		return nil, ErrNotFound
+	}
+
+	// We already know this is a function
+	// and that returns 1 or more values
+	vtyp := reflect.TypeOf(v)
+	if vtyp.Out(0).Kind() == reflect.Func {
+		fparam := make([]reflect.Value, len(params))
+		for i := range params {
+			fparam[i] = reflect.ValueOf(params[i])
+		}
+		// Call the func and return the thing
+		v = reflect.ValueOf(v).Call(fparam)[0].Interface()
+	}
+
+	return v, nil
+}
+
+// opFunc creator
+/*type opFactory func() *opFunc
+
+// Registry of operator factory functions
+type Registry struct {
+	opFactory map[string]opFactory
+}
+
+// NewRegistry Creates a new registry
+func NewRegistry() *Registry {
+	r := &Registry{
+		map[string]opFactory{},
+	}
+	return r
+}
+
+// Register a new operator
+func (r *Registry) Register(name string, fn interface{}) error {
+
+	fntyp := reflect.TypeOf(fn)
+	if fntyp.Kind() != reflect.Func {
+		return ErrNotFunc
+	}
+	if fntyp.NumOut() == 0 {
+		return ErrOutput
+	}
+
+	// Directly add this factory?
+	if f, ok := fn.(opFactory); ok {
+		r.opFactory[name] = f
+	}
+
+	// Constructor for func
+	// opFunc creator?
+	cfn := func() *opFunc {
+		op := &opFunc{
+			executor: fn,
+		}
+		return op
+	}
+
+	// Create function factory for function?
+
+	//Create factory from func
+	r.opFactory[name] = cfn
+	//return nil
+	return nil
+}
+
+//Get a New Operation
+func (r *Registry) Get(name string) (*opFunc, error) {
+	createOP, ok := r.opFactory[name]
+	if !ok {
+		return nil, errors.New("Does not exists")
+	}
+	return createOP(), nil
+}*/

+ 67 - 0
x/flowt2/registry_test.go

@@ -0,0 +1,67 @@
+package flow_test
+
+import (
+	flow "flow/x/flowt2"
+	"reflect"
+	"testing"
+)
+
+type Stateful struct {
+	i int
+}
+
+func (s *Stateful) Increment() int {
+	s.i++
+	return s.i
+}
+
+// Returns a function
+func StatefulConstructor() func() int {
+	i := 0
+	return func() int {
+		i++
+		return i
+	}
+}
+
+func TestRegistry(t *testing.T) {
+	s := &Stateful{}
+	r := flow.NewRegistry()
+	r.Register("stateful1", s.Increment)
+	r.Register("stateful2", StatefulConstructor)
+	{
+		f := flow.New()
+		f.SetRegistry(r)
+		s1op1 := f.Op("stateful1")
+		s1op2 := f.Op("stateful1")
+
+		s2op1 := f.Op("stateful2")
+		s2op2 := f.Op("stateful2")
+
+		var err error
+		g, err := f.Build() // Get graph
+		if err != nil {
+			t.Fatal(err)
+		}
+
+		res, err := g.Run(s1op1, s1op1, s1op2) // Each time running it will increment all
+		errcheck(t, err)
+		t.Log("Reg:", res)
+		if !reflect.DeepEqual(res, []interface{}{1, 2, 3}) {
+			t.Fatal("Result mismatch")
+		}
+
+		res, err = g.Run(s2op1, s2op1, s2op2) // Each time it will increment instance
+		errcheck(t, err)
+		t.Log("Reg:", res)
+		if !reflect.DeepEqual(res, []interface{}{1, 2, 1}) {
+			t.Fatal("Result mismatch")
+		}
+	}
+}
+
+func errcheck(t *testing.T, err error) {
+	if err != nil {
+		t.Fatal(err)
+	}
+}

+ 37 - 0
x/nn/main.go

@@ -0,0 +1,37 @@
+package main
+
+import (
+	"flow"
+	"log"
+	"math/rand"
+)
+
+func main() {
+	// Prepare registry
+	reg() // Initialize register
+
+	// Define operations
+	// Several flows
+	// Model a flow
+	nn := flow.New("neural")
+	nn.Op("vecrand", 10)
+
+	res := nn.Run()
+	log.Println(res)
+
+}
+
+func reg() {
+	flow.Register("vecrand", normFloat)
+}
+
+// Generate random floats
+func normFloat(sz int) []float32 {
+	out := make([]float32, sz)
+
+	for i := range out {
+		out[i] = rand.Float32() // 0 to 1?
+	}
+
+	return out
+}

+ 19 - 0
x/nodelist/node.go

@@ -0,0 +1,19 @@
+package nodelist
+
+type Data = interface{} // Any data
+
+type Core struct {
+	node []Node
+}
+
+// Node Inputs data outputs data
+type Node interface {
+	Process(Data) Data
+}
+
+func main() {
+	c := &Core{[]Node{}}
+	c.Add("add", params...)
+
+	c.Run(input)
+}

+ 17 - 0
x/ref/flow.go

@@ -0,0 +1,17 @@
+package flow
+
+type Data = interface{}
+
+// Operations
+type Flow struct {
+}
+
+
+func (f *Flow) Op(name string, ... interface{}) {
+}
+
+
+type FlowOp struct {
+	Name string // Constructor name
+	Input []int
+}

+ 65 - 0
x/sample1/main.go

@@ -0,0 +1,65 @@
+package main
+
+import (
+	"flow"
+	"io/ioutil"
+	"log"
+	"math/rand"
+	"net/http"
+	"time"
+
+	"github.com/gohxs/prettylog"
+)
+
+func main() {
+	prettylog.Global()
+	rand.Seed(int64(time.Now().Nanosecond()))
+
+	flow.Register("randpick", randpick)
+	flow.Register("httpget", httpget)
+
+	urls := []string{
+		"http://www.bing.com/?q=test",
+		"http://www.google.com/?q=test",
+	}
+
+	f := flow.New()
+	//	urlsVar := f.Variable(urls)
+
+	single := f.Op("randpick", f.In(0))
+	doget := f.Op("httpget", single)
+	res := doget.Process(urls)
+	log.Println("f:", f)
+
+	//res, err := f.Run(doget)
+	//if err != nil {
+	//	log.Fatal(err)
+	//}
+	log.Println("Result:", res)
+
+}
+
+func randpick(s []string) string {
+	log.Println("Picking between:", s)
+	pick := rand.Intn(len(s))
+	log.Println("Picking:", pick, s[pick], len(s))
+	return s[pick]
+}
+
+// Get body
+func httpget(s string) string {
+
+	res, err := http.Get(s)
+	if err != nil { // Error stater
+		return ""
+	}
+	defer res.Body.Close()
+
+	data, err := ioutil.ReadAll(res.Body)
+	if err != nil {
+		return ""
+	}
+
+	return string(data)
+
+}

BIN
x/testing/debug


+ 31 - 0
x/testing/main.go

@@ -0,0 +1,31 @@
+package main
+
+import (
+	"flow"
+	"log"
+
+	vecasm "github.com/gohxs/vec-benchmark/asm"
+)
+
+func vecmul(a, b []float32) []float32 {
+
+	sz := len(a)
+	if sz > len(b) {
+		sz = len(b)
+	}
+	out := make([]float32, sz)
+	vecasm.VecMulf32x8(a, b, out)
+	return out
+}
+
+func main() {
+
+	flow.Register("vecmul", vecmul)
+
+	f := flow.New("f1")
+	f.SetOutput(f.Op("vecmul", []float32{1, 2, 3}, []float32{4, 3, 2}))
+
+	log.Println("res:", f.Run())
+	log.Println("Recurse:", f)
+
+}