This commit is contained in:
Michael Schimmel
2025-10-31 18:12:53 +01:00
parent 0526ec8a24
commit 8abec8e98f
8 changed files with 199 additions and 106 deletions
+61 -42
View File
@@ -4,6 +4,8 @@ interface
uses
System.SysUtils,
System.Generics.Collections,
System.Generics.Defaults,
Myc.Data.Decimal,
Myc.Data.Series,
Myc.Data.Keyword;
@@ -92,21 +94,22 @@ type
TScalarTuple = TArray<TScalar>;
// A field definition for a scalar record.
TScalarRecordField = TKeywordMapping<TScalar.TKind>.TField;
TScalarRecordDefinition = TKeywordMapping<TScalar.TKind>;
TScalarRecordField = TPair<IKeyword, TScalar.TKind>;
IScalarRecordDefinition = IKeywordMapping<TScalar.TKind>;
TScalarRecordRegistry = TKeywordMappingRegistry<TScalar.TKind>;
// A record of scalar values, based on a definition.
TScalarRecord = record
public
constructor Create(const ADef: TScalarRecordDefinition; const AFields: TArray<TScalar.TValue>);
function GetDef: TScalarRecordDefinition; inline;
constructor Create(const ADef: IScalarRecordDefinition; const AFields: TArray<TScalar.TValue>);
function GetDef: IScalarRecordDefinition; inline;
function GetFields: TArray<TScalar.TValue>; inline;
function GetKeys(const Key: IKeyword): TScalar;
property Def: TScalarRecordDefinition read GetDef;
property Def: IScalarRecordDefinition read GetDef;
property Fields: TArray<TScalar.TValue> read GetFields;
property Keys[const Key: IKeyword]: TScalar read GetKeys; default;
strict private
FDef: TScalarRecordDefinition;
FDef: IScalarRecordDefinition;
FFields: TArray<TScalar.TValue>;
end;
@@ -142,22 +145,21 @@ type
IRecordSeries = interface
{$region 'private'}
function GetCount: Int64;
function GetDef: TScalarRecordDefinition;
function GetItems(Idx: Integer): TScalarRecord;
function GetDef: IScalarRecordDefinition;
function GetTotalCount: Int64;
function GetFields(const Key: IKeyword): ISeries;
{$endregion}
procedure Add(const Item: TScalarRecord; Lookback: Int64 = -1);
function CreateMemberSeries(const Key: IKeyword): ISeries;
property Count: Int64 read GetCount;
property Def: TScalarRecordDefinition read GetDef;
property Items[Idx: Integer]: TScalarRecord read GetItems; default;
property Def: IScalarRecordDefinition read GetDef;
property Fields[const Key: IKeyword]: ISeries read GetFields; default;
property TotalCount: Int64 read GetTotalCount;
end;
// A time series of scalar records, optimized for memory and access speed.
TScalarRecordSeries = class(TInterfacedObject, IRecordSeries)
type
TMemberSeries = class(TInterfacedObject, ISeries)
TMemberSeries = class(TObject, ISeries)
private
FRecordSeries: TScalarRecordSeries;
FKind: TScalar.TKind;
@@ -165,26 +167,29 @@ type
function GetCount: Int64;
function GetItems(Idx: Integer): TScalar;
function GetTotalCount: Int64;
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
public
constructor Create(ARecordSeries: TScalarRecordSeries; AElementIdx: Integer);
destructor Destroy; override;
end;
private
FDef: TScalarRecordDefinition;
FDef: IScalarRecordDefinition;
FArray: TChunkArray<TScalar.TValue>;
FFields: TArray<TMemberSeries>;
FTotalCount: Int64;
function GetCount: Int64; inline;
function GetDef: TScalarRecordDefinition; inline;
function GetItems(Idx: Integer): TScalarRecord; inline;
function GetFields(const Key: IKeyword): ISeries;
function GetDef: IScalarRecordDefinition; inline;
function GetTotalCount: Int64; inline;
function GetItemRef(Idx: Integer): TChunkArray<TScalar.TValue>.PT; inline;
public
constructor Create(const ADef: TScalarRecordDefinition);
constructor Create(const ADef: IScalarRecordDefinition);
destructor Destroy; override;
procedure Add(const Item: TScalarRecord; Lookback: Int64 = -1);
function CreateMemberSeries(const Key: IKeyword): ISeries;
property Count: Int64 read GetCount;
property Def: TScalarRecordDefinition read GetDef;
property Items[Idx: Integer]: TScalarRecord read GetItems; default;
property Fields[const Key: IKeyword]: ISeries read GetFields; default;
property Def: IScalarRecordDefinition read GetDef;
property TotalCount: Int64 read GetTotalCount;
end;
@@ -519,14 +524,14 @@ end;
{ TScalarRecord }
constructor TScalarRecord.Create(const ADef: TScalarRecordDefinition; const AFields: TArray<TScalar.TValue>);
constructor TScalarRecord.Create(const ADef: IScalarRecordDefinition; const AFields: TArray<TScalar.TValue>);
begin
Assert(Length(ADef.Fields) = Length(AFields), 'Field definition and value count must match.');
FDef := ADef;
FFields := AFields;
end;
function TScalarRecord.GetDef: TScalarRecordDefinition;
function TScalarRecord.GetDef: IScalarRecordDefinition;
begin
Result := FDef;
end;
@@ -549,11 +554,21 @@ end;
{ TScalarRecordSeries }
constructor TScalarRecordSeries.Create(const ADef: TScalarRecordDefinition);
constructor TScalarRecordSeries.Create(const ADef: IScalarRecordDefinition);
begin
Assert(Length(ADef.Fields) > 0);
FDef := ADef;
FTotalCount := 0;
SetLength(FFields, Length(FDef.Fields));
for var i := 0 to High(FFields) do
FFields[i] := TMemberSeries.Create(Self, i);
end;
destructor TScalarRecordSeries.Destroy;
begin
for var i := High(FFields) downto 0 do
FFields[i].Free;
inherited;
end;
procedure TScalarRecordSeries.Add(const Item: TScalarRecord; Lookback: Int64 = -1);
@@ -562,13 +577,13 @@ begin
inc(FTotalCount);
end;
function TScalarRecordSeries.CreateMemberSeries(const Key: IKeyword): ISeries;
function TScalarRecordSeries.GetFields(const Key: IKeyword): ISeries;
begin
var elem := FDef.IndexOf(Key);
if elem < 0 then
raise EArgumentException.CreateFmt('Field ":%s" not found in record definition.', [Key.Name]);
Result := TMemberSeries.Create(Self, elem);
Result := FFields[elem];
end;
function TScalarRecordSeries.GetCount: Int64;
@@ -576,7 +591,7 @@ begin
Result := FArray.Count div Length(FDef.Fields);
end;
function TScalarRecordSeries.GetDef: TScalarRecordDefinition;
function TScalarRecordSeries.GetDef: IScalarRecordDefinition;
begin
Result := FDef;
end;
@@ -587,15 +602,6 @@ begin
Result := FArray.ItemRef[(FArray.Count - len) - (Idx * len)];
end;
function TScalarRecordSeries.GetItems(Idx: Integer): TScalarRecord;
var
values: TArray<TScalar.TValue>;
begin
SetLength(values, Length(FDef.Fields));
Move(GetItemRef(Idx)^, values[0], sizeof(TScalar.TValue) * Length(values));
Result.Create(FDef, values);
end;
function TScalarRecordSeries.GetTotalCount: Int64;
begin
Result := FTotalCount;
@@ -643,21 +649,16 @@ begin
end;
end;
{ TScalarRecordSeries.TMemberSeries }
constructor TScalarRecordSeries.TMemberSeries.Create(ARecordSeries: TScalarRecordSeries; AElementIdx: Integer);
begin
inherited Create;
FRecordSeries := ARecordSeries;
FRecordSeries._AddRef;
FKind := FRecordSeries.FDef.Fields[AElementIdx].Value;
FOffset := sizeof(TScalar.TValue) * AElementIdx;
end;
destructor TScalarRecordSeries.TMemberSeries.Destroy;
begin
FRecordSeries._Release;
inherited;
end;
function TScalarRecordSeries.TMemberSeries.GetCount: Int64;
begin
Result := FRecordSeries.Count;
@@ -677,6 +678,24 @@ begin
Result := FRecordSeries.TotalCount;
end;
function TScalarRecordSeries.TMemberSeries.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
if GetInterface(IID, Obj) then
Result := S_OK
else
Result := E_NOINTERFACE;
end;
function TScalarRecordSeries.TMemberSeries._AddRef: Integer;
begin
Result := FRecordSeries._AddRef;
end;
function TScalarRecordSeries.TMemberSeries._Release: Integer;
begin
Result := FRecordSeries._Release;
end;
{ TScalarSeries }
constructor TScalarSeries.Create(AKind: TScalar.TKind);