unit Unit_NumPy;
interface
uses
System.Classes, System.SysUtils, System.Generics.Collections, System.Math;
type
T2DDoubleArray =
array of array of Double;
TNDArray = TArray<Double>;
TNDArray2 = TArray<TNDArray> ;
TByteArray = TArray<Byte>;
TBoolArray = Tarray<Boolean>;
TCardinalArray = TArray<Cardinal>;
TIntegerArray = TArray<Integer>;
TNumPy =
class
class var
FWidth: Integer;
FHeight: Integer;
private
public
class function arange(
const start, stop, step: Double): TNDArray;
static;
class function ToArray(
const Values:
array of Double): TNDArray;
overload;
static;
class function ToArray(
const Values: T2DDoubleArray): TArray<TNDArray>;
overload;
static;
class function diff(
const a: TNDArray): TNDArray;
static;
class function mean(
const a: TNDArray): Double;
static;
class function sum(
const a: TNDArray): Double;
static;
class function prod(
const a: TNDArray): Double;
static;
class function ConvertByteArrayToNDArray(
const a: TByteArray)
: TNDArray;
static;
class function max(
const a: TNDArray): Double;
static;
class function min(
const a: TNDArray): Double;
static;
class function unique(
const a: TNDArray): TNDArray;
static;
class function isnan(
const a: TNDArray): TBoolArray;
static;
class function all(
const a: TNDArray): Boolean;
class procedure Shape(X, y: Integer);
class procedure Savetxt(
const fname:
string;
const X: TNDArray;
const fmt:
string = '
%.18e';
const delimiter:
string = '
;';
const newline:
string = #10;
const header:
string = '
';
const footer:
string = '
';
const comments:
string = '
# ';
const encoding: TEncoding =
nil);
end;
implementation
{ TNumPy }
class function TNumPy.min(
const a: TNDArray): Double;
var
i: Integer;
n: Integer;
begin
n := Length(a);
if n = 0
then
Exit(0);
Result := a[0];
for i := 1
to n - 1
do
if a[i] < Result
then
Result := a[i];
end;
class function TNumPy.max(
const a: TNDArray): Double;
var
i: Integer;
n: Integer;
begin
n := Length(a);
if n = 0
then
Exit(0);
Result := a[0];
for i := 1
to n - 1
do
if a[i] > Result
then
Result := a[i];
end;
class function TNumPy.ToArray(
const Values:
array of Double): TNDArray;
var
i: Integer;
begin
SetLength(Result, Length(Values));
for i := 0
to High(Values)
do
Result[i] := Values[i];
end;
class function TNumPy.isnan(
const a: TNDArray): TBoolArray;
var
i: Integer;
n: Integer;
begin
n := Length(a);
SetLength(Result, n);
for i := 0
to n - 1
do
Result[i] := System.Math.IsNan(a[i]);
end;
class function TNumPy.ToArray(
const Values: T2DDoubleArray): TArray<TNDArray>;
var
i, j: Integer;
begin
SetLength(Result, Length(Values));
for i := 0
to High(Values)
do
begin
SetLength(Result[i], Length(Values[i]));
for j := 0
to High(Values[i])
do
Result[i][j] := Values[i][j];
end;
end;
class function TNumPy.arange(
const start, stop, step: Double): TNDArray;
var
i: Integer;
n: Integer;
begin
n := Round((stop - start) / step);
SetLength(Result, n);
for i := 0
to n - 1
do
Result[i] := start + i * step;
end;
class function TNumPy.ConvertByteArrayToNDArray(
const a: TByteArray): TNDArray;
var
i: Integer;
n: Integer;
begin
n := Length(a);
SetLength(Result, n);
for i := 0
to n - 1
do
Result[i] := a[i];
end;
class function TNumPy.diff(
const a: TNDArray): TNDArray;
var
i: Integer;
n: Integer;
begin
n := Length(a) - 1;
SetLength(Result, n);
for i := 0
to n - 1
do
Result[i] := a[i + 1] - a[i];
end;
class function TNumPy.mean(
const a: TNDArray): Double;
var
i: Integer;
n: Integer;
begin
n := Length(a);
if n = 0
then
Exit(0);
Result := 0;
for i := 0
to n - 1
do
Result := Result + a[i];
Result := Result / n;
end;
class function TNumPy.prod(
const a: TNDArray): Double;
var
i: Integer;
n: Integer;
begin
n := Length(a);
Result := 1;
for i := 0
to n - 1
do
Result := Result * a[i];
end;
class procedure TNumPy.Shape(X, y: Integer);
begin
FWidth := X;
FHeight := y;
end;
class function TNumPy.unique(
const a: TNDArray): TNDArray;
var
i, j: Integer;
temp: Double;
uniqueArr: TList<Double>;
begin
uniqueArr := TList<Double>.Create;
try
for i := 0
to Length(a) - 1
do
begin
temp := a[i];
if not uniqueArr.
Contains(temp)
then
uniqueArr.Add(temp);
end;
SetLength(Result, uniqueArr.Count);
for j := 0
to uniqueArr.Count - 1
do
Result[j] := uniqueArr[j];
finally
uniqueArr.Free;
end;
end;
class function TNumPy.sum(
const a: TNDArray): Double;
var
i: Integer;
n: Integer;
begin
n := Length(a);
Result := 0;
for i := 0
to n - 1
do
Result := Result + a[i];
end;
class procedure TNumPy.Savetxt(
const fname:
string;
const X: TNDArray;
const fmt:
string = '
%.18e';
const delimiter:
string = '
;';
const newline:
string = #10;
const header:
string = '
';
const footer:
string = '
';
const comments:
string = '
# ';
const encoding: TEncoding =
nil);
var
sl: TStringList;
i, j: Integer;
row:
string;
width, height: Integer;
begin
width := FWidth;
Height := FHeight;
if (width = 0)
or (height = 0)
then
raise Exception.Create('
Invalid array shape');
sl := TStringList.Create;
try
if header <> '
'
then
sl.Add(comments + header);
for i := 0
to height - 1
do
begin
row := Format(fmt, [X[i * width]]);
for j := 1
to width - 1
do
row := row + delimiter + Format(fmt, [X[i * width + j]]);
sl.Add(row);
end;
if footer <> '
'
then
sl.Add(comments + footer);
sl.SaveToFile(fname, encoding);
finally
sl.Free;
end;
end;
class function TNumPy.all(
const a: TNDArray): Boolean;
var
i: Integer;
begin
for i := 0
to Length(a) - 1
do
begin
if not (a[i] <> 0)
then
begin
Result := False;
Exit;
end;
end;
Result := True;
end;
end.