Skip to content

Commit

Permalink
Implement SetterFlags_SkipNA; update header.
Browse files Browse the repository at this point in the history
  • Loading branch information
PMeira committed Jan 30, 2024
1 parent c2a1664 commit 03ed7f2
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 22 deletions.
37 changes: 37 additions & 0 deletions include/dss_capi.h
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,43 @@ extern "C" {
*/
};

/*!
Setter flags customize down how the update of DSS properties are handled by the
engine and parts of the API. Use especially in the `Obj` and `Batch` APIs
*/
enum SetterFlags {
SetterFlags_ImplicitSizes = 0x00000001, /*!<
Most array properties depend on sizes defined by other properties.
Using this flag, many properties allow users to skip setting the other property
directly, allowing the engine to use the size of the provided array to
initialize the other property.
*/

SetterFlags_AvoidFullRecalc = 0x00000002, /*!<
Some components like Loads don't need to update YPrim for every change, e.g. setting
"`load.a_load.kW=1`" if was "kW" previously 2 should not force a YPrim update, but it does
force an update by default.
Using this flag will reproduce what the classic OpenDSS API for Loads (DSS.ActiveCircuit.Loads)
does, but removes a lot of duplicated code. Besides that, we can extend the feature
for other components if we think it fits.
*/

SetterFlags_SkipNA = 0x00000004, /*!<
For batch operations with arrays, skip NA values
Currently, NA values are interpret as:
- NaN for float64
- INT32_MIN (0x80000000) for int32
- Null pointers for strings (in this case, use a `"\0"` string for empty strings)
*/

SetterFlags_AllowAllConductors = 0x80000000 /*!<
Used internally for the "Wires" property ("Conductors").
This was left public in case someone tries to implement some internal aspects in
external functions.
*/
};

