Consider an arbitrary vector $\boldsymbol v\equiv(v_i)_{i=1}^N\in\mathbb C^{nm}$ of length $n m$ (if you care only about qubits, just fix $n=m=2$).
For $\boldsymbol v$ to have an $(n,m)$ partition means that we can write it as $\boldsymbol v=\boldsymbol u\otimes \boldsymbol w$ for some $\boldsymbol u\in\mathbb C^n$ and $\boldsymbol w\in\mathbb C^m$.
If this is the case, then the components of $\boldsymbol v$ must be related to those of $\boldsymbol u,\boldsymbol w$ via
$$v_{ij}=u_i w_j. \tag A$$
The first thing to notice is that the tensor product operation $(\boldsymbol u,\boldsymbol w)\mapsto\boldsymbol v$ is not injective. In particular, for any $\lambda\in\mathbb C$ we have $(\lambda \boldsymbol u)\otimes \boldsymbol w=\boldsymbol u\otimes(\lambda \boldsymbol w)$, and thus given a separable $\boldsymbol v$ we can only recover its "reduced vectors" up to their individual norms and phase factors.
Because we are interested in quantum states, this means that we don't need to worry about neither the normalisation nor the phase of the vectors $\boldsymbol u,\boldsymbol w$.
A remarkable property of (A) is that, for any pair of indices $j\neq j'$ and $i$, we have $v_{ij}/v_{ij'}=w_j/w_{j'}$, where, you might notice, the $i$ index does not appear on the right-hand side.
This property characterises separable vectors: check that $v_{ij}/v_{ij'}$ does not depend on $i$ for all $j,j'$, and if so, define $w_i\equiv v_{i1}/v_{ij}$, where we are using the fact that $\boldsymbol w$ is defined up to normalisation to assume $w_1=1$ (when some of the elements $v_{ij}$ we might not be able to assume this, but those cases are usually trivial to handle separately).
Once you have $\boldsymbol w$, you can find $u_i$ by simply computing $v_{ij}/w_j$.
For example, if $\boldsymbol v=(1,1,2,2)^T$, then
$$v_{11}=v_{12}=1, \qquad v_{21}=v_{22}=2,$$
and thus $v_{12}/v_{11}=v_{22}/v_{21}=1$. You can thus define $\boldsymbol w=(1,1)$. You then compute $u_1=v_{11}/w_1=1$ and $u_2=v_{21}/w_1=2$, which tells you that $\boldsymbol u=(1,2)$.
For example, if $\boldsymbol v=(0,1,0,0)^T$ and $n=m=2$, then by definition
$$v_{11}=v_{21}=v_{22}=0 \qquad\text{and}\qquad v_{12}=1.$$
Because $v_{11}=0$, we cannot use directly the procedure above, but the fact that $v_{2j}=0$ for all $j$ tells you immediately that $\boldsymbol u=(1,0)$, and then finding $\boldsymbol v$ is easy.
As for how numerically efficient this particular method is, I'm not so sure. The main problem is that all these divisions will be prone to numerical instability for small values of the amplitudes. Methods that are based on computing entropies might work better, but I'm not sure.
reverse_normalised_kronecker(qstate, 2**first_reg_size, 2**second_reg_size, 2**ancilla_size)
. $\endgroup$