UBBFriend: Email This Page to Someone!
  uCalc Message Forums
  Official Announcements
  Transitioning from UCalc Fast Math Parser 2.0 to the next version

Post New Topic  Post A Reply
profile | register | preferences | faq | search

next newest topic | next oldest topic
Author Topic:   Transitioning from UCalc Fast Math Parser 2.0 to the next version
Daniel Corbier
posted 04-09-2007 04:18 PM     Click Here to See the Profile for Daniel Corbier     Edit/Delete Message Reply w/Quote
A. General comments
B. List of things that have changed
C. Features that are no longer supported
D. Partial list of new features

A. General comments

As work progresses towards the completion of the next version of UCalc Fast Math Parser, it is increasingly important for current version 2.0 users to start planning their migration towards the next version. Eventually, once the next version is released, regular support for 2.0 will likely come to an end, and be replaced with support for the new version.

This month's beta now includes specific support for UCalc Fast Math Parser in a separate download, for those who might not be interested in the advanced Language Builder functionality featured in previous betas this year. An effort was made to preserve compatibility between FMP 2.0 and this beta where possible. In many cases, however, it was not possible. It will be important to browse through the following lists (especially the list of obsolete features), and to also test the beta, in order to identify any changes that might prevent you from being able to do things you were able to do with FMP 2.0.

If you encounter any problem, now is the best time to speak up. Or if everything mostly works just fine, your feedback confirming this is equally requested. Your feedback may help accelerate the release of the next version.

Unfortunately, a help file is not yet available in this beta. However, demos files for VB.NET, VB classic, Delphi, C++ Builder, and PowerBASIC are included. Overall, you will likely understand how the beta works just by browsing through the demo source code.

Download the new UCalc FMP beta from www.ucalc.com/newbetafmp.html .

B. List of things that have changed

Everything mentioned below should be considered tentative, and is subject to further change.

- uCalc Fast Math Parser will likely no longer be the flagship product. The main item would be uCalc Language Builder, and uCalc FMP would simply be one out of many possible components that could be derived from the language builder. uCalc FMP only uses a fraction of the functionality of the language builder.

- By default relational operators (>, <, ==, etc...) return a -1 for True instead of 1.

- Only three exported routines from the DLL are required: 1. uCalc() which encapsulates the entire functionality of uCalc FMP / Language Builder, 2. ucEvaluate(), which can be derived from uCalc() but is exported separately for efficiency, and 3. the ucStrReturn helper function, which simply allows you to retrieve a string value from uCalc() (uCalc() itself can only return a 32-bit number).

In contrast, the DLL in version 2.0 exported dozens of routines. Functions such as ucDefineFunction, ucDefineVariable, etc..., are now merely wrappers that call uCalc(), and these are defined in the include file.

- Implementation across the various compilers is more uniform. Also, the PowerBASIC, Delphi, and C++ demos were updated to make them more user-friendly, just like the VB form-based demo. (A new VB.NET demo was added as well).

- Error Handling is very different.

Unfortunately it is not well documented in this beta yet. You can still check the value of ucError after evaluating an expression, if you want. However, the new and improved way is to define one (or more) error handling callback routine(s), which can handle all errors wherever they may occur. With this, it is no longer necessary to use ucError throughout your code like before.

Also, you have full control of the FPU, which can for instance, decide whether 1 / 0 should raise an error, or be treated as a numeric value of Infinity. The demo shows one of the ways to control the FPU.

Something important to all users, even if you don't care anything about FPU control per se, is that uCalc maintains a separate FPU word from your host program, and both are insulated from each other. The end result is that this resolves a problem that some users encountered, which was caused by their host program changing the FPU setting (without the programmer being aware), and preventing UCalc from working.

- Division-by-0, at least, was handled in version 2.0, even if in a limited way. Overflow, however, wasn't detected at all in 2.0. Now overflow too, and others are handled the same flexible way based on the FPU setting.

- Error numbers returned by ucError, and error messages returned by ucErrorMessage have changed. See the include file for new values and messages.

- ucErrorMessage was renamed to ucGetErrorMessage. The include file for PowerBASIC had a different syntax for ucErrorMessage. It is now uniform with other include files, and there is no separate ucErrMsg function.

