Calculator function for my irc bot

My irc bot follows commands by looking up a table with command strings linked with function pointers. Today I’ve created a postfix calculator command. It can recognize decimal, hex, and octal. It also uses an array of long double math functions defined from math.h.

This function utilizes string manipulations and number conversions from my personal axcel c++ library. I have yet to document the recent version of this library I’ve uploaded. You can get the source for the bot at http://abacus.subluminal.net/~jakashthree/sauce and you can download the undocumented axcel library at https://sourceforge.net/projects/libaxcel/

void calc() {
	sock << "PRIVMSG " << im.param(0) <<  " :";
	if (buf.empty()) {
		sock << "Postfix calcuator. Operators: > < = ? # $ + - * / % & | ^. Functions: "
				"acosh acos asinh asin atanh atan cbrt ceil cosh cos erfc erf "
				"exp2 exp expm1 fabs floor ilogb lgamma llrint llround log10 "
				"log1p log2 logb log lrint lround nearbyint rint round sinh "
				"sin sqrt tanh tan tgamma trunc\r\n";
		return;
	}
	register long double a, b;
	std::stack<long double> nums;
	std::deque<String> s = buf.split(" ,");
	for (; !s.empty(); s.pop_front()) {
		if (s.front().munch("0x").rep(".", "").isxdigit()) {
			if (s.front().chr('.') == -1) nums.push((long double)stoi<long>(s.front(), 0));
			else nums.push(stof<long double>(s.front()));
			continue;
		}
#ifdef _ISOC99_SOURCE
		if (nums.size() < 1) continue;
		a = nums.top(); nums.pop();
		if (s.front()[1] == 0) nums.push(a);
		else if (s.front() == "acosh") nums.push(acoshl(a));
		else if (s.front() == "acos") nums.push(acosl(a));
		else if (s.front() == "asinh") nums.push(asinhl(a));
		else if (s.front() == "asin") nums.push(asinl(a));
		else if (s.front() == "atanh") nums.push(atanhl(a));
		else if (s.front() == "atan") nums.push(atanl(a));
		else if (s.front() == "cbrt") nums.push(cbrtl(a));
		else if (s.front() == "ceil") nums.push(ceill(a));
		else if (s.front() == "cosh") nums.push(coshl(a));
		else if (s.front() == "cos") nums.push(cosl(a));
		else if (s.front() == "erfc") nums.push(erfcl(a));
		else if (s.front() == "erf") nums.push(erfl(a));
		else if (s.front() == "exp2") nums.push(exp2l(a));
		else if (s.front() == "exp") nums.push(expl(a));
		else if (s.front() == "expm1") nums.push(expm1l(a));
		else if (s.front() == "fabs") nums.push(fabsl(a));
		else if (s.front() == "floor") nums.push(floorl(a));
		else if (s.front() == "ilogb") nums.push((long double)ilogbl(a));
		else if (s.front() == "lgamma") nums.push(lgammal(a));
		else if (s.front() == "llrint") nums.push(llrintl(a));
		else if (s.front() == "llround") nums.push(llroundl(a));
		else if (s.front() == "log10") nums.push(log10l(a));
		else if (s.front() == "log1p") nums.push(log1pl(a));
		else if (s.front() == "log2") nums.push(log2l(a));
		else if (s.front() == "logb") nums.push(logbl(a));
		else if (s.front() == "log") nums.push(logl(a));
		else if (s.front() == "lrint") nums.push(lrintl(a));
		else if (s.front() == "lround") nums.push(lroundl(a));
		else if (s.front() == "nearbyint") nums.push(nearbyintl(a));
		else if (s.front() == "rint") nums.push(rintl(a));
		else if (s.front() == "round") nums.push(roundl(a));
		else if (s.front() == "sinh") nums.push(sinhl(a));
		else if (s.front() == "sin") nums.push(sinl(a));
		else if (s.front() == "sqrt") nums.push(sqrtl(a));
		else if (s.front() == "tanh") nums.push(tanhl(a));
		else if (s.front() == "tan") nums.push(tanl(a));
		else if (s.front() == "tgamma") nums.push(tgammal(a));
		else if (s.front() == "trunc") nums.push(truncl(a));
		else nums.push(a);
#endif
		unless (s.front()[1] == 0 && !isalnum(s.front()[0])) continue;
		if (nums.size() < 2) continue;
		a = nums.top(); nums.pop();
		b = nums.top(); nums.pop();
		switch (s.front()[0]) {
		case '?': 
			if (b > a) nums.push(1);
			else if (b < a) nums.push(-1);
			else if (b == a) nums.push(0); 
			break;
		case '#': nums.push(rand((int)b, (int)a)); break;
		case '>': nums.push(b > a); break;
		case '<': nums.push(b < a); break;
		case '=': nums.push(b == a); break;
		case '$': nums.push(powl(b, a)); break;
		case '+': nums.push(b + a); break;
		case '-': nums.push(b - a); break;
		case '*': nums.push(b * a); break;
		case '/': nums.push(b / a); break;
		case '%': 
			if (a == 0) { sock << "VOID\r\n"; return; }
			nums.push((long double)((long)b % (long)a)); break;
		case '&': nums.push((long double)((long)b & (long)a)); break;
		case '|': nums.push((long double)((long)b | (long)a)); break;
		case '^': nums.push((long double)((long)b ^ (long)a)); break;
		default: nums.push(b); nums.push(a);
		}
	}
	for (; !nums.empty(); nums.pop()) sock << nums.top() << " ";
	sock << "\r\n";
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: