mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-10-31 07:31:49 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			284 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			284 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| {
 | |
|    This file is part of the Free Pascal run time library.
 | |
|    Copyright (c) 2004 by Marco van de Voort
 | |
|    member of the Free Pascal development team.
 | |
| 
 | |
|    An implementation for unit convutils, which converts between
 | |
|    units and simple combinations of them.
 | |
| 
 | |
|    Based on a guessed interface derived from some programs on the web. (Like
 | |
|    Marco Cantu's EuroConv example), so things can be a bit Delphi
 | |
|    incompatible. Also part on Delphibasics.co.uk.
 | |
| 
 | |
|    Quantities are mostly taken from my HP48g/gx or the unix units program
 | |
| 
 | |
|    This program is distributed in the hope that it will be useful,
 | |
|    but WITHOUT ANY WARRANTY;without even the implied warranty of
 | |
|    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 | |
| 
 | |
| **********************************************************************}
 | |
| 
 | |
| unit convutils;
 | |
| 
 | |
| interface
 | |
| 
 | |
| {$mode objfpc}
 | |
| {$H+}
 | |
| 
 | |
| {$ifndef FPUNONE}
 | |
| Type TConvType        = type Integer;
 | |
|      TConvFamily      = type Integer;
 | |
|      TConvFamilyArray = array of TConvFamily;
 | |
|      TConvTypeArray   = array of TConvType;
 | |
|      TConversionProc  = function(const AValue: Double): Double;
 | |
|      TConvUtilFloat   = double;
 | |
| 
 | |
| Function RegisterConversionFamily(Const S : String):TConvFamily;
 | |
| Function RegisterConversionType(Fam:TConvFamily;Const S:String;Value:TConvUtilFloat):TConvType;
 | |
| 
 | |
| function Convert ( const Measurement  : Double; const FromType, ToType  : TConvType ) :TConvUtilFloat;
 | |
| function Convert ( const Measurement  : Double; const FromType1, FromType2, ToType1, ToType2  : TConvType ) :TConvUtilFloat;
 | |
| 
 | |
| function ConvFamilyToDescription(const AFamily: TConvFamily): string;
 | |
| function ConvTypeToDescription(const AType: TConvType): string;
 | |
| procedure GetConvFamilies(out AFamilies: TConvFamilyArray);
 | |
| procedure GetConvTypes(const AFamily: TConvFamily; out ATypes: TConvTypeArray);
 | |
| 
 | |
| Type
 | |
|   TConvTypeInfo = Class(Tobject)
 | |
|   private
 | |
|      FDescription : String;
 | |
|      FConvFamily  : TConvFamily;
 | |
|      FConvType	  : TConvType;
 | |
|   public
 | |
|      Constructor Create(Const AConvFamily : TConvFamily;const ADescription:String);
 | |
|      function ToCommon(const AValue: Double) : Double; virtual; abstract;
 | |
|      function FromCommon(const AValue: Double) : Double; virtual; abstract;
 | |
|      property ConvFamily : TConvFamily read FConvFamily;
 | |
|      property ConvType   : TConvType   read FConvType;
 | |
|      property Description: String      read FDescription;
 | |
|   end;
 | |
| 
 | |
|   TConvTypeFactor = class(TConvTypeInfo)
 | |
|   private
 | |
|     FFactor: Double;
 | |
|   protected
 | |
|     property Factor: Double read FFactor;
 | |
|   public
 | |
|     constructor Create(const AConvFamily: TConvFamily; const ADescription: string;
 | |
|       const AFactor: Double);
 | |
|     function ToCommon(const AValue: Double): Double; override;
 | |
|     function FromCommon(const AValue: Double): Double; override;
 | |
|   end;
 | |
| 
 | |
|   TConvTypeProcs = class(TConvTypeInfo)
 | |
|   private
 | |
|     FToProc: TConversionProc;
 | |
|     FFromProc: TConversionProc;
 | |
|   public
 | |
|     constructor Create(const AConvFamily: TConvFamily; const ADescription: string;
 | |
|       const AToProc, AFromProc: TConversionProc);
 | |
|     function ToCommon(const AValue: Double): Double; override;
 | |
|     function FromCommon(const AValue: Double): Double; override;
 | |
|   end;
 | |
| 
 | |
| Implementation
 | |
| 
 | |
| Type ResourceData = record
 | |
|                       Description : String;
 | |
|                       Value       : TConvUtilFloat;
 | |
|                       Fam         : TConvFamily;
 | |
|                      end;
 | |
| 
 | |
| 
 | |
| var TheUnits    : array of ResourceData =nil;
 | |
|     TheFamilies : array of string =nil;
 | |
| 
 | |
| function ConvFamilyToDescription(const AFamily: TConvFamily): string;
 | |
| 
 | |
| begin
 | |
|   result:='';
 | |
|   if AFamily<length(TheFamilies) then
 | |
|     result:=TheFamilies[AFamily];
 | |
| end;
 | |
| 
 | |
| procedure GetConvFamilies(out AFamilies: TConvFamilyArray);
 | |
| 
 | |
| var i : integer;
 | |
| begin
 | |
|  setlength(AFamilies,length(thefamilies));
 | |
|  for i:=0 to length(TheFamilies)-1 do
 | |
|    AFamilies[i]:=i;
 | |
| end;
 | |
| 
 | |
| procedure GetConvTypes(const AFamily: TConvFamily; out ATypes: TConvTypeArray);
 | |
| 
 | |
| var i,j,nrTypes:integer;
 | |
| 
 | |
| begin
 | |
|   nrTypes:=0;
 | |
|   for i:=0 to length(TheUnits)-1 do
 | |
|     if TheUnits[i].fam=AFamily Then
 | |
|      inc(nrTypes);
 | |
|   setlength(atypes,nrtypes);
 | |
|   j:=0;
 | |
|   for i:=0 to length(TheUnits)-1 do
 | |
|     if TheUnits[i].fam=AFamily Then
 | |
|      begin
 | |
|        atypes[j]:=i;
 | |
|        inc(j);
 | |
|      end;	
 | |
| end;
 | |
| 
 | |
| function ConvTypeToDescription(const AType: TConvType): string;
 | |
| 
 | |
| Begin
 | |
|   result:='';
 | |
|   if AType<length(TheUnits) then
 | |
|     result:=TheUnits[AType].Description;
 | |
| end;
 | |
| 
 | |
| Function RegisterConversionFamily(Const S:String):TConvFamily;
 | |
| 
 | |
| var i,l : Longint;
 | |
| 
 | |
| begin
 | |
|   l:=Length(TheFamilies);
 | |
|   If l=0 Then
 | |
|     begin
 | |
|       SetLength(TheFamilies,1);
 | |
|       TheFamilies[0]:=S;
 | |
|       Result:=0;
 | |
|     end
 | |
|   else
 | |
|     begin
 | |
|       i:=0;
 | |
|       while (i<l) and (s<>TheFamilies[i]) do inc(i);
 | |
|       if i=l Then
 | |
|          begin
 | |
|            SetLength(TheFamilies,l+1);
 | |
|            TheFamilies[l]:=s;
 | |
|          end;
 | |
|        Result:=i;
 | |
|     end;
 | |
| end;
 | |
| 
 | |
| Function CheckFamily(i:TConvFamily):Boolean;
 | |
| 
 | |
| begin
 | |
|   Result:=i<Length(TheFamilies);
 | |
| end;
 | |
| 
 | |
| const macheps=1E-9;
 | |
| 
 | |
| Function RegisterConversionType(Fam:TConvFamily;Const S:String;Value:TConvUtilFloat):TConvType;
 | |
| 
 | |
| var l1 : Longint;
 | |
| 
 | |
| begin
 | |
|   If NOT CheckFamily(Fam) Then exit(-1); // family not registered.
 | |
|   if (value+1.0)<macheps then            // not properly defined yet.
 | |
|     exit(-1);
 | |
|   l1:=length(theunits);
 | |
|   Setlength(theunits,l1+1);
 | |
|   theunits[l1].description:=s;
 | |
|   theunits[l1].value:=value;
 | |
|   theunits[l1].fam:=fam;
 | |
|   Result:=l1;
 | |
| end;
 | |
| 
 | |
| function SearchConvert(TheType:TConvType; var r:ResourceData):Boolean;
 | |
| 
 | |
| var l1 : longint;
 | |
| 
 | |
| begin
 | |
|   l1:=length(TheUnits);
 | |
|   if thetype>=l1 then
 | |
|     exit(false);
 | |
|   r:=theunits[thetype];
 | |
|   result:=true;
 | |
| end;
 | |
| 
 | |
| function Convert ( const Measurement  : Double; const FromType, ToType  : TConvType ) :TConvUtilFloat;
 | |
| 
 | |
| var
 | |
|   fromrec,torec :   resourcedata;
 | |
| 
 | |
| begin
 | |
|   if not SearchConvert(fromtype,fromrec) then
 | |
|    exit(-1.0);                                  // raise exception?
 | |
|   if not SearchConvert(totype,torec) then
 | |
|    exit(-1.0);                                  // raise except?
 | |
|   if fromrec.fam<>torec.fam then
 | |
|    exit(-1.0);
 | |
|   result:=Measurement*fromrec.value/torec.value;
 | |
| end;
 | |
| 
 | |
| function Convert ( const Measurement  : Double; const FromType1, FromType2, ToType1, ToType2  : TConvType ) :TConvUtilFloat;
 | |
| var
 | |
|   fromrec1,fromrec2,torec1 ,
 | |
|   torec2 :   resourcedata;
 | |
| 
 | |
| begin
 | |
|   if not SearchConvert(fromtype1,fromrec1) then
 | |
|    exit(-1.0);                                  // raise exception?
 | |
|   if not SearchConvert(totype1,torec1) then
 | |
|    exit(-1.0);                                  // raise except?
 | |
|   if not SearchConvert(fromtype2,fromrec2) then
 | |
|    exit(-1.0);                                  // raise exception?
 | |
|   if not SearchConvert(totype2,torec2) then
 | |
|    exit(-1.0);                                  // raise except?
 | |
|   if (fromrec1.fam<>torec1.fam) or (fromrec1.fam<>torec1.fam) then
 | |
|    exit(-1.0);
 | |
|   result:=Measurement*(fromrec1.value/fromrec2.value)/(torec1.value/torec2.value);
 | |
| end;
 | |
| 
 | |
| Constructor TConvTypeInfo.Create(Const AConvFamily : TConvFamily;const ADescription:String);
 | |
| 
 | |
| begin
 | |
|   FDescription:=ADescription;
 | |
|   FConvFamily :=AConvFamily;
 | |
| end;
 | |
| 
 | |
| 
 | |
| constructor TConvTypeFactor.Create(const AConvFamily: TConvFamily; const ADescription: string;const AFactor: Double);
 | |
| begin
 | |
|   inherited create(AConvFamily,ADescription);
 | |
|   FFactor:=AFactor;
 | |
| end;
 | |
| 
 | |
| function TConvTypeFactor.ToCommon(const AValue: Double): Double; 
 | |
| begin
 | |
|   result:=AValue * FFactor;
 | |
| end;
 | |
| 
 | |
| function TConvTypeFactor.FromCommon(const AValue: Double): Double; 
 | |
| begin
 | |
|   result:=AValue / FFactor;
 | |
| end;
 | |
| 
 | |
| constructor TConvTypeProcs.Create(const AConvFamily: TConvFamily; const ADescription: string; const AToProc, AFromProc: TConversionProc);
 | |
| begin
 | |
|   inherited create(AConvFamily,ADescription);
 | |
|   ftoproc:=AToProc;
 | |
|   ffromproc:=AFromProc;
 | |
| end;
 | |
| 
 | |
| function TConvTypeProcs.ToCommon(const AValue: Double): Double; 
 | |
| begin
 | |
|   result:=FTOProc(Avalue);
 | |
| end;
 | |
| 
 | |
| function TConvTypeProcs.FromCommon(const AValue: Double): Double; 
 | |
| begin
 | |
|   result:=FFromProc(Avalue);
 | |
| end;
 | |
| 
 | |
| finalization
 | |
|   setlength(theunits,0);
 | |
|   setlength(thefamilies,0);
 | |
| {$else}
 | |
| implementation
 | |
| {$endif}
 | |
| end.
 | 
