Numeric Functions
Updated: Jan 24, 2007

Return numeric result r based on applicable numeric or string arguments.
Arguments are described as "string", "number" (any type), "integer" 
(INTEGER, LONG, DWORD) and "immediate" number like "0" or "1".

Please refer to the FPU object for other numerical methods.

Function  Arguments, Comments, Examples
~~~~~~~~  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~     
@, VARPTR Returns DWORD address of argument

  Addr = @MySUB: Addr = @MySTRING: Addr = @MyMEMORY
  Addr = VARPTR(MySUB): Addr = VARPTR(MySTRING): Addr = VARPTR(MyMEMORY)
  Used for certain arguments in API calls or in MEMCPY, MEMCMP, etc.

  For Arrays, omit subscripts and note: A.Pointer = @A
  If you need the address of an element in the array, several methods work,

  Addr = @A + offset 'you compute your offset, or try

  x=A(i,j,k): Addr = @A + A.Position - SIZEOF(A)

  For UDT's, you can use @MyType.MemberItem syntax

ABS       Absolute value, r = ABS(number)

ACOS      Arc cosine, r = ACOS(number)

ARRAYREF +
          Reads numeric array value based on a pointer to the array object
          and the element subscripts.

  r = ARRAYREF(lpArrayObject, subscripts)

  where lpArrayObject is obtained with the OBJPTR() Numeric Function and
  subscripts is a comma-delimited list of numeric values as might be used in
  reading a conventional array value.

  DIM A(99,99) As LONG
  DEFINT Aptr = OBJPTR(A)
  DEFINT i, j
  'code to set values for i and j  
  r = ARRAYREF(Aptr,i,j)  'same as r = A(i,j)

  Notice you can pass an OBJPTR() value as an argument to a procedure which
  may read/write array values based on a pointer, not the dimensioned name of
  the array.

  Please see the ARRAYREF() statement in Advanced Techniques.

ASC       ASCII value of first character, r = ASC(string)

ASIN      Arc sine, r = ASIN(number)

ATAN, ATN Arc tangent, r = ATAN(number) 'or ATN(number)

ATN       Same as ATAN

BOOLEAN, BOOL +
          Boolean value (1,0) of expression
          r = BOOLEAN(x1 = x2)
          r = BOOLEAN(a$ >= b$)

BYREF +   Gets value at address.  r = BYREF(address)

  Please see the related BYREF statement in Advanced Techniques.

BYTESWAP  Reverses byte order in 32-bit, non-floating values i.
          r = BYTESWAP(i)  'i is variable or expression

  Please see the BYTESWAP statement for more details.

CALLBACK, CODEPTR
          Returns DWORD address of SUB or LABEL (please see GOSUB)

CEIL      Round up to positive infinity; r = CEIL(number)

[Change Sign]
          FPU.load r: FPU.chs: r = FPU.pop; please see NEG().

CINT, CLNG, ROUND
          Convert to integer by round method; r = ROUND(number)

CLNG      Same as CINT

CODEPTR   Same as CALLBACK

COMMANDCOUNT
          Number of command line arguments; r = COMMANDCOUNT

COS       Cosine of number in radians; r = COS(number)

CPUCOUNT  Number of processors on machine; r = CPUCOUNT

  CPUCOUNT is part of HotBasic's Multi-Threading (MT), Multi-CPU support.