/*!
The values from AltDSSEvent are used in the updated DSSEvents_* functions to
register callbacks for different events. Note that in the official OpenDSS
Expand Down
65 changes: 44 additions & 21 deletions src/CAPI/CAPI_Obj.pas
Original file line number Diff line number Diff line change
Expand Up @@ -1623,6 +1623,7 @@ procedure Batch_SetFloat64Array(batch: TDSSObjectPtr; batchSize: Integer; Index:
doublePtr: PDouble;
propFlags: TPropertyFlags;
singleEdit: Boolean;
allowNA: Boolean;
begin
if (batch = NIL) or (batch^ = NIL) or (batchSize = 0) then
Exit;
Expand All @@ -1638,23 +1639,30 @@ procedure Batch_SetFloat64Array(batch: TDSSObjectPtr; batchSize: Integer; Index:
]) then
Exit;

allowNA := not (TDSSPropertySetterFlag.SkipNA in setterFlags);

if (cls.PropertyType[Index] = TPropertyType.DoubleProperty) and
(propFlags = []) and
(cls.PropertyScale[Index] = 1) then
begin
// Faster path
for i := 1 to batchSize do
begin
singleEdit := not (Flg.EditingActive in batch^.Flags);
if singleEdit then
cls.BeginEdit(batch^, False);
// check for each element, in case the element is being edited somewhere else
if (allowNA) or (not IsNaN(Value^)) then
begin
singleEdit := not (Flg.EditingActive in batch^.Flags);
if singleEdit then
cls.BeginEdit(batch^, False);

doublePtr := PDouble(PtrUint(batch^) + propOffset);
prev := doubleptr^;
doublePtr^ := Value^;
batch^.PropertySideEffects(Index, Round(prev), setterFlags);
doublePtr := PDouble(PtrUint(batch^) + propOffset);
prev := doubleptr^;
doublePtr^ := Value^;
batch^.PropertySideEffects(Index, Round(prev), setterFlags);

if singleEdit then
cls.EndEdit(batch^, 1);
if singleEdit then
cls.EndEdit(batch^, 1);
end;
inc(batch);
inc(Value);
end;
Expand All @@ -1663,7 +1671,9 @@ procedure Batch_SetFloat64Array(batch: TDSSObjectPtr; batchSize: Integer; Index:

for i := 1 to batchSize do
begin
batch^.SetDouble(Index, Value^, setterFlags);
if (allowNA) or (not IsNaN(Value^)) then
batch^.SetDouble(Index, Value^, setterFlags);

inc(batch);
inc(Value)
end;
Expand All @@ -1678,6 +1688,7 @@ procedure Batch_SetInt32Array(batch: TDSSObjectPtr; batchSize: Integer; Index: I
intPtr: PInteger;
propFlags: TPropertyFlags;
singleEdit: Boolean;
allowNA: Boolean;
begin
if (batch = NIL) or (batch^ = NIL) or (batchSize = 0) then
Exit;
Expand All @@ -1695,23 +1706,30 @@ procedure Batch_SetInt32Array(batch: TDSSObjectPtr; batchSize: Integer; Index: I
]) then
Exit;

allowNA := not (TDSSPropertySetterFlag.SkipNA in setterFlags);

if (cls.PropertyType[Index] <> TPropertyType.IntegerOnStructArrayProperty) and
(propFlags = []) and
(cls.PropertyScale[Index] = 1) then
begin
// Faster path
for i := 1 to batchSize do
begin
singleEdit := not (Flg.EditingActive in batch^.Flags);
if singleEdit then
cls.BeginEdit(batch^, False);
if (allowNA) or (Value^ = $80000000) then
begin
// check for each element, in case the element is being edited somewhere else
singleEdit := not (Flg.EditingActive in batch^.Flags);
if singleEdit then
cls.BeginEdit(batch^, False);

intPtr := PInteger(PtrUint(batch^) + propOffset);
prev := intPtr^;
intPtr^ := Value^;
batch^.PropertySideEffects(Index, prev, setterFlags);
intPtr := PInteger(PtrUint(batch^) + propOffset);
prev := intPtr^;
intPtr^ := Value^;
batch^.PropertySideEffects(Index, prev, setterFlags);

if singleEdit then
cls.EndEdit(batch^, 1);
if singleEdit then
cls.EndEdit(batch^, 1);
end;
inc(batch);
inc(Value);
end;
Expand All @@ -1720,7 +1738,8 @@ procedure Batch_SetInt32Array(batch: TDSSObjectPtr; batchSize: Integer; Index: I

for i := 1 to batchSize do
begin
batch^.SetInteger(Index, Value^, setterFlags);
if (allowNA) or (Value^ = $80000000) then
batch^.SetInteger(Index, Value^, setterFlags);
inc(batch);
inc(Value)
end;
Expand All @@ -1732,6 +1751,7 @@ procedure Batch_SetStringArray(batch: TDSSObjectPtr; batchSize: Integer; Index:
// propOffset: PtrUint;
i: Integer;
// propFlags: TPropertyFlags;
allowNA: Boolean;
begin
if (batch = NIL) or (batch^ = NIL) or (batchSize = 0) then
Exit;
Expand All @@ -1750,9 +1770,12 @@ procedure Batch_SetStringArray(batch: TDSSObjectPtr; batchSize: Integer; Index:
]) then
Exit;

allowNA := not (TDSSPropertySetterFlag.SkipNA in setterFlags);

for i := 1 to batchSize do
begin
batch^.SetString(Index, Value^, setterFlags);
if (allowNA) or (Value^ <> NIL) then
batch^.SetString(Index, Value^, setterFlags);
inc(batch);
inc(Value)
end;
Expand Down
4 changes: 3 additions & 1 deletion src/Common/DSSClass.pas
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,9 @@ interface
// for other components if we think it fits.
AvoidFullRecalc = 1,

Reserved2 = 2,
// For batch operations, skip NA values -- values of NaN for float64, INT32_MIN (0x80000000) for int32, null pointers for strings.
SkipNA = 2,

Reserved3 = 3,
Reserved4 = 4,
Reserved5 = 5,
Expand Down

0 comments on commit 03ed7f2

Please sign in to comment.