It is understandable that it may not be used in GMP, it was mainly
developed to reduce the time for multiplications of two interval numbers.
The returned limb in this case can be used to "extend the precision of
the produced result"/reduce the produced interval compared to when
simply using MPFR's mulhigh.
Now, MPFR does not deal with interval arithmetic, but for interval
arithmetic where we can afford a somewhat more sloppy interval, this
will speed up computations compared to simply using mpn_mul_basecase.
For profiling results (comparing against mpn_mul_basecase and
mpfr_mulhigh_n) on Zen 3, see
https://github.com/flintlib/flint/pull/1768#issuecomment-1930356804.
More importantly, this function probably reduces the number of
reallocations as we do not require a destination with `2 * n' limbs, but
rather `n' limbs.
Best,
Albin
On 2/11/24 19:35, marco.bodr...@tutanota.com wrote:
Thank you Albin,
currently we don't have any mulhi function, so we didn't decide a
possible interface for it.
There are some comments in the code where a full mul is used, but some
"mulhi" function could be enough. Many of them seem to use unbalanced
operands, and might require the exact result or more limbs than the
higher half...
By the way, I like the idea of computing one more limb, that way one may
know whether the limbs obtained by mulhi are exact or not.
Ĝis,
mb
6 feb 2024, 23:27 da albin.ahlb...@gmail.com:
Hello,
I just wrote an implementation for mpn_mulhigh_basecase for
Broadwell-type processors (that is, x86_64 with BMI2 and ADX
instructions) based on Torbjörn's `mpn_mullo_basecase'.
It is currently declared on the form
mp_limb_t flint_mpn_mulhigh_basecase(mp_ptr rp, mp_srcptr xp,
mp_srcptr yp, mp_size_t n),
as it was developed for FLINT (Fast Library for Number Theory). Note
that `rp' cannot be aliased with `xp' or `yp'.
It will compute an approximation of the upper most `n + 1' limbs of
`{xp, n}' times `{yp, n}', where the upper most `n' limbs are pushed
to `rp[0]', ..., `rp[n - 1]' and the least significant computed limb
is returned (via %rax). This returned limb should have an error of
something along `n' ULPs.
Note that this differs from MPFR's (private) function
`mpfr_mulhigh_n', which computes the approximation of the upper most
`n' limbs into `rp[n]', ..., `rp[2 * n - 1]', where `rp[n]' has an
error of something along `n' ULPs at most.
Feel free to change it according to your needs (perhaps you do not
want to compute `n + 1' limbs, but rather `n' limbs).
If this code will be used in GMP, feel free to remove the copyright
claim for FLINT and put my name (spelled Albin Ahlbäck) in the GMP
copyright claim instead.
Just some notes:
- We use our own M4 syntax for the beginning and ending of the
function, but it should be easy to translate to GMP's syntax.
- It currently only works for n > 5 (I believe) as we in FLINT have
specialized routines for small n.
- It would be nice to avoid pushing five register, and only push four.
- Reduce the size of the `L(end)' code, and try to avoid multiple
jumps therein.
- Move the code-snippet of `L(f2)' to just above `L(b2)', so that no
jump is needed in between. (This currently does not work because
`L(end)' as well as this code-snippet is too large for a relative
8-bit jump.)
- Start out with an mul_1 sequence with just a mulx+add+adc chain,
just like in `mpn_mullo_basecase'.
- Remove the first multiplication in each `L(fX)' and put it in
`L(end)' instead.
- The `adcx' instruction in `L(fX)' can be removed (then one needs
to adjust the `L(bX)'-label), but I found it to be slower. Can we
remove it and somehow maintain the same performance?
Best,
Albin
_______________________________________________
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel