Files
harbour-core/harbour/source/rtl/math.c
Przemyslaw Czerpak c3e1436da0 2009-06-26 02:22 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
* harbour/include/hbvm.h
  * harbour/include/hbrdddbf.h
  * harbour/include/hbapidbg.h
  * harbour/include/hbset.h
  * harbour/include/hbcomp.h
  * harbour/include/hbapirdd.h
  * harbour/include/hbstack.h
  * harbour/include/hbsxfunc.h
  * harbour/include/hbapilng.h
  * harbour/include/hbgtcore.h
  * harbour/include/hbapifs.h
  * harbour/include/hbdbsort.h
  * harbour/include/hbapigt.h
  * harbour/include/hbapi.h
  * harbour/include/hbapierr.h
  * harbour/include/hbapiitm.h
  * harbour/include/hbrddfpt.h
  * harbour/contrib/hbmysql/mysql.c
  * harbour/contrib/hbct/bitnum.c
  * harbour/contrib/hbct/token2.c
  * harbour/contrib/hbct/charsprd.c
  * harbour/contrib/hbct/ctnet.c
  * harbour/contrib/hbct/charonly.c
  * harbour/contrib/hbct/atadjust.c
  * harbour/contrib/hbct/ctwin.c
  * harbour/contrib/hbct/charsort.c
  * harbour/contrib/hbct/ctwin.h
  * harbour/contrib/hbct/charmix.c
  * harbour/contrib/hbct/charevod.c
  * harbour/contrib/hbct/maxline.c
  * harbour/contrib/hbct/wordrepl.c
  * harbour/contrib/hbct/charrepl.c
  * harbour/contrib/hbct/files.c
  * harbour/contrib/hbct/video.c
  * harbour/contrib/hbct/charswap.c
  * harbour/contrib/hbct/dattime3.c
  * harbour/contrib/hbct/charop.c
  * harbour/contrib/hbct/misc2.c
  * harbour/contrib/hbct/charone.c
  * harbour/contrib/hbct/ctstr.c
  * harbour/contrib/hbct/screen1.c
  * harbour/contrib/hbct/token1.c
  * harbour/contrib/hbct/ctstr.h
  * harbour/contrib/hbct/charmirr.c
  * harbour/contrib/hbct/relation.c
  * harbour/contrib/hbct/atnum.c
  * harbour/contrib/hbct/like.c
  * harbour/contrib/hbct/count.c
  * harbour/contrib/hbct/disk.c
  * harbour/contrib/hbct/ctstrfil.c
  * harbour/contrib/hbct/posdiff.c
  * harbour/contrib/hbct/addascii.c
  * harbour/contrib/hbct/tab.c
  * harbour/contrib/hbct/numline.c
  * harbour/contrib/hbct/dattime2.c
  * harbour/contrib/hbct/asciisum.c
  * harbour/contrib/hbct/expand.c
  * harbour/contrib/hbct/pos2.c
  * harbour/contrib/hbct/numat.c
  * harbour/contrib/hbct/atrepl.c
  * harbour/contrib/hbct/wordtoch.c
  * harbour/contrib/hbct/print.c
  * harbour/contrib/hbct/justify.c
  * harbour/contrib/xhb/hbxml.c
  * harbour/contrib/xhb/dbf2txt.c
  * harbour/contrib/xhb/xhbis.c
  * harbour/contrib/xhb/fparse.c
  * harbour/contrib/xhb/xstrdel.c
  * harbour/contrib/xhb/hbcomprs.c
  * harbour/contrib/xhb/datesxhb.c
  * harbour/contrib/xhb/xhbmsgs.c
  * harbour/contrib/xhb/freadlin.c
  * harbour/contrib/xhb/txtline.c
  * harbour/contrib/xhb/xhbtrim.c
  * harbour/contrib/xhb/xhbcopyf.c
  * harbour/contrib/xhb/cstructc.c
  * harbour/contrib/xhb/xhbfunc.c
  * harbour/contrib/hbtpathy/tplinux.c
  * harbour/contrib/hbgt/charmixg.c
  * harbour/contrib/hbgt/strexpan.c
  * harbour/contrib/hbgt/charodd.c
  * harbour/contrib/hbgt/strright.c
  * harbour/contrib/hbgt/asciisgt.c
  * harbour/contrib/hbgt/strdiffg.c
  * harbour/contrib/hbgt/chrtotal.c
  * harbour/contrib/hbgt/strcount.c
  * harbour/contrib/hbgt/strleft.c
  * harbour/contrib/hbgt/ascposgt.c
  * harbour/contrib/hbgt/chrfirst.c
  * harbour/contrib/hbgt/chrcount.c
  * harbour/contrib/hbgt/strpbrk.c
  * harbour/contrib/hbgt/chareven.c
  * harbour/contrib/hbgt/strcspn.c
  * harbour/contrib/hbgt/atdiff.c
  * harbour/contrib/hbsqlit3/hbsqlit3.c
  * harbour/contrib/hbmzip/hbmzip.c
  * harbour/contrib/hbnf/proper.c
  * harbour/contrib/hbnf/fttext.c
  * harbour/contrib/hbnf/chdir.c
  * harbour/contrib/hbnf/getver.c
  * harbour/contrib/hbnf/ftattr.c
  * harbour/contrib/hbnf/mkdir.c
  * harbour/contrib/hbnf/rmdir.c
  * harbour/contrib/Makefile
  * harbour/contrib/hbcurl/hbcurl.c
  * harbour/contrib/rddsql/sddmy/mysqldd.c
  * harbour/contrib/rddsql/sddpg/pgsqldd.c
  * harbour/contrib/rddsql/sddfb/fbirddd.c
  * harbour/contrib/rddsql/sddodbc/odbcdd.c
  * harbour/contrib/rddsql/sqlmix.c
  * harbour/contrib/hbhpdf/harupdf.c
  * harbour/contrib/rddads/adsx.c
  * harbour/contrib/rddads/adsfunc.c
  * harbour/contrib/rddads/rddads.h
  * harbour/contrib/rddads/ads1.c
  * harbour/contrib/hbmisc/hb_f.c
  * harbour/contrib/hbmisc/strfmt.c
  * harbour/contrib/hbmisc/stringsx.c
  * harbour/contrib/hbmisc/spd.c
  * harbour/contrib/hbtip/utils.c
  * harbour/contrib/hbwin/wapi_winbase.c
  * harbour/contrib/hbwin/win_misc.c
  * harbour/contrib/hbbtree/hb_btree.h
  * harbour/contrib/hbbtree/hb_btree.c
  * harbour/source/pp/hbpp.c
  * harbour/source/vm/runner.c
  * harbour/source/vm/estack.c
  * harbour/source/vm/itemapi.c
  * harbour/source/vm/hvm.c
  * harbour/source/vm/cmdarg.c
  * harbour/source/vm/memvars.c
  * harbour/source/vm/dynlibhb.c
  * harbour/source/vm/set.c
  * harbour/source/main/harbour.c
  * harbour/source/debug/dbgentry.c
  * harbour/source/common/hbfsapi.c
  * harbour/source/common/hbfopen.c
  * harbour/source/rtl/gtdos/gtdos.c
  * harbour/source/rtl/diskspac.c
  * harbour/source/rtl/console.c
  * harbour/source/rtl/chrasc.c
  * harbour/source/rtl/fscopy.c
  * harbour/source/rtl/run.c
  * harbour/source/rtl/spfiles.c
  * harbour/source/rtl/defpath.c
  * harbour/source/rtl/philes.c
  * harbour/source/rtl/oldbox.c
  * harbour/source/rtl/math.c
  * harbour/source/rtl/hbgtcore.c
  * harbour/source/rtl/cdpapi.c
  * harbour/source/rtl/gtcrs/gtcrs.c
  * harbour/source/rtl/dirdrive.c
  * harbour/source/rtl/hbi18n1.c
  * harbour/source/rtl/trim.c
  * harbour/source/rtl/hbzlibgz.c
  * harbour/source/rtl/philesx.c
  * harbour/source/rtl/mlcfunc.c
  * harbour/source/rtl/filehb.c
  * harbour/source/rtl/fstemp.c
  * harbour/source/rtl/is.c
  * harbour/source/rtl/hbrunfun.c
  * harbour/source/rtl/ampm.c
  * harbour/source/rtl/setcolor.c
  * harbour/source/rtl/oemansi.c
  * harbour/source/rtl/disksphb.c
  * harbour/source/rtl/hbzlib.c
  * harbour/source/rtl/strpeek.c
  * harbour/source/rtl/replic.c
  * harbour/source/rtl/stuff.c
  * harbour/source/rtl/hbstrfmt.c
  * harbour/source/rtl/transfrm.c
  * harbour/source/rtl/hbhex.c
  * harbour/source/rtl/trace.c
  * harbour/source/rtl/hbadler.c
  * harbour/source/rtl/samples.c
  * harbour/source/rtl/filebuf.c
  * harbour/source/rtl/hbcrc.c
  * harbour/source/rtl/gete.c
  * harbour/source/rtl/hbmd5.c
  * harbour/source/rtl/langapi.c
  * harbour/source/rtl/gtcgi/gtcgi.c
  * harbour/source/rtl/errapi.c
  * harbour/source/rtl/hbregexc.c
  * harbour/source/rtl/natmsg.c
  * harbour/source/rtl/fssize.c
  * harbour/source/rtl/hbinet.c
  * harbour/source/rtl/colorind.c
  * harbour/source/rtl/copyfile.c
  * harbour/source/rtl/mouseapi.c
  * harbour/source/rtl/soundex.c
  * harbour/source/rtl/memofile.c
  * harbour/source/rtl/hbffind.c
  * harbour/source/rtl/gtapi.c
  * harbour/source/rtl/direct.c
  * harbour/source/rtl/filesys.c
  * harbour/source/rtl/file.c
  * harbour/source/rtl/val.c
  * harbour/source/rtl/hbregex.c
  * harbour/source/rtl/rat.c
  * harbour/source/rtl/isprint.c
  * harbour/source/rdd/dbfntx/dbfntx1.c
  * harbour/source/rdd/dbsql.c
  * harbour/source/rdd/workarea.c
  * harbour/source/rdd/wacore.c
  * harbour/source/rdd/sdf1.c
  * harbour/source/rdd/dbdetach.c
  * harbour/source/rdd/dbcmdx.c
  * harbour/source/rdd/dbfnsx/dbfnsx1.c
  * harbour/source/rdd/dbcmd.c
  * harbour/source/rdd/dbfcdx/dbfcdx1.c
  * harbour/source/rdd/delim1.c
  * harbour/source/rdd/dbf1.c
  * harbour/source/rdd/hsx/hsx.c
  * harbour/source/rdd/dbcmd53.c
  * harbour/source/rdd/usrrdd/usrrdd.c
  * harbour/source/rdd/wafunc.c
  * harbour/source/rdd/dbffpt/dbffpt1.c
  * harbour/source/rdd/hbsix/sxsem.c
  * harbour/source/rdd/hbsix/sxord.c
  * harbour/source/rdd/hbsix/sxfname.c
  * harbour/source/rdd/hbsix/sxtable.c
  * harbour/source/rdd/hbsix/sxdate.c
  * harbour/source/rdd/hbsix/sxutil.c
  * harbour/source/rdd/hbsix/sxcompr.c
  * harbour/source/compiler/hbmain.c
  * harbour/source/compiler/cmdcheck.c
  * harbour/source/compiler/hbpcode.c
  * harbour/source/compiler/genc.c
  * harbour/source/compiler/gencc.c
  * harbour/source/compiler/hbcmplib.c
  * harbour/source/compiler/ppcomp.c
    * changed 'char *' and changed 'BYTE *' to 'const char *' in
      the following functions:
         const char * hb_vmFindModuleSymbolName( PHB_SYMB pSym );
         void  hb_vmInitSymbolGroup( void * hNewDynLib, int argc,
                                     const char * argv[] );
         void hb_dbgEntry( int nMode, int nLine, const char *szName,
                           int nIndex, PHB_ITEM pFrame );
         void hb_dbgAddBreak( void *handle, const char *cModule,
                              int nLine, const char *szFunction );
         void hb_dbgAddWatch( void *handle, const char *szExpr, BOOL bTrace );
         PHB_ITEM hb_dbgGetExpressionValue( void *handle,
                                            const char *expression );
         BOOL hb_dbgIsValidStopLine( void *handle, const char *szModule,
                                     int nLine );
         void hb_dbgSetToCursor( void *handle, const char *szModule,
                                 int nLine );
         void hb_dbgSetWatch( void *handle, int nWatch,
                              const char *szExpr, BOOL bTrace );
         const char * hb_setGetCPtr( HB_set_enum set_specifier );
         const char * hb_setGetAltFile( void );
         const char * hb_setGetDateFormat( void );
         const char * hb_setGetTimeFormat( void );
         const char * hb_setGetDefault( void );
         const char * hb_setGetDelimChars( void );
         const char * hb_setGetDevice( void );
         const char * hb_setGetExtraFile( void );
         const char * hb_setGetPath( void );
         const char * hb_setGetMFileExt( void );
         const char * hb_setGetPrintFile( void );
         const char * hb_setGetEOL( void );
         const char * hb_setGetHBOUTLOG( void );
         const char * hb_setGetHBOUTLOGINFO( void );
         const char * hb_setGetOSCODEPAGE( void );
         void hb_compInitPP( HB_COMP_DECL, int argc,
                             const char * const argv[] );
         void hb_compGenPCodeN( const BYTE * pBuffer, ULONG ulSize,
                                HB_COMP_DECL );
         int  hb_compMain( int argc, const char * const argv[],
                           BYTE ** pBufPtr, ULONG * pulSize,
                           const char * szSource );
         void hb_compChkCompilerSwitch( HB_COMP_DECL, int,
                                        const char * const args[] );
         void hb_compChkDefines( HB_COMP_DECL, int iArg,
                                 const char * const args[] );
         void hb_compGenCString( FILE * yyc, const BYTE * pText, ULONG ulLen );
         AREAP hb_rddRequestArea( const char * szAlias, PHB_ITEM pCargo,
                                  BOOL fNewArea, BOOL fWait );
         char * hb_stackDirBuffer( void );
         LONG hb_sxPtoD( const char * pDate );
         const char * hb_langID( void );
         const char * hb_langSelectID( const char * pszID );
         const char * hb_langDGetItem( int iIndex );
         const char * hb_langDGetErrorDesc( ULONG ulIndex );
         BOOL       hb_fsChDir( const char * pszDirName );
         HB_FHANDLE hb_fsCreate( const char * pszFileName, ULONG ulAttr );
         HB_FHANDLE hb_fsCreateEx( const char * pszFilename, ULONG ulAttr,
                                   USHORT uiFlags );
         HB_FHANDLE hb_fsCreateTemp( const char * pszDir,
                                     const char * pszPrefix,
                                     ULONG ulAttr, char * pszName );
         HB_FHANDLE hb_fsCreateTempEx( char * pszName, const char * pszDir,
                                       const char * pszPrefix,
                                       const char * pszExt, ULONG ulAttr );
         const char * hb_fsCurDir( USHORT uiDrive );
         USHORT     hb_fsCurDirBuff( USHORT uiDrive, char * pbyBuffer,
                                     ULONG ulLen );
         void       hb_fsBaseDirBuff( char * pbyBuffer );
         BOOL       hb_fsDelete( const char * pszFileName );
         BOOL       hb_fsFile( const char * pszFileName );
         BOOL       hb_fsIsDirectory( const char * pszFilename );
         HB_FOFFSET hb_fsFSize( const char * pszFileName, BOOL bUseDirEntry );
         HB_FHANDLE hb_fsExtOpen( const char * pszFileName,
                                  const char * pDefExt,
         char *     hb_fsExtName( const char * pFilename,
                                  const char * pDefExt, USHORT uiExFlags,
                                  const char * pPaths );
         BOOL       hb_fsMkDir( const char * pszDirName );
         HB_FHANDLE hb_fsOpen( const char * pszFileName, USHORT uiFlags );
         BOOL       hb_fsRmDir( const char * pszDirName );
         BOOL       hb_fsRename( const char * pszOldName,
                                 const char * pszNewName );
         BOOL       hb_fsGetFileTime( const char * pszFileName,
                                      LONG * plJulian, LONG * plMillisec );
         BOOL       hb_fsSetFileTime( const char * pszFileName,
                                      LONG lJulian, LONG lMillisec );
         BOOL       hb_fsGetAttr( const char * pszFileName, ULONG * pulAttr );
         BOOL       hb_fsSetAttr( const char * pszFileName, ULONG ulAttr );
         HB_FHANDLE hb_fsPOpen( const char * pFilename, const char * pMode );
         BOOL       hb_fsCopy( const char * pSource, const char * pDest );
         BOOL       hb_spFile( const char * pFilename, char * pRetPath );
         BOOL       hb_spFileExists( const char * pFilename, char * pRetPath );
         HB_FHANDLE hb_spOpen( const char * pFilename, USHORT uiFlags );
         HB_FHANDLE hb_spCreate( const char * pFilename, ULONG ulAttr );
         HB_FHANDLE hb_spCreateEx( const char * pFilename,
                                   ULONG ulAttr, USHORT uiFlags );
         PHB_FILE   hb_fileExtOpen( const char * pFilename,
                                    const char * pDefExt, USHORT uiExFlags,
                                    const char * pPaths, PHB_ITEM pError );
         PHB_FILE   hb_fileCreateTemp( const char * pszDir,
                                       const char * pszPrefix,
                                       ULONG ulAttr, char * pszName );
         PHB_FILE   hb_fileCreateTempEx( char * pszName, const char * pszDir,
                                         const char * pszPrefix,
                                         const char * pszExt, ULONG ulAttr );
         HB_ERRCODE hb_gtBox( SHORT uiTop, SHORT uiLeft, SHORT uiBottom,
                              SHORT uiRight, const BYTE * pbyFrame );
         HB_ERRCODE hb_gtDrawBox( SHORT uiTop, SHORT uiLeft, SHORT uiBottom,
                                  SHORT uiRight, const BYTE * pbyFrame,
                                  int iColor );
         HB_ERRCODE hb_gtWrite( const BYTE * pbyStr, ULONG ulLen );
         HB_ERRCODE hb_gtWriteAt( USHORT uiRow, USHORT uiCol,
                                  const BYTE * pbyStr, ULONG ulLen );
         HB_ERRCODE hb_gtWriteCon( const BYTE * pbyStr, ULONG ulLen );
         HB_ERRCODE hb_gtPutText( USHORT uiRow, USHORT uiCol,
                                  const BYTE * pStr, ULONG ulLength,
                                  int iColor );
         HB_ERRCODE hb_gtOutStd( const BYTE * pbyStr, ULONG ulLen );
         HB_ERRCODE hb_gtOutErr( const BYTE * pbyStr, ULONG ulLen );
         HB_ERRCODE hb_gtBoxEx( int iTop, int iLeft, int iBottom, int iRight,
                                const BYTE * pbyFrame, int iColor );
         void       hb_mouseRestoreState( const BYTE * pBuffer );
         const char * hb_strLTrim( const char * szText, ULONG * ulLen );
         const char * hb_conNewLine( void );
         const char * hb_conSetColor( const char * szColor );
         const char * hb_errGetDescription( PHB_ITEM pError );
         const char * hb_errGetFileName( PHB_ITEM pError );
         const char * hb_errGetOperation( PHB_ITEM pError );
         const char * hb_errGetSubSystem( PHB_ITEM pError );
         int hb_ctwAddWindowBox( int iWindow, const BYTE * szBox, int iColor );
         const char *ct_at_exact_forward
                              ( const char *pcString, size_t sStrLen,
                                const char *pcMatch, size_t sMatchLen,
                                size_t *psMatchStrLen );
         const char *ct_at_exact_backward
                              ( const char *pcString, size_t sStrLen,
                                const char *pcMatch, size_t sMatchLen,
                                size_t *psMatchStrLen );
         const char *ct_at_wildcard_forward
                              ( const char *pcString, size_t sStrLen,
                                const char *pcMatch, size_t sMatchLen,
                                char cWildCard, size_t *psMatchStrLen );
         const char *ct_at_wildcard_backward
                              ( const char *pcString, size_t sStrLen,
                                const char *pcMatch, size_t sMatchLen,
                                char cWildCard, size_t *psMatchStrLen );
         const char *ct_at_charset_forward
                              ( const char *pcString, size_t sStrLen,
                                const char *pcCharSet, size_t sCharSetLen,
                                size_t *psMatchedCharPos );
         const char *ct_at_charset_backward
                              ( const char *pcString, size_t sStrLen,
                                const char *pcCharSet, size_t sCharSetLen,
                                size_t *psMatchedCharPos );
         char * hb_adsOemToAnsi( const char * pcString, ULONG ulLen );
         char * hb_adsAnsiToOem( const char * pcString, ULONG ulLen );
         struct hb_BTree * hb_BTreeNew( const char *FileName,
                                        USHORT usPageSize, USHORT usKeySize,
                                        ULONG ulFlags, USHORT usBuffers );
         struct hb_BTree * hb_BTreeOpen( const char *FileName, ULONG lFlags,
                                         USHORT usBuffers );
         BOOL hb_BTreeInsert( struct hb_BTree * pBTree, const char * szKey,
                              PHB_ITEM pData );
         BOOL hb_BTreeDelete( struct hb_BTree * pBTree, const char * szKey,
                              LONG lData );
         BOOL hb_BTreeSeek( struct hb_BTree * pBTree, const char * szKey,
                            LONG lData, BOOL bSoftSeek );
         const char * hb_BTreeKey( struct hb_BTree * pBTree );

    * modified RDD methods:
         HB_ERRCODE PUTVALUEFILE( AREAP, USHORT, const char *, USHORT );
         HB_ERRCODE GETVALUEFILE( AREAP, USHORT, const char *, USHORT );
    * modified GT methods:
         void REST( HB_GT_PTR, int, int, int, int, const BYTE * );
         void PUTTEXT( HB_GT_PTR, int, int, BYTE, const BYTE *, ULONG );
         void WRITEAT( HB_GT_PTR, int, int, const BYTE *, ULONG );
         void WRITE( HB_GT_PTR, const BYTE *, ULONG );
         void WRITECON( HB_GT_PTR, const BYTE *, ULONG );
         void BOX( HB_GT_PTR, int, int, int, int, const BYTE *, BYTE );
         void BOXD( HB_GT_PTR, int, int, int, int, const BYTE *, BYTE );
         void BOXS( HB_GT_PTR, int, int, int, int, const BYTE *, BYTE );
         void OUTSTD( HB_GT_PTR, BYTE *, ULONG );
         void OUTERR( HB_GT_PTR, BYTE *, ULONG );
         void MOUSERESTORESTATE( HB_GT_PTR, const BYTE * );
    * modified RDD structers:
         DBFIELDINFO, DBOPENINFO, DBORDERCONDINFO, DBCONSTRAINTINFO,
         DBORDERCREATEINFO
    + modified parameters and behevior:
         const char * hb_fsNameConv( const char * szFileName, char ** pszFree );
         const char * hb_osEncode( const char * szFileName, char ** pszFree );
         const char * hb_osDecode( const char * szFileName, char ** pszFree );
      Please look at implementation and current usage of these functions.
    + added new function:
         BOOL hb_itemGetWriteCL( PHB_ITEM pItem,
                                 char ** pszValue, ULONG * pulLen );
      which converts item string buffer to writable state to use with
      functions like FREAD() instead of hb_itemUnShare*()
    * updatd other code to respect above modifications
    ! fixed bugs (also GPF traps) located by above modifications

   TODO: please make build tests. Especially in OS2 - not tested at all.
2009-06-26 00:33:38 +00:00

750 lines
22 KiB
C

/*
* $Id$
*/
/*
* Harbour Project source code:
* Math functions
*
* Copyright 1999 Matthew Hamilton <mhamilton@bunge.com.au>
*
* Functions for user defined math error handlers, changes and fixes
* Copyright 2001/2002 IntTec GmbH, Freiburg, Germany,
* Author: Martin Vogel <vogel@inttec.de>
*
* www - http://www.harbour-project.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* 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. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/).
*
* As a special exception, the Harbour Project gives permission for
* additional uses of the text contained in its release of Harbour.
*
* The exception is that, if you link the Harbour libraries with other
* files to produce an executable, this does not by itself cause the
* resulting executable to be covered by the GNU General Public License.
* Your use of that executable is in no way restricted on account of
* linking the Harbour library code into it.
*
* This exception does not however invalidate any other reasons why
* the executable file might be covered by the GNU General Public License.
*
* This exception applies only to the code released by the Harbour
* Project under the name Harbour. If you copy code from other
* Harbour Project or Free Software Foundation releases into a copy of
* Harbour, as the General Public License permits, the exception does
* not apply to the code that you add in this way. To avoid misleading
* anyone as to the status of such modified files, you must delete
* this exception notice from them.
*
* If you write modifications of your own for Harbour, it is your choice
* whether to permit this exception to apply to your modifications.
* If you do not wish that, delete this exception notice.
*
*/
#if defined(__DJGPP__)
# include <libm/math.h>
_LIB_VERSION_TYPE _LIB_VERSION = _XOPEN_;
#else
# include <math.h>
#endif
#include "hbapi.h"
#include "hbapiitm.h"
#include "hbapierr.h"
#include "hbvm.h"
#include "hbstack.h"
#include "hbmath.h"
#if defined(HB_MATH_ERRNO)
# include <errno.h>
#endif
#if defined(HB_OS_SUNOS)
# include <ieeefp.h>
#endif
typedef struct
{
int mode;
PHB_ITEM block;
HB_MATH_HANDLERPROC handler;
HB_MATH_HANDLERPROC prevHandler;
#if defined(HB_MATH_HANDLER)
HB_MATH_EXCEPTION exception;
#endif
} HB_MATHERRDATA, * PHB_MATHERRDATA;
/* Harbour default math error handling routine */
static int hb_matherr( HB_MATH_EXCEPTION * pexc )
{
int mode = hb_mathGetErrMode();
int iRet = 1;
HB_TRACE( HB_TR_DEBUG, ( "hb_matherr(%p)", pexc ) );
if( pexc == NULL || pexc->handled != 0 )
{
/* error already handled by other handlers ! */
return 1;
}
if( mode == HB_MATH_ERRMODE_USER || mode == HB_MATH_ERRMODE_USERDEFAULT ||
mode == HB_MATH_ERRMODE_USERCDEFAULT )
{
PHB_ITEM pArg1, pArg2, pError;
PHB_ITEM pMatherrResult;
/* create an error object */
/* NOTE: In case of HB_MATH_ERRMODE_USER[C]DEFAULT, I am setting both EF_CANSUBSTITUTE and EF_CANDEFAULT to .T. here.
This is forbidden according to the original Cl*pper docs, but I think this reflects the situation best here:
The error handler can either substitute the errorneous value (by returning a numeric value) or choose the
default error handling (by returning .F., as usual) [martin vogel] */
pError = hb_errRT_New_Subst( ES_ERROR, "MATH", EG_NUMERR, pexc->type,
pexc->error, pexc->funcname, 0, EF_CANSUBSTITUTE |
( mode == HB_MATH_ERRMODE_USER ? 0 : EF_CANDEFAULT ) );
/* Assign the new array to the object data item. */
/* NOTE: Unfortunately, we cannot decide whether one or two parameters have been used when the
math function has been called, so we always take two */
pArg1 = hb_itemPutND( NULL, pexc->arg1 );
pArg2 = hb_itemPutND( NULL, pexc->arg2 );
hb_errPutArgs( pError, 2, pArg1, pArg2 );
hb_itemRelease( pArg1 );
hb_itemRelease( pArg2 );
/* launch error codeblock */
pMatherrResult = hb_errLaunchSubst( pError );
hb_errRelease( pError );
if( pMatherrResult )
{
if( HB_IS_NUMERIC( pMatherrResult ) )
{
pexc->retval = hb_itemGetND( pMatherrResult );
hb_itemGetNLen( pMatherrResult, &pexc->retvalwidth, &pexc->retvaldec );
pexc->handled = 1;
}
hb_itemRelease( pMatherrResult );
}
}
/* math exception not handled by Harbour error routine above ? */
if( pexc->handled == 0 )
{
switch( mode )
{
case HB_MATH_ERRMODE_USER:
/* user failed to handle the math exception, so quit the app [yes, that's the meaning of this mode !!] */
iRet = 0;
hb_vmRequestQuit();
break;
case HB_MATH_ERRMODE_DEFAULT:
case HB_MATH_ERRMODE_USERDEFAULT:
/* return 1 to suppress C RTL error msgs, but leave error handling to the calling Harbour routine */
break;
case HB_MATH_ERRMODE_CDEFAULT:
case HB_MATH_ERRMODE_USERCDEFAULT:
/* use the correction value supplied in pexc->retval */
pexc->handled = 1;
break;
}
}
return iRet; /* error handling successful */
}
static void hb_mathErrDataInit( void * Cargo )
{
PHB_MATHERRDATA pMathErr = ( PHB_MATHERRDATA ) Cargo;
pMathErr->mode = HB_MATH_ERRMODE_DEFAULT;
pMathErr->handler = hb_matherr;
#if defined(HB_MATH_HANDLER)
pMathErr->exception.type = HB_MATH_ERR_NONE;
pMathErr->exception.funcname = "";
pMathErr->exception.error = "";
pMathErr->exception.arg1 = 0.0;
pMathErr->exception.arg2 = 0.0;
pMathErr->exception.retval = 0.0;
pMathErr->exception.retvalwidth = -1; /* we don't know */
pMathErr->exception.retvaldec = -1; /* use standard SET DECIMALS */
pMathErr->exception.handled = 1;
#endif
}
static void hb_mathErrDataRelease( void * Cargo )
{
PHB_MATHERRDATA pMathErr = ( PHB_MATHERRDATA ) Cargo;
hb_itemRelease( pMathErr->block );
}
static HB_TSD_NEW( s_mathErrData, sizeof( HB_MATHERRDATA ),
hb_mathErrDataInit, hb_mathErrDataRelease );
#define hb_mathErrData() ( ( PHB_MATHERRDATA ) hb_stackGetTSD( &s_mathErrData ) )
/*
* ************************************************************
* Harbour Math functions Part I:
* handling math errors, C math lib redirection
* ************************************************************
*/
/* reset math error information */
void hb_mathResetError( HB_MATH_EXCEPTION * phb_exc )
{
HB_TRACE( HB_TR_DEBUG, ( "hb_mathResetError(%p)", phb_exc ) );
HB_SYMBOL_UNUSED( phb_exc );
#if defined(HB_MATH_HANDLER)
{
PHB_MATHERRDATA pMathErr = hb_mathErrData();
pMathErr->exception.type = HB_MATH_ERR_NONE;
pMathErr->exception.funcname = "";
pMathErr->exception.error = "";
pMathErr->exception.arg1 = 0.0;
pMathErr->exception.arg2 = 0.0;
pMathErr->exception.retval = 0.0;
pMathErr->exception.retvalwidth = -1; /* we don't know */
pMathErr->exception.retvaldec = -1; /* use standard SET DECIMALS */
pMathErr->exception.handled = 1;
}
#elif defined(HB_MATH_ERRNO)
errno = 0;
#endif
}
/* route C math lib errors to Harbour error handling */
#if defined(HB_MATH_HANDLER)
int matherr( struct exception *err )
{
int retval;
HB_MATH_HANDLERPROC mathHandler;
HB_MATH_EXCEPTION * pExc;
HB_TRACE( HB_TR_DEBUG, ( "matherr(%p)", err ) );
pExc = &hb_mathErrData()->exception;
/* map math error types */
switch( err->type )
{
case DOMAIN:
pExc->type = HB_MATH_ERR_DOMAIN;
pExc->error = "Argument not in domain of function";
break;
case SING:
pExc->type = HB_MATH_ERR_SING;
pExc->error = "Calculation results in singularity";
break;
case OVERFLOW:
pExc->type = HB_MATH_ERR_OVERFLOW;
pExc->error = "Calculation result too large to represent";
break;
case UNDERFLOW:
pExc->type = HB_MATH_ERR_UNDERFLOW;
pExc->error = "Calculation result too small to represent";
break;
case TLOSS:
pExc->type = HB_MATH_ERR_TLOSS;
pExc->error = "Total loss of significant digits";
break;
case PLOSS:
pExc->type = HB_MATH_ERR_PLOSS;
pExc->error = "Partial loss of significant digits";
break;
default:
pExc->type = HB_MATH_ERR_UNKNOWN;
pExc->error = "Unknown math error";
break;
}
pExc->funcname = err->name;
pExc->arg1 = err->arg1;
pExc->arg2 = err->arg2;
pExc->retval = err->retval;
pExc->handled = 0;
mathHandler = hb_mathGetHandler();
if( mathHandler )
{
retval = ( *( mathHandler ) ) ( pExc );
err->retval = pExc->retval;
}
else
{
/* there is no custom math handler */
retval = 1; /* don't print any message, don't set errno and use return value provided by C RTL */
}
return retval;
}
#endif
BOOL hb_mathGetError( HB_MATH_EXCEPTION * phb_exc, const char *szFunc,
double arg1, double arg2, double dResult )
{
#if defined(HB_MATH_ERRNO)
int errCode;
HB_TRACE( HB_TR_DEBUG, ( "hb_mathGetError(%p,%s,%lf,%lf,%lf)", phb_exc, szFunc, arg1, arg2, dResult ) );
switch( errno )
{
case 0:
return FALSE;
case EDOM:
case ERANGE:
# if defined(EOVERFLOW)
case EOVERFLOW:
# endif
errCode = errno;
break;
default:
if( isnan( dResult ) )
errCode = EDOM;
# if defined(HB_OS_SUNOS)
else if( !finite( dResult ) )
# elif defined(HB_OS_OS2)
else if( !isfinite( dResult ) )
# else
else if( isinf( dResult ) )
# endif
errCode = ERANGE;
else
errCode = errno;
}
/* map math error types */
switch( errCode )
{
case EDOM:
phb_exc->type = HB_MATH_ERR_DOMAIN;
phb_exc->error = "Argument not in domain of function";
break;
case ERANGE:
phb_exc->type = HB_MATH_ERR_SING;
phb_exc->error = "Calculation results in singularity";
break;
# if defined(EOVERFLOW)
case EOVERFLOW:
phb_exc->type = HB_MATH_ERR_OVERFLOW;
phb_exc->error = "Calculation result too large to represent";
break;
# endif
default:
phb_exc->type = HB_MATH_ERR_UNKNOWN;
phb_exc->error = "Unknown math error";
break;
}
phb_exc->funcname = szFunc;
phb_exc->arg1 = arg1;
phb_exc->arg2 = arg2;
phb_exc->retval = dResult;
phb_exc->handled = 0;
phb_exc->retvalwidth = -1; /* we don't know */
phb_exc->retvaldec = -1; /* use standard SET DECIMALS */
{
HB_MATH_HANDLERPROC mathHandler = hb_mathGetHandler();
if( mathHandler )
( *mathHandler )( phb_exc );
}
return TRUE;
#else
HB_TRACE( HB_TR_DEBUG, ( "hb_mathGetError(%p,%s,%lf,%lf,%lf)", phb_exc, szFunc, arg1, arg2, dResult ) );
HB_SYMBOL_UNUSED( dResult );
HB_SYMBOL_UNUSED( arg1 );
HB_SYMBOL_UNUSED( arg2 );
HB_SYMBOL_UNUSED( szFunc );
# if defined(HB_MATH_HANDLER)
memcpy( phb_exc, &hb_mathErrData()->exception, sizeof( HB_MATH_EXCEPTION ) );
return phb_exc->type != HB_MATH_ERR_NONE;
# else
HB_SYMBOL_UNUSED( phb_exc );
return FALSE;
# endif
#endif
}
/*
* ************************************************************
* Harbour Math functions Part II:
* handling math errors, Harbour default handling routine
* ************************************************************
*/
/* set error handling mode of hb_matherr() */
int hb_mathSetErrMode( int imode )
{
PHB_MATHERRDATA pMathErr;
int oldmode;
HB_TRACE( HB_TR_DEBUG, ( "hb_mathSetErrMode (%i)", imode ) );
pMathErr = hb_mathErrData();
oldmode = pMathErr->mode;
if( imode == HB_MATH_ERRMODE_DEFAULT ||
imode == HB_MATH_ERRMODE_CDEFAULT ||
imode == HB_MATH_ERRMODE_USER ||
imode == HB_MATH_ERRMODE_USERDEFAULT ||
imode == HB_MATH_ERRMODE_USERCDEFAULT )
{
pMathErr->mode = imode;
}
return oldmode;
}
/* get error handling mode of hb_matherr() */
int hb_mathGetErrMode( void )
{
HB_TRACE( HB_TR_DEBUG, ( "hb_mathGetErrMode()" ) );
return hb_mathErrData()->mode;
}
/* Harbour equivalent to mathSet/GetErrMode */
HB_FUNC( HB_MATHERMODE ) /* ([<nNewMode>]) -> <nOldMode> */
{
hb_retni( hb_mathGetErrMode() );
/* set new mode */
if( HB_ISNUM( 1 ) )
hb_mathSetErrMode( hb_parni( 1 ) );
}
/*
* ************************************************************
* Harbour Math functions Part III:
* (de)installing and (de)activating custom math error handlers
* ************************************************************
*/
/* install a harbour-like math error handler (that will be called by the matherr() function), return old handler */
HB_MATH_HANDLERPROC hb_mathSetHandler( HB_MATH_HANDLERPROC handlerproc )
{
HB_MATH_HANDLERPROC oldHandlerProc;
PHB_MATHERRDATA pMathErr;
HB_TRACE( HB_TR_DEBUG, ( "hb_mathSetHandler (%p)", handlerproc ) );
pMathErr = hb_mathErrData();
oldHandlerProc = pMathErr->handler;
pMathErr->handler = handlerproc;
return oldHandlerProc;
}
/* get current harbour-like math error handler */
HB_MATH_HANDLERPROC hb_mathGetHandler( void )
{
HB_TRACE( HB_TR_DEBUG, ( "hb_mathGetHandler ()" ) );
return hb_mathErrData()->handler;
}
/*
* ************************************************************
* Harbour Math functions Part IV:
* example of hb_mathSet/GetHandler: add a new math handler that
* calls a given codeblock for every math error
* ************************************************************
*/
static int hb_matherrblock( HB_MATH_EXCEPTION * pexc )
{
PHB_MATHERRDATA pMathErr = hb_mathErrData();
int retval;
/* call codeblock for both case: handled and unhandled exceptions */
if( pMathErr->block )
{
PHB_ITEM pArray, pRet;
PHB_ITEM pType, pFuncname, pError, pArg1, pArg2, pRetval, pHandled;
pType = hb_itemPutNI( NULL, pexc->type );
pFuncname = hb_itemPutC( NULL, pexc->funcname );
pError = hb_itemPutC( NULL, pexc->error );
pArg1 = hb_itemPutND( NULL, pexc->arg1 );
pArg2 = hb_itemPutND( NULL, pexc->arg2 );
pRetval = hb_itemPutNDLen( NULL, pexc->retval, pexc->retvalwidth, pexc->retvaldec );
pHandled = hb_itemPutL( NULL, pexc->handled );
pArray = hb_itemArrayNew( 2 );
hb_itemArrayPut( pArray, 1, pRetval );
hb_itemArrayPut( pArray, 2, pHandled );
/* launch error codeblock that can
a) change the members of the array = {dRetval, lHandled} to set the return value of the math C RTL routine and
the <exception handled flag> and it
b) can return an integer value to set the return value of matherr().
NOTE that these values are only used if lHandled was .F. and is set to .T. within the codeblock */
pRet = hb_itemDo( pMathErr->block, 6, pType, pFuncname, pError, pArg1, pArg2, pArray );
hb_itemRelease( pType );
hb_itemRelease( pFuncname );
hb_itemRelease( pError );
hb_itemRelease( pArg1 );
hb_itemRelease( pArg2 );
hb_itemRelease( pRetval );
hb_itemRelease( pHandled );
if( pexc->handled )
{
/* math exception has already been handled, so codeblock call above was only informative */
retval = 1;
}
else
{
/* exception handled by codeblock ? */
pHandled = hb_itemArrayGet( pArray, 2 );
if( pHandled )
{
pexc->handled = hb_itemGetL( pHandled );
hb_itemRelease( pHandled );
}
if( pexc->handled )
{
/* YES ! */
/* extract retval for math routine and matherr() */
pRetval = hb_itemArrayGet( pArray, 1 );
if( pRetval )
{
pexc->retval = hb_itemGetND( pRetval );
hb_itemGetNLen( pRetval, &pexc->retvalwidth, &pexc->retvaldec );
hb_itemRelease( pRetval );
}
if( pRet && HB_IS_NUMERIC( pRet ) )
{
retval = hb_itemGetNI( pRet ); /* block may also return 0 to force C math lib warnings */
hb_itemRelease( pRet );
}
else
{
retval = 1; /* default return value to suppress C math lib warnings */
}
}
else
{
/* NO ! */
retval = 1;
}
}
hb_itemRelease( pArray );
}
else
{
retval = 1; /* default return value to suppress C math lib warnings */
}
if( pMathErr->prevHandler )
{
if( pexc->handled )
{
/* the error is handled, so simply inform the previous handler */
( *pMathErr->prevHandler ) ( pexc );
}
else
{
/* else go on error handling within previous handler */
retval = ( *pMathErr->prevHandler ) ( pexc );
}
}
return retval;
}
/* set/get math error block */
HB_FUNC( HB_MATHERBLOCK ) /* ([<nNewErrorBlock>]) -> <nOldErrorBlock> */
{
PHB_MATHERRDATA pMathErr = hb_mathErrData();
/* immediately install hb_matherrblock and keep it permanently installed !
This is not dangerous because hb_matherrorblock will always call the previous error handler */
if( pMathErr->prevHandler == NULL )
{
pMathErr->prevHandler = hb_mathSetHandler( hb_matherrblock );
}
/* return old math handler */
if( pMathErr->block == NULL )
{
hb_ret();
}
else
{
hb_itemReturn( pMathErr->block );
}
if( hb_pcount() > 0 )
{
/* set new error block */
PHB_ITEM pNewErrorBlock = hb_param( 1, HB_IT_BLOCK );
if( pNewErrorBlock )
{
if( pMathErr->block == NULL )
{
pMathErr->block = hb_itemNew( NULL );
}
hb_itemCopy( pMathErr->block, pNewErrorBlock );
}
else
{
/* a parameter other than a block has been passed -> delete error handler ! */
if( pMathErr->block )
{
hb_itemRelease( pMathErr->block );
pMathErr->block = NULL;
}
}
}
}
/*
* ************************************************************
* Harbour Math functions Part V:
* EXP(), LOG(), SQRT()
* ************************************************************
*/
HB_FUNC( EXP )
{
if( HB_ISNUM( 1 ) )
{
HB_MATH_EXCEPTION hb_exc;
double dResult, dArg = hb_parnd( 1 );
hb_mathResetError( &hb_exc );
dResult = exp( dArg );
if( hb_mathGetError( &hb_exc, "EXP", dArg, 0.0, dResult ) )
{
if( hb_exc.handled )
hb_retndlen( hb_exc.retval, hb_exc.retvalwidth, hb_exc.retvaldec );
else
{
/* math exception is up to the Harbour function, so do this as Clipper compatible as possible */
if( hb_exc.type == HB_MATH_ERR_OVERFLOW )
hb_retndlen( HUGE_VAL, -1, -1 );
else
hb_retnd( 0.0 );
}
}
else
hb_retnd( dResult );
}
else
hb_errRT_BASE_SubstR( EG_ARG, 1096, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
}
HB_FUNC( LOG )
{
if( HB_ISNUM( 1 ) )
{
HB_MATH_EXCEPTION hb_exc;
double dResult, dArg = hb_parnd( 1 );
if( dArg <= 0 )
hb_retndlen( -HUGE_VAL, -1, -1 ); /* return -infinity */
else
{
hb_mathResetError( &hb_exc );
dResult = log( dArg );
if( hb_mathGetError( &hb_exc, "LOG", dArg, 0.0, dResult ) )
{
if( hb_exc.handled )
hb_retndlen( hb_exc.retval, hb_exc.retvalwidth, hb_exc.retvaldec );
else
{
/* math exception is up to the Harbour function, so do this as Clipper compatible as possible */
switch( hb_exc.type )
{
case HB_MATH_ERR_SING: /* argument to log was 0.0 */
case HB_MATH_ERR_DOMAIN: /* argument to log was < 0.0 */
hb_retndlen( -HUGE_VAL, -1, -1 ); /* return -infinity */
break;
default:
hb_retnd( 0.0 );
break;
}
}
}
else
hb_retnd( dResult );
}
}
else
hb_errRT_BASE_SubstR( EG_ARG, 1095, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
}
HB_FUNC( SQRT )
{
if( HB_ISNUM( 1 ) )
{
HB_MATH_EXCEPTION hb_exc;
double dResult, dArg = hb_parnd( 1 );
if( dArg <= 0 )
hb_retnd( 0.0 );
else
{
hb_mathResetError( &hb_exc );
dResult = sqrt( dArg );
if( hb_mathGetError( &hb_exc, "SQRT", dArg, 0.0, dResult ) )
{
if( hb_exc.handled )
hb_retndlen( hb_exc.retval, hb_exc.retvalwidth, hb_exc.retvaldec );
else
/* math exception is up to the Harbour function, so do this as Clipper compatible as possible */
hb_retnd( 0.0 ); /* return 0.0 on all errors (all (?) of type DOMAIN) */
}
else
hb_retnd( dResult );
}
}
else
hb_errRT_BASE_SubstR( EG_ARG, 1097, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
}