unit Myc.Data.Types.Float; interface uses System.SysUtils, Myc.Data.Types; type // Implements the float data type. TImplDataFloatType = 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; type // Implements the float data value. TImplDataFloatValue = class(TInterfacedObject, IDataValue, IDataFloatValue) private FValue: Double; public constructor Create(const AValue: Double); // IDataValue function GetDataType: IDataType; function GetAsString: string; // IDataFloatValue function GetValue: Double; end; // Special implementation for the value 0.0 (Singleton) TImplDataFloatValueZero = class(TInterfacedObject, IDataValue, IDataFloatValue) public function GetDataType: IDataType; function GetAsString: string; function GetValue: Double; end; // Special implementation for NaN (Not a Number) (Singleton) TImplDataFloatValueNaN = class(TInterfacedObject, IDataValue, IDataFloatValue) public function GetDataType: IDataType; function GetAsString: string; function GetValue: Double; end; { TImplDataFloatValue } constructor TImplDataFloatValue.Create(const AValue: Double); begin inherited Create; FValue := AValue; end; function TImplDataFloatValue.GetDataType: IDataType; begin Result := TImplDataFloatType.Singleton; end; function TImplDataFloatValue.GetAsString: string; begin Result := FloatToStr(FValue); end; function TImplDataFloatValue.GetValue: Double; begin Result := FValue; end; function TImplDataFloatValueZero.GetAsString: string; begin Result := '0'; end; function TImplDataFloatValueZero.GetDataType: IDataType; begin Result := TImplDataFloatType.Singleton; end; function TImplDataFloatValueZero.GetValue: Double; begin Result := 0.0; end; function TImplDataFloatValueNaN.GetAsString: string; begin Result := 'NaN'; end; function TImplDataFloatValueNaN.GetDataType: IDataType; begin Result := TImplDataFloatType.Singleton; end; function TImplDataFloatValueNaN.GetValue: Double; begin Result := NaN; end; { TImplDataFloatType } class constructor TImplDataFloatType.CreateClass; begin FSingleton := TImplDataFloatType.Create; FZero := TImplDataFloatValueZero.Create; FNaN := TImplDataFloatValueNaN.Create; end; function TImplDataFloatType.GetName: String; begin Result := 'Float'; end; function TImplDataFloatType.GetKind: TDataKind; begin Result := dkFloat; end; function TImplDataFloatType.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 := TImplDataFloatValue.Create(Init); end; end.