187 lines
4.1 KiB
ObjectPascal
187 lines
4.1 KiB
ObjectPascal
unit Myc.Data.Types.Float;
|
|
|
|
interface
|
|
|
|
uses
|
|
System.SysUtils,
|
|
Myc.Data.Types;
|
|
|
|
type
|
|
// Implements the float data type.
|
|
TDataFloatType = class(TInterfacedObject, IDataType, IDataFloatType)
|
|
strict private
|
|
class var
|
|
FSingleton: IDataFloatType;
|
|
FZero: IDataFloatValue;
|
|
FNaN: IDataFloatValue;
|
|
class constructor CreateClass;
|
|
public
|
|
function GetName: String;
|
|
function GetKind: TDataKind;
|
|
function CreateValue(Init: Double): IDataFloatValue;
|
|
class property Singleton: IDataFloatType read FSingleton;
|
|
end;
|
|
|
|
implementation
|
|
|
|
uses
|
|
System.Math,
|
|
System.Rtti;
|
|
|
|
type
|
|
// Implements the float data value.
|
|
TDataFloatValue = class(TInterfacedObject, IDataValue, IDataFloatValue)
|
|
private
|
|
FValue: Double;
|
|
public
|
|
constructor Create(const AValue: Double);
|
|
|
|
// IDataValue
|
|
function GetDataType: IDataType;
|
|
function GetAsString: string;
|
|
function AsTValue: TValue;
|
|
|
|
// IDataFloatValue
|
|
function GetValue: Double;
|
|
end;
|
|
|
|
// Special implementation for the value 0.0 (Singleton)
|
|
TDataFloatValueZero = class(TInterfacedObject, IDataValue, IDataFloatValue)
|
|
strict private
|
|
class var
|
|
FValue: TValue;
|
|
class constructor CreateClass;
|
|
public
|
|
function GetDataType: IDataType;
|
|
function GetAsString: string;
|
|
function GetValue: Double;
|
|
function AsTValue: TValue;
|
|
end;
|
|
|
|
// Special implementation for NaN (Not a Number) (Singleton)
|
|
TDataFloatValueNaN = class(TInterfacedObject, IDataValue, IDataFloatValue)
|
|
strict private
|
|
class var
|
|
FValue: TValue;
|
|
class constructor CreateClass;
|
|
public
|
|
function GetDataType: IDataType;
|
|
function GetAsString: string;
|
|
function GetValue: Double;
|
|
function AsTValue: TValue;
|
|
end;
|
|
|
|
{ TDataFloatValue }
|
|
|
|
constructor TDataFloatValue.Create(const AValue: Double);
|
|
begin
|
|
inherited Create;
|
|
FValue := AValue;
|
|
end;
|
|
|
|
function TDataFloatValue.GetDataType: IDataType;
|
|
begin
|
|
Result := TDataFloatType.Singleton;
|
|
end;
|
|
|
|
function TDataFloatValue.GetAsString: string;
|
|
begin
|
|
Result := FloatToStr(FValue);
|
|
end;
|
|
|
|
function TDataFloatValue.AsTValue: TValue;
|
|
begin
|
|
Result := TValue.From<Double>(FValue);
|
|
end;
|
|
|
|
function TDataFloatValue.GetValue: Double;
|
|
begin
|
|
Result := FValue;
|
|
end;
|
|
|
|
{ TDataFloatValueZero }
|
|
|
|
class constructor TDataFloatValueZero.CreateClass;
|
|
begin
|
|
FValue := TValue.From<Double>(0.0);
|
|
end;
|
|
|
|
function TDataFloatValueZero.GetAsString: string;
|
|
begin
|
|
Result := '0';
|
|
end;
|
|
|
|
function TDataFloatValueZero.GetDataType: IDataType;
|
|
begin
|
|
Result := TDataFloatType.Singleton;
|
|
end;
|
|
|
|
function TDataFloatValueZero.GetValue: Double;
|
|
begin
|
|
Result := 0.0;
|
|
end;
|
|
|
|
function TDataFloatValueZero.AsTValue: TValue;
|
|
begin
|
|
Result := FValue;
|
|
end;
|
|
|
|
{ TDataFloatValueNaN }
|
|
|
|
class constructor TDataFloatValueNaN.CreateClass;
|
|
begin
|
|
FValue := TValue.From<Double>(NaN);
|
|
end;
|
|
|
|
function TDataFloatValueNaN.GetAsString: string;
|
|
begin
|
|
Result := 'NaN';
|
|
end;
|
|
|
|
function TDataFloatValueNaN.GetDataType: IDataType;
|
|
begin
|
|
Result := TDataFloatType.Singleton;
|
|
end;
|
|
|
|
function TDataFloatValueNaN.GetValue: Double;
|
|
begin
|
|
Result := NaN;
|
|
end;
|
|
|
|
function TDataFloatValueNaN.AsTValue: TValue;
|
|
begin
|
|
Result := FValue;
|
|
end;
|
|
|
|
{ TDataFloatType }
|
|
|
|
class constructor TDataFloatType.CreateClass;
|
|
begin
|
|
FSingleton := TDataFloatType.Create;
|
|
FZero := TDataFloatValueZero.Create;
|
|
FNaN := TDataFloatValueNaN.Create;
|
|
end;
|
|
|
|
function TDataFloatType.GetName: String;
|
|
begin
|
|
Result := 'Float';
|
|
end;
|
|
|
|
function TDataFloatType.GetKind: TDataKind;
|
|
begin
|
|
Result := dkFloat;
|
|
end;
|
|
|
|
function TDataFloatType.CreateValue(Init: Double): IDataFloatValue;
|
|
begin
|
|
// Return singleton instances for 0.0 and NaN to avoid unnecessary allocations.
|
|
if (Init = 0.0) then
|
|
Result := FZero
|
|
else if IsNaN(Init) then
|
|
Result := FNaN
|
|
else
|
|
Result := TDataFloatValue.Create(Init);
|
|
end;
|
|
|
|
end.
|