div/2 operators (from WG17 and #176)
This commit is contained in:
parent
4e04e87ab6
commit
e4a15cba33
66
C/arith2.c
66
C/arith2.c
@ -101,6 +101,69 @@ zero_divisor:
|
|||||||
return Yap_ArithError(EVALUATION_ERROR_ZERO_DIVISOR, t2, "X is mod 0");
|
return Yap_ArithError(EVALUATION_ERROR_ZERO_DIVISOR, t2, "X is mod 0");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Term
|
||||||
|
p_div2(Term t1, Term t2) {
|
||||||
|
switch (ETypeOfTerm(t1)) {
|
||||||
|
case (CELL)long_int_e:
|
||||||
|
switch (ETypeOfTerm(t2)) {
|
||||||
|
case (CELL)long_int_e:
|
||||||
|
/* two integers */
|
||||||
|
{
|
||||||
|
Int i1 = IntegerOfTerm(t1);
|
||||||
|
Int i2 = IntegerOfTerm(t2);
|
||||||
|
Int res;
|
||||||
|
|
||||||
|
if (i2 == 0) goto zero_divisor;
|
||||||
|
if (i1 == Int_MIN && i2 == -1) {
|
||||||
|
#ifdef USE_GMP
|
||||||
|
return Yap_gmp_add_ints(Int_MAX, 1);
|
||||||
|
#else
|
||||||
|
return Yap_ArithError(EVALUATION_ERROR_INT_OVERFLOW, t1,
|
||||||
|
"// /2 with %d and %d", i1, i2);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
res = (i1 - i1%i2) / i2;
|
||||||
|
RINT(res);
|
||||||
|
}
|
||||||
|
case (CELL)double_e:
|
||||||
|
return Yap_ArithError(TYPE_ERROR_INTEGER, t2, "div/2");
|
||||||
|
case (CELL)big_int_e:
|
||||||
|
#ifdef USE_GMP
|
||||||
|
return Yap_gmp_div_int_big(IntegerOfTerm(t1), t2);
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
RERROR();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case (CELL)double_e:
|
||||||
|
return Yap_ArithError(TYPE_ERROR_INTEGER, t2, "div/2");
|
||||||
|
case (CELL)big_int_e:
|
||||||
|
#ifdef USE_GMP
|
||||||
|
switch (ETypeOfTerm(t2)) {
|
||||||
|
case long_int_e:
|
||||||
|
/* modulo between bignum and integer */
|
||||||
|
{
|
||||||
|
Int i2 = IntegerOfTerm(t2);
|
||||||
|
|
||||||
|
if (i2 == 0) goto zero_divisor;
|
||||||
|
return Yap_gmp_div2_big_int(t1, i2);
|
||||||
|
}
|
||||||
|
case (CELL)big_int_e:
|
||||||
|
/* two bignums */
|
||||||
|
return Yap_gmp_div2_big_big(t1, t2);
|
||||||
|
case double_e:
|
||||||
|
return Yap_ArithError(TYPE_ERROR_INTEGER, t2, "mod/2");
|
||||||
|
default:
|
||||||
|
RERROR();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
RERROR();
|
||||||
|
}
|
||||||
|
zero_divisor:
|
||||||
|
return Yap_ArithError(EVALUATION_ERROR_ZERO_DIVISOR, t2, "X is div 0");
|
||||||
|
}
|
||||||
|
|
||||||
static Term
|
static Term
|
||||||
p_rem(Term t1, Term t2) {
|
p_rem(Term t1, Term t2) {
|
||||||
switch (ETypeOfTerm(t1)) {
|
switch (ETypeOfTerm(t1)) {
|
||||||
@ -912,6 +975,8 @@ eval2(Int fi, Term t1, Term t2) {
|
|||||||
return p_times(t1, t2);
|
return p_times(t1, t2);
|
||||||
case op_div:
|
case op_div:
|
||||||
return p_div(t1, t2);
|
return p_div(t1, t2);
|
||||||
|
case op_idiv:
|
||||||
|
return p_div2(t1, t2);
|
||||||
case op_and:
|
case op_and:
|
||||||
return p_and(t1, t2);
|
return p_and(t1, t2);
|
||||||
case op_or:
|
case op_or:
|
||||||
@ -959,6 +1024,7 @@ static InitBinEntry InitBinTab[] = {
|
|||||||
{"mod", op_mod},
|
{"mod", op_mod},
|
||||||
{"rem", op_rem},
|
{"rem", op_rem},
|
||||||
{"//", op_div},
|
{"//", op_div},
|
||||||
|
{"div", op_idiv},
|
||||||
{"<<", op_sll},
|
{"<<", op_sll},
|
||||||
{">>", op_slr},
|
{">>", op_slr},
|
||||||
{"/\\", op_and},
|
{"/\\", op_and},
|
||||||
|
@ -220,7 +220,7 @@ Yap_gmp_div_int_big(Int i, Term t)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* div i / b using temporary bigint new */
|
/* div b / i using temporary bigint new */
|
||||||
Term
|
Term
|
||||||
Yap_gmp_div_big_int(Term t, Int i)
|
Yap_gmp_div_big_int(Term t, Int i)
|
||||||
{
|
{
|
||||||
@ -263,6 +263,37 @@ Yap_gmp_div_big_int(Term t, Int i)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* div b / i using temporary bigint new */
|
||||||
|
Term
|
||||||
|
Yap_gmp_div2_big_int(Term t, Int i)
|
||||||
|
{
|
||||||
|
CELL *pt = RepAppl(t);
|
||||||
|
if (pt[1] == BIG_INT) {
|
||||||
|
MP_INT new;
|
||||||
|
MP_INT *b = Yap_BigIntOfTerm(t);
|
||||||
|
|
||||||
|
mpz_init_set(&new, b);
|
||||||
|
if (i > 0) {
|
||||||
|
mpz_fdiv_q_ui(&new, &new, i);
|
||||||
|
} else if (i == 0) {
|
||||||
|
return Yap_ArithError(EVALUATION_ERROR_ZERO_DIVISOR, MkIntTerm(0), "// /2");
|
||||||
|
} else {
|
||||||
|
/* we do not handle MIN_INT */
|
||||||
|
mpz_fdiv_q_ui(&new, &new, -i);
|
||||||
|
mpz_neg(&new, &new);
|
||||||
|
}
|
||||||
|
return MkBigAndClose(&new);
|
||||||
|
} else {
|
||||||
|
MP_RAT new;
|
||||||
|
MP_RAT *b = Yap_BigRatOfTerm(t);
|
||||||
|
|
||||||
|
mpq_init(&new);
|
||||||
|
mpq_set_si(&new, i, 1L);
|
||||||
|
mpq_div(&new, b, &new);
|
||||||
|
return MkRatAndClose(&new);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* and i - b using temporary bigint new */
|
/* and i - b using temporary bigint new */
|
||||||
Term
|
Term
|
||||||
Yap_gmp_and_int_big(Int i, Term t)
|
Yap_gmp_and_int_big(Int i, Term t)
|
||||||
@ -533,6 +564,44 @@ Yap_gmp_div_big_big(Term t1, Term t2)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* div i div b using temporary bigint new */
|
||||||
|
Term
|
||||||
|
Yap_gmp_div2_big_big(Term t1, Term t2)
|
||||||
|
{
|
||||||
|
CELL *pt1 = RepAppl(t1);
|
||||||
|
CELL *pt2 = RepAppl(t2);
|
||||||
|
if (pt1[1] == BIG_INT && pt2[1] == BIG_INT) {
|
||||||
|
MP_INT new;
|
||||||
|
MP_INT *b1 = Yap_BigIntOfTerm(t1);
|
||||||
|
MP_INT *b2 = Yap_BigIntOfTerm(t2);
|
||||||
|
|
||||||
|
mpz_init_set(&new, b1);
|
||||||
|
mpz_fdiv_q(&new, &new, b2);
|
||||||
|
return MkBigAndClose(&new);
|
||||||
|
} else {
|
||||||
|
MP_RAT new;
|
||||||
|
MP_RAT *b1, bb1;
|
||||||
|
MP_RAT *b2, bb2;
|
||||||
|
if (pt1[1] == BIG_INT) {
|
||||||
|
b1 = &bb1;
|
||||||
|
mpq_init(b1);
|
||||||
|
mpq_set_z(b1, Yap_BigIntOfTerm(t1));
|
||||||
|
} else {
|
||||||
|
b1 = Yap_BigRatOfTerm(t1);
|
||||||
|
}
|
||||||
|
if (pt2[1] == BIG_INT) {
|
||||||
|
b2 = &bb2;
|
||||||
|
mpq_init(b2);
|
||||||
|
mpq_set_z(b2, Yap_BigIntOfTerm(t2));
|
||||||
|
} else {
|
||||||
|
b2 = Yap_BigRatOfTerm(t2);
|
||||||
|
}
|
||||||
|
mpq_init(&new);
|
||||||
|
mpq_div(&new, b1, b2);
|
||||||
|
return MkRatAndClose(&new);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Term
|
Term
|
||||||
Yap_gmp_and_big_big(Term t1, Term t2)
|
Yap_gmp_and_big_big(Term t1, Term t2)
|
||||||
{
|
{
|
||||||
|
3
H/eval.h
3
H/eval.h
@ -108,6 +108,7 @@ typedef enum {
|
|||||||
op_mod,
|
op_mod,
|
||||||
op_rem,
|
op_rem,
|
||||||
op_div,
|
op_div,
|
||||||
|
op_idiv,
|
||||||
op_sll,
|
op_sll,
|
||||||
op_slr,
|
op_slr,
|
||||||
op_and,
|
op_and,
|
||||||
@ -236,6 +237,7 @@ Term STD_PROTO(Yap_gmp_sub_big_int,(Term, Int));
|
|||||||
Term STD_PROTO(Yap_gmp_mul_int_big,(Int, Term));
|
Term STD_PROTO(Yap_gmp_mul_int_big,(Int, Term));
|
||||||
Term STD_PROTO(Yap_gmp_div_int_big,(Int, Term));
|
Term STD_PROTO(Yap_gmp_div_int_big,(Int, Term));
|
||||||
Term STD_PROTO(Yap_gmp_div_big_int,(Term, Int));
|
Term STD_PROTO(Yap_gmp_div_big_int,(Term, Int));
|
||||||
|
Term STD_PROTO(Yap_gmp_div2_big_int,(Term, Int));
|
||||||
Term STD_PROTO(Yap_gmp_fdiv_int_big,(Int, Term));
|
Term STD_PROTO(Yap_gmp_fdiv_int_big,(Int, Term));
|
||||||
Term STD_PROTO(Yap_gmp_fdiv_big_int,(Term, Int));
|
Term STD_PROTO(Yap_gmp_fdiv_big_int,(Term, Int));
|
||||||
Term STD_PROTO(Yap_gmp_and_int_big,(Int, Term));
|
Term STD_PROTO(Yap_gmp_and_int_big,(Int, Term));
|
||||||
@ -246,6 +248,7 @@ Term STD_PROTO(Yap_gmp_add_big_big,(Term, Term));
|
|||||||
Term STD_PROTO(Yap_gmp_sub_big_big,(Term, Term));
|
Term STD_PROTO(Yap_gmp_sub_big_big,(Term, Term));
|
||||||
Term STD_PROTO(Yap_gmp_mul_big_big,(Term, Term));
|
Term STD_PROTO(Yap_gmp_mul_big_big,(Term, Term));
|
||||||
Term STD_PROTO(Yap_gmp_div_big_big,(Term, Term));
|
Term STD_PROTO(Yap_gmp_div_big_big,(Term, Term));
|
||||||
|
Term STD_PROTO(Yap_gmp_div2_big_big,(Term, Term));
|
||||||
Term STD_PROTO(Yap_gmp_fdiv_big_big,(Term, Term));
|
Term STD_PROTO(Yap_gmp_fdiv_big_big,(Term, Term));
|
||||||
Term STD_PROTO(Yap_gmp_and_big_big,(Term, Term));
|
Term STD_PROTO(Yap_gmp_and_big_big,(Term, Term));
|
||||||
Term STD_PROTO(Yap_gmp_ior_big_big,(Term, Term));
|
Term STD_PROTO(Yap_gmp_ior_big_big,(Term, Term));
|
||||||
|
@ -3903,6 +3903,9 @@ Integer remainder.
|
|||||||
@item @var{X} rem @var{Y} [ISO]
|
@item @var{X} rem @var{Y} [ISO]
|
||||||
Integer remainder, the same as @code{mod}.
|
Integer remainder, the same as @code{mod}.
|
||||||
|
|
||||||
|
@item @var{X} div @var{Y} [ISO]
|
||||||
|
Integer division, as if defined by @code{(@var{X} - @var{X} mod @var{Y}) // @var{Y}}.
|
||||||
|
|
||||||
@item exp(@var{X}) [ISO]
|
@item exp(@var{X}) [ISO]
|
||||||
Natural exponential.
|
Natural exponential.
|
||||||
|
|
||||||
@ -15850,6 +15853,7 @@ a solution was found.
|
|||||||
Notice that you cannot create new slots if an YAP_EnterGoal goal is open.
|
Notice that you cannot create new slots if an YAP_EnterGoal goal is open.
|
||||||
|
|
||||||
@item @code{YAP_Bool} YAP_RetryGoal(@code{YAP_dogoalinfo *} @var{infop})
|
@item @code{YAP_Bool} YAP_RetryGoal(@code{YAP_dogoalinfo *} @var{infop})
|
||||||
|
|
||||||
@findex YAP_RetryGoal (C-Interface function)
|
@findex YAP_RetryGoal (C-Interface function)
|
||||||
Backtrack to a query created by @code{YAP_EnterGoal}. The query is
|
Backtrack to a query created by @code{YAP_EnterGoal}. The query is
|
||||||
given by the handle @var{infop}. Returns whether a new solution could
|
given by the handle @var{infop}. Returns whether a new solution could
|
||||||
|
Reference in New Issue
Block a user