M1 is M + 1,
msb_(X1, M1, N).
-number_to_rational(Real0, Fraction) :-
- ( var(Real0) -> instantiation_error(number_to_rational/2)
- ; Real0 = R1/R2 ->
- ( member(R, [R1, R2]), \+ number(R) ->
- type_error(number, R, number_to_rational/2)
- ; Real = R1/R2
- )
- ; number(Real0),
- Real = Real0/1
- ),
- number_to_rational(1.0e-6/1, Real, Fraction).
+number_to_rational(Real, Fraction) :-
+ ( var(Real) -> instantiation_error(number_to_rational/2)
+ ; integer(Real) -> Fraction is Real rdiv 1
+ ; (rational(Real) ; float(Real)) ->
+ number_to_rational(1.0e-6, Real, Fraction)
+ ; type_error(number, Real, number_to_rational/2)
+ ).
% If 0 <= Eps0 <= 1e-16 then the search is for "infinite" precision.
number_to_rational(Eps0, Real0, Fraction) :-
( var(Eps0) -> instantiation_error(number_to_rational/3)
- ; Eps0 = E0/E1 ->
- ( member(E, [E0, E1]), \+ number(E) ->
- type_error(number, E, number_to_rational/3)
- ; Eps = E0/E1
- )
- ; number(Eps0),
- Eps = Eps0/1
+ ; \+ number(Eps0) -> type_error(number, Eps0, number_to_rational/3)
+ ; Eps0 < 0 -> domain_error(not_less_than_zero, Eps0, number_to_rational/3)
+ ; Eps_ is Eps0 rdiv 1,
+ rational_numerator_denominator(Eps_, EpsN, EpsD),
+ Eps = EpsN/EpsD
),
( var(Real0) -> instantiation_error(number_to_rational/3)
- ; Real0 = R1/R2 ->
- ( member(R, [R1, R2]), \+ number(R) ->
- type_error(number, R, number_to_rational/3)
- ; Real = R1/R2
- )
- ; number(Real0),
- Real = Real0/1
+ ; \+ number(Real0) -> type_error(number, Eps0, number_to_rational/3)
+ ; Real_ is Real0 rdiv 1,
+ rational_numerator_denominator(Real_, RealN, RealD),
+ Real = RealN/RealD
),
E0/E1 = Eps,
P0/Q0 = Real,
- S is sign(E0) * sign(E1),
- ( S < 0 -> domain_error(not_less_than_zero, Eps0, number_to_rational/3)
- ; P1 is abs(P0),
- Q1 is abs(Q0),
- Qn1n is P1 * E1 - Q1 * E0,
+ ( P0 < 0 -> I1 is -1 + P0 // Q0
+ ; I1 is P0 // Q0
+ ),
+ P1 is P0 mod Q0,
+ Q1 = Q0,
+ ( P1 =:= 0 -> Fraction is I1 + 0 rdiv 1
+ ; Qn1n is max(P1 * E1 - Q1 * E0, 0),
Qn1d is Q1 * E1,
Qn1 = Qn1n/Qn1d,
Qp1n is P1 * E1 + Q1 * E0,
Qp1d = Qn1d,
Qp1 = Qp1n/Qp1d,
stern_brocot_(Qn1, Qp1, 0/1, 1/0, P2/Q2),
- P3 is sign(P0) * sign(Q0) * P2,
- Fraction is P3 rdiv Q2
- ).
+ Fraction is I1 + P2 rdiv Q2
+ ),
+ !.
number(X) :-
( integer(X)
simplify_fraction(A0/B0, A/B) :-
G is gcd(A0, B0),
- A is A0 div G,
- B is B0 div G.
+ A is A0 // G,
+ B is B0 // G.
rational_numerator_denominator(R, N, D) :-
write_term_to_chars(R, [], Cs),