// rational().

// General includes.
#include "cl_sysdep.h"

// Specification.
#include "cln/float.h"


// Implementation.

#include "cln/integer.h"
#include "cl_RA.h"

namespace cln {

const cl_RA rational (const cl_F& x)
{
  // Methode:
  // Der mathematische Wert eines Float ist, wenn INTEGER-DECODE-FLOAT die
  // drei Zahlen m,e,s (Mantisse, Exponent, Vorzeichen) liefert,
  // = s * 2^e * m.
  // n:=m. Falls s<0, setze n:=-m.
  // Falls e>=0, ist (ash n e) das Ergebnis,
  // sonst ist die rationale Zahl (/ n (ash 1 (- e))) das Ergebnis.
	var cl_idecoded_float x_decoded = integer_decode_float(x);
	var cl_I& m = x_decoded.mantissa;
	var cl_I& e = x_decoded.exponent;
	var cl_I& s = x_decoded.sign;
	var cl_I n = (!minusp(s) ? m : -m);
	if (!minusp(e))
		return ash(n,e);
	else {
#if 0
		return I_posI_div_RA(n, ash(1,-e));
#else // spart ggT
		// n /= 0, -e > 0. Kürze mit ggT(n,2^(-e)) = 2^min(ord2(n),-e).
		// 0 < -e <= LF_exp_mid-LF_exp_low + intDsize*len < 2^32,
		var cl_I minus_e = -e;
		var uintL _e = cl_I_to_UL(minus_e); // daher kein Überlauf
		var uintL k = ord2(n);
		if (k >= _e)
			// Kürze mit 2^(-e).
			return ash(n,e);
		else
			// Kürze mit 2^k, 0 <= k < -e.
			return I_I_to_RT(ash(n,-(sintL)k),
					 ash(1,minus_e-UL_to_I(k)));
#endif
	}
}

}  // namespace cln
