1108 lines
26 KiB
Go
1108 lines
26 KiB
Go
// Generated by tmpl
|
|
// https://github.com/benbjohnson/tmpl
|
|
//
|
|
// DO NOT EDIT!
|
|
// Source: arrayvalues.gen.go.tmpl
|
|
|
|
package cursors
|
|
|
|
type FloatArray struct {
|
|
Timestamps []int64
|
|
Values []float64
|
|
}
|
|
|
|
func NewFloatArrayLen(sz int) *FloatArray {
|
|
return &FloatArray{
|
|
Timestamps: make([]int64, sz),
|
|
Values: make([]float64, sz),
|
|
}
|
|
}
|
|
|
|
func (a *FloatArray) MinTime() int64 {
|
|
return a.Timestamps[0]
|
|
}
|
|
|
|
func (a *FloatArray) MaxTime() int64 {
|
|
return a.Timestamps[len(a.Timestamps)-1]
|
|
}
|
|
|
|
func (a *FloatArray) Len() int {
|
|
return len(a.Timestamps)
|
|
}
|
|
|
|
// search performs a binary search for UnixNano() v in a
|
|
// and returns the position, i, where v would be inserted.
|
|
// An additional check of a.Timestamps[i] == v is necessary
|
|
// to determine if the value v exists.
|
|
func (a *FloatArray) search(v int64) int {
|
|
// Define: f(x) → a.Timestamps[x] < v
|
|
// Define: f(-1) == true, f(n) == false
|
|
// Invariant: f(lo-1) == true, f(hi) == false
|
|
lo := 0
|
|
hi := a.Len()
|
|
for lo < hi {
|
|
mid := int(uint(lo+hi) >> 1)
|
|
if a.Timestamps[mid] < v {
|
|
lo = mid + 1 // preserves f(lo-1) == true
|
|
} else {
|
|
hi = mid // preserves f(hi) == false
|
|
}
|
|
}
|
|
|
|
// lo == hi
|
|
return lo
|
|
}
|
|
|
|
// FindRange returns the positions where min and max would be
|
|
// inserted into the array. If a[0].UnixNano() > max or
|
|
// a[len-1].UnixNano() < min then FindRange returns (-1, -1)
|
|
// indicating the array is outside the [min, max]. The values must
|
|
// be deduplicated and sorted before calling FindRange or the results
|
|
// are undefined.
|
|
func (a *FloatArray) FindRange(min, max int64) (int, int) {
|
|
if a.Len() == 0 || min > max {
|
|
return -1, -1
|
|
}
|
|
|
|
minVal := a.MinTime()
|
|
maxVal := a.MaxTime()
|
|
|
|
if maxVal < min || minVal > max {
|
|
return -1, -1
|
|
}
|
|
|
|
return a.search(min), a.search(max)
|
|
}
|
|
|
|
// Exclude removes the subset of values in [min, max]. The values must
|
|
// be deduplicated and sorted before calling Exclude or the results are undefined.
|
|
func (a *FloatArray) Exclude(min, max int64) {
|
|
rmin, rmax := a.FindRange(min, max)
|
|
if rmin == -1 && rmax == -1 {
|
|
return
|
|
}
|
|
|
|
// a.Timestamps[rmin] ≥ min
|
|
// a.Timestamps[rmax] ≥ max
|
|
|
|
if rmax < a.Len() {
|
|
if a.Timestamps[rmax] == max {
|
|
rmax++
|
|
}
|
|
rest := a.Len() - rmax
|
|
if rest > 0 {
|
|
ts := a.Timestamps[:rmin+rest]
|
|
copy(ts[rmin:], a.Timestamps[rmax:])
|
|
a.Timestamps = ts
|
|
|
|
vs := a.Values[:rmin+rest]
|
|
copy(vs[rmin:], a.Values[rmax:])
|
|
a.Values = vs
|
|
return
|
|
}
|
|
}
|
|
|
|
a.Timestamps = a.Timestamps[:rmin]
|
|
a.Values = a.Values[:rmin]
|
|
}
|
|
|
|
// Include returns the subset values between min and max inclusive. The values must
|
|
// be deduplicated and sorted before calling Include or the results are undefined.
|
|
func (a *FloatArray) Include(min, max int64) {
|
|
rmin, rmax := a.FindRange(min, max)
|
|
if rmin == -1 && rmax == -1 {
|
|
a.Timestamps = a.Timestamps[:0]
|
|
a.Values = a.Values[:0]
|
|
return
|
|
}
|
|
|
|
// a.Timestamps[rmin] ≥ min
|
|
// a.Timestamps[rmax] ≥ max
|
|
|
|
if rmax < a.Len() && a.Timestamps[rmax] == max {
|
|
rmax++
|
|
}
|
|
|
|
if rmin > -1 {
|
|
ts := a.Timestamps[:rmax-rmin]
|
|
copy(ts, a.Timestamps[rmin:rmax])
|
|
a.Timestamps = ts
|
|
vs := a.Values[:rmax-rmin]
|
|
copy(vs, a.Values[rmin:rmax])
|
|
a.Values = vs
|
|
} else {
|
|
a.Timestamps = a.Timestamps[:rmax]
|
|
a.Values = a.Values[:rmax]
|
|
}
|
|
}
|
|
|
|
// Merge overlays b to top of a. If two values conflict with
|
|
// the same timestamp, b is used. Both a and b must be sorted
|
|
// in ascending order.
|
|
func (a *FloatArray) Merge(b *FloatArray) {
|
|
if a.Len() == 0 {
|
|
*a = *b
|
|
return
|
|
}
|
|
|
|
if b.Len() == 0 {
|
|
return
|
|
}
|
|
|
|
// Normally, both a and b should not contain duplicates. Due to a bug in older versions, it's
|
|
// possible stored blocks might contain duplicate values. Remove them if they exists before
|
|
// merging.
|
|
// a = a.Deduplicate()
|
|
// b = b.Deduplicate()
|
|
|
|
if a.MaxTime() < b.MinTime() {
|
|
a.Timestamps = append(a.Timestamps, b.Timestamps...)
|
|
a.Values = append(a.Values, b.Values...)
|
|
return
|
|
}
|
|
|
|
if b.MaxTime() < a.MinTime() {
|
|
var tmp FloatArray
|
|
tmp.Timestamps = append(b.Timestamps, a.Timestamps...)
|
|
tmp.Values = append(b.Values, a.Values...)
|
|
*a = tmp
|
|
return
|
|
}
|
|
|
|
out := NewFloatArrayLen(a.Len() + b.Len())
|
|
i, j, k := 0, 0, 0
|
|
for i < len(a.Timestamps) && j < len(b.Timestamps) {
|
|
if a.Timestamps[i] < b.Timestamps[j] {
|
|
out.Timestamps[k] = a.Timestamps[i]
|
|
out.Values[k] = a.Values[i]
|
|
i++
|
|
} else if a.Timestamps[i] == b.Timestamps[j] {
|
|
out.Timestamps[k] = b.Timestamps[j]
|
|
out.Values[k] = b.Values[j]
|
|
i++
|
|
j++
|
|
} else {
|
|
out.Timestamps[k] = b.Timestamps[j]
|
|
out.Values[k] = b.Values[j]
|
|
j++
|
|
}
|
|
k++
|
|
}
|
|
|
|
if i < len(a.Timestamps) {
|
|
n := copy(out.Timestamps[k:], a.Timestamps[i:])
|
|
copy(out.Values[k:], a.Values[i:])
|
|
k += n
|
|
} else if j < len(b.Timestamps) {
|
|
n := copy(out.Timestamps[k:], b.Timestamps[j:])
|
|
copy(out.Values[k:], b.Values[j:])
|
|
k += n
|
|
}
|
|
|
|
a.Timestamps = out.Timestamps[:k]
|
|
a.Values = out.Values[:k]
|
|
}
|
|
|
|
type IntegerArray struct {
|
|
Timestamps []int64
|
|
Values []int64
|
|
}
|
|
|
|
func NewIntegerArrayLen(sz int) *IntegerArray {
|
|
return &IntegerArray{
|
|
Timestamps: make([]int64, sz),
|
|
Values: make([]int64, sz),
|
|
}
|
|
}
|
|
|
|
func (a *IntegerArray) MinTime() int64 {
|
|
return a.Timestamps[0]
|
|
}
|
|
|
|
func (a *IntegerArray) MaxTime() int64 {
|
|
return a.Timestamps[len(a.Timestamps)-1]
|
|
}
|
|
|
|
func (a *IntegerArray) Len() int {
|
|
return len(a.Timestamps)
|
|
}
|
|
|
|
// search performs a binary search for UnixNano() v in a
|
|
// and returns the position, i, where v would be inserted.
|
|
// An additional check of a.Timestamps[i] == v is necessary
|
|
// to determine if the value v exists.
|
|
func (a *IntegerArray) search(v int64) int {
|
|
// Define: f(x) → a.Timestamps[x] < v
|
|
// Define: f(-1) == true, f(n) == false
|
|
// Invariant: f(lo-1) == true, f(hi) == false
|
|
lo := 0
|
|
hi := a.Len()
|
|
for lo < hi {
|
|
mid := int(uint(lo+hi) >> 1)
|
|
if a.Timestamps[mid] < v {
|
|
lo = mid + 1 // preserves f(lo-1) == true
|
|
} else {
|
|
hi = mid // preserves f(hi) == false
|
|
}
|
|
}
|
|
|
|
// lo == hi
|
|
return lo
|
|
}
|
|
|
|
// FindRange returns the positions where min and max would be
|
|
// inserted into the array. If a[0].UnixNano() > max or
|
|
// a[len-1].UnixNano() < min then FindRange returns (-1, -1)
|
|
// indicating the array is outside the [min, max]. The values must
|
|
// be deduplicated and sorted before calling FindRange or the results
|
|
// are undefined.
|
|
func (a *IntegerArray) FindRange(min, max int64) (int, int) {
|
|
if a.Len() == 0 || min > max {
|
|
return -1, -1
|
|
}
|
|
|
|
minVal := a.MinTime()
|
|
maxVal := a.MaxTime()
|
|
|
|
if maxVal < min || minVal > max {
|
|
return -1, -1
|
|
}
|
|
|
|
return a.search(min), a.search(max)
|
|
}
|
|
|
|
// Exclude removes the subset of values in [min, max]. The values must
|
|
// be deduplicated and sorted before calling Exclude or the results are undefined.
|
|
func (a *IntegerArray) Exclude(min, max int64) {
|
|
rmin, rmax := a.FindRange(min, max)
|
|
if rmin == -1 && rmax == -1 {
|
|
return
|
|
}
|
|
|
|
// a.Timestamps[rmin] ≥ min
|
|
// a.Timestamps[rmax] ≥ max
|
|
|
|
if rmax < a.Len() {
|
|
if a.Timestamps[rmax] == max {
|
|
rmax++
|
|
}
|
|
rest := a.Len() - rmax
|
|
if rest > 0 {
|
|
ts := a.Timestamps[:rmin+rest]
|
|
copy(ts[rmin:], a.Timestamps[rmax:])
|
|
a.Timestamps = ts
|
|
|
|
vs := a.Values[:rmin+rest]
|
|
copy(vs[rmin:], a.Values[rmax:])
|
|
a.Values = vs
|
|
return
|
|
}
|
|
}
|
|
|
|
a.Timestamps = a.Timestamps[:rmin]
|
|
a.Values = a.Values[:rmin]
|
|
}
|
|
|
|
// Include returns the subset values between min and max inclusive. The values must
|
|
// be deduplicated and sorted before calling Include or the results are undefined.
|
|
func (a *IntegerArray) Include(min, max int64) {
|
|
rmin, rmax := a.FindRange(min, max)
|
|
if rmin == -1 && rmax == -1 {
|
|
a.Timestamps = a.Timestamps[:0]
|
|
a.Values = a.Values[:0]
|
|
return
|
|
}
|
|
|
|
// a.Timestamps[rmin] ≥ min
|
|
// a.Timestamps[rmax] ≥ max
|
|
|
|
if rmax < a.Len() && a.Timestamps[rmax] == max {
|
|
rmax++
|
|
}
|
|
|
|
if rmin > -1 {
|
|
ts := a.Timestamps[:rmax-rmin]
|
|
copy(ts, a.Timestamps[rmin:rmax])
|
|
a.Timestamps = ts
|
|
vs := a.Values[:rmax-rmin]
|
|
copy(vs, a.Values[rmin:rmax])
|
|
a.Values = vs
|
|
} else {
|
|
a.Timestamps = a.Timestamps[:rmax]
|
|
a.Values = a.Values[:rmax]
|
|
}
|
|
}
|
|
|
|
// Merge overlays b to top of a. If two values conflict with
|
|
// the same timestamp, b is used. Both a and b must be sorted
|
|
// in ascending order.
|
|
func (a *IntegerArray) Merge(b *IntegerArray) {
|
|
if a.Len() == 0 {
|
|
*a = *b
|
|
return
|
|
}
|
|
|
|
if b.Len() == 0 {
|
|
return
|
|
}
|
|
|
|
// Normally, both a and b should not contain duplicates. Due to a bug in older versions, it's
|
|
// possible stored blocks might contain duplicate values. Remove them if they exists before
|
|
// merging.
|
|
// a = a.Deduplicate()
|
|
// b = b.Deduplicate()
|
|
|
|
if a.MaxTime() < b.MinTime() {
|
|
a.Timestamps = append(a.Timestamps, b.Timestamps...)
|
|
a.Values = append(a.Values, b.Values...)
|
|
return
|
|
}
|
|
|
|
if b.MaxTime() < a.MinTime() {
|
|
var tmp IntegerArray
|
|
tmp.Timestamps = append(b.Timestamps, a.Timestamps...)
|
|
tmp.Values = append(b.Values, a.Values...)
|
|
*a = tmp
|
|
return
|
|
}
|
|
|
|
out := NewIntegerArrayLen(a.Len() + b.Len())
|
|
i, j, k := 0, 0, 0
|
|
for i < len(a.Timestamps) && j < len(b.Timestamps) {
|
|
if a.Timestamps[i] < b.Timestamps[j] {
|
|
out.Timestamps[k] = a.Timestamps[i]
|
|
out.Values[k] = a.Values[i]
|
|
i++
|
|
} else if a.Timestamps[i] == b.Timestamps[j] {
|
|
out.Timestamps[k] = b.Timestamps[j]
|
|
out.Values[k] = b.Values[j]
|
|
i++
|
|
j++
|
|
} else {
|
|
out.Timestamps[k] = b.Timestamps[j]
|
|
out.Values[k] = b.Values[j]
|
|
j++
|
|
}
|
|
k++
|
|
}
|
|
|
|
if i < len(a.Timestamps) {
|
|
n := copy(out.Timestamps[k:], a.Timestamps[i:])
|
|
copy(out.Values[k:], a.Values[i:])
|
|
k += n
|
|
} else if j < len(b.Timestamps) {
|
|
n := copy(out.Timestamps[k:], b.Timestamps[j:])
|
|
copy(out.Values[k:], b.Values[j:])
|
|
k += n
|
|
}
|
|
|
|
a.Timestamps = out.Timestamps[:k]
|
|
a.Values = out.Values[:k]
|
|
}
|
|
|
|
type UnsignedArray struct {
|
|
Timestamps []int64
|
|
Values []uint64
|
|
}
|
|
|
|
func NewUnsignedArrayLen(sz int) *UnsignedArray {
|
|
return &UnsignedArray{
|
|
Timestamps: make([]int64, sz),
|
|
Values: make([]uint64, sz),
|
|
}
|
|
}
|
|
|
|
func (a *UnsignedArray) MinTime() int64 {
|
|
return a.Timestamps[0]
|
|
}
|
|
|
|
func (a *UnsignedArray) MaxTime() int64 {
|
|
return a.Timestamps[len(a.Timestamps)-1]
|
|
}
|
|
|
|
func (a *UnsignedArray) Len() int {
|
|
return len(a.Timestamps)
|
|
}
|
|
|
|
// search performs a binary search for UnixNano() v in a
|
|
// and returns the position, i, where v would be inserted.
|
|
// An additional check of a.Timestamps[i] == v is necessary
|
|
// to determine if the value v exists.
|
|
func (a *UnsignedArray) search(v int64) int {
|
|
// Define: f(x) → a.Timestamps[x] < v
|
|
// Define: f(-1) == true, f(n) == false
|
|
// Invariant: f(lo-1) == true, f(hi) == false
|
|
lo := 0
|
|
hi := a.Len()
|
|
for lo < hi {
|
|
mid := int(uint(lo+hi) >> 1)
|
|
if a.Timestamps[mid] < v {
|
|
lo = mid + 1 // preserves f(lo-1) == true
|
|
} else {
|
|
hi = mid // preserves f(hi) == false
|
|
}
|
|
}
|
|
|
|
// lo == hi
|
|
return lo
|
|
}
|
|
|
|
// FindRange returns the positions where min and max would be
|
|
// inserted into the array. If a[0].UnixNano() > max or
|
|
// a[len-1].UnixNano() < min then FindRange returns (-1, -1)
|
|
// indicating the array is outside the [min, max]. The values must
|
|
// be deduplicated and sorted before calling FindRange or the results
|
|
// are undefined.
|
|
func (a *UnsignedArray) FindRange(min, max int64) (int, int) {
|
|
if a.Len() == 0 || min > max {
|
|
return -1, -1
|
|
}
|
|
|
|
minVal := a.MinTime()
|
|
maxVal := a.MaxTime()
|
|
|
|
if maxVal < min || minVal > max {
|
|
return -1, -1
|
|
}
|
|
|
|
return a.search(min), a.search(max)
|
|
}
|
|
|
|
// Exclude removes the subset of values in [min, max]. The values must
|
|
// be deduplicated and sorted before calling Exclude or the results are undefined.
|
|
func (a *UnsignedArray) Exclude(min, max int64) {
|
|
rmin, rmax := a.FindRange(min, max)
|
|
if rmin == -1 && rmax == -1 {
|
|
return
|
|
}
|
|
|
|
// a.Timestamps[rmin] ≥ min
|
|
// a.Timestamps[rmax] ≥ max
|
|
|
|
if rmax < a.Len() {
|
|
if a.Timestamps[rmax] == max {
|
|
rmax++
|
|
}
|
|
rest := a.Len() - rmax
|
|
if rest > 0 {
|
|
ts := a.Timestamps[:rmin+rest]
|
|
copy(ts[rmin:], a.Timestamps[rmax:])
|
|
a.Timestamps = ts
|
|
|
|
vs := a.Values[:rmin+rest]
|
|
copy(vs[rmin:], a.Values[rmax:])
|
|
a.Values = vs
|
|
return
|
|
}
|
|
}
|
|
|
|
a.Timestamps = a.Timestamps[:rmin]
|
|
a.Values = a.Values[:rmin]
|
|
}
|
|
|
|
// Include returns the subset values between min and max inclusive. The values must
|
|
// be deduplicated and sorted before calling Include or the results are undefined.
|
|
func (a *UnsignedArray) Include(min, max int64) {
|
|
rmin, rmax := a.FindRange(min, max)
|
|
if rmin == -1 && rmax == -1 {
|
|
a.Timestamps = a.Timestamps[:0]
|
|
a.Values = a.Values[:0]
|
|
return
|
|
}
|
|
|
|
// a.Timestamps[rmin] ≥ min
|
|
// a.Timestamps[rmax] ≥ max
|
|
|
|
if rmax < a.Len() && a.Timestamps[rmax] == max {
|
|
rmax++
|
|
}
|
|
|
|
if rmin > -1 {
|
|
ts := a.Timestamps[:rmax-rmin]
|
|
copy(ts, a.Timestamps[rmin:rmax])
|
|
a.Timestamps = ts
|
|
vs := a.Values[:rmax-rmin]
|
|
copy(vs, a.Values[rmin:rmax])
|
|
a.Values = vs
|
|
} else {
|
|
a.Timestamps = a.Timestamps[:rmax]
|
|
a.Values = a.Values[:rmax]
|
|
}
|
|
}
|
|
|
|
// Merge overlays b to top of a. If two values conflict with
|
|
// the same timestamp, b is used. Both a and b must be sorted
|
|
// in ascending order.
|
|
func (a *UnsignedArray) Merge(b *UnsignedArray) {
|
|
if a.Len() == 0 {
|
|
*a = *b
|
|
return
|
|
}
|
|
|
|
if b.Len() == 0 {
|
|
return
|
|
}
|
|
|
|
// Normally, both a and b should not contain duplicates. Due to a bug in older versions, it's
|
|
// possible stored blocks might contain duplicate values. Remove them if they exists before
|
|
// merging.
|
|
// a = a.Deduplicate()
|
|
// b = b.Deduplicate()
|
|
|
|
if a.MaxTime() < b.MinTime() {
|
|
a.Timestamps = append(a.Timestamps, b.Timestamps...)
|
|
a.Values = append(a.Values, b.Values...)
|
|
return
|
|
}
|
|
|
|
if b.MaxTime() < a.MinTime() {
|
|
var tmp UnsignedArray
|
|
tmp.Timestamps = append(b.Timestamps, a.Timestamps...)
|
|
tmp.Values = append(b.Values, a.Values...)
|
|
*a = tmp
|
|
return
|
|
}
|
|
|
|
out := NewUnsignedArrayLen(a.Len() + b.Len())
|
|
i, j, k := 0, 0, 0
|
|
for i < len(a.Timestamps) && j < len(b.Timestamps) {
|
|
if a.Timestamps[i] < b.Timestamps[j] {
|
|
out.Timestamps[k] = a.Timestamps[i]
|
|
out.Values[k] = a.Values[i]
|
|
i++
|
|
} else if a.Timestamps[i] == b.Timestamps[j] {
|
|
out.Timestamps[k] = b.Timestamps[j]
|
|
out.Values[k] = b.Values[j]
|
|
i++
|
|
j++
|
|
} else {
|
|
out.Timestamps[k] = b.Timestamps[j]
|
|
out.Values[k] = b.Values[j]
|
|
j++
|
|
}
|
|
k++
|
|
}
|
|
|
|
if i < len(a.Timestamps) {
|
|
n := copy(out.Timestamps[k:], a.Timestamps[i:])
|
|
copy(out.Values[k:], a.Values[i:])
|
|
k += n
|
|
} else if j < len(b.Timestamps) {
|
|
n := copy(out.Timestamps[k:], b.Timestamps[j:])
|
|
copy(out.Values[k:], b.Values[j:])
|
|
k += n
|
|
}
|
|
|
|
a.Timestamps = out.Timestamps[:k]
|
|
a.Values = out.Values[:k]
|
|
}
|
|
|
|
type StringArray struct {
|
|
Timestamps []int64
|
|
Values []string
|
|
}
|
|
|
|
func NewStringArrayLen(sz int) *StringArray {
|
|
return &StringArray{
|
|
Timestamps: make([]int64, sz),
|
|
Values: make([]string, sz),
|
|
}
|
|
}
|
|
|
|
func (a *StringArray) MinTime() int64 {
|
|
return a.Timestamps[0]
|
|
}
|
|
|
|
func (a *StringArray) MaxTime() int64 {
|
|
return a.Timestamps[len(a.Timestamps)-1]
|
|
}
|
|
|
|
func (a *StringArray) Len() int {
|
|
return len(a.Timestamps)
|
|
}
|
|
|
|
// search performs a binary search for UnixNano() v in a
|
|
// and returns the position, i, where v would be inserted.
|
|
// An additional check of a.Timestamps[i] == v is necessary
|
|
// to determine if the value v exists.
|
|
func (a *StringArray) search(v int64) int {
|
|
// Define: f(x) → a.Timestamps[x] < v
|
|
// Define: f(-1) == true, f(n) == false
|
|
// Invariant: f(lo-1) == true, f(hi) == false
|
|
lo := 0
|
|
hi := a.Len()
|
|
for lo < hi {
|
|
mid := int(uint(lo+hi) >> 1)
|
|
if a.Timestamps[mid] < v {
|
|
lo = mid + 1 // preserves f(lo-1) == true
|
|
} else {
|
|
hi = mid // preserves f(hi) == false
|
|
}
|
|
}
|
|
|
|
// lo == hi
|
|
return lo
|
|
}
|
|
|
|
// FindRange returns the positions where min and max would be
|
|
// inserted into the array. If a[0].UnixNano() > max or
|
|
// a[len-1].UnixNano() < min then FindRange returns (-1, -1)
|
|
// indicating the array is outside the [min, max]. The values must
|
|
// be deduplicated and sorted before calling FindRange or the results
|
|
// are undefined.
|
|
func (a *StringArray) FindRange(min, max int64) (int, int) {
|
|
if a.Len() == 0 || min > max {
|
|
return -1, -1
|
|
}
|
|
|
|
minVal := a.MinTime()
|
|
maxVal := a.MaxTime()
|
|
|
|
if maxVal < min || minVal > max {
|
|
return -1, -1
|
|
}
|
|
|
|
return a.search(min), a.search(max)
|
|
}
|
|
|
|
// Exclude removes the subset of values in [min, max]. The values must
|
|
// be deduplicated and sorted before calling Exclude or the results are undefined.
|
|
func (a *StringArray) Exclude(min, max int64) {
|
|
rmin, rmax := a.FindRange(min, max)
|
|
if rmin == -1 && rmax == -1 {
|
|
return
|
|
}
|
|
|
|
// a.Timestamps[rmin] ≥ min
|
|
// a.Timestamps[rmax] ≥ max
|
|
|
|
if rmax < a.Len() {
|
|
if a.Timestamps[rmax] == max {
|
|
rmax++
|
|
}
|
|
rest := a.Len() - rmax
|
|
if rest > 0 {
|
|
ts := a.Timestamps[:rmin+rest]
|
|
copy(ts[rmin:], a.Timestamps[rmax:])
|
|
a.Timestamps = ts
|
|
|
|
vs := a.Values[:rmin+rest]
|
|
copy(vs[rmin:], a.Values[rmax:])
|
|
a.Values = vs
|
|
return
|
|
}
|
|
}
|
|
|
|
a.Timestamps = a.Timestamps[:rmin]
|
|
a.Values = a.Values[:rmin]
|
|
}
|
|
|
|
// Include returns the subset values between min and max inclusive. The values must
|
|
// be deduplicated and sorted before calling Include or the results are undefined.
|
|
func (a *StringArray) Include(min, max int64) {
|
|
rmin, rmax := a.FindRange(min, max)
|
|
if rmin == -1 && rmax == -1 {
|
|
a.Timestamps = a.Timestamps[:0]
|
|
a.Values = a.Values[:0]
|
|
return
|
|
}
|
|
|
|
// a.Timestamps[rmin] ≥ min
|
|
// a.Timestamps[rmax] ≥ max
|
|
|
|
if rmax < a.Len() && a.Timestamps[rmax] == max {
|
|
rmax++
|
|
}
|
|
|
|
if rmin > -1 {
|
|
ts := a.Timestamps[:rmax-rmin]
|
|
copy(ts, a.Timestamps[rmin:rmax])
|
|
a.Timestamps = ts
|
|
vs := a.Values[:rmax-rmin]
|
|
copy(vs, a.Values[rmin:rmax])
|
|
a.Values = vs
|
|
} else {
|
|
a.Timestamps = a.Timestamps[:rmax]
|
|
a.Values = a.Values[:rmax]
|
|
}
|
|
}
|
|
|
|
// Merge overlays b to top of a. If two values conflict with
|
|
// the same timestamp, b is used. Both a and b must be sorted
|
|
// in ascending order.
|
|
func (a *StringArray) Merge(b *StringArray) {
|
|
if a.Len() == 0 {
|
|
*a = *b
|
|
return
|
|
}
|
|
|
|
if b.Len() == 0 {
|
|
return
|
|
}
|
|
|
|
// Normally, both a and b should not contain duplicates. Due to a bug in older versions, it's
|
|
// possible stored blocks might contain duplicate values. Remove them if they exists before
|
|
// merging.
|
|
// a = a.Deduplicate()
|
|
// b = b.Deduplicate()
|
|
|
|
if a.MaxTime() < b.MinTime() {
|
|
a.Timestamps = append(a.Timestamps, b.Timestamps...)
|
|
a.Values = append(a.Values, b.Values...)
|
|
return
|
|
}
|
|
|
|
if b.MaxTime() < a.MinTime() {
|
|
var tmp StringArray
|
|
tmp.Timestamps = append(b.Timestamps, a.Timestamps...)
|
|
tmp.Values = append(b.Values, a.Values...)
|
|
*a = tmp
|
|
return
|
|
}
|
|
|
|
out := NewStringArrayLen(a.Len() + b.Len())
|
|
i, j, k := 0, 0, 0
|
|
for i < len(a.Timestamps) && j < len(b.Timestamps) {
|
|
if a.Timestamps[i] < b.Timestamps[j] {
|
|
out.Timestamps[k] = a.Timestamps[i]
|
|
out.Values[k] = a.Values[i]
|
|
i++
|
|
} else if a.Timestamps[i] == b.Timestamps[j] {
|
|
out.Timestamps[k] = b.Timestamps[j]
|
|
out.Values[k] = b.Values[j]
|
|
i++
|
|
j++
|
|
} else {
|
|
out.Timestamps[k] = b.Timestamps[j]
|
|
out.Values[k] = b.Values[j]
|
|
j++
|
|
}
|
|
k++
|
|
}
|
|
|
|
if i < len(a.Timestamps) {
|
|
n := copy(out.Timestamps[k:], a.Timestamps[i:])
|
|
copy(out.Values[k:], a.Values[i:])
|
|
k += n
|
|
} else if j < len(b.Timestamps) {
|
|
n := copy(out.Timestamps[k:], b.Timestamps[j:])
|
|
copy(out.Values[k:], b.Values[j:])
|
|
k += n
|
|
}
|
|
|
|
a.Timestamps = out.Timestamps[:k]
|
|
a.Values = out.Values[:k]
|
|
}
|
|
|
|
type BooleanArray struct {
|
|
Timestamps []int64
|
|
Values []bool
|
|
}
|
|
|
|
func NewBooleanArrayLen(sz int) *BooleanArray {
|
|
return &BooleanArray{
|
|
Timestamps: make([]int64, sz),
|
|
Values: make([]bool, sz),
|
|
}
|
|
}
|
|
|
|
func (a *BooleanArray) MinTime() int64 {
|
|
return a.Timestamps[0]
|
|
}
|
|
|
|
func (a *BooleanArray) MaxTime() int64 {
|
|
return a.Timestamps[len(a.Timestamps)-1]
|
|
}
|
|
|
|
func (a *BooleanArray) Len() int {
|
|
return len(a.Timestamps)
|
|
}
|
|
|
|
// search performs a binary search for UnixNano() v in a
|
|
// and returns the position, i, where v would be inserted.
|
|
// An additional check of a.Timestamps[i] == v is necessary
|
|
// to determine if the value v exists.
|
|
func (a *BooleanArray) search(v int64) int {
|
|
// Define: f(x) → a.Timestamps[x] < v
|
|
// Define: f(-1) == true, f(n) == false
|
|
// Invariant: f(lo-1) == true, f(hi) == false
|
|
lo := 0
|
|
hi := a.Len()
|
|
for lo < hi {
|
|
mid := int(uint(lo+hi) >> 1)
|
|
if a.Timestamps[mid] < v {
|
|
lo = mid + 1 // preserves f(lo-1) == true
|
|
} else {
|
|
hi = mid // preserves f(hi) == false
|
|
}
|
|
}
|
|
|
|
// lo == hi
|
|
return lo
|
|
}
|
|
|
|
// FindRange returns the positions where min and max would be
|
|
// inserted into the array. If a[0].UnixNano() > max or
|
|
// a[len-1].UnixNano() < min then FindRange returns (-1, -1)
|
|
// indicating the array is outside the [min, max]. The values must
|
|
// be deduplicated and sorted before calling FindRange or the results
|
|
// are undefined.
|
|
func (a *BooleanArray) FindRange(min, max int64) (int, int) {
|
|
if a.Len() == 0 || min > max {
|
|
return -1, -1
|
|
}
|
|
|
|
minVal := a.MinTime()
|
|
maxVal := a.MaxTime()
|
|
|
|
if maxVal < min || minVal > max {
|
|
return -1, -1
|
|
}
|
|
|
|
return a.search(min), a.search(max)
|
|
}
|
|
|
|
// Exclude removes the subset of values in [min, max]. The values must
|
|
// be deduplicated and sorted before calling Exclude or the results are undefined.
|
|
func (a *BooleanArray) Exclude(min, max int64) {
|
|
rmin, rmax := a.FindRange(min, max)
|
|
if rmin == -1 && rmax == -1 {
|
|
return
|
|
}
|
|
|
|
// a.Timestamps[rmin] ≥ min
|
|
// a.Timestamps[rmax] ≥ max
|
|
|
|
if rmax < a.Len() {
|
|
if a.Timestamps[rmax] == max {
|
|
rmax++
|
|
}
|
|
rest := a.Len() - rmax
|
|
if rest > 0 {
|
|
ts := a.Timestamps[:rmin+rest]
|
|
copy(ts[rmin:], a.Timestamps[rmax:])
|
|
a.Timestamps = ts
|
|
|
|
vs := a.Values[:rmin+rest]
|
|
copy(vs[rmin:], a.Values[rmax:])
|
|
a.Values = vs
|
|
return
|
|
}
|
|
}
|
|
|
|
a.Timestamps = a.Timestamps[:rmin]
|
|
a.Values = a.Values[:rmin]
|
|
}
|
|
|
|
// Include returns the subset values between min and max inclusive. The values must
|
|
// be deduplicated and sorted before calling Include or the results are undefined.
|
|
func (a *BooleanArray) Include(min, max int64) {
|
|
rmin, rmax := a.FindRange(min, max)
|
|
if rmin == -1 && rmax == -1 {
|
|
a.Timestamps = a.Timestamps[:0]
|
|
a.Values = a.Values[:0]
|
|
return
|
|
}
|
|
|
|
// a.Timestamps[rmin] ≥ min
|
|
// a.Timestamps[rmax] ≥ max
|
|
|
|
if rmax < a.Len() && a.Timestamps[rmax] == max {
|
|
rmax++
|
|
}
|
|
|
|
if rmin > -1 {
|
|
ts := a.Timestamps[:rmax-rmin]
|
|
copy(ts, a.Timestamps[rmin:rmax])
|
|
a.Timestamps = ts
|
|
vs := a.Values[:rmax-rmin]
|
|
copy(vs, a.Values[rmin:rmax])
|
|
a.Values = vs
|
|
} else {
|
|
a.Timestamps = a.Timestamps[:rmax]
|
|
a.Values = a.Values[:rmax]
|
|
}
|
|
}
|
|
|
|
// Merge overlays b to top of a. If two values conflict with
|
|
// the same timestamp, b is used. Both a and b must be sorted
|
|
// in ascending order.
|
|
func (a *BooleanArray) Merge(b *BooleanArray) {
|
|
if a.Len() == 0 {
|
|
*a = *b
|
|
return
|
|
}
|
|
|
|
if b.Len() == 0 {
|
|
return
|
|
}
|
|
|
|
// Normally, both a and b should not contain duplicates. Due to a bug in older versions, it's
|
|
// possible stored blocks might contain duplicate values. Remove them if they exists before
|
|
// merging.
|
|
// a = a.Deduplicate()
|
|
// b = b.Deduplicate()
|
|
|
|
if a.MaxTime() < b.MinTime() {
|
|
a.Timestamps = append(a.Timestamps, b.Timestamps...)
|
|
a.Values = append(a.Values, b.Values...)
|
|
return
|
|
}
|
|
|
|
if b.MaxTime() < a.MinTime() {
|
|
var tmp BooleanArray
|
|
tmp.Timestamps = append(b.Timestamps, a.Timestamps...)
|
|
tmp.Values = append(b.Values, a.Values...)
|
|
*a = tmp
|
|
return
|
|
}
|
|
|
|
out := NewBooleanArrayLen(a.Len() + b.Len())
|
|
i, j, k := 0, 0, 0
|
|
for i < len(a.Timestamps) && j < len(b.Timestamps) {
|
|
if a.Timestamps[i] < b.Timestamps[j] {
|
|
out.Timestamps[k] = a.Timestamps[i]
|
|
out.Values[k] = a.Values[i]
|
|
i++
|
|
} else if a.Timestamps[i] == b.Timestamps[j] {
|
|
out.Timestamps[k] = b.Timestamps[j]
|
|
out.Values[k] = b.Values[j]
|
|
i++
|
|
j++
|
|
} else {
|
|
out.Timestamps[k] = b.Timestamps[j]
|
|
out.Values[k] = b.Values[j]
|
|
j++
|
|
}
|
|
k++
|
|
}
|
|
|
|
if i < len(a.Timestamps) {
|
|
n := copy(out.Timestamps[k:], a.Timestamps[i:])
|
|
copy(out.Values[k:], a.Values[i:])
|
|
k += n
|
|
} else if j < len(b.Timestamps) {
|
|
n := copy(out.Timestamps[k:], b.Timestamps[j:])
|
|
copy(out.Values[k:], b.Values[j:])
|
|
k += n
|
|
}
|
|
|
|
a.Timestamps = out.Timestamps[:k]
|
|
a.Values = out.Values[:k]
|
|
}
|
|
|
|
type TimestampArray struct {
|
|
Timestamps []int64
|
|
}
|
|
|
|
func NewTimestampArrayLen(sz int) *TimestampArray {
|
|
return &TimestampArray{
|
|
Timestamps: make([]int64, sz),
|
|
}
|
|
}
|
|
|
|
func (a *TimestampArray) MinTime() int64 {
|
|
return a.Timestamps[0]
|
|
}
|
|
|
|
func (a *TimestampArray) MaxTime() int64 {
|
|
return a.Timestamps[len(a.Timestamps)-1]
|
|
}
|
|
|
|
func (a *TimestampArray) Len() int {
|
|
return len(a.Timestamps)
|
|
}
|
|
|
|
// search performs a binary search for UnixNano() v in a
|
|
// and returns the position, i, where v would be inserted.
|
|
// An additional check of a.Timestamps[i] == v is necessary
|
|
// to determine if the value v exists.
|
|
func (a *TimestampArray) search(v int64) int {
|
|
// Define: f(x) → a.Timestamps[x] < v
|
|
// Define: f(-1) == true, f(n) == false
|
|
// Invariant: f(lo-1) == true, f(hi) == false
|
|
lo := 0
|
|
hi := a.Len()
|
|
for lo < hi {
|
|
mid := int(uint(lo+hi) >> 1)
|
|
if a.Timestamps[mid] < v {
|
|
lo = mid + 1 // preserves f(lo-1) == true
|
|
} else {
|
|
hi = mid // preserves f(hi) == false
|
|
}
|
|
}
|
|
|
|
// lo == hi
|
|
return lo
|
|
}
|
|
|
|
// FindRange returns the positions where min and max would be
|
|
// inserted into the array. If a[0].UnixNano() > max or
|
|
// a[len-1].UnixNano() < min then FindRange returns (-1, -1)
|
|
// indicating the array is outside the [min, max]. The values must
|
|
// be deduplicated and sorted before calling FindRange or the results
|
|
// are undefined.
|
|
func (a *TimestampArray) FindRange(min, max int64) (int, int) {
|
|
if a.Len() == 0 || min > max {
|
|
return -1, -1
|
|
}
|
|
|
|
minVal := a.MinTime()
|
|
maxVal := a.MaxTime()
|
|
|
|
if maxVal < min || minVal > max {
|
|
return -1, -1
|
|
}
|
|
|
|
return a.search(min), a.search(max)
|
|
}
|
|
|
|
// Exclude removes the subset of timestamps in [min, max]. The timestamps must
|
|
// be deduplicated and sorted before calling Exclude or the results are undefined.
|
|
func (a *TimestampArray) Exclude(min, max int64) {
|
|
rmin, rmax := a.FindRange(min, max)
|
|
if rmin == -1 && rmax == -1 {
|
|
return
|
|
}
|
|
|
|
// a.Timestamps[rmin] ≥ min
|
|
// a.Timestamps[rmax] ≥ max
|
|
|
|
if rmax < a.Len() {
|
|
if a.Timestamps[rmax] == max {
|
|
rmax++
|
|
}
|
|
rest := a.Len() - rmax
|
|
if rest > 0 {
|
|
ts := a.Timestamps[:rmin+rest]
|
|
copy(ts[rmin:], a.Timestamps[rmax:])
|
|
a.Timestamps = ts
|
|
return
|
|
}
|
|
}
|
|
|
|
a.Timestamps = a.Timestamps[:rmin]
|
|
}
|
|
|
|
// Contains returns true if values exist between min and max inclusive. The
|
|
// values must be sorted before calling Contains or the results are undefined.
|
|
func (a *TimestampArray) Contains(min, max int64) bool {
|
|
rmin, rmax := a.FindRange(min, max)
|
|
if rmin == -1 && rmax == -1 {
|
|
return false
|
|
}
|
|
|
|
// a.Timestamps[rmin] ≥ min
|
|
// a.Timestamps[rmax] ≥ max
|
|
|
|
if a.Timestamps[rmin] == min {
|
|
return true
|
|
}
|
|
|
|
if rmax < a.Len() && a.Timestamps[rmax] == max {
|
|
return true
|
|
}
|
|
|
|
return rmax-rmin > 0
|
|
}
|