def is_deriv_k(fa, fd, DE):
    # Compute Df/f
    dfa, dfd = fd*(fd*derivation(fa, DE) - fa*derivation(fd, DE)), fd**2*fa
    dfa, dfd = dfa.cancel(dfd, include=True)

    # Our assumption here is that each monomial is recursively transcendental
    if len(DE.L_K) + len(DE.E_K) != len(DE.D) - 1:
        if [i for i in DE.cases if i == 'tan'] or \
                set([i for i in DE.cases if i == 'primitive']) - set(DE.L_K):
            raise NotImplementedError("Real version of the structure "
                "theorems with hypertangent support is not yet implemented.")

        # TODO: What should really be done in this case?
        raise NotImplementedError("Nonelementary extensions not supported "
            "in the structure theorems.")

    E_part = [DE.D[i].quo(Poly(DE.T[i], DE.T[i])).as_expr() for i in DE.E_K]
    L_part = [DE.D[i].as_expr() for i in DE.L_K]

    lhs = Matrix([E_part + L_part])
    rhs = Matrix([dfa.as_expr()/dfd.as_expr()])

    A, u = constant_system(lhs, rhs, DE)

    if not all(derivation(i, DE, basic=True).is_zero for i in u) or not A:
        # If the elements of u are not all constant
        # Note: See comment in constant_system

        # Also note: derivation(basic=True) calls cancel()
        return None
    else:
        if not all(i.is_Rational for i in u):
            raise NotImplementedError("Cannot work with non-rational "
                "coefficients in this case.")
        else:
            terms = DE.E_args + [DE.T[i] for i in DE.L_K]
            ans = list(zip(terms, u))
            result = Add(*[Mul(i, j) for i, j in ans])
            argterms = [DE.T[i] for i in DE.E_K] + DE.L_args
            l = []
            ld = []
            for i, j in zip(argterms, u):
                # We need to get around things like sqrt(x**2) != x
                # and also sqrt(x**2 + 2*x + 1) != x + 1
                # Issue 10798: i need not be a polynomial
                i, d = i.as_numer_denom()
                icoeff, iterms = sqf_list(i)
                l.append(Mul(*([Pow(icoeff, j)] + [Pow(b, e*j) for b, e in iterms])))
                dcoeff, dterms = sqf_list(d)
                ld.append(Mul(*([Pow(dcoeff, j)] + [Pow(b, e*j) for b, e in dterms])))
            const = cancel(fa.as_expr()/fd.as_expr()/Mul(*l)*Mul(*ld))

            return (ans, result, const)
Checks if Df/f is the derivative of an element of k(t).
dataset/ETHPy150Open sympy/sympy/sympy/integrals/prde.py/is_deriv_k