I've noticed that the composite_fields method can be quite slow when used on larger number fields (degree above 10).
This is partially due to the checking of correct embeddings done by Sage after using pari's polcompositum method,
which was not necessary for the application I needed.
When trying to improve further I started to read the pari documentation on polcompositum and I noted a particular line of interest:
polcompositum(P, Q, {flag = 0})
...
Assuming P is irreducible (of smaller degree than Q for efficiency), it is in general much faster to proceed as follows
nf = nfinit(P); L = nffactor(nf, Q)[,1];
vector(#L, i, rnfequation(nf, L[i]))
to obtain the same result.
This could easily be written in Sage by writing
def self.composite_field(other, names=None):
if self.absolute_degree() > other.absolute_degree():
return other.composite_field(self)
f = other.absolute_polynomial()
g = f.change_ring(self).factor()[0][0]
return self.extension(g, names=names).absolute_field(names=names)
With some more work you could also make sure the extensions respect given embeddings by checking all factors of f over self and choosing the one which vanishes on a generator of other.
Returning the appropriate embeddings to the final field is also easy, for self it is the natural coercion map combined with the structure isomorphism of the absolute field, and for other it is the map that maps the generator of other to the generator of the extension defined by g combined with the isomorphism of the absolute field.
Doing some testing this seems to be faster when the degree grows as suggested by the pari documentation.