- When you re-define a variable, it does not replace or change the old variable definition. Instead the old definition continues to co-exist with the new. The most recent definition will be the only one visible for subsequent use. But if you release the newer definition, the older definition will regain its place as the visible one.

- When you re-define a function, if it has the same arguments as the previous definition, then it behaves the same way as described in the previous paragraph for variables. If the arguments are different, then they operate as overloaded definitions, meaning that the appropriate definition will be used depending on the context. For instance, if you define MyFunc(x), and MyFunc(x, y), then you can use an expression such as "MyFunc(5) + MyFunc(3, 4)"

- ucDefineFunction.

  • The following 2.0 way of using ucDefineFunction is no longer supported:

    ucDefineFunction "FunctionName(ParamCount)", CodeAddress

    Functions defined this way were faster than regular callback definitions. However, you were limited to two arguments; and they could only be numeric. Now, for even better efficiency, use NativeCall. This supports any kind of data type, and any number of arguments. NativeCall allows you to define the fastest kind of callback uCalc knows how to handle, with low overhead. For instance, arithmetic operators, trig functions, etc... are defined this way.

  • The optional second argument for callback address was removed. Now, the optional callback address must instead be converted to a string and concatenated to the first argument. (The optional second argument now is for a thread handle). See the Demo files for the various compilers to see how that works.

  • You can define function arguments using ByRef, and ByVal, or the special ByExpr, and ByHandle directives. Also, you are no longer restricted to a generic numeric or string type. Specific data types are available, such as Single, Long, Double, String, LPCSTR, etc.... If no type is specified, then the default type (which is Extended, but can be set to something else) is used.

  • Variable number of arguments is now denoted with three consecutive dots (...). You can have a fixed number of arguments followed by a variable number of arguments. In 2.0, you didn't have the choice of requiring some arguments if you also had a variable number of args. Also, you now have the option of restricting the data type of the variable number of args.

  • In 2.0 "#", "$", "@", and "&" were used as special argument identifiers in function definitions. Now, more expressive words are used instead, such as "ByExpr", "As String", "As Double" (or any other type). The special "variable" type argument is no longer supported. However, the new ByHandle can often do the same thing.

- Operator definitions.

  • In version 2.0 operators were defined with ucDefineFunction. Now, there is a separate function for defining operators: ucDefineOperator.

  • In 2.0 when you defined an operator, it also defined a function of the same name. It is no longer done that way. When you define an operator, it will only work in the syntax of an operator. You can of course change the syntax of operator definitions to mimic the old way if you need that.

- Alphanumeric names by default can no longer have a period (.) in them. It isn't hard-coded that way, however. You can change what constitutes a valid "alphanumeric" name by doing a search for "alphanumeric" in the include file, and modifying the regular expression pattern you find there.

- ucDefineVariable no longer supports an optional second string parameter. The optional second parameter is now for passing a thread handle.

- In addition to ucDefineFunction, ucDefineVariable, other functions as well, such as ucParse, etc... now have an optional last parameter for passing a thread handle.

- ucReleaseExpr.

  • ucReleaseExpr was removed, and replaced with ucReleaseItem. IMPORTANT: You should not merely replace occurrences of ucReleaseExpr in your code with ucReleaseItem, as they work very differently. The old ucReleaseExpr was capable of releasing expressions only in sequential order. And if you supplied an argument (which was optional), it would release that number of recent expressions.

    With the new ucReleaseItem, you can release individual items in any order. The argument passed to ucReleaseItem is the handle of the specific item you want to release. Anything you can define (expressions, functions, variables, threads, syntaxes, patterns, etc...) is now an item. Each item has a handle, and can be released using this handle.

  • Examples in version 2.0 showed that you could call ucReleaseExpr immediately after ucParse, even before calling ucEvaluate. This was OK in version 2.0, because ucReleaseExpr simply set a marker for the data to be overwritten later. However, now, ucReleaseItem actually releases the item from memory, after which you cannot use the item any more.

  • An item that is incorrectly defined is automatically released, and has a handle of 0. ucReleaseItem(0) simply does nothing. So it is always OK to release an item, without first checking to see if it has a non-0 handle.

  • ucReleaseVariable was also removed and replaced with ucReleaseItem. The help file in version 2.0 mentioned an extra step to take when releasing a string variable. This is no longer necessary.

  • ucReleaseItem as defined in the include file releases an item by handle. To release an item by name, simply use uCalc(uc_ReleaseItem, "MyItem"), where MyItem is the name of your variable, function, or any other named item.

