// NewBlankMachine creates a new Golog machine without loading the // standard library (prelude) func NewBlankMachine() Machine { var m machine m.db = NewDatabase() m.env = NewBindings() m.disjs = ps.NewList() m.conjs = ps.NewList() for i := 0; i < smallThreshold; i++ { m.smallForeign[i] = ps.NewMap() } m.largeForeign = ps.NewMap() return (&m).DemandCutBarrier() }
// Merge combines the two Metrics and returns a new result. func (m Metric) Merge(other Metric) Metric { // Merge two lists of samples in O(n) curr1, curr2, acc := m.Samples, other.Samples, ps.NewList() for { if curr1 == nil || curr1.IsNil() { acc = revCons(acc, curr2) break } else if curr2 == nil || curr2.IsNil() { acc = revCons(acc, curr1) break } s1 := curr1.Head().(Sample) s2 := curr2.Head().(Sample) if s1.Timestamp.Equal(s2.Timestamp) { curr1, curr2, acc = curr1.Tail(), curr2.Tail(), acc.Cons(s1) } else if s1.Timestamp.After(s2.Timestamp) { curr1, acc = curr1.Tail(), acc.Cons(s1) } else { curr2, acc = curr2.Tail(), acc.Cons(s2) } } return Metric{ Samples: acc, Max: math.Max(m.Max, other.Max), Min: math.Min(m.Min, other.Min), First: first(m.First, other.First), Last: last(m.Last, other.Last), } }
// Add returns a new Metric with (t, v) added to its Samples. Add is the only // valid way to grow a Metric. func (m Metric) Add(t time.Time, v float64) Metric { // Find the first element which is before you element, and insert // your new element in the list. NB we want to dedupe entries with // equal timestamps. // This should be O(1) to insert a latest element, and O(n) in general. curr, acc := m.Samples, ps.NewList() for { if curr == nil || curr.IsNil() { acc = acc.Cons(Sample{t, v}) break } currSample := curr.Head().(Sample) if currSample.Timestamp.Equal(t) { acc, curr = acc.Cons(Sample{t, v}), curr.Tail() break } if currSample.Timestamp.Before(t) { acc = acc.Cons(Sample{t, v}) break } acc, curr = acc.Cons(curr.Head()), curr.Tail() } acc = revCons(acc, curr) return Metric{ Samples: acc, Max: math.Max(m.Max, v), Min: math.Min(m.Min, v), First: first(m.First, t), Last: last(m.Last, t), } }
func (m WireMetrics) fromIntermediate() Metric { samples := ps.NewList() for _, s := range m.Samples { samples = samples.Cons(s) } return Metric{ Samples: samples, Max: m.Max, Min: m.Min, First: parseTime(m.First), Last: parseTime(m.Last), } }
// Div returns a new copy of the metric, with each value divided by n. func (m Metric) Div(n float64) Metric { curr, acc := m.Samples, ps.NewList() for curr != nil && !curr.IsNil() { s := curr.Head().(Sample) curr, acc = curr.Tail(), acc.Cons(Sample{s.Timestamp, s.Value / n}) } acc = acc.Reverse() return Metric{ Samples: acc, Max: m.Max / n, Min: m.Min / n, First: m.First, Last: m.Last, } }
// Extend behaves like Append, except it takes a single slice or array value // which will be concatenated to the named list. // // Unlike a variadic call to Append - which requires a []interface{} value - // Extend accepts slices or arrays of any type. // // Extend will panic if the given value is not a slice, array, or nil. func Extend(builder interface{}, name string, vs interface{}) interface{} { if vs == nil { return builder } maybeList, ok := getBuilderMap(builder).Lookup(name) var list ps.List if ok { list, ok = maybeList.(ps.List) } if !ok { list = ps.NewList() } forEach(vs, func(v interface{}) { list = list.Cons(v) }) return Set(builder, name, list) }
// Metric is a list of timeseries data with some metadata. Clients must use the // Add method to add values. Metrics are immutable. type Metric struct { Samples ps.List Min, Max float64 First, Last time.Time } // Sample is a single datapoint of a metric. type Sample struct { Timestamp time.Time `json:"date"` Value float64 `json:"value"` } var nilMetric = Metric{Samples: ps.NewList()} // MakeMetric makes a new Metric. func MakeMetric() Metric { return nilMetric } // Copy returns a value copy of the Metric. Metric is immutable, so we can skip // this. func (m Metric) Copy() Metric { return m } // WithFirst returns a fresh copy of m, with First set to t. func (m Metric) WithFirst(t time.Time) Metric { return Metric{
func (m *machine) ClearDisjs() Machine { m1 := m.clone() m1.disjs = ps.NewList() return m1 }
func (m *machine) ClearConjs() Machine { m1 := m.clone() m1.conjs = ps.NewList() return m1 }