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(FValue); end; function TDataFloatValue.GetValue: Double; begin Result := FValue; end; { TDataFloatValueZero } class constructor TDataFloatValueZero.CreateClass; begin FValue := TValue.From(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(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.