Dze je subor www.TrSek.com/pas/math.pas{ MATH.PAS Copyleft (c) Zdeno Sekerák, <etrsek@gmail.com> }
{ Trsek mathematics function for unit bignumber }
{ }
{ Tento program je slobodný software. Mo¾ete ho ïalej distribuova» a/alebo }
{ upravova» pod podmienkou licence GNU General Public License vydanej }
{ organizáciou Free Software Foundation, verzia licencie 3 alebo vy¹¹ej. }
{ }
{ Tento program je distribuvaný v nádeji, ¾e bude u¾itoèným, ale }
{ NEPOSKYTUJE ®IADNE ZÁRUKY. Bez akejkoµvek vyplývajúcej záruky na }
{ OBCHODOVATE¥NOS« alebo VHODNOS« PRE KONKRÉTNE POU®ITIE. Pre viac }
{ podrobností si preèítajte licenciu GNU General Public Licence. }
{ }
{ http://www.gnu.org/copyleft/gpl.html }
{ }
{ Author: Zdeno Sekerák (TrSek) }
{ Datum : 08.01.2010 }
{ Verzia: 0.91 RC1 http://www.trsek.com }
unit Math;
interface
uses Objects, Crt, Dos, BigNum;
{ make testing computing in native format, use for debuging }
{ for release use UNDEF _BN_NATIVE }
{ DEFINE _BN_NATIVE}
{ view computing time with scroolbar }
{$DEFINE _BN_SCROOL_TIME}
{ view parcial computing number }
{$DEFINE _BN_SCROLL_NUMBER}
const BN_EPSILON : integer = -100; { variable !?! }
BN_EPSILON_MAX = BN_MAX_DIGIT-2; { maximal epsilon exponent for taylor polynom }
BN_EPSILON_PI = -5; { epsilon for taylor polynom less }
BN_INFINITY = BN_MAX_DIGIT;
function Odd:boolean; { Testuje, zda argumentem je liche cislo. }
function SizeOf:integer; { Vypocita velikost argumentu v bajtech. }
procedure KurzorOnOff(OnOff:boolean); { zapne/vypne kurzor }
{ operacie porovnania }
function lt (x: bignumber):boolean; { less-than x }
function equal (x: bignumber):boolean; { identical to x }
function ne (x: bignumber):boolean; { not equal to x }
function gt (x: bignumber):boolean; { greater-than x }
function le (x: bignumber):boolean; { less-than or equal to x }
function ge (x: bignumber):boolean; { greater-than or equal to x }
{ operacie pre ine primitiva }
procedure Copy(r: extended);
procedure Copy_bn(bn: infinity);
function ReadLn(ch:char):char;
procedure WriteLn(n,d:integer);
{ destructor, nothing do }
destructor infinity.done;
begin
end;
{---------------------------------------------------------------------------}
{ zmensi/zvacsi presnot pre taylorove rady }
procedure infinity.SetEpsilon(_eps: integer);
begin
{ vzdy minus }
BN_EPSILON := system.abs(_eps);
{ nie viac ako maximum }
if(BN_EPSILON > BN_EPSILON_MAX)then
BN_EPSILON := BN_EPSILON_MAX;
{ nie menej ako bezne }
if(BN_EPSILON < 10)then
BN_EPSILON := 10;
{ vzdy minus }
BN_EPSILON := (-1)* BN_EPSILON;
end;
{---------------------------------------------------------------------------}
{ povie aka je presnost pre taylorove rady }
function infinity.GetEpsilon:integer;
begin
GetEpsilon := system.abs(BN_EPSILON);
end;
{---------------------------------------------------------------------------}
procedure infinity.SetRadian;
begin
_rdg_type := BN_RADIAN;
end;
procedure infinity.SetDegree;
begin
_rdg_type := BN_DEGREE;
end;
procedure infinity.SetGradient;
begin
_rdg_type := BN_GRADIENT;
end;
{---------------------------------------------------------------------------}
function infinity.GetRDG : integer;
begin
GetRDG := _rdg_type;
end;
{---------------------------------------------------------------------------}
{ konvert stupne na radiany }
procedure infinity.ToRadian;
var pom: infinity;
begin
pom.Pi;
self.Divide_r(180);
self.Multiply(pom);
end;
{---------------------------------------------------------------------------}
{ konvert radiany na stupne }
procedure infinity.ToDegree;
var pom: infinity;
begin
pom.Pi;
self.Divide(pom);
self.Multiply_r(180);
end;
{---------------------------------------------------------------------------}
{ Vypocita absolutni hodnotu argumentu. }
procedure infinity.Abs;
begin
{$IFDEF _BN_NATIVE}
{ for test }
_bn.native:=system.abs( _bn.native );
{$ENDIF}
{ Vygeneguje nahodne cislo. }
procedure infinity.Random;
var i: integer;
s: string;
begin
for i:=1 to BN_MAX_DIGIT do
_bn.mantisa[i]:= system.random( BN_NUMSYSTEM );
{ for test }
s:=self.Str(18,18);
system.Val(s, _bn.native, i);
{$ENDIF}
end;
{---------------------------------------------------------------------------}
{ Vypocita velikost argumentu v bajtech. }
function infinity.SizeOf: integer;
begin
SizeOf := BN_MAX_DIGIT;
end;
{---------------------------------------------------------------------------}
{ zapne/vypne kurzor }
procedure infinity.KurzorOnOff(OnOff:boolean);
var Regs : Registers;
begin
with Regs do
begin
AH := $03;
BH := $00;
Intr($10,Regs);
If not (OnOff) then
CH := CH or $20
else
CH := CH and $DF;
{ Vypocita druhou mocninu argumentu. }
procedure infinity.Sqr;
var pom: bignumber;
begin
pom._bn := _bn;
self.Multiply(pom);
end;
{---------------------------------------------------------------------------}
{ n-ta mocnina }
procedure infinity.SqrY(b:bignumber);
var pom: infinity;
step: real;
i,kolko: longint;
begin
{ je to celociselny mocnitel }
pom._bn := b._bn;
pom.Frac;
if( pom._bn.zero )then begin
pom._bn := self._bn;
kolko := b.ToInt( b.Str(BN_INFINITY, BN_INFINITY))-1;
ScroolBarStart;
{ nasobime }
for i:=1 to kolko do begin
self.Multiply(pom);
step:=i*BN_EPSILON/kolko;
ScroolBarInc( system.trunc(step));
end;
{ finish }
ScroolBarFinish;
end
else begin
{ je to mocnenie desatinnym cislom }
self.Ln;
self.Multiply(b);
self.Exp;
end;
end;
{---------------------------------------------------------------------------}
{ Testuje, zda argumentem je liche cislo. }
function infinity.Odd:boolean;
var i:integer;
begin
{ ak je to velke cislo je sude/parne }
Odd:=false;
if( _bn.exponent > BN_MAX_DIGIT )then
exit;
{ pozriem na konkretne cislo }
if((_bn.exponent >= 1)
and(_bn.exponent <= BN_MAX_DIGIT))then
begin
if((_bn.mantisa[_bn.exponent] div 2) <> 0)then
Odd:=true
else Odd:=false;
exit;
end;
{ ak ma desatinnu cast potom je liche/neparne }
for i:=_bn.Exponent + 1 to BN_MAX_DIGIT do
if(_bn.mantisa[i] <> 0 )then begin
Odd:=true;
exit;
end;
{ inak je sude/parne }
Odd:=false;
end;
{---------------------------------------------------------------------------}
{ Zaokrouhli realnou hodnotu na celociselnou. }
procedure infinity.Round;
var pom: bignumber;
begin
{ nema zmysel }
if(self._bn.exponent < -1)then
begin
self.Init('0');
exit;
end;
{ cislo je mensie ako x }
function infinity.lt(x: bignumber):boolean;
begin
{ rozdielne znamienka tam je to jasne }
if(_bn.sign <> x._bn.sign)then begin
if( _bn.sign )then
lt:=true
else lt:=false;
exit;
end;
{ pozerame sa na zaporne }
if( _bn.sign )then begin
lt:=false;
if(_bn.exponent < x._bn.exponent )then
exit;
{ cislo je rovnake ako x }
function infinity.equal(x: bignumber):boolean;
begin
equal:=true;
if(_bn.sign = x._bn.sign )then
if(_bn.exponent = x._bn.exponent )then
if(self.compare_mantisa(x) = BN_MANTISA_EQUAL)then
exit;
{ cislo nieje rovnake ako x }
function infinity.ne(x: bignumber):boolean;
begin
ne:=not(self.equal(x));
end;
{------------------------------------------------------------------------------}
{ cislo je vacsie ako x }
{ !!! optimalizovat }
function infinity.gt(x: bignumber):boolean;
begin
if(self.equal(x))then
gt:=false
else
gt:=not(self.lt(x));
end;
{------------------------------------------------------------------------------}
{ cislo je mensie rovnake ako x }
{ !!! optimalizovat }
function infinity.le(x: bignumber):boolean;
begin
if(self.equal(x))then
le:=true
else
le:=self.lt(x);
end;
{------------------------------------------------------------------------------}
{ cislo je vacsie rovnake ako x }
{ !!! optimalizovat }
function infinity.ge(x: bignumber):boolean;
begin
if(self.equal(x))then
ge:=true
else
ge:=not(self.lt(x));
end;
{------------------------------------------------------------------------------}
{ prekopiruje realne cislo do formatu bignumber }
procedure infinity.Copy(r: extended);
var s:string;
begin
system.Str(r,s);
self.Val(s);
end;
{------------------------------------------------------------------------------}
{ prekopiruje cislo do clenskej premennej }
procedure infinity.Copy_bn(bn: infinity);
begin
_bn := bn._bn;
function infinity.ReadLn(ch:char):char;
begin
ReadLn:=self.Read(ch);
system.Writeln;
end;
{------------------------------------------------------------------------------}
procedure infinity.WriteLn(n,d:integer);
begin
self.Write(n,d);
system.Writeln;
end;
{------------------------------------------------------------------------------}
{ pretazene pre pracu s realnymi cislami }
procedure infinity.Plus_r(r: extended);
var pom:infinity;
begin
pom.Copy(r);
self.Plus(pom);
end;
procedure infinity.Minus_r(r: extended);
var pom:infinity;
begin
pom.Copy(r);
self.Minus(pom);
end;
procedure infinity.Multiply_r(r: extended);
var pom:infinity;
begin
pom.Copy(r);
self.Multiply(pom);
end;
procedure infinity.Divide_r(r: extended);
var pom:infinity;
begin
pom.Copy(r);
self.Divide(pom);
end;
{------------------------------------------------------------------------------}
for i:=1 to _scroolBarD do
if((_step/step) >= i) or (_step = BN_EPSILON)then
system.Write( BN_SCROOL_OK )
else begin
if ruzicka then begin
ruzicka:=false;
_scroolBarDis := (_scroolBarDis+1) mod 4;
system.Write( BN_SCROOL_RUZICA[ _scroolBarDis+1 ]);
end
else
system.Write( BN_SCROOL_WAIT );
end;
{ este percenta }
step:=100*(_step/BN_EPSILON);
system.Write(step:3:0,'%');
{$IFDEF _BN_SCROOL_TIME}
{ este cas }
gettime(h,m,s,ss);
_time:=((longint(h)*60 + m)*60 + s)*10 + (ss div 10) - _scroolBarTime;
system.Write((_time div 10):3, '.', (_time mod 10), 's');
{$ENDIF}
{ n-ta cela tretia odmocnina cisla }
{ ale uz 4 odmocnina konverguje strasne pomaly }
procedure infinity.SqrtN(n:integer);
var x: infinity;
clen: infinity;
nasob: infinity;
_exp: longint;
_sign: boolean;
i: integer;
begin
{ it isn't possible for even sqrt }
if(((n mod 2)=0) and ( self._bn.sign ))
or ( n<2) then begin
self.Copy(0);
_bn.overflow := BNE_SQRT_MINUS;
exit;
end;
{ odd sqrt is possible }
_sign := false;
if( self._bn.sign )then begin
_sign := _bn.sign;
_bn.sign := false;
end;
ScroolBarStart;
ScroolBarInc(1);
{ upravime velky exponent }
_exp := self._bn.exponent div n;
self._bn.exponent := self._bn.exponent mod n;
procedure infinity.Tan;
var clen: infinity;
begin
clen.Copy_bn(self);
self.Sin;
clen.Cos;
self.Divide(clen);
end;
{------------------------------------------------------------------------------}
procedure infinity.Cotan;
var clen: infinity;
begin
clen.Copy_bn(self);
self.Cos;
clen.Sin;
self.Divide(clen);
end;
{------------------------------------------------------------------------------}
{ Vypocita hodnotu pi. }
{ this version is very lazy }
procedure infinity.PiCompute;
var clen: infinity;
n: longint;
sign: integer;
begin
self.Copy(0);
clen.Copy_bn(self);
ScroolBarStart;
sign:=1;
n:=0;
while( clen._bn.exponent > BN_EPSILON_PI ) do
begin
clen.Copy(sign);
clen.Divide_r(2*n+1);
self.Plus(clen);
while(( clen._bn.exponent > BN_EPSILON ) and not(clen._bn.zero)) do
begin
clen.Multiply(x); { clen:=clen * x * x *n/((n+1)*(n+2)) }
clen.Multiply(x);
clen.Multiply_r(n);
clen.Divide_r((n+1)*(n+2));
begin
system.writeln('This program use unit math (trsek mathematic s for infinity number).');
system.writeln('Author: Zdeno Sekerak (TrSek), www.trsek.com ');
system.writeln('Copyleft 2010, http://www.gnu.org/copyleft/gpl.html');
end.