CREATETHREAD(lpFunc, lpParam)

  Syntax: ThreadID = CREATETHREAD lpFunc, lpParam
  where lpFunc is CODEPTR(Proc_Name) and lpParam is the address of a
  variable or UDT with the procedure's parameters.

  The prototype for Proc_Name is:

  DECLARE SUB Proc_Name STD (lpDat as LONG)

  On entry, Proc_Name's argument (lpDat above) receives the lpParam value
  from CREATETHREAD.  lpParam can be zero, if Proc_Name requires no parameters.
  Proc_Name's code can access any global variables or arrays in your program.

  For any set of SUBs (threads) that run concurrently, your names for
  "Proc_Name" and "lpDat" should be different for each SUB, as shown in the
  DualCore demo download. 

  CREATETHREAD is part of HotBasic's Multi-Threading (MT), Multi-CPU support.
  The DualCore download shows usage of MT keywords in a working example.

  Similar to single thread programs, MT requires that thread code does not
  interfere with subsequent code.  Mostly this reduces to care in writing
  variables by concurrently running threads (e.g., i = 1), where the value
  will be used later.  Whether single or multiple threads are involved, you
  avoid inserting statements like i = 0, where subsequent code will expect
  that i = 1.

  Fortunately, the OS requires that thread code be packaged in a procedure as
  described above.  Each such procedure (thread) can DIM the scratch variables
  needed; these will all be local and there will be no conflict among threads
  running simultaneously in their time slices and perhaps on different CPUs 
  as well.

  Much literature stresses "how difficult" MT can be.  Basically, you just
  want to avoid doing nutty things in multi-CPU apps, mostly the same crazy
  things you avoid in a single thread app.  In short, if you have supervised
  two or more children at play and they live through it, if you have organized
  a work crew with everybody busy most of the time and not interfering with
  each other, then you can do MT also; similar organization principles apply.

  On a single CPU machine, new threads will compete for CPU time slices with
  the main thread of your program.  MT on single CPU machines lets each 
  thread maintain control, so to speak, until its task is completed.

  On multi-CPU machines (e.g., Dual-Core), the OS will distribute thread
  time slices among the processors, which can result in a dramatic increase
  in computation speed.   CREATETHREAD can launch any number of threads.
  The CPUCOUNT Numeric Function can be used to design maximal usage of all
  available processors by parsing task components among them using MT.

  Please see the WAITTHREAD(ThreadID) Statement and Numeric Function. 
  A key component of MT computing is BEGIN THREAD/END THREAD code blocks.

CSRLIN    Current cursor line; r = CSRLIN: LOCATE CSRLIN,21

DIREXISTS TRUE if DIREXISTS(string)

  IF NOT DIREXISTS(string) THEN MKDIR string

EAX       Same as RETFUNC

EXP       Exponential function; e raised to the power of number;
          r = EXP(number)

FALSE     Same as ZERO

FILEEXISTS TRUE if FILEEXISTS(string)

  DIM F As FILE
  IF FILEEXISTS(string) THEN F.OPEN(string,2) ELSE F.OPEN(string,65535)

FIX, INT  Largest integer less than or equal to number; r = INT(number)

FLOOR     Round down to negative infinity; r = FLOOR(number)

FRAC      Fractional part of number; r = FRAC(number)

GETLASTERROR
          W32 API GetLastError; r = GETLASTERROR

HCOS      Hyperbolic cosine of number in radians; r =HCOS(number)

HEX2DW    Convert hex string; r = HEX2DW("3CFF") or HEX2DW(string)

HIWORD    High word of 32-bit value; r = HIWORD(number)

HSIN      Hyperbolic sine of number in radians; r =HSIN(number)

HTAN      Hyperbolic tangent of number in radians; r =HTAN(number)

IIF +     Evaluated expression and returns either number1 (true) or
          number2 (false).  r = IFF(expression, number1, number2)

  r = IIF(2 > 1, TRUE, FALSE)  'returns TRUE (1)
  r = IIF(a$ > b$, 1, 0)

  Note: There is an IIF$ string function (please see String Functions).

INP       Byte read from I/O port number 0 to 65535; r = INP(integer)

INPW      Word read from I/O port number 0 to 65535; r = INPW(integer)

INSTR     Position of string2 in string1 starting at optional integer
          position; r = INSTR([integer,] string1, string2)

  IF INSTR(name$,letter$) THEN PRINT letter$ + " was found in " + name$   
  Note: string values may be dimensioned As STRING, As LIST or As MEMORY
  
INT       Same as FIX

ISCONSOLE Returns 1 if $AppType = "CONSOLE" else returns 0; r = ISCONSOLE

  IF ISCONSOLE THEN PRINT "Great! GUI stuff won't slow my work."

LBOUND    Lower bound of ARRAY subscript index; r = LBOUND(ARRAY, integer)

  DIM A(10, 20, 10) As LONG: r = LBOUND(A, 2) 'r = 0 for second subscript

LEN       Length of non-unicode text; r = LEN(string)

  IF string.Length <> LEN(string) THEN PRINT "String is binary or unicode?"
 
LN        Natural logarithm; r = LN(number)

LNTWO     Natural log of 2; r = LNTWO

