Merge pull request #417 from notoria/mediants
Implemented predicate mediants/2 with Stern-Brocot tree
This commit is contained in:
@@ -1,6 +1,10 @@
|
|||||||
:- module(arithmetic, [msb/2, lsb/2]).
|
:- module(arithmetic, [lsb/2, msb/2, number_to_rational/2,
|
||||||
|
number_to_rational/3,
|
||||||
|
rational_numerator_denominator/3]).
|
||||||
|
|
||||||
|
:- use_module(library(charsio), [write_term_to_chars/3]).
|
||||||
:- use_module(library(error)).
|
:- use_module(library(error)).
|
||||||
|
:- use_module(library(lists), [append/3, member/2]).
|
||||||
|
|
||||||
lsb(X, N) :-
|
lsb(X, N) :-
|
||||||
builtins:must_be_number(X, lsb/2),
|
builtins:must_be_number(X, lsb/2),
|
||||||
@@ -25,3 +29,80 @@ msb_(X, M, N) :-
|
|||||||
X1 is X >> 1,
|
X1 is X >> 1,
|
||||||
M1 is M + 1,
|
M1 is M + 1,
|
||||||
msb_(X1, M1, N).
|
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).
|
||||||
|
|
||||||
|
% 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
|
||||||
|
),
|
||||||
|
( 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
|
||||||
|
),
|
||||||
|
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,
|
||||||
|
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
|
||||||
|
).
|
||||||
|
|
||||||
|
number(X) :-
|
||||||
|
( integer(X)
|
||||||
|
; float(X)
|
||||||
|
; rational(X)
|
||||||
|
).
|
||||||
|
|
||||||
|
stern_brocot_(Qnn/Qnd, Qpn/Qpd, A/B, C/D, Fraction) :-
|
||||||
|
Fn1 is A + C,
|
||||||
|
Fd1 is B + D,
|
||||||
|
simplify_fraction(Fn1/Fd1, Fn/Fd),
|
||||||
|
S1 is sign(Fn * Qnd - Fd * Qnn),
|
||||||
|
S2 is sign(Fn * Qpd - Fd * Qpn),
|
||||||
|
( S1 < 0 -> stern_brocot_(Qnn/Qnd, Qpn/Qpd, Fn/Fd, C/D, Fraction)
|
||||||
|
; S2 > 0 -> stern_brocot_(Qnn/Qnd, Qpn/Qpd, A/B, Fn/Fd, Fraction)
|
||||||
|
; Fraction = Fn/Fd
|
||||||
|
).
|
||||||
|
|
||||||
|
simplify_fraction(A0/B0, A/B) :-
|
||||||
|
G is gcd(A0, B0),
|
||||||
|
A is A0 div G,
|
||||||
|
B is B0 div G.
|
||||||
|
|
||||||
|
rational_numerator_denominator(R, N, D) :-
|
||||||
|
write_term_to_chars(R, [], Cs),
|
||||||
|
append(Ns, [' ', r, d, i, v, ' '|Ds], Cs),
|
||||||
|
number_chars(N, Ns),
|
||||||
|
number_chars(D, Ds).
|
||||||
|
|||||||
@@ -53,12 +53,23 @@ impl CodeRepo {
|
|||||||
self.term_dir
|
self.term_dir
|
||||||
.get_mut(&key)
|
.get_mut(&key)
|
||||||
.map(|entry| {
|
.map(|entry| {
|
||||||
(
|
let terms =
|
||||||
Predicate((entry.0).0.drain(len..).collect()),
|
if len < (entry.0).0.len() {
|
||||||
entry.1.drain(queue_len..).collect(),
|
(entry.0).0.drain(len ..).collect()
|
||||||
)
|
} else {
|
||||||
|
vec![]
|
||||||
|
};
|
||||||
|
|
||||||
|
let queue =
|
||||||
|
if queue_len < entry.1.len() {
|
||||||
|
entry.1.drain(queue_len ..).collect()
|
||||||
|
} else {
|
||||||
|
VecDeque::new()
|
||||||
|
};
|
||||||
|
|
||||||
|
(Predicate(terms), queue)
|
||||||
})
|
})
|
||||||
.unwrap_or((Predicate::new(), VecDeque::from(vec![])))
|
.unwrap_or((Predicate::new(), VecDeque::new()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate)
|
pub(crate)
|
||||||
|
|||||||
@@ -181,6 +181,7 @@ impl<'a> TermStream<'a> {
|
|||||||
te_len,
|
te_len,
|
||||||
te_queue_len,
|
te_queue_len,
|
||||||
);
|
);
|
||||||
|
|
||||||
let goal_expansion_additions = self.wam.code_repo.truncate_terms(
|
let goal_expansion_additions = self.wam.code_repo.truncate_terms(
|
||||||
(clause_name!("goal_expansion"), 2),
|
(clause_name!("goal_expansion"), 2),
|
||||||
ge_len,
|
ge_len,
|
||||||
|
|||||||
Reference in New Issue
Block a user