[GiNaC-devel] [PATCH] Improve (fix?) smod: now it really converts into symmetric representation...

Richard B. Kreckel kreckel at ginac.de
Tue Jan 20 00:59:41 CET 2009


Dear Alexei,

Alexei Sheplyakov wrote:
> ... instead of clumsy convention inspirited by some proprietary CAS.

Ironically, your patch seems to adjust smod to the definition of that 
proprietary CAS.  ;-)

> ---
>  doc/tutorial/ginac.texi |    2 +-
>  ginac/numeric.cpp       |   19 +++++++++++--------
>  2 files changed, 12 insertions(+), 9 deletions(-)
> 
> diff --git a/doc/tutorial/ginac.texi b/doc/tutorial/ginac.texi
> index 3207a96..fe7a264 100644
> --- a/doc/tutorial/ginac.texi
> +++ b/doc/tutorial/ginac.texi
> @@ -1479,7 +1479,7 @@ evaluated immediately:
>  @tab modulus in positive representation (in the range @code{[0, abs(b)-1]} with the sign of b, or zero)
>  @cindex @code{mod()}
>  @item @code{smod(a, b)}
> - at tab modulus in symmetric representation (in the range @code{[-iquo(abs(b)-1, 2), iquo(abs(b), 2)]})
> + at tab modulus in symmetric representation (in the range @code{[-iquo(abs(b), 2), iquo(abs(b), 2)]})
>  @cindex @code{smod()}
>  @item @code{irem(a, b)}
>  @tab integer remainder (has the sign of @math{a}, or is zero)
> diff --git a/ginac/numeric.cpp b/ginac/numeric.cpp
> index 91721e1..50d873a 100644
> --- a/ginac/numeric.cpp
> +++ b/ginac/numeric.cpp
> @@ -2337,15 +2337,18 @@ const numeric mod(const numeric &a, const numeric &b)
>  
>  
>  /** Modulus (in symmetric representation).
> - *  Equivalent to Maple's mods.
>   *
> - *  @return a mod b in the range [-iquo(abs(b)-1,2), iquo(abs(b),2)]. */
> -const numeric smod(const numeric &a, const numeric &b)
> -{
> -	if (a.is_integer() && b.is_integer()) {
> -		const cln::cl_I b2 = cln::ceiling1(cln::the<cln::cl_I>(b.to_cl_N()) >> 1) - 1;
> -		return numeric(cln::mod(cln::the<cln::cl_I>(a.to_cl_N()) + b2,
> -		                cln::the<cln::cl_I>(b.to_cl_N())) - b2);
> + *  @return a mod b in the range [-iquo(abs(b),2), iquo(abs(b),2)]. */
> +const numeric smod(const numeric &a_, const numeric &b_)
> +{
> +	if (a_.is_integer() && b_.is_integer()) {
> +		const cln::cl_I a = cln::the<cln::cl_I>(a_.to_cl_N());
> +		const cln::cl_I b = cln::the<cln::cl_I>(b_.to_cl_N());
> +		const cln::cl_I b2 = b >> 1;
> +		const cln::cl_I m = cln::mod(a, b);
> +		const cln::cl_I m_b = m - b;
> +		const cln::cl_I ret = m > b2 ? m_b : m;
> +		return numeric(ret);
>  	} else
>  		return *_num0_p;
>  }

Looking at the comment and the documentation, though, it appears like 
your patch really adjusts it to what it was always meant to do. The 
interval of your function *is* [-iquo(abs(b)-1,2), iquo(abs(b),2)], and 
not [-iquo(abs(b),2), iquo(abs(b),2)]. This is as "symmetric" as it can get.

E.g. -iquo(abs(4)-1,2) = -1, but -iquo(abs(4),2) = -2, and we have:
smod(-2,4)==+2
smod(-1,4)==-1
smod(+0,4)== 0
smod(+1,4)==+1
smod(+2,4)==+2
smod(+3,4)==-1

Cheers
    -richy.
-- 
Richard B. Kreckel
<http://www.ginac.de/~kreckel/>


More information about the GiNaC-devel mailing list