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();
}