-/** Helper function to divide rational functions, as needed in any Bareiss
- * elimination scheme over a quotient field.
- *
- * @see divide() */
-bool rat_divide(const ex & a, const ex & b, ex & q, bool check_args = true)
-{
- q = _ex0();
- if (b.is_zero())
- throw(std::overflow_error("rat_divide(): division by zero"));
- if (a.is_zero())
- return true;
- if (is_ex_exactly_of_type(b, numeric)) {
- q = a / b;
- return true;
- } else if (is_ex_exactly_of_type(a, numeric))
- return false;
- ex a_n = a.numer();
- ex a_d = a.denom();
- ex b_n = b.numer();
- ex b_d = b.denom();
- ex n; // new numerator
- ex d; // new denominator
- bool check = true;
- check &= divide(a_n, b_n, n, check_args);
- check &= divide(a_d, b_d, d, check_args);
- q = n/d;
- return check;
-}
-
-
-/** Determinant computed by using fraction free elimination. This
- * routine is only called internally by matrix::determinant().
- *
- * @param normalize may be set to false only in integral domains. */
-ex matrix::determinant_bareiss(bool normalize) const
-{
- if (rows()==1)
- return m[0];
-
- int sign = 1;
- ex divisor = 1;
- ex dividend;
-
- // we populate a tmp matrix to subsequently operate on, it should
- // be normalized even though this algorithm doesn't need GCDs since
- // the elements of *this might be unnormalized, which complicates
- // things:
- matrix tmp(*this);
- exvector::const_iterator i = m.begin();
- exvector::iterator ti = tmp.m.begin();
- for (; i!= m.end(); ++i, ++ti) {
- if (normalize)
- (*ti) = (*i).normal();
- else
- (*ti) = (*i);
- }
-
- for (unsigned r1=0; r1<row-1; ++r1) {
- int indx = tmp.pivot(r1);
- if (indx==-1)
- return _ex0();
- if (indx>0)
- sign = -sign;
- if (r1>0) {
- divisor = tmp.m[(r1-1)*col+(r1-1)].expand();
- // delete the elements we don't need anymore:
- for (unsigned c=0; c<col; ++c)
- tmp.m[(r1-1)*col+c] = _ex0();
- }
- for (unsigned r2=r1+1; r2<row; ++r2) {
- for (unsigned c=r1+1; c<col; ++c) {
- lst srl; // symbol replacement list for .to_rational()
- dividend = (tmp.m[r1*tmp.col+r1]*tmp.m[r2*tmp.col+c]
- -tmp.m[r2*tmp.col+r1]*tmp.m[r1*tmp.col+c]).expand();
- if (normalize) {
-#ifdef DO_GINAC_ASSERT
- GINAC_ASSERT(rat_divide(dividend.to_rational(srl),
- divisor.to_rational(srl),
- tmp.m[r2*tmp.col+c],true));
-#else
- rat_divide(dividend.to_rational(srl),
- divisor.to_rational(srl),
- tmp.m[r2*tmp.col+c],false);
-#endif
- }
- else {
-#ifdef DO_GINAC_ASSERT
- GINAC_ASSERT(divide(dividend.to_rational(srl),
- divisor.to_rational(srl),
- tmp.m[r2*tmp.col+c],true));
-#else
- divide(dividend.to_rational(srl),
- divisor.to_rational(srl),
- tmp.m[r2*tmp.col+c],false);
-#endif
- }
- tmp.m[r2*tmp.col+c] = tmp.m[r2*tmp.col+c].subs(srl);
- }
- for (unsigned c=0; c<=r1; ++c)
- tmp.m[r2*tmp.col+c] = _ex0();
- }
- }
-
- return sign*tmp.m[tmp.row*tmp.col-1];
-}
-