static conts limbs_per_fixnum = (FIXNUM_BITS + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS;
#endif
-#define WITH_TEMP_BIGNUM(name,n) \
- mp_limb_t name##data[n]; \
- volatile struct ecl_bignum name##aux; \
- const cl_object name = (name##aux.big_num->_mp_alloc = n, \
- name##aux.big_num->_mp_size = 0, \
- name##aux.big_num->_mp_d = name##data, \
- (cl_object)(&name##aux))
cl_object
_ecl_fix_times_fix(cl_fixnum x, cl_fixnum y)
{
#if ECL_LONG_BITS >= FIXNUM_BITS
- WITH_TEMP_BIGNUM(z,4);
+ ECL_WITH_TEMP_BIGNUM(z,4);
mpz_set_si(z->big.big_num, x);
mpz_mul_si(z->big.big_num, z->big.big_num, y);
#else
- WITH_TEMP_BIGNUM(z,4);
- WITH_TEMP_BIGNUM(w,4);
+ ECL_WITH_TEMP_BIGNUM(z,4);
+ ECL_WITH_TEMP_BIGNUM(w,4);
mpz_set_si(z->big.big_num, x);
mpz_set_si(w->big.big_num, y);
mpz_mu(z->big.big_num, z->big.big_num, w->big.big_num);
return big_normalize(z);
}
+cl_object
+_ecl_big_divided_by_big(cl_object a, cl_object b)
+{
+ cl_object z;
+ cl_index size_a = (a->big.big_size < 0)? -a->big.big_size : a->big.big_size;
+ cl_index size_b = (b->big.big_size < 0)? -b->big.big_size : b->big.big_size;
+ cl_fixnum size_z = size_a - size_b + 1;
+ if (size_z <= 0) size_z = 1;
+ z = _ecl_alloc_compact_bignum(size_z);
+ mpz_tdiv_q(z->big.big_num,a->big.big_num,b->big.big_num);
+ return big_normalize(z);
+}
+
+cl_object
+_ecl_big_divided_by_fix(cl_object x, cl_fixnum y)
+{
+ ECL_WITH_TEMP_BIGNUM(by, 2);
+ _ecl_big_set_fixnum(by, y);
+ return _ecl_big_divided_by_big(x, by);
+}
+
+cl_object
+_ecl_big_ceiling(cl_object a, cl_object b, cl_object *pr)
+{
+ cl_object q = _ecl_big_register0();
+ cl_object r = _ecl_big_register1();
+ mpz_cdiv_qr(q->big.big_num, r->big.big_num, a->big.big_num, b->big.big_num);
+ *pr = _ecl_big_register_normalize(r);
+ return _ecl_big_register_normalize(q);
+}
+
+cl_object
+_ecl_big_floor(cl_object a, cl_object b, cl_object *pr)
+{
+ cl_object q = _ecl_big_register0();
+ cl_object r = _ecl_big_register1();
+ mpz_fdiv_qr(q->big.big_num, r->big.big_num, a->big.big_num, b->big.big_num);
+ *pr = _ecl_big_register_normalize(r);
+ return _ecl_big_register_normalize(q);
+}
+
+cl_object
+_ecl_fix_divided_by_big(cl_fixnum x, cl_object y)
+{
+ ECL_WITH_TEMP_BIGNUM(bx, 2);
+ _ecl_big_set_fixnum(bx, x);
+ return _ecl_big_divided_by_big(bx, y);
+}
+
static void *
mp_alloc(size_t size)
{
z->big.big_num = x->big.big_num + y;
return big_normalize(z);
}
+
cl_object
_ecl_fix_times_fix(cl_fixnum x, cl_fixnum y)
{
return big_normalize(z);
}
+cl_object
+_ecl_big_ceiling(cl_object a, cl_object b, cl_object *pr)
+{
+ cl_object q = ecl_alloc_object(t_bignum);
+ cl_object r = ecl_alloc_object(t_bignum);
+ q->big.num = x->big.num / y->big.big_num;
+ r->big.num = x->big.num % y->big.big_num;
+ *pr = big_normalize(r);
+ return big_normalize(q);
+}
+
+cl_object
+_ecl_big_floor(cl_object a, cl_object b, cl_object *pr)
+{
+ cl_object q = ecl_alloc_object(t_bignum);
+ cl_object r = ecl_alloc_object(t_bignum);
+ q->big.num = x->big.num / y->big.big_num;
+ r->big.num = x->big.num % y->big.big_num;
+ *pr = big_normalize(r);
+ return big_normalize(q);
+}
cl_object
_ecl_big_negate(cl_object x)
if (y == MAKE_FIXNUM(0))
FEdivision_by_zero(x, y);
return MAKE_FIXNUM(fix(x) / fix(y));
- }
- if (ty == t_bignum) {
- /* The only number "x" which can be a bignum and be
- * as large as "-x" is -MOST_NEGATIVE_FIXNUM. However
- * in newer versions of ECL we will probably choose
- * MOST_NEGATIVE_FIXNUM = - MOST_POSITIVE_FIXNUM.
- */
- if (-MOST_NEGATIVE_FIXNUM > MOST_POSITIVE_FIXNUM) {
- if (_ecl_big_cmp_si(y, -fix(x)))
- return MAKE_FIXNUM(0);
- else
- return MAKE_FIXNUM(-1);
- } else {
- return MAKE_FIXNUM(0);
- }
- }
- FEtype_error_integer(y);
+ } else if (ty == t_bignum) {
+ return _ecl_fix_divided_by_big(fix(x), y);
+ } else {
+ FEtype_error_integer(y);
+ }
}
if (tx == t_bignum) {
- cl_object q = _ecl_big_register0();
if (ty == t_bignum) {
- _ecl_big_tdiv_q(q, x, y);
+ return _ecl_big_divided_by_big(x, y);
} else if (ty == t_fixnum) {
- long j = fix(y);
- _ecl_big_tdiv_q_ui(q, x, labs(j));
- if (j < 0)
- _ecl_big_complement(q, q);
+ return _ecl_big_divided_by_fix(x, fix(y));
} else {
FEtype_error_integer(y);
}
- return _ecl_big_register_normalize(q);
}
FEtype_error_integer(x);
}
* x = MOST_NEGATIVE_FIXNUM
* y = - MOST_NEGATIVE_FIXNUM
*/
- cl_object q = _ecl_big_register0();
- cl_object r = _ecl_big_register1();
-#ifdef WITH_GMP
- cl_object j = _ecl_big_register2();
- mpz_set_si(j->big.big_num, fix(x));
- mpz_fdiv_qr(q->big.big_num, r->big.big_num, j->big.big_num, y->big.big_num);
-#else /* WITH_GMP */
- q->big.big_num = (big_num_t)fix(x) / y->big.big_num;
- r->big.big_num = (big_num_t)fix(x) % y->big.big_num;
-#endif /* WITH_GMP */
- v0 = _ecl_big_register_normalize(q);
- v1 = _ecl_big_register_normalize(r);
+ ECL_WITH_TEMP_BIGNUM(bx,4);
+ _ecl_big_set_fixnum(bx, fix(x));
+ v0 = _ecl_big_floor(bx, y, &v1);
break;
}
case t_ratio: /* FIX / RAT */
case t_bignum:
switch(ty) {
case t_fixnum: { /* BIG / FIX */
- cl_object q = _ecl_big_register0();
- cl_object r = _ecl_big_register1();
-#ifdef WITH_GMP
- cl_object j = _ecl_big_register2();
- mpz_set_si(j->big.big_num, fix(y));
- mpz_fdiv_qr(q->big.big_num, r->big.big_num, x->big.big_num, j->big.big_num);
-#else /* WITH_GMP */
- q->big.big_num = x->big.big_num / fix(y);
- r->big.big_num = x->big.big_num % fix(y);
-#endif /* WITH_GMP */
- v0 = _ecl_big_register_normalize(q);
- v1 = _ecl_big_register_normalize(r);
+ ECL_WITH_TEMP_BIGNUM(by,4);
+ _ecl_big_set_fixnum(by, fix(y));
+ v0 = _ecl_big_floor(x, by, &v1);
break;
}
case t_bignum: { /* BIG / BIG */
- cl_object q = _ecl_big_register0();
- cl_object r = _ecl_big_register1();
-#ifdef WITH_GMP
- mpz_fdiv_qr(q->big.big_num, r->big.big_num, x->big.big_num, y->big.big_num);
-#else /* WITH_GMP */
- q = x->big.big_num / y->big.big_num;
- r = x->big.big_num % y->big.big_num;
-#endif /* WITH_GMP */
- v0 = _ecl_big_register_normalize(q);
- v1 = _ecl_big_register_normalize(r);
+ v0 = _ecl_big_floor(x, y, &v1);
break;
}
case t_ratio: /* BIG / RAT */
* x = MOST_NEGATIVE_FIXNUM
* y = - MOST_NEGATIVE_FIXNUM
*/
- cl_object q = _ecl_big_register0();
- cl_object r = _ecl_big_register1();
-#ifdef WITH_GMP
- cl_object j = _ecl_big_register2();
- mpz_set_si(j->big.big_num, fix(x));
- mpz_cdiv_qr(q->big.big_num, r->big.big_num, j->big.big_num, y->big.big_num);
-#else /* WITH_GMP */
- q = (big_num_t)fix(x) / y->big.big_num;
- r = (big_num_t)fix(x) % y->big.big_num;
-#endif /* WITH_GMP */
- v0 = _ecl_big_register_normalize(q);
- v1 = _ecl_big_register_normalize(r);
+ ECL_WITH_TEMP_BIGNUM(bx,4);
+ _ecl_big_set_fixnum(bx, fix(x));
+ v0 = _ecl_big_ceiling(bx, y, &v1);
break;
}
case t_ratio: /* FIX / RAT */
case t_bignum:
switch(type_of(y)) {
case t_fixnum: { /* BIG / FIX */
- cl_object q = _ecl_big_register0();
- cl_object r = _ecl_big_register1();
-#ifdef WITH_GMP
- cl_object j = _ecl_big_register2();
- mpz_set_si(j->big.big_num, fix(y));
- mpz_cdiv_qr(q->big.big_num, r->big.big_num, x->big.big_num, j->big.big_num);
-#else /* WITH_GMP */
- q = x->big.big_num / fix(y);
- r = x->big.big_num % fix(y);
-#endif /* WITH_GMP */
- v0 = _ecl_big_register_normalize(q);
- v1 = _ecl_big_register_normalize(r);
+ ECL_WITH_TEMP_BIGNUM(by,4);
+ _ecl_big_set_fixnum(by, fix(y));
+ v0 = _ecl_big_ceiling(x, by, &v1);
break;
}
case t_bignum: { /* BIG / BIG */
- cl_object q = _ecl_big_register0();
- cl_object r = _ecl_big_register1();
-#ifdef WITH_GMP
- mpz_cdiv_qr(q->big.big_num, r->big.big_num, x->big.big_num, y->big.big_num);
-#else /* WITH_GMP */
- q->big.big_num = x->big.big_num / y->big.big_num;
- r->big.big_num = x->big.big_num % y->big.big_num;
-#endif /* WITH_GMP */
- v0 = _ecl_big_register_normalize(q);
- v1 = _ecl_big_register_normalize(r);
+ v0 = _ecl_big_ceiling(x, y, &v1);
break;
}
case t_ratio: /* BIG / RAT */
"(double)(#0)*(double)(#1)" :exact-return-type t)
(def-inline * :always (fixnum-float fixnum-float) :float
"(float)(#0)*(float)(#1)" :exact-return-type t)
-(def-inline * :always (fixnum fixnum) t "fixnum_times(#0,#1)" :exact-return-type t)
+(def-inline * :always (fixnum fixnum) t "_ecl_fix_times_fix(#0,#1)" :exact-return-type t)
(def-inline * :always (fixnum fixnum) :fixnum "(#0)*(#1)" :exact-return-type t)
(proclaim-function / (t *) t :no-side-effects t)
extern ECL_API cl_object _ecl_big_plus_big(cl_object x, cl_object y);
extern ECL_API cl_object _ecl_fix_minus_big(cl_fixnum x, cl_object y);
extern ECL_API cl_object _ecl_big_minus_big(cl_object x, cl_object y);
+extern ECL_API cl_object _ecl_fix_divided_by_big(cl_fixnum x, cl_object y);
+extern ECL_API cl_object _ecl_big_divided_by_fix(cl_object x, cl_fixnum y);
+extern ECL_API cl_object _ecl_big_divided_by_big(cl_object x, cl_object y);
+extern ECL_API cl_object _ecl_big_ceiling(cl_object x, cl_object y, cl_object *r);
+extern ECL_API cl_object _ecl_big_floor(cl_object x, cl_object y, cl_object *r);
extern ECL_API cl_object _ecl_big_negate(cl_object x);
extern ECL_API void _ecl_big_register_free(cl_object x);
extern ECL_API cl_object bignum1(cl_fixnum val);
#define ECL_BIG_REGISTER_SIZE 32
#ifdef WITH_GMP
+#define ECL_WITH_TEMP_BIGNUM(name,n) \
+ mp_limb_t name##data[n]; \
+ volatile struct ecl_bignum name##aux; \
+ const cl_object name = (name##aux.big_num->_mp_alloc = n, \
+ name##aux.big_num->_mp_size = 0, \
+ name##aux.big_num->_mp_d = name##data, \
+ (cl_object)(&name##aux))
#if ECL_LONG_BITS >= FIXNUM_BITS
#define _ecl_big_set_fixnum(x, f) mpz_set_si((x)->big.big_num,(f))
#define _ecl_big_set_index(x, f) mpz_set_ui((x)->big.big_num,(f))
#else /* WITH_GMP */
+#define ECL_WITH_TEMP_BIGNUM(name,n) \
+ volatile struct ecl_bignum name##aux; \
+ const cl_object name = (name##aux.big_num = 0, \
+ (cl_object)(&name##aux))
#define _ecl_big_set_fixnum(x,f) ((x)->big.big_num=(f))
#define _ecl_big_set_index(x,f) ((x)->big.big_num=(f))
#define _ecl_big_init2(x,size) ((x)->big.big_num=0)
"(double)(#0)*(double)(#1)" :exact-return-type t)
(def-inline * :always (fixnum-float fixnum-float) :float
"(float)(#0)*(float)(#1)" :exact-return-type t)
-(def-inline * :always (fixnum fixnum) t "fixnum_times(#0,#1)" :exact-return-type t)
+(def-inline * :always (fixnum fixnum) t "_ecl_fix_times_fix(#0,#1)" :exact-return-type t)
(def-inline * :always (fixnum fixnum) :fixnum "(#0)*(#1)" :exact-return-type t)
(def-inline / :always (t t) t "ecl_divide(#0,#1)")