URI:
       dc: Don't use negative numbers in divscale() - sbase - suckless unix tools
  HTML git clone git://git.suckless.org/sbase
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit b7e30e59700d9af15a83ce9dc06a05b4f7926332
   DIR parent a2940adeba5293032f6ceb7d218dc9f09d6de984
  HTML Author: Roberto E. Vargas Caballero <k0ga@shike2.net>
       Date:   Tue, 20 Jan 2026 16:00:33 +0100
       
       dc: Don't use negative numbers in divscale()
       
       Divscale uses the function muln() that is not prepared to handle
       negative numbers. The solution is to convert them to positive
       numbers and handle the sign in divnum() and modnum(). We don't
       need a copy of the parameters because they are used directly
       with values from the stack, or from the expnum() function that
       discards the input parameters when it calls divnum().
       
       Diffstat:
         M dc.c                                |      28 +++++++++++++++++++++++++++-
         A tests/0049-dc.sh                    |      16 ++++++++++++++++
       
       2 files changed, 43 insertions(+), 1 deletion(-)
       ---
   DIR diff --git a/dc.c b/dc.c
       @@ -876,16 +876,39 @@ divscale(Num *divd, Num *divr)
        static Num *
        divnum(Num *a, Num *b)
        {
       +        Num *r;
       +        int siga, sigb;
       +
       +        siga = negative(a);
       +        if (siga)
       +                chsign(a);
       +
       +        sigb = negative(b);
       +        if (sigb)
       +                chsign(b);
       +
                if (!divscale(a, b))
                        return copy(&zero);
        
       -        return divmod(a, b, NULL);
       +        r = divmod(a, b, NULL);
       +        if (siga ^ sigb)
       +                chsign(r);
       +        return r;
        }
        
        static Num *
        modnum(Num *a, Num *b)
        {
                Num *mod, *c;
       +        int siga, sigb;
       +
       +        siga = negative(a);
       +        if (siga)
       +                chsign(a);
       +
       +        sigb = negative(b);
       +        if (sigb)
       +                chsign(b);
        
                if (!divscale(a, b))
                        return copy(&zero);
       @@ -893,6 +916,9 @@ modnum(Num *a, Num *b)
                c = divmod(a, b, &mod);
                freenum(c);
        
       +        if (siga)
       +                chsign(mod);
       +
                return mod;
        }
        
   DIR diff --git a/tests/0049-dc.sh b/tests/0049-dc.sh
       @@ -0,0 +1,16 @@
       +#!/bin/sh
       +
       +tmp=$$.tmp
       +
       +trap 'rm -f $tmp' EXIT
       +trap 'exit $?' HUP INT TERM
       +
       +cat <<'EOF' > $tmp
       +-.2840790438404122960275
       +EOF
       +
       +$EXEC ../dc <<'EOF' | diff -u - $tmp
       +22k
       +_.1755705045849462583368
       +.618033988749894848204/p
       +EOF