// 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 }