int elem_equal(elem_srcptr op1, elem_srcptr op2, const ring_t ring) { switch (ring->type) { case TYPE_FMPZ: return fmpz_equal(op1, op2); case TYPE_LIMB: return *((mp_srcptr) op1) == *((mp_srcptr) op2); case TYPE_POLY: return elem_poly_equal(op1, op2, ring); case TYPE_MOD: return elem_equal(op1, op2, ring->parent); case TYPE_FRAC: return elem_equal(NUMER(op1, ring), NUMER(op2, ring), RING_NUMER(ring)) && elem_equal(DENOM(op1, ring), DENOM(op2, ring), RING_DENOM(ring)); case TYPE_COMPLEX: return elem_equal(REALPART(op1, ring), REALPART(op2, ring), RING_PARENT(ring)) && elem_equal(IMAGPART(op1, ring), IMAGPART(op2, ring), RING_PARENT(ring)); default: NOT_IMPLEMENTED("equal", ring); } }
void elem_frac_poly_divrem(elem_ptr Q, elem_ptr R, elem_srcptr A, elem_srcptr B, const ring_t ring) { if (elem_is_zero(B, ring)) { printf("Exception: division by zero in elem_frac_poly_divrem\n"); abort(); } else if (Q == R) { printf("Exception: output arguments Q and R may not be aliased\n"); abort(); } else if (((const elem_poly_struct *) A)->length < ((const elem_poly_struct *) B)->length) { elem_set(R, A, ring); elem_zero(Q, ring); } else if (Q == A || Q == B) { elem_ptr tmp; ELEM_TMP_INIT(tmp, ring); elem_frac_poly_divrem(tmp, R, A, B, ring); elem_swap(Q, tmp, ring); ELEM_TMP_CLEAR(tmp, ring); } else if (R == B) { elem_ptr tmp; ELEM_TMP_INIT(tmp, ring); elem_frac_poly_divrem(Q, tmp, A, B, ring); elem_swap(R, tmp, ring); ELEM_TMP_CLEAR(tmp, ring); } else { /* if the denominators are the same as coefficients, we can do pseudo division */ if (RING_DENOM(ring) == RING_PARENT(RING_NUMER(ring))) { _elem_frac_poly_divrem_wrap(NUMER(Q, ring), DENOM(Q, ring), NUMER(R, ring), DENOM(R, ring), NUMER(A, ring), DENOM(A, ring), NUMER(B, ring), DENOM(B, ring), RING_NUMER(ring), RING_DENOM(ring)); } else { NOT_IMPLEMENTED("polynomial divrem with different denominator type", ring); } } }
/* Return the product of two expressions */ static exp_t * prod(exp_t *a1, exp_t *a2) { exp_t *res; CHKNUM(a1, *); CHKNUM(a2, *); if (isfloat(a1) || isfloat(a2)) res = nfloat(VALUE(a1) * VALUE(a2)); else res = nrat(NUMER(a1) * NUMER(a2), DENOM(a1) * DENOM(a2)); return res; }
/* Return the division of two expressions */ static exp_t * divs(exp_t *a1, exp_t *a2) { exp_t *res; CHKNUM(a1, /); CHKNUM(a2, /); if (VALUE(a2) == 0) everr("/: argument is divided by zero", a1); if (isfloat(a1) || isfloat(a2)) res = nfloat(VALUE(a1) / VALUE(a2)); else res = nrat(NUMER(a1) * DENOM(a2), NUMER(a2) * DENOM(a1)); return res; }
/* Return the difference of two expressions */ static exp_t * sub(exp_t *a1, exp_t *a2) { long n1, n2, d1, d2; exp_t *res; CHKNUM(a1, -); CHKNUM(a2, -); if (isfloat(a1) || isfloat(a2)) res = nfloat(VALUE(a1) - VALUE(a2)); else { n1 = NUMER(a1), n2 = NUMER(a2); d1 = DENOM(a1), d2 = DENOM(a2); res = nrat(n1*d2 - n2*d1, d1 * d2); } return res; }
void elem_set(elem_ptr res, elem_srcptr src, const ring_t ring) { if (res != src) { switch (ring->type) { case TYPE_FMPZ: fmpz_set(res, src); break; case TYPE_LIMB: *((mp_ptr) res) = *((mp_srcptr) src); break; case TYPE_MOD: elem_set(res, src, ring->parent); break; case TYPE_POLY: elem_poly_set(res, src, ring); break; case TYPE_FRAC: elem_set(NUMER(res, ring), NUMER(src, ring), RING_NUMER(ring)); elem_set(DENOM(res, ring), DENOM(src, ring), RING_DENOM(ring)); break; case TYPE_COMPLEX: elem_set(REALPART(res, ring), REALPART(src, ring), RING_PARENT(ring)); elem_set(IMAGPART(res, ring), IMAGPART(src, ring), RING_PARENT(ring)); break; default: NOT_IMPLEMENTED("set", ring); } } }
void elem_set_si(elem_ptr elem, long v, const ring_t ring) { switch (ring->type) { case TYPE_FMPZ: fmpz_set_si(elem, v); break; case TYPE_LIMB: *((mp_ptr) elem) = v; break; case TYPE_POLY: elem_poly_set_si(elem, v, ring); break; case TYPE_MOD: { switch (RING_PARENT(ring)->type) { case TYPE_FMPZ: fmpz_set_si(elem, v); fmpz_mod(elem, elem, RING_MODULUS(ring)); break; case TYPE_LIMB: *((mp_ptr) elem) = nmod_set_si(v, ring->nmod); break; default: NOT_IMPLEMENTED("set_si (mod)", ring); } } break; case TYPE_FRAC: elem_set_si(NUMER(elem, ring), v, RING_NUMER(ring)); elem_one(DENOM(elem, ring), RING_DENOM(ring)); break; case TYPE_COMPLEX: elem_set_si(REALPART(elem, ring), v, ring->parent); elem_zero(IMAGPART(elem, ring), ring->parent); break; default: NOT_IMPLEMENTED("set_si", ring); } }
void elem_frac_canonicalise(elem_srcptr x, const ring_t ring) { _elem_frac_canonicalise(NUMER(x, ring), DENOM(x, ring), RING_NUMER(ring), RING_DENOM(ring)); }