a^n*b^n => (ab)^n



> ((-c+sqrt(c^2+4*d))/2/d)^n*((-c-sqrt(c^2+4*d))/2/d)^n; This should simplify to (-1/d)^n, if I'm not mistaken,

As far as I know, rootscontract (or radcan, ...) does not simplify this expression to (-1/d)^n. Rootsconmode modifies the behavior of
rootscontact, but it seems that rootscontract only looks for rational exponents.

You could experiment with something like the untested:

/* for pop & push */

load(basic)$

mexptp(e) := block([inflag : true, sqrtdispflag : false], not mapatom(e) and op(e) = "^")$

/* input is a list of mexptp expressions-- for list members of the form x^n, y^n, replace with (x*y)^n. Return the product of list members. */

crunch(l) := block([x,n,q:1,inflag : true],
  l : sort(l, lambda([a,b], orderlessp(second(a),second(b)))),
  l : map('args,l),
  while l # [] do (
     [x,n]: pop(l),
     while l # [] and second(first(l))=n do (
        x : x * first(pop(l))),
      q : q * ratsimp(x)^n),
   q)$

/* in expression e, replace terms of the form x^n * y^n with (x*y)^n */

combine_powers(e) := subst("*" = lambda([[l]], block([z : [],q : 1, sqrtdispflag : false,inflag : true],
  for lx in l do (
    if mexptp(lx) then push(lx, z) else q : q * lx),
  q * crunch(z))), e)$

Examples:

  (%i55) combine_powers(((-c+sqrt(c^2+4*d))/2/d)^n*((-c-sqrt(c^2+4*d))/2/d)^n),domain : complex;
  (%o55) (-1/d)^n

  (%i56) combine_powers(2^x * 3^x * 9^x);
  (%o56) 54^x

  (%i57) combine_powers(a^(x)* b^x);
  (%o57) (a*b)^x

  (%i58) radcan(%);
  (%o58) a^x*b^x

  (%i59) combine_powers(x^p*y^p - exp(2^x * 3^x)/8);
  (%o59) (x*y)^p-%e^6^x/8

Of course, combine_powers assumes that you are comfortable with bogus simplifications on unspecified hunks of the complex plane:

  (%i76) combine_powers(sqrt(x) * sqrt(y)) /( sqrt(x) * sqrt(y));
  (%o76) sqrt(x*y)/(sqrt(x)*sqrt(y))

  (%i77) subst([x=-1,y=-1],%);
  (%o77) -1

Likely my code doesn't catch everything it should or it is broken. I wouldn't trust combine_powers without lots of checking.

Substituting a lambda form for *, +, or ^ has been called my favorite trick. Try it, you might like it.

Maybe letsimp or friends provides an easier way to do  x^n * y^n --> (x*y)^n?

--Barton