Objective
Take \$a \in ℤ_{>1}\$ and \$b \in ℤ_+\$ as inputs. Write a function \$f\$ such that:
$$ f(a,b) = \left\{ \begin{array}{ll} \log_ab & \quad \text{if} \space \log_ab \in ℚ \\ -1 & \quad \text{otherwise} \end{array} \right. $$
Rules
Types and formats of the inputs doesn't matter.
Type and format of the output doesn't matter either, but the fraction must be irreducible. In C++,
std::pair<int,unsigned>
is an example. (Regarding logarithms, the numerator and the denominator need not to be arbitrary-length integers.)Regardless of whether the input type can handle arbitrary-length integers, the algorithm must be "as if" it were handling those. So using floating-point numbers is implicitly banned.
If \$a\$ and \$b\$ aren't in the sets as specified above, the challenge falls in don't care situation.
\$f\$ may be curried or uncurried.
As this is a code-golf, the shortest code in bytes wins.
Test cases
a b => answer
-----------------
2 8 => 3/1
3 9 => 2/1
8 2 => 1/3
9 3 => 1/2
4 8 => 3/2
64 256 => 4/3
999 1 => 0/1
-----------------
2 7 => -1
10 50 => -1
5 15 => -1
they must be able to represent arbitrary-length integers
This is a rather odd requirement, since it unfairly penalizes languages which don't have access to arbitrary-precision integer type (many of them don't even have a thing called "import"). Instead, we usually say "use the most natural number type for the language, but the underlying algorithm should generalize to higher numbers." \$\endgroup\$