LOG       Logarithm base 10; r = LOG(number)

LOG2E     Logarithm base 2 of e; r = LOG2E

LOG2TEN   Logarithm base 2 of 10; r = LOG2TEN

LOGTWO    Logarithm base 10 of 2; r = LOGTWO

LOWORD    Low word of 32-bit value; r = LOWORD(number)

MEMCMP    Compares nbytes at addr1 and addr2

  r = MEMCMP(addr1, addr2, nbytes) where nbytes, addr1 and addr2 are integers.
  r = 0 if equal, r = 1 if addr1 data > addr2 data and r = -1 if addr1 < addr2

  HotBasic uses MEMCMP in evaluating string comparisons like
  IF j$ >= k$ THEN ...    However, behind the scenes, the compiler provides
  a fourth parameter so MEMCMP has two pointers and two lengths, so "ABCDEF"
  is said to be greater than "ABC" and "AACDEF" is less than "ABC".

  Therefore, if your strings are of different length, use IF ... THEN instead.
  Don't worry, the strings don't have to be text-only data.

  r = MEMCMP(@string1, @string2, string1.Length)  'or string2.Length if lesser.
  r = MEMCMP(@var1, @var2, 8) 'compares 8 bytes of data.  

  Note:
  RapidQ Basic returns 0 for *not* equal;
  HotBasic returns 1 or -1 for *not* equal.

  IF MEMCMP(@var1, @var2, 8) THEN PRINT "var1 is not equal to var2"

MESSAGEBOX Returns user response to message box.

  r = MESSAGEBOX string1, string2, integer

  where string1 is message, string2 is title and integer is messagebox
  style bit mask (0 is just "OK").  A partial listing of mask bits:

  $DEFINE MB_OK 0
  $DEFINE MB_OKCANCEL 1
  $DEFINE MB_ABORTRETRYIGNORE 2
  $DEFINE MB_YESNOCANCEL 3
  $DEFINE MB_YESNO 4
  $DEFINE MB_RETRYCANCEL 5
  $DEFINE MB_ICONHAND &H10
  $DEFINE MB_ICONQUESTION &H20
  $DEFINE MB_ICONEXCLAMATION &H30
  $DEFINE MB_ICONASTERISK &H40
  $DEFINE MB_USERICON &H80

  User response (function success) is coded as a non-zero r:
  1 OK
  2 Cancel
  3 Abort
  4 Retry
  5 Ignore
  6 Yes
  7 No
  8 Close
  9 Help

[NAPIER]  Napier value e from FPU; FPU.napier: r = FPU.pop

NEG, -    Negates value; r = NEG(x)  'same as -(x)

NOT       Boolean NOT; r = not(j)  'r = 0 if j <> 0; r = 1 if j = 0

OBJPTR +  Pointer of array object; r = OBJPTR(a)  'a is dimensioned array

  Please see the ARRAYREF family of keywords for usage example. 

ONE, TRUE One, faster than "1"; r = ONE: r = ONE/x

  TRUE is merely an alias for ONE.  Logical True is not zero and therefore
  is not necessarily = 1.  Therefore, write:
  IF MyValue THEN  'rather than IF MyValue = TRUE THEN

PI        Pi as stored by the FPU; r = PI: r = 2*PI*r^2: r = ONE/PI

POS, POS() Cursor column position; r = POS: LOCATE line,POS

POSTMESSAGE hWnd, uMsg, wParam, lParam; where all arguments are integers.

  Used to send message to hWnd object.  Please see SENDMESSAGE below.
  Sends message and does not wait for the message to be processed.

RESOURCE  Used as argument in EXTRACTRESOURCE; RESOURCE(immediate)

RESOURCECOUNT
          Number of resources in executable; r = RESOURCECOUNT

RETFUNC, EAX
          MyVar = RETFUNC; assigns value of CPU eax register to MyVar.

  Using alias, MyVar = EAX
  Used to get result of a function in an external .obj or .dll module or the OS.
  Normally, one declares the function with LIB and writes:

  MyVar=DeclaredFunction(args,...)

  That is, it works just like the function was in your program.
  An alternative is:

  Call[Func] SomeProcedure[Addr]
  MyVar = RETFUNC   'now we have the result of SomeProcedure

  Also, advanced programmers may want to call a callback procedure they wrote.