- ucReset was removed and some of its functionality replaced. ucReset was a multipurpose routine. So each aspect will be discussed separately:

  • Releasing everything. Apparently many users used ucReset in this way due to the limitations of ucReleaseExpr. In such cases, you can now use the more flexible ucReleaseItem. However, you still can release everything defined in a given thread (including its sub-threads), by invoking ucReleaseItem with the handle of the thread you want to release. Be careful when releasing the default thread, as you might need to re-define everything as found in the Initialization section of the include file (since there are no "built-in" operators, functions, syntax, or anything).

  • Allocating definition space. This is now irrelevant, as definition space is allocated automatically as you go along. You do not have to allocate a maximum chunk of memory ahead of time and worry about whether you might reach that limit.

  • Setting Relational True. The Language Builder does not have "built-in" relational operators. However, the same library from which FMP's relational operators are defined also has a provision for changing the True value. ucAddr(uc_True) contains the address to a 32-bit value that contains the value of True. The default is now -1 instead of 1.

  • Precedence level. Each operator can now be defined with its own precedence level at the moment it is defined. Still, you can set/retrieve the default level by calling uCalc() with uc_GetDefaultPrecedence or uc_SetDefaultPrecedence if you want. However, explicitly assigning a level in each operator definition is recommend. Even after an operator is defined, you can change its precedence level with the uc_Precedence argument in uCalc(). Precedence levels can be any arbitrary positive integer value (less than 2^31), with its meaning being relative to the values of other operators. In 2.0, you were limited to values between 1 and 22 (which was the level range of hard-coded built-in operators).

    Precedence levels for operators are no longer hard-coded. They are defined in the include files. You can change the levels there, or you can even change them during runtime. In version 2.0, you could only set the precedence levels for user-defined operators, and then it was one level for all user-operators.

  • DecimalSeparator and ArgumentSeparator . Use ucDefineSyntax for this instead.

- ucDefineFunction and ucDefineVariable were preserved for compatibility. However, these are merely wrappers to the more flexible ucDefine function, which in turn places a call to the all-purpose uCalc() function. Advanced users might eventually want to use ucDefine directly for additional functionality.

