123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- {
- This file is part of the Free Pascal run time library.
- Copyright (c) 1999-2001 by Several contributors
- Generic mathemtical routines in libc
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- 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.
- **********************************************************************}
- { for 80x86, we can easily write the optimal inline code }
- { Furthermore, the routines below only go up to double }
- { precision and we need extended precision if supported }
- {$ifndef FPC_HAS_TYPE_EXTENDED}
- {$ifdef aix}
- { aix math library routines don't raise exceptions, you have to manually
- check for them }
- function feclearexcept(flags: longint): longint; cdecl; external 'c';
- function fetestexcept(flags: longint): longint; cdecl; external 'c';
- const
- FE_DIVBYZERO = $04000000;
- FE_INEXACT = $02000000;
- FE_INVALID = $20000000;
- FE_OVERFLOW = $10000000;
- FE_UNDERFLOW = $08000000;
- FE_ALL_EXCEPT = $3E000000;
- procedure resetexcepts;
- begin
- seterrno(0);
- feclearexcept(FE_ALL_EXCEPT);
- end;
- procedure checkexcepts;
- var
- feres: longint;
- sfexcepts: TFPUExceptionMask;
- begin
- feres:=fetestexcept(FE_ALL_EXCEPT);
- sfexcepts:=[];
- if feres<>0 then
- begin
- if (feres and FE_DIVBYZERO) <> 0 then
- include(sfexcepts,float_flag_divbyzero);
- if (feres and FE_INEXACT) <> 0 then
- include(sfexcepts,float_flag_inexact);
- if (feres and FE_INVALID) <> 0 then
- include(sfexcepts,float_flag_invalid);
- if (feres and FE_OVERFLOW) <> 0 then
- include(sfexcepts,float_flag_overflow);
- if (feres and FE_UNDERFLOW) <> 0 then
- include(sfexcepts,float_flag_underflow);
- end
- { unknown error }
- else if (geterrno<>0) then
- include(sfexcepts,float_flag_invalid);
- if sfexcepts<>[] then
- float_raise(sfexcepts);
- end;
- {$else aix}
- procedure resetexcepts; inline;
- begin
- end;
- procedure checkexcepts; inline;
- begin
- end;
- {$endif aix}
- {$ifndef SOLARIS}
- {$ifndef FPC_SYSTEM_HAS_INT}
- {$define FPC_SYSTEM_HAS_INT}
- {$ifdef SUPPORT_DOUBLE}
- function c_trunc(d: double): double; cdecl; external 'c' name 'trunc';
- function fpc_int_real(d: ValReal): ValReal;compilerproc; {$ifdef MATHINLINE}inline;{$endif}
- begin
- resetexcepts;
- result := c_trunc(d);
- checkexcepts;
- end;
- {$else SUPPORT_DOUBLE}
- function c_truncf(d: single): double; cdecl; external 'c' name 'truncf';
- function fpc_int_real(d: ValReal): ValReal;compilerproc; {$ifdef MATHINLINE}inline;{$endif}
- begin
- { this will be correct since real = single in the case of }
- { the motorola version of the compiler... }
- resetexcepts;
- int:=c_truncf(d);
- checkexcepts;
- end;
- {$endif SUPPORT_DOUBLE}
- {$endif FPC_SYSTEM_HAS_INT}
- {$endif SOLARIS}
- {$ifndef SYSTEM_HAS_FREXP}
- {$define SYSTEM_HAS_FREXP}
- function c_frexp(x: double; out e: longint): double; cdecl; external 'c' name 'frexp';
- procedure frexp(x:ValReal; out Mantissa: ValReal; out Exponent: longint); {$ifdef MATHINLINE}inline;{$endif}
- begin
- resetexcepts;
- Mantissa := c_frexp(x,Exponent);
- checkexcepts;
- end;
- {$endif not SYSTEM_HAS_FREXP}
- {$ifndef SYSTEM_HAS_LDEXP}
- {$define SYSTEM_HAS_LDEXP}
- function c_ldexp(x: double; n: longint): double; cdecl; external 'c' name 'ldexp';
- function ldexp( x: ValReal; N: Integer):ValReal;{$ifdef MATHINLINE}inline;{$endif}
- begin
- resetexcepts;
- ldexp := c_ldexp(x,n);
- checkexcepts;
- end;
- {$endif not SYSTEM_HAS_LDEXP}
- {$ifndef FPC_SYSTEM_HAS_SQRT}
- {$define FPC_SYSTEM_HAS_SQRT}
- function c_sqrt(d: double): double; cdecl; external 'c' name 'sqrt';
- function fpc_sqrt_real(d:ValReal):ValReal;compilerproc; {$ifdef MATHINLINE}inline;{$endif}
- begin
- resetexcepts;
- result := c_sqrt(d);
- checkexcepts;
- end;
- {$endif}
- {$ifndef FPC_SYSTEM_HAS_EXP}
- {$define FPC_SYSTEM_HAS_EXP}
- function c_exp(d: double): double; cdecl; external 'c' name 'exp';
- function fpc_Exp_real(d:ValReal):ValReal;compilerproc; {$ifdef MATHINLINE}inline;{$endif}
- begin
- resetexcepts;
- result := c_exp(d);
- checkexcepts;
- end;
- {$endif}
- { buggy on aix, sets DIV_BY_ZERO flag for some valid inputs }
- {$ifndef aix}
- {$ifndef FPC_SYSTEM_HAS_LN}
- {$define FPC_SYSTEM_HAS_LN}
- function c_log(d: double): double; cdecl; external 'c' name 'log';
- function fpc_Ln_real(d:ValReal):ValReal;compilerproc;{$ifdef MATHINLINE}inline;{$endif}
- begin
- resetexcepts;
- result := c_log(d);
- checkexcepts;
- end;
- {$endif}
- {$endif}
- {$ifndef FPC_SYSTEM_HAS_SIN}
- {$define FPC_SYSTEM_HAS_SIN}
- function c_sin(d: double): double; cdecl; external 'c' name 'sin';
- function fpc_Sin_real(d:ValReal):ValReal;compilerproc; {$ifdef MATHINLINE}inline;{$endif}
- begin
- resetexcepts;
- result := c_sin(d);
- checkexcepts;
- end;
- {$endif}
- {$ifndef FPC_SYSTEM_HAS_COS}
- {$define FPC_SYSTEM_HAS_COS}
- function c_cos(d: double): double; cdecl; external 'c' name 'cos';
- function fpc_Cos_real(d:ValReal):ValReal;compilerproc; {$ifdef MATHINLINE}inline;{$endif}
- begin
- resetexcepts;
- result := c_cos(d);
- checkexcepts;
- end;
- {$endif}
- {$ifndef FPC_SYSTEM_HAS_ARCTAN}
- {$define FPC_SYSTEM_HAS_ARCTAN}
- function c_atan(d: double): double; cdecl; external 'c' name 'atan';
- function fpc_ArcTan_real(d:ValReal):ValReal;compilerproc; {$ifdef MATHINLINE}inline;{$endif}
- begin
- resetexcepts;
- result := c_atan(d);
- checkexcepts;
- end;
- {$endif}
- {$endif not FPC_HAS_TYPE_EXTENDED}
|