The OpenD Programming Language

mir_series

Plain index series data structure.

*.index[i]/*.key[i]/*.time corresponds to *.data[i]/*.value.

Index is assumed to be sorted. sort can be used to normalise a series.

@fmamath
@serdeFields
struct mir_series (
IndexIterator_
Iterator_
size_t N_ = 1
SliceKind kind_ = Contiguous
) {}

Constructors

this
this(Slice!IndexIterator index, Slice!(Iterator, N, kind) data)
this
this(typeof(null) )

Construct from null

Members

Aliases

Data
alias Data = typeof(typeof(this).init.data.front)

Data / Value type aliases

Index
alias Index = typeof(typeof(this).init.index.front)

Index / Key / Time type aliases

IndexIterator
alias IndexIterator = IndexIterator_
Iterator
alias Iterator = Iterator_

Functions

asSlice
auto asSlice()
back
auto back()

ndslice-like primitives

contains
bool contains(Index key)
empty
bool empty()
front
auto front()

ndslice-like primitives

get
ref get(Index key, Value _default)
auto get(Index key, Value _default)

Gets data for the index.

get
auto ref get(Index key)
auto ref get(Index key, Exception exc)

Gets data for the index.

getExtraVerbose
auto ref getExtraVerbose(Index key, string exceptionInto, string file, int line)

Gets data for the index (extra verbose exception).

getVerbose
auto ref getVerbose(Index key, string file, int line)

Gets data for the index (verbose exception).

index
auto index()
void index(Slice!IndexIterator index)

Index series is assumed to be sorted.

length
size_t length()

ndslice-like primitives

lightConst
Series!(LightConstOf!IndexIterator, LightConstOf!Iterator, N, kind) lightConst()
lightImmutable
Series!(LightImmutableOf!IndexIterator, LightImmutableOf!Iterator, N, kind) lightImmutable()
lightScope
Series!(LightScopeOf!IndexIterator, LightScopeOf!Iterator, N, kind) lightScope()
Series!(LightConstOf!(LightScopeOf!IndexIterator), LightConstOf!(LightScopeOf!Iterator), N, kind) lightScope()
lowerBound
auto lowerBound(Index key)

This function uses a search with policy sp to find the largest left subrange on which t < key is true for all t. The search schedule and its complexity are documented in std.range.SearchPolicy.

opAssign
ref opAssign(typeof(this) rvalue)
ref opAssign(Series!(RIndexIterator, RIterator, N, kind) rvalue)
ref opAssign(typeof(null) )
opBinary
typeof(this) opBinary(typeof(this) rhs)
auto opBinary(typeof(this) rhs)
opBinaryRight
auto opBinaryRight(Index key)
opDollar
size_t opDollar()

ndslice-like primitives

opEquals
bool opEquals(Series!(RIndexIterator, RIterator, RN, rkind) rhs)
opIndex
auto opIndex(Slices slices)

ndslice-like primitives

opIndexAssign
void opIndexAssign(Series!(IndexIterator_, Iterator_, N_, kind_) r)

Special [] = index-assign operator for index-series. Assigns data from r with index intersection. If a index index in r is not in the index index for this series, then no op-assign will take place. This and r series are assumed to be sorted.

opIndexOpAssign
void opIndexOpAssign(Series!(IndexIterator_, Iterator_, N_, kind_) rSeries)

Special [] op= index-op-assign operator for index-series. Op-assigns data from r with index intersection. If a index index in r is not in the index index for this series, then no op-assign will take place. This and r series are assumed to be sorted.

opSlice
Slice!(IotaIterator!size_t) opSlice(size_t i, size_t j)
popBack
void popBack()
popBackExactly
void popBackExactly(size_t n)
popBackN
void popBackN(size_t n)
popFront
void popFront()
popFrontExactly
void popFrontExactly(size_t n)
popFrontN
void popFrontN(size_t n)

ndslice-like primitives

save
auto save()
serdeFinalize
void serdeFinalize()
toConst
auto toConst()
toString
void toString(Writer w)
tryGet
bool tryGet(Index key, Value val)

Tries to get the first value, such that key_i == key.

tryGetFirst
bool tryGetFirst(Index lowerBound, Index upperBound, Value val)

Tries to get the first value, such that lowerBound <= key_i <= upperBound.

tryGetFirstUpdateLower
bool tryGetFirstUpdateLower(Index lowerBound, Index upperBound, Value val)

Tries to get the first value, such that lowerBound <= key_i <= upperBound. Updates lowerBound with key_i.

tryGetLast
bool tryGetLast(Index lowerBound, Index upperBound, Value val)

Tries to get the last value, such that lowerBound <= key_i <= upperBound.

tryGetLastUpdateKey
bool tryGetLastUpdateKey(Index lowerBound, Index upperBound, Value val)

Tries to get the last value, such that lowerBound <= key_i <= upperBound. Updates upperBound with key_i.

tryGetNext
bool tryGetNext(Index key, Value val)

Tries to get the first value, such that key_i >= key.

tryGetNextUpdateKey
bool tryGetNextUpdateKey(Index key, Value val)

Tries to get the first value, such that key_i >= key. Updates key with key_i.

tryGetPrev
bool tryGetPrev(Index key, Value val)

Tries to get the last value, such that key_i <= key.

tryGetPrevUpdateKey
bool tryGetPrevUpdateKey(Index key, Value val)

Tries to get the last value, such that key_i <= key. Updates key with key_i.

upperBound
auto upperBound(Index key)

This function uses a search with policy sp to find the largest right subrange on which t > key is true for all t. The search schedule and its complexity are documented in std.range.SearchPolicy.

Variables

N
enum size_t N;
_index
IndexIterator _index;
data
Slice!(Iterator, N, kind) data;

Data is any ndslice with only one constraints, data and index lengths should be equal.

kind
enum SliceKind kind;

Examples

1-dimensional data

auto index = [1, 2, 3, 4];
auto data = [2.1, 3.4, 5.6, 7.8];
auto series = index.series(data);
const cseries = series;

assert(series.contains(2));
assert( ()@trusted{ return (2 in series) is &data[1]; }() );

assert(!series.contains(5));
assert( ()@trusted{ return (5 in series) is null; }() );

assert(series.lowerBound(2) == series[0 .. 1]);
assert(series.upperBound(2) == series[2 .. $]);

assert(cseries.lowerBound(2) == cseries[0 .. 1]);
assert(cseries.upperBound(2) == cseries[2 .. $]);

// slicing type deduction for const / immutable series
static assert(is(typeof(series[]) ==
    Series!(int*, double*)));
static assert(is(typeof(cseries[]) ==
    Series!(const(int)*, const(double)*)));
static assert(is(typeof((cast(immutable) series)[]) ==
    Series!(immutable(int)*, immutable(double)*)));

/// slicing
auto seriesSlice  = series[1 .. $ - 1];
assert(seriesSlice.index == index[1 .. $ - 1]);
assert(seriesSlice.data == data[1 .. $ - 1]);
static assert(is(typeof(series) == typeof(seriesSlice)));

/// indexing
assert(series[1] == observation(2, 3.4));

/// range primitives
assert(series.length == 4);
assert(series.front == observation(1, 2.1));

series.popFront;
assert(series.front == observation(2, 3.4));

series.popBackN(10);
assert(series.empty);

2-dimensional data

import mir.date: Date;
import mir.ndslice.topology: canonical, iota;

size_t row_length = 5;

auto index = [
    Date(2017, 01, 01),
    Date(2017, 02, 01),
    Date(2017, 03, 01),
    Date(2017, 04, 01)];

//  1,  2,  3,  4,  5
//  6,  7,  8,  9, 10
// 11, 12, 13, 14, 15
// 16, 17, 18, 19, 20
auto data = iota!int([index.length, row_length], 1);

// canonical and universal ndslices are more flexible then contiguous
auto series = index.series(data.canonical);

/// slicing
auto seriesSlice  = series[1 .. $ - 1, 2 .. 4];
assert(seriesSlice.index == index[1 .. $ - 1]);
assert(seriesSlice.data == data[1 .. $ - 1, 2 .. 4]);

static if (kindOf!(typeof(series.data)) != Contiguous)
    static assert(is(typeof(series) == typeof(seriesSlice)));

/// indexing
assert(series[1, 4] == observation(Date(2017, 02, 01), 10));
assert(series[2] == observation(Date(2017, 03, 01), iota!int([row_length], 11)));

/// range primitives
assert(series.length == 4);
assert(series.length!1 == 5);

series.popFront!1;
assert(series.length!1 == 4);

Construct from null

import mir.series;
alias Map = Series!(string*, double*);
Map a = null;
auto b = Map(null);
assert(a.empty);
assert(b.empty);

auto fun(Map a = null)
{

}
import mir.series: series, sort;
auto s = ["b", "a"].series([9, 8]).sort;

import mir.format : text;
assert(s.text == `{ index: [a, b], data: [8, 9] }`);

Meta