RGB       Convert red, green, blue values to RGB value;
          r = RGB(red_integer, green_integer, blue_integer)

  r = RGB(255, 0, 0) 'red with r = &H0000FF
  r = RGB(0, 0, 255) 'blue and r = &HFF0000

RND       Random integer between 0 and integer; r = RND(integer)
          Without argument, random floating value 0 to 1; r = RND    

ROUND     Same as CINT

SCREEN    ASCII value of character; r = SCREEN(row_integer, col_integer)

SGN       Sign; r = SGN(number) '1 positive, 0 zero, -1 negative

SENDMESSAGE hWnd, uMsg, wParam, lParam; where all arguments are integers.

  Used to send message to hWnd object.  Uses SendMessageA w32 function.
  Sends message and waits for the message to be processed.

  r = SendMessage(MyForm, MyMessage, MyParam1, MyParam2)

  Each GUI object has many valid messages which set or get values or
  properties.  This is a "work-horse" function in GUI programming.
  Please see HBguidef.inc in HotInclude and Objects > FORM Objects.

SHELL     r = SHELL cmd$; where r is exit code of cmd$

  If pipe symbols are used in cmd$, then "command.com /c" or "cmd.exe /c" may
  have to be added as a prefix to cmd$.

SIN       Sine of number in radians; r = SIN(number)

SIZEOF    Length in bytes of object
          r = SIZEOF(MyUDT): r = SIZEOF(variable)

  For ARRAYs, returns element size.  MyArray.Length gives total length.
  For strings, MyString.Length gives length even for binary data.

SQR       Square root; r = SQR(number)

TALLY     Count of number of string2 in string1;
          r = TALLY(string1, string2)

  r = TALLY(s$,CRLF) 'r now has line count and if s$ is LIST, r = item count!
  IF TALLY(s$,CHR$(0)) THEN
    PRINT "Hey, what are null chars doing in my string?"
    PRINT "Reply: hmmm, did you get that from a socket?"
  END IF

TAN       Tangent; r = TAN(number) where number is an X/Y value.

TIME      Nano-seconds in epoch since Jan 1, 1970; r = TIME / 10000000 gives
          seconds in epoch.  For r = TIME, r should be an INT64 variable,
          which is equivalent to a Windows FILETIME value.  That is, @r (the
          address of r) is the same as a pointer to a FILETIME value.

TIMER     Returns floating number of seconds since computer booted;
          r = TIMER 

[Toggle 0, 1]
          r = ABS(r - 1)  'or IF r THEN r = 0 ELSE r = 1

TRUE      Same as ONE; use only as alias for ONE, not as logical true.

UBOUND    Upper bound of ARRAY subscript index; r = UBOUND(ARRAY, integer)

  DIM A(10, 20, 10) As LONG: r = UBOUND(A, 2) 'r = 20 for second subscript

VAL       Value of string representation of number; r = VAL(string)

  Note: An invalid string should return a zero result which may be ambiguous.
  Conclusion: User code should check the validity of string data arguments.

VARIANTREF
          Accesses VARIANT data by pointer; r = VARIANTREF(integer)
          where integer is a pointer to a VARIANT.

  VariantRef() reads VARIANT data by reference, useful when functions in other
  modules may provide a result as a pointer to VARIANT.

VARPTR    Same as @

VARTYPE   Type of dimensioned variable; r = VARTYPE(MyVar) where
          r = 0 (non-float number), 1 (floating number), 2 (string), 3 (variant)
  
WAITTHREAD
          Gets thread completion status; r = WAITTHREAD(ThreadID)
          where ThreadID is the result of the CREATETHREAD function.
          The boolean result r is true if the thread is still running.

  WAITTHREAD is part of HotBasic's Multi-Threading (MT), Multi-CPU support.

WINDOW +  Gets FORM object numeric property by object handle.

  r = WINDOW(handle).Left  'get property

  Syntax:  WINDOW(handle[,qualified_type]).property

  The optional qualified_type argument is needed in special cases where the
  compiler needs this information to generate special code in your application.
  If handle alone does not work, add the qualified type.

ZERO
          Zero, faster than "0"; r = ZERO; IF r = ZERO THEN


+ Penthouse (registered) version

Copyright 2003-2006 James J Keene PhD
Original Publication: Oct 8, 2003
