Requesting opinions

Dec 29, 2011 at 1:18am
I just released a project I've been working on for a while, and would appreciate any opinions, comments, etc. anyone might have about it. It's a math parsing library, and can be found here:
https://sourceforge.net/projects/ub3rmath/

Thanks in advance,
Richard Carson
Dec 29, 2011 at 4:24am
Tried it out, but came up with an error. Could not #include <unordered_map> from the math library. What library or include, is this from? I'm using Microsoft Visual C++ 2008 Express Edition.
Dec 29, 2011 at 4:43am
¿where is the source code?

@whitenite1: that's from the new standard.
Dec 29, 2011 at 5:11am
Its in a git repo
https://sourceforge.net/p/ub3rmath/code/ci/3abeaf4cfe0b46898fc96e607e449f29309b953f/tree/

I can upload the source as a tarball though, if that's easier
Dec 29, 2011 at 5:12am
Thanks for clarifying that for me ne555. At least I won't keep attempting to use it, til I get the newer compiler. I found the mentioned source code by going to the above https site, but leaving off the last forward slash.
Dec 29, 2011 at 3:17pm
line 357 of Solver.cpp should be delete [] eqParse;
But maybe it would be better if you use std::vector instead.

Don't using namespace std; in headers. It pollutes everything.
You could create a namespace too.

Prefer constants to defines.
Dec 29, 2011 at 3:39pm
Thank you very much for the response,
I am currently working on those, and in the mean time have updated it to use std::map instead of std::unordered_map. It's a hit on performance, but eliminates the need to support the new standard.
Dec 29, 2011 at 3:55pm
Isn't there a pre-defined symbol for C++11 that you can use to conditionally use either one, assuming they work the same (same method names and such)? If not you can always #define your own.

Users of your library would do:

1
2
#define NOCPP11
#include "theheaderfile.h" 


And your header would do something like:

1
2
3
4
5
6
7
#ifdef NOCPP11
#include <map>
typedef std::map map_type;
#else
#include <unordered_map>
typedef std::unordered_map map_type;
#endif 


And then you use the type map_type everywhere else in your library.
Dec 29, 2011 at 4:06pm
That's a great idea :D

edit:

Something like this?
1
2
3
4
5
6
7
#ifdef __GXX_EXPERIMENTAL_CXX0X__
	#include <unordered_map>
	typedef std::unordered_map __map__;
#else
	#include <map>
	typedef std::map __map__;
#endif 
Last edited on Dec 29, 2011 at 4:23pm
Dec 29, 2011 at 7:24pm
Also, I was thinking of adding unit conversion filters, like:
1
2
3
4
5
6
7
8
celciustofahrenheit
fahrenheittocelcius
metrestofeet
feettometres
inchestocm
cmtoinches
poundstokg
kgtopounds 


Any others I could add? I also am looking to add more constants. All I have is e and pi at the moment.

Thanks again :D
Last edited on Dec 29, 2011 at 7:24pm
Dec 29, 2011 at 9:13pm
It's a bad idea to name your symbols with __ at the begining, i think it's used by the compiler and the standard library.
Dec 29, 2011 at 9:30pm
Any conventions as to how to name a pseudo type like this?
Dec 29, 2011 at 10:04pm
Just add a namespace to your library. Namespaces are exactly for that: Name conflict resolution.
Dec 30, 2011 at 2:31pm
I see in ConstantesManipulation.cpp that you pass string by value. This is very bad for performances, consider using const& string to avoid copy.
In general, the only types you sould pass by value are primitives types(int, float, double, char, pointers) and very small types designed to be passed by value like iterators and functors.
The only benefit to pass by value is to not have indirection when using the parameter.
Dec 30, 2011 at 2:55pm
This is personal opinion: in Function.cpp, i find your
1
2
3
4
5
6
7
8
9
10
ver_tmp == '0' ||
ver_tmp == '1' ||
ver_tmp == '2' ||
ver_tmp == '3' ||
ver_tmp == '4' ||
ver_tmp == '5' ||
ver_tmp == '6' ||
ver_tmp == '7' ||
ver_tmp == '8' ||
ver_tmp == '9')

very ugly, why not put it in a function and use comparison instead?
This function may be useful:
1
2
3
4
5
template <char lower, char upper>
inline bool in_range(char letter)
{
    return lower <= letter && letter <= upper;
}


and then you have:
1
2
inline bool is_decimal(char letter) { return in_range<'0', '10'>(letter); }
inline bool is_octal(char letter) { return in_range<'0', '8'>(letter); }


and so on...
Dec 30, 2011 at 2:59pm
Epic! I was looking for a better way of doing this.
Dec 30, 2011 at 3:50pm
Another idea for performance: in your main loop in Solver.cpp, you do this:
1
2
3
4
string nextChunk = GetNextChunk(&equation);
/* some code which don't use the string value of nextChunk but its type with GetChunkType */
switch  (getChunkType(nextChunk)
/* ... */


I think it would be better not to treat chunk as string as it doesn't not hold the real information you want to manipulate. In fact, GetNextChunk already knows the data in your chunk because it parse it. So it should return something like a boost::variant<float, string, operator,...> (a variant is a type which can hold data of multiple types and knows about the data of its type). Thus you don't have to call GetChunkType multiple times.
If you don't want to use boost::variant you can easily create your own with an union and an enum for exemple.
Dec 30, 2011 at 3:56pm
Good idea... I could do something like this maybe:
1
2
3
4
5
struct Chunk
{
     string data;
     int chunkType;
};
Dec 30, 2011 at 4:07pm
Yes that better but use an enum instead of an int.
Dec 30, 2011 at 5:07pm
I did not know about enum. This is handy.
Topic archived. No new replies allowed.