Can’t sleep: My mind is wandering about in my skull, a kitty among the bins. I can’t make up my mind how to represent an atomic algebraic expression term.

Clearly, an expression term, and an elementary binary operator are two different kinds of objects. What do I make, then, of an expression term such as sin(x)? It’s a function operator taking a single argument. I’d like to be able to manipulate a pair of rational expressions like

How about 2x? It’s an elementary product expression consisting of a constant and a variable. I’m beginning to think each subexpression ought to be represented as an object, now – so that I could replace the factor 2 with an expression, for example. This pretty much puts paid to representing an algebraic polynomial term as a struct:

struct Monomial {
public:
integer coeff;
Variable x;
Exponent t;
}

Each member coeff, x,  and t would then be an Expr:

struct Monomial {
protected:
Expr coeff;
Expr x;
Expr t;
}

Then I should represent elementary operations as functors as well, perhaps. Hmm. This eliminates the need for a Monomial type:

Expr x('x'), X;
X = 2 * x ^ 3;
cout << X.strict().toString() << endl; // 2*(x^3)
cout << X.toHumanString() << endl; // 2x3
cout << X.toMathML() << endl; // Something like 2x(super)3

I need to look into operator associativity rules and find out whether any combination of member and nonmember functions will cause type coercion of the RHS into an Expr type.

***

My goal is to be able to create simple code to generate elementary algebra expressions programmatically, like so:

Expr a('a', '1/(x+2)');
Expr b('b', '2/(x+7)');
Expr c;
c = a * b;
cout << c.toMathML() << endl;
cout << c.execute().toMathML() << endl; // 1/(x^2 + 9x + 14)

Then a simple, short chunk of code could do and generate an online algebra workbook of arbitrary complexity:

string generate_rational_fraction_sum( int terms, int glbpower, int lubpower ) {
Expr rfs;
Expr numerator;
Expr denominator;
Expr monomial('x');
for ( int i = 0 ; i < terms ; i++ ) {
integer r = rand(glbpower, lubpower);
integer q = rand(1,10);
denominator.clear();
for ( int j = 0 ; j < r ; j++ ) {
// Generate an order-j polynomial expression for the denominator
integer k = rand(1,10);
denominator += k * monomial ^ j;
}
numerator = rand(1,10);
rfs += numerator / denominator;
}
return rfs.execute().toMathML();
}