-
Posts
227 -
Joined
-
Last visited
-
Days Won
26
Content Type
Profiles
Forums
Downloads
Gallery
Posts posted by Porter
-
-
Agreed. For compatibility sake, I won't modify the behavior of log(). It would just cause more confusion.
-
In testing I noticed that muParser's log() function is base e, while excel's log() function is base 10.
I usually expect log() to be base 10 because ln() is base e.
Any opinions on this? Is it an engineering vs physics/mathematics convention issue?
This behavior can be changed in muParser.cpp, line 297. I'm very tempted to change log() to refer to log10() instead of ln() and add an additional function lg() as an unambiguous log10() shorthand.
-
I've re-built the package with VIPM 2014:
- 1
-
On 10/29/2017 at 3:42 AM, ensegre said:
Noob question about vipm: I can't install the vip on linux, as it was build with vipm-2017. How can I build the package from the sources with vipm-2014, which is the latest available for linux (jki said no schedule for a new release). "Open Package Build Spec" LV_muParser.vipb gives me a blunt "VI Package Builder was unable to open the build spec due to an error".
I didn't realize that there was no vipm 2017 for linux. I will need to re-do the vipb file with vipm 2014. Have to find a computer that hasn't upgraded to vipm 2017 yet.
-
Version 1.0.0 is available for download. It is a vip package.
It will install muParser dlls to "<LabVIEW>\resource\" and mupLib, mupExpr to "<LabVIEW>\vi.lib\LAVA\muParser\".
mupExpr VIs are located on the function palette under "Addons > LAVA > muParser"
Documentation and examples have not been included yet. But you should be able to figure it out for now.
The development version is available on github: https://github.com/rfporter/LV-muParser
-
On 10/22/2017 at 3:53 AM, ensegre said:
No big deal, they are all very simple. The full message from mupGetErrorMsg() is already more informative, beyond that I can't imagine. See my go at it:
Thanks. That saves me some time. I will try to take a look at it this evening. I will also try to fix up the examples and make a vip package to install the mupLib and mupExpr into "<LabVIEW>\vi.lib\LAVA\" and the dlls to "<LabVIEW>\resource\".
-
I don't really see the point of evaluating asynchronously either. But I do sleep better knowing that the muparser handle and variable pointers are wrapped in something that is also passed around by reference. If the muExpr DVR is valid, I can assume that its variable pointers and muparser handle are also valid. If the DVR is not valid, most likely the variable pointers and muparser handle are also not valid. An error will be generated. No harm done.
I've added two polymorphic VIs to the class to aggregate the set variable value and eval functions. So finally, the top level api will look like:
construct
select single variable
set variable value
eval
destructThrough these you are able to access all combinations of single variable, multi variable, multi expression, bulk mode. Note that bulk mode doesn't support multi expression. It just evaluates the last expression in the list.
Latest version here: muParser_byRef2.zip
-
Single element queue didn't perform as well as expected. Here is where I'm at with the DVR version: muParser_byRef.zip
I've added bulk mode and multi result (multi expression) evaluation functions. Check the mupExpr Demo 3 and Demo 4.
Not ready for another release. Hasn't been thoroughly tested yet.
-
My intention for the mupExpr class is to abstract away the details of interfacing with the muparser dll. The developer shouldn't have to worry (too much) about the handle and variable pointers.
I think that I can just obtain a queue or notifier reference in construct and release it in destruct. I will check if the reference is valid before trying to use the muparser handle or variable pointers. It is like an "is initialized" flag. That way I can generate an error instead of risk crashing labview if the muparser handle is not initialized or has been released somewhere.
Splitting the mupExpr wire could be useful if you want to, for example, update variable values in one loop and evaluate in another loop
-
22 hours ago, ensegre said:
wishlist: comprehensive error handling using http://beltoforion.de/article.php?a=muparser&hl=en&p=errorhandling, to locate expression syntax errors
Yup. I have a few more functions to implement for error handling. For now I just check for an error and return the error code.
-
Thanks for pointing out that typo.
I will definitely add the multi-variable multi-expression evaluation function to the mupExpr class. I am also planning to add bulk mode eval.
The last thing I was working on was to put the mupExpr inside a DVR. I did this because I was worried about the case of splitting the mupExpr wire, calling destruct on one of them, then continuing to use the other. This could cause labview to crash because its variable pointers and muparser handle have been released. Of course, putting everything inside a DVR slows things down a bit but I think that it might be worth it to avoid a crash. The other option is single element queue(s) to store the variable pointers and muparser handle. Not sure if this would reduce the performance hit though. Haven't tried yet.
Unfortunately I've been sidetracked by home renovations. I'm going to continue development on this project soon though.
-
On 9/10/2017 at 2:58 AM, ensegre said:
mupEvalMulti.vi dies on DSDisposePtr. Shouldn't there be a DSNewPtr somewhere, like in other VIs using LabVIEW:MoveBlock?
mupEvalMulti returns a pointer to an array of doubles. I'm using that as the source for MoveBlock. Then I initialize an array of doubles to the correct size and pass its array data pointer as the destination for MoveBlock. The destination pointer, I'm assuming, is allocated and disposed of internally by LabVIEW. The source pointer should be allocated and disposed of by muParser. So I should not use the DSDisposePtr at all in this case... ?
On 9/10/2017 at 2:58 AM, ensegre said:Besides, your .so doesn't load on my system, and I have to use the one I compiled locally, but that is expected, as said above. Only confirming that it is vane to target all possible linux distros at once.
The .so files included in the zip are the ones that you posted earlier. Maybe I messed them up when I renamed them? Or perhaps they break if loaded from "<LabVIEW>/resource" directory? Sorry I can't test any of this; I don't have access to LabVIEW for Linux.
-
V0.0.5 is up. Added bulk mode and multiple return value functions to mupLib.
-
V0.0.4 is up. I've named the muparser shared libraries as "libmuparser-[bitness]-lv.dll". For now, you need to manually copy them over to your "<LabVIEW>\resource" directory (or somewhere else in the search path).
Now to concentrate on features...
- Bulk mode
- Multiple return values
- Multiple type support (MUP_BASETYPE)? -
Quote
MUP_STRING_TYPE
This definition determines the string type used by muParser. This can either be
std::string
orstd::wstring
. This definition shouldn't be set directly. It is defined tostd::wstring
if there is a preprocessor macro_UNICODE
present. (This definition is set by VS2008 accoring to the project settings.But it sounds like your "/usr/lib/x86_64-linux-gnu/libmuparser.so.2" is using std::string.
-
How about these names:
libmuparser-x32-ascii-lv.dll
libmuparser-x64-ascii-lv.dll
libmuparser-x32-ascii-lv.so.2.2.5
libmuparser-x64-ascii-lv.so.2.2.5I will assume that they will be located in the "<LabVIEW>\resource" directory.
Note that a major difference between the modified version and a possible standard version of libmuparser is the character encoding. By default, Visual studio 2013 compiles muparser with _UNICODE preprocessor macro. This does not play nice with LabVIEW's strings.
-
I also prefer the statically linked dll because I can imagine that no one will remember to include the correct DLL or even know where to find the DLL when they build their exe.
However, since this library is under development, I think that it is wise to stick with the in-lined mupLibPath vi for now.
When we get closer to V1.0 perhaps it will be worth putting in the extra effort to setup a conditional disable structure around each CLN.
- 1
-
Of course this will eventually be distributed as a vip not a zip.
-
Version 0.0.3 uses library name instead of path.
-
To simplify the path logic to a constant, we could reference the shared library by name rather than full path. To do this, we need to place the library in the search path. For LV windows, linux and OSX development environment the search path includes "<LabVIEW>\resource". For a LV-built application in windows, the directory of the executable seems to also be included in the search path. Not sure about LV-built applications for Linux though.
See: http://digital.ni.com/public.nsf/websearch/EBAE870D564CBBE78625788B004E76D3
Benchmark shows very little difference (<100ns) in performance between static, constant (full path) and in-line VI (providing library name).
-
Here are my results (Windows 7, LabVIEW 2015 32-bit):
path constant average: 13.515us
no path constant average: 13.437us
path from control on front panel average: 13.958us (an attempt to simulate the V0.0.2 implementation)- 1
-
How about statically linking (not specifying path on diagram) and putting a conditional disable structure around each CLN? It is a pain to maintain but I think that it would give us the best performance. Also, when built to exe, the correct OS & bitness dll/so will be included automatically.
-
Modified version with mupGetExprVar fixed, path wired to CLNs, muParser dll moved to mupLib directory: muParser.zip
Lets call it V0.0.2
-
7 hours ago, ensegre said:
In any case, have you noted the shift register for that pointer? This should keep the case of N=0 exprs from crashing.
Good catch. I missed that one. I was too distracted by my struggles with the getValueByPointer xnode (which does not work properly when built into an executable).
7 hours ago, ensegre said:mupGetExprVars still crashes if called with Parser in=0, that should perhaps be trapped in a production version.
Indeed, LabVIEW does not like an uninitialized parser reference. Now is it worth checking for hParser=0 in every mup vi? My plan was to create a wrapper for the mup VIs (muExpr class) to protect the end user from inadvertently crashing LabVIEW. Within that wrapper I make sure that the parser handle is properly initialized and pointers to variables are properly created/released.
[CR] LV muParser
in Code Repository (Certified)
Posted
V1.1.0 released.
I've decided to add get variable value to mupExpr. This allows you to retrieve the value of a variable that may have been modified by evaluation of the expression (the assignment operator "=" is supported).
Examples for mupExpr and mupLib have been included in "<LabVIEW>\examples\LAVA\muParser\".