- Strings are handled very differently.

  • Technically uCalc Language Builder does not have "built-in" support for strings, or any kind of data type for that matter. Instead it allows you to define data types yourself. A library of common types from which to choose from is included, so you don't have to start entirely from scratch. String types chosen in the include file for FMP (you can add or remove as needed), include: Dynamic AnsiString, LPCSTR (null-terminated), and Fixed length strings, [Unicode: Not yet]. The default "String" as defined in the include file is AnsiString.

  • The $ character no longer designates a function or argument as a string during definition. Instead, use "As String" (or As LPCSTR, etc...). If you are using the Language Builder, you can define a syntax that uses the $ in the same way as BASIC, if you prefer. (The usage of $ in version 2.0 was vaguely reminiscent of, but not consistent with the $ string notation of BASIC).

  • ucParamStr, ucGetParamStr, and ucSetParamStr, are no longer relevant in callbacks. You can now define your callbacks the way you normally would define a function in your compiler. The only considerations are that VB uses Unicode strings internally, which can be a problem if you are passing the default uCalc "String" (AnsiString multibyte). In that case, you can pass uCalc string arguments ByExpr, instead of ByRef, and receive a Long (32-bit) in your callback, and use ucEvaluateStr() to retrieve the string. See the Demo files for various compilers to see several ways of passing strings as arguments.

  • The single quote (') and double quote (") delimiters for string literals were hard-coded in version 2.0. Now, this syntax is defined in the include file, and can be changed either there, or during runtime.

  • The & operator is no longer hard-coded as a concatenation symbol, nor is the Concatenate() function, though you are free to define them (there are several ways of doing this).

  • Passing a string argument in place of a numeric expression where a ByExpr (formerly expression type) argument is expected is no longer supported. Instead you can define a ByExpr argument As String, or as any other type, so it would no longer make sense for uCalc to force a string arg to convert into a numeric expression if that's not your intention. You can simulate the old behavior by receiving a string and using ucEvalStr on the argument once inside the callback.

  • When defining a string variable, you must now explicitly use "As String". In version 2.0, the presence of quotes was enough for uCalc to determine that you wanted to define a variable as a string.

- You are no longer restricted to defining your callbacks using a special uCalc kind of template (which consisted of a function with no args, which was required to return a floating point, even if you were dealing with strings). You will need to modify all your callbacks, first so that your code will work, and secondly to take advantage of the simpler way of creating callbacks.

- Some of the contact info found in the help file is outdated. The preferred contact information can be found at www.ucalc.com/contact.html

C. Features that are no longer supported

- Some user-level functions or operators are defined with several alternative names in version 2.0. For instance, both Fact() and ! for factorial. The following alternative names are no longer included: Fact, **, DIV, =<, =>, =, & (for AND), & (for CONCATENATE)|, ATN, LN, SQRT. You can easily re-instate any of these if needed.

- The following functions, operators, or constant(s) aren't present in this beta. They may or may not be included in the final: % (percentage), XOR, EQV, IMP, MIN, MAX, ASIN, ACOS, SEC, CSC, COT, Hyperbolic functions (SINH, COSH, TANH, etc...), EXP2, EXP10, LOG2, LOG10, RND, INT, SGN, CONCATENATE, PI. The programmer can define some of these on his/her own if needed.

- There are in fact no longer any "built-in" functions, operators, or constants at all. Some common items, such as arithmetic, trigonometric, and miscellaneous items are included in a library in the DLL, and are activated in the include file. You can remove, rename, or add items to the list. You can implement new items using the same kind of NativeCall procedure callbacks as the ones in the library, achieving the same maximum speed. (Standard procedures, which are easier to implement, can be defined as well, and are generally sufficiently fast).

- ucAlias was removed. Its functionality can be duplicated (and greatly superceded) with ucDefineSyntax. For the renaming aspect of ucAlias, see the RenameItem function defined in the Library.uc file that comes with the Language Builder (downloadable from www.ucalc.com/newbeta.html ).

- Implicit multiplication notation is no longer supported.
Alternative: Use syntax definitions (ucDefineSyntax). Send feedback if you're stuck.

- Numeric base notations, such as #b101 (binary) or #hAEFF are no longer built-in.
Alternative: Create your own syntax. See the "&b" notation in DemoDefs.Txt.

- ucErrorData, along with ucGetErrorData and ucErrorData were removed. Use ucGetSymbol in place of ucGetErrorData.

- ucReset was removed. See earlier explanation.

- ucTrigMode, ucSetTrigMode, ucGetTrigMode. There is no direct replacement. However, there might be several potential strategies you can try, to mimic this.

- ucIsString was removed. Use uCalc(uc_GetItemData, ...) instead. You can now determine the data type (not just whether or not if it's a string), as well as other properties of an item. See ExprType in the Library.uc file of the Language Builder for an example of how to determine the data type of an expression.

- ucParam, ucParamStr, and ucGetParamStr were removed. Version 2.0 required you to define your callbacks in a special UCalc way. Retrieving arguments required the use of ucParam or ucParamStr. Now you don't have to pattern your callback in a special way for it to work with uCalc. With the new way of doing it, ucParam and ucParamStr are irrelevant. Callbacks are much easier to write (in fact you can call DLL functions that weren't even designed with uCalc in mind), and they will run faster as well.

- ucSetParamStr, and ucParamStr functionality in the context of ucPreParse is no longer available, since pre-parsing itself is no longer available.

- ucParamCount was removed for the same reason described earlier under ucParam. However, for functions with a variable number of arguments, you can retrieve the number of passed arguments using [... not documented yet]

- ucPreParse is no longer supported. The main example in version 2.0 involved two alternatives of a function definition. Now you can directly define multiple version of a function without doing anything extra for it to work. For aspects of ucPreParse's functionality dealing with expressions, use ucDefineSyntax instead.

- ucVariableValue, ucGetVariableValue, ucSetVariableValue, ucVariableValueStr, ucGetVariableValueStr, ucSetVariableValueStr. These are now irrelevant under the new way of doing things, as you can now attach a uCalc variable directly to the address of a variable in your source code. This results in less code, which also runs faster. See the source code for the Plot or Sum examples in the demo program.

Unfortunately, for "managed" code which makes it difficult (or impossible) to work with fixed pointers, something akin to ucVariableValue is still required. A special routine named ucSetValueDbl is defined in the VB.NET include file. It simply places a call to uCalc() using uc_SetItemData and uc_Value as parameters. This can be extended to other fixed-memory data types the same way, if needed. ucSetValueDbl is much less efficient than attaching the variable to an address.

D. Partial list of new features

The improvements mentioned below are relevant mainly in the context of moving from version 2.0 to the next version. uCalc FMP barely scratches the surface of the Language Builder's functionality, which is not discussed in this file. (Download the separate Language Builder file from www.ucalc.com/newbeta.html

- The IIF() function evaluates either the True argument or the False argument, depending on the value of the Condition argument, but not both, unlike version 2.0 which always evaluated both.

- You can define callback functions similar to IIF() such that arguments passed ByExpr (as opposed to ByRef or ByVal) are not evaluated ahead of time. This was not possible in version 2.0.

- It is no longer necessary to set up definition space boundaries ahead of time. Memory is gradually allocated as needed. You won't need ucReset, and you won't have to worry about running out of definition space (assuming you don't intentionally, or inadvertently devise a way to consume all your gigs of memory). And there is no maximum number of arguments per function.

- FMP 2.0 only allowed you to define infix (binary) operators. Now you can also define prefix and postfix operators as well. See DemoDefs.Txt for examples.

- FMP 2.0 operator definitions didn't allow you to set individual precedence levels for each operator, as you can do now. See DemoDefs.Txt for examples.

- Case sensitivity can be turned on or off. (It's off by default).

- User-friendly form-based demos for PowerBASIC, Borland C++ Builder, and VB.NET are now included. (VB classic, and Delphi already had form-based demos). [VC++ not yet].

- Support [partial] for VB.NET [Problems with callbacks for now. Send feedback if you have suggestions].

- Speed. The new uCalc should be much faster, both in terms of parsing speed, and in evaluation speed. The difference in speed may range from barely noticeable to very dramatic, depending on what you are doing, and in some cases which compiler you are using. By default, compilers that have native support for 80-bit precision can benefit the most in numeric calculations. Compilers that support pointers can create callbacks that use uCalc's NativeCall for more efficiency.

Also you can attach a uCalc variable to the address of a variable defined in your source code. See the source code for the Plotting, and Sum examples in the demo files (excluding VB.NET).

[Unfortunately, "managed" code (VB.NET) suffers a great speed penalty especially where ucSetValueDbl must be used. For best speed, create callbacks in a DLL compiled with an unmanaged compiler, which you can then call from VB.NET].

- Specific data types are supported, instead of only generic numeric and string.

- There is no longer a problem with using ucEval or ucEvalStr in your callbacks.

- Function overloading is supported.

- Multi-threading. See ucNewThread().

- Function recursion is supported.

- FPU word of host program is preserved.

- More function definition flexibility is supported.

- [Complex numbers]

- uCalc() encapsulates all functionality. You can call it from your source code, or even at the end-user level (if you choose to make this available to the end-user).

See the uCalc FMP April 2007 beta Announcement.

Please send some feedback if you want uCalc FMP to be released sooner.

- There is no guarantee as to the date of release for the next version.
- There is no guarantee as to the features of the next version.
- There is no guarantee as to the suitability of this version for purposes other than beta testing.
- All parts of the beta version are subject to change without notice, and without regard to compatibility from one beta version to the next.
- A license for the beta cannot be purchased. Until the next version is no longer in beta, only a license for version 2.0 can be purchased.

Note: Purchasing a license for version 2.0 entitles you to a free upgrade when the next version comes out.

Daniel Corbier
UCalc FMP author

[This message has been edited by Daniel Corbier (edited 04-09-2007).]

IP: Logged

All times are Eastern Time (US)

next newest topic | next oldest topic

Administrative Options: Close Topic | Archive/Move | Delete Topic
Post New Topic  Post A Reply
Hop to:

Contact Us | uCalc

Copyright 2000-2007 by Daniel Corbier

Powered by: Ultimate Bulletin Board, Version 5.42a
© Infopop Corporation (formerly Madrona Park, Inc.), 1998 - 1999.