GNU bug report logs -
#40744
guile-2.2.4 (integer-length 0) erroneously returns 0, not 1
Previous Next
To reply to this bug, email your comments to 40744 AT debbugs.gnu.org.
Toggle the display of automated, internal messages from the tracker.
Report forwarded
to
bug-guix <at> gnu.org
:
bug#40744
; Package
guix
.
(Tue, 21 Apr 2020 13:05:01 GMT)
Full text and
rfc822 format available.
Acknowledgement sent
to
Bengt Richter <bokr <at> bokr.com>
:
New bug report received and forwarded. Copy sent to
bug-guix <at> gnu.org
.
(Tue, 21 Apr 2020 13:05:02 GMT)
Full text and
rfc822 format available.
Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):
Hello guix/guile bug-squashers,
The tl;dr is:
(integer-length 0) should agree with:
(string-length (number->string 0 2)) =-> 1
-- and not: (integer-length 0) =-> 0
The integer length in bits (short for binary digits :)
is the number digits required to write the integer value
in conventional big-endian digit order, signifying coefficients
of successive powers of the radix used.
This applies irrespective of the radix. Thus "11" in decimal is
"1*10^1 + 1*10^0"
or hex is
"11*16^0"
or binary is
"1*2^1 + 1*2^0"
So, the crux of the argument is that it takes one digit to write
either 1 or 0:
--8<---------------cut here---------------start------------->8---
Inputs: 1 (radix 10, decimal value unsigned 1) (output radix 2)
Number as radix-2 glyph{0..1} string (unsigned)
"1"
Number as glyphs representing coefficient values of radix polynomial for number value:
("1")
(1) -- corresponding coefficient values
Number as polynomial expression:
"1*2^0"
(1) -- corresponding term values
1 -- sum of term values
The following should be equal to guile's (integer-length 1):
1 integer-digit (radix 2)
--8<---------------cut here---------------end--------------->8---
--8<---------------cut here---------------start------------->8---
Inputs: 0 (radix 10, decimal value unsigned 0) (output radix 2)
Number as radix-2 glyph{0..1} string (unsigned)
"0"
Number as glyphs representing coefficient values of radix polynomial for number value:
("0")
(0) -- corresponding coefficient values
Number as polynomial expression:
"0*2^0"
(0) -- corresponding term values
0 -- sum of term values
The following should be equal to guile's (integer-length 0):
1 integer-digit (radix 2)
--8<---------------cut here---------------end--------------->8---
BTW, this works for signed numbers as well, if you use a complement
representation making the sign digit 0 for positive and radix-1 for
negative (thus 0 and 1 for radix 2, and e.g. 0 and f for radix 16).
Decimal is just another radix:
Inputs: -11 (radix 10, decimal value minus 11) (output radix 10)
Number as radix-10 glyph{0..9} string (radix-complement -sign prefix)
"989" (complement notation)
^--(note that 0 and "9" (radix10 -1) are sign digits for 0 and -1 coefficient values in the polynomial)
Number as glyphs representing coefficient values of radix polynomial for number value:
("-1" "8" "9")
(-1 8 9) -- corresponding coefficient values
Number as polynomial expression:
"-1*10^2 + 8*10^1 + 9*10^0"
(-100 80 9) -- corresponding term values
-11 -- sum of term values
Tip: for guile integer-length, enter unsigned value with output radix 2
3 integer-digits (radix 10)
The extreme for this version is radix 36:
Inputs: -11 (radix 36, decimal value minus 37) (output radix 36)
Number as radix-36 glyph{0..z} string (radix-complement -sign prefix)
"zyz" (complement notation)
^--(note that 0 and "z" (radix36 -1) are sign digits for 0 and -1 coefficient values in the polynomial)
Number as glyphs representing coefficient values of radix polynomial for number value:
("-1" "y" "z")
(-1 34 35) -- corresponding coefficient values
Number as polynomial expression:
"-1*36^2 + 34*36^1 + 35*36^0"
(-1296 1224 35) -- corresponding term values
-37 -- sum of term values
Tip: for guile integer-length, enter unsigned value with output radix 2
3 integer-digits (radix 36)
I got a little carried away exploring the complement notation, and wrote
a thing to explain the meanings. Please copy snip to int2poly and chmod 755 it.
Then run once without args for usage help.
I hope it will convince you that guile (integer-length 0) should be 1 ;-)
--8<---------------cut here---------------start------------->8---
#!/usr/bin/env -S guile -e main -s
!#
;; run without arguments for usage, or read below
;; int2poly-0.1.0 -- 2020-04-21
(use-modules (ice-9 format)
(ice-9 regex))
(define self (basename (car (command-line))))
(define verbose #f)
(define (usage)
(begin
(let*((selfxxx (basename (car (command-line)))))
(begin
(format (current-error-port)
"Usage:
~a [-v ] | NUMSTR [out-radix] [inp-radix]
where *-radix are entered in decimal, and
out-radix defaults to 2 and inp-radix defaults to 10,
but may set independently to 2..36 to demo generality.
-v for verbose output explanations
NUMSTR will be written in radix digits representing
polynomial coefficients, which is presented in series terms
and evaluated back to the original number.
The NUMSTR character set is the same as for (number->string radix)
but could be any chosen set of distinct glyphs for values {0..<radix -1>}.
guile integer-length can be considered a special case of
coefficient count for radix 2, which is printed in the last
line of output as \"N integer-digits (radix N)\n"
self ))
(if (= (integer-length 0) 0)
(begin
(format #t "\nGuile[1] bug:
(integer-length 0) should agree with:
(string-length (number->string 0 2)) =-> ~s
-- and not: (integer-length 0) =-> ~s
And it should agree with integer-digits for ~a 1 and ~a 0
Try ~a 0, and note that it is 1 for any radix 2-36
and numstr is 10 for ~a radix radix also for any radix ;-)\n\n"
(string-length (number->string 0 2))
(integer-length 0)
self self self self)
(display "[1] ----\n")
(system "guile -v")
(display "----\n ")
)))))
(define (main argl)
(begin
(set! argl (cdr argl))
(if (not (pair? argl)) (begin (usage) (exit)))
(if (string=? "-v" (car argl)) (begin (set! verbose #t) (set! argl (cdr argl))))
(if (not (pair? argl)) (begin (usage) (exit)))
(let*((matstr (string-match "[0-9a-z]+" (string-join argl " "))) ;; for <prefix><substring><suffix>
(sgnstr (match:prefix matstr)) ;; [<sign>]
(absstr (match:substring matstr)) ;; <inpnum> [<out-radix>] [<in-radix>]
(matst2 (string-match "[0-9]+" (match:suffix matstr))) ;; demo radix (spec in decimal) [<out-radix>] [<inp-radix>]
(radix (if matst2 (string->number (match:substring matst2)) 2)) ;; default demo radix is 2
(matst3 (if matst2 (string-match "[0-9]+" (match:suffix matst2)) #f)) ;; [<inp-radix>]
(iradix (if matst3 (string->number (match:substring matst3)) 10)) ;; default input radix 10
(absnum (string->number absstr iradix)) ;; abs math value of input
(abswid (string-length (number->string absnum radix)))
(radixp (integer-expt radix (+ 1 abswid))) ;; 2nd bit above msb of absnum
(usenum (if (string=? "-" sgnstr) (- radixp absnum) (+ radixp absnum))) ;; 10abs or 10000-abs
;; _1xyx
;; or 10000 if abs=0
(numstr1 (number->string usenum radix))
(numoff (if (string=? "" sgnstr)
2
(- (string-length numstr1) (+ 1 abswid))))
(numstr (substring numstr1 numoff))
(coeffs (map match:substring (list-matches "(.)" numstr)))
(coeffs (if (string=? "" sgnstr)
coeffs
(begin
(if (char=? (string-ref numstr 0)
(string-ref (number->string (- radix 1) radix) 0))
(cons "-1" (cdr coeffs))
coeffs))))
(coeffv (map (lambda (s) (string->number s radix)) coeffs))
(ncoeff (length coeffs))
(terms (string-join (reverse (map (lambda (coeff power)
(begin (format #f "~d*~d^~d" coeff radix power))) (reverse coeffv) (iota ncoeff))) " + "))
(termv (reverse (map (lambda (coeff power)
(begin (* coeff (integer-expt radix power)))) (reverse coeffv) (iota ncoeff))))
(polyv (apply + termv))
(signword (begin (cond
((string=? "" sgnstr) "unsigned")
((string=? "+" sgnstr) "plus")
((string=? "-" sgnstr) "minus")
(else (throw 'int2poly "bad sign:" sgnstr)))))
(sgnnote (begin (cond
((string=? "" sgnstr) "(unsigned)")
((string=? "+" sgnstr) "(radix-complement +sign prefix)")
((string=? "-" sgnstr) "(radix-complement -sign prefix)")
(else (throw 'int2poly "bad sign:" sgnstr)))))
)
(begin
(format #t "Inputs: ~a~a (radix ~s, decimal value ~a ~s) (output radix ~s)\n" sgnstr absstr iradix signword absnum radix)
(if verbose (format #t " Number as radix-~s glyph{~a..~a} string ~a\n"
radix (number->string 0 radix) (number->string (- radix 1) radix) sgnnote))
(format #t " ~s~a\n" numstr (if (string=? "" sgnstr) "" " (complement notation)"))
(if (and verbose (not (string=? sgnstr "")))
(format #t " ^--(note that 0 and ~s (radix~a -1) are sign digits for 0 and -1 coefficient values in the polynomial)\n"
(number->string (- radix 1) radix) radix))
(format #t "~a ~s\n" (if verbose " Number as glyphs representing coefficient values of radix polynomial for number value:\n" "") coeffs)
(format #t " ~s~a\n" coeffv (if verbose " -- corresponding coefficient values" ""))
(format #t "~a ~s\n" (if verbose " Number as polynomial expression:\n" "") terms)
(format #t " ~s~a\n" termv (if verbose " -- corresponding term values" ""))
(format #t " ~s~a\n" polyv (if verbose " -- sum of term values" ""))
(if verbose
(if (and (= radix 2) (string=? sgnstr ""))
(format #t " The following should be equal to guile's (integer-length ~s):\n" absnum)
(format #t " Tip: for guile integer-length, enter unsigned value with output radix 2\n")))
(format #t " ~s integer-digit~a (radix ~a)\n" ncoeff (if (> ncoeff 1) "s" "") radix))
)))
--8<---------------cut here---------------end--------------->8---
--
Regards,
Bengt Richter
Information forwarded
to
bug-guix <at> gnu.org
:
bug#40744
; Package
guix
.
(Sat, 25 Apr 2020 21:35:01 GMT)
Full text and
rfc822 format available.
Message #8 received at 40744 <at> debbugs.gnu.org (full text, mbox):
Apologies for my faux pas ;-/
This was not a guix bug, and you have rightly ignored my report.
(now submitted to bug-guile, with hopes of nz human acks :)
(I guess it will get a new number, so 40744 can be closed?)
(BTW, no offense intended in addressing you as "guix/guile bug-squashers" ;-/)
On +2020-04-21 15:03:44 +0200, Bengt Richter wrote:
> Hello guix/guile bug-squashers,
>
> The tl;dr is:
> (integer-length 0) should agree with:
> (string-length (number->string 0 2)) =-> 1
> -- and not: (integer-length 0) =-> 0
--
Regards,
Bengt Richter
bug reassigned from package 'guix' to 'guile'.
Request was from
Leo Famulari <leo <at> famulari.name>
to
control <at> debbugs.gnu.org
.
(Sat, 25 Apr 2020 23:29:02 GMT)
Full text and
rfc822 format available.
Merged 40744 40855.
Request was from
Leo Famulari <leo <at> famulari.name>
to
control <at> debbugs.gnu.org
.
(Sat, 25 Apr 2020 23:29:03 GMT)
Full text and
rfc822 format available.
Reply sent
to
Björn Höfling <bjoern.hoefling <at> bjoernhoefling.de>
:
You have taken responsibility.
(Tue, 28 Apr 2020 18:09:02 GMT)
Full text and
rfc822 format available.
Notification sent
to
Bengt Richter <bokr <at> bokr.com>
:
bug acknowledged by developer.
(Tue, 28 Apr 2020 18:09:02 GMT)
Full text and
rfc822 format available.
Message #17 received at 40744-done <at> debbugs.gnu.org (full text, mbox):
[Message part 1 (text/plain, inline)]
On Sat, 25 Apr 2020 23:33:50 +0200
Bengt Richter <bokr <at> bokr.com> wrote:
> Apologies for my faux pas ;-/
>
> This was not a guix bug, and you have rightly ignored my report.
> (now submitted to bug-guile, with hopes of nz human acks :)
>
> (I guess it will get a new number, so 40744 can be closed?)
>
> (BTW, no offense intended in addressing you as "guix/guile
> bug-squashers" ;-/)
There is a significant overlap between both groups and all like bugs to
be gone :-)
Bugreport was re-opened under the guile package here:
https://debbugs.gnu.org/cgi/bugreport.cgi?bug=40855
Closing this one.
Björn
[Message part 2 (application/pgp-signature, inline)]
Reply sent
to
Björn Höfling <bjoern.hoefling <at> bjoernhoefling.de>
:
You have taken responsibility.
(Tue, 28 Apr 2020 18:09:02 GMT)
Full text and
rfc822 format available.
Notification sent
to
Bengt Richter <bokr <at> bokr.com>
:
bug acknowledged by developer.
(Tue, 28 Apr 2020 18:09:03 GMT)
Full text and
rfc822 format available.
Did not alter fixed versions and reopened.
Request was from
Debbugs Internal Request <help-debbugs <at> gnu.org>
to
internal_control <at> debbugs.gnu.org
.
(Tue, 28 Apr 2020 18:38:01 GMT)
Full text and
rfc822 format available.
Information forwarded
to
bug-guile <at> gnu.org
:
bug#40744
; Package
guile
.
(Tue, 28 Apr 2020 18:42:01 GMT)
Full text and
rfc822 format available.
Message #27 received at 40744 <at> debbugs.gnu.org (full text, mbox):
[Message part 1 (text/plain, inline)]
On Tue, 28 Apr 2020 20:08:10 +0200
Björn Höfling <bjoern.hoefling <at> bjoernhoefling.de> wrote:
> Bugreport was re-opened under the guile package here:
>
> https://debbugs.gnu.org/cgi/bugreport.cgi?bug=40855
>
> Closing this one.
Oh, I didn't realize they were merged. So, I reopened them again :-)
Björn
[Message part 2 (application/pgp-signature, inline)]
Information forwarded
to
bug-guile <at> gnu.org
:
bug#40744
; Package
guile
.
(Fri, 16 Jul 2021 03:02:01 GMT)
Full text and
rfc822 format available.
Message #30 received at 40744 <at> debbugs.gnu.org (full text, mbox):
Hmm, the zero result appears to be intentional, i.e. it's mentioned in
the examples here:
https://www.gnu.org/software/guile/manual/guile.html#Arithmetic
and is also specified by Chez Scheme and SRFI-60:
https://www.scheme.com/csug8/numeric.html
https://srfi.schemers.org/srfi-60/srfi-60.html
--
Rob Browning
rlb @defaultvalue.org and @debian.org
GPG as of 2011-07-10 E6A9 DA3C C9FD 1FF8 C676 D2C4 C0F0 39E9 ED1B 597A
GPG as of 2002-11-03 14DD 432F AE39 534D B592 F9A0 25C8 D377 8C7E 73A4
Information forwarded
to
bug-guile <at> gnu.org
:
bug#40744
; Package
guile
.
(Sat, 24 Jul 2021 17:13:02 GMT)
Full text and
rfc822 format available.
Message #33 received at 40744 <at> debbugs.gnu.org (full text, mbox):
Oops, forgot to reply-all -- sorry about the dup, Rob ;/
On +2021-07-15 22:01:32 -0500, Rob Browning wrote:
>
> Hmm, the zero result appears to be intentional, i.e. it's mentioned in
> the examples here:
>
> https://www.gnu.org/software/guile/manual/guile.html#Arithmetic
>
> and is also specified by Chez Scheme and SRFI-60:
>
> https://www.scheme.com/csug8/numeric.html
> https://srfi.schemers.org/srfi-60/srfi-60.html
>
> --
> Rob Browning
> rlb @defaultvalue.org and @debian.org
> GPG as of 2011-07-10 E6A9 DA3C C9FD 1FF8 C676 D2C4 C0F0 39E9 ED1B 597A
> GPG as of 2002-11-03 14DD 432F AE39 534D B592 F9A0 25C8 D377 8C7E 73A4
I tried to make a pitch for (integer-length 0) =-> 1 in
[1] https://lists.gnu.org/archive/html/bug-guile/2020-04/msg00027.html
though I now think integer-length is a useful measure of mathematical
integervalues that can be generalized to any rational numbers and
complex numbers with rational real and imaginary parts.
Also their printed representations can have any rational radix other
than 1 and negative generalized integer-lengths can be meaningful for
length of 1/x vs x (which brings in the zero issue).
For the "integer-length" I compute in [1], I would now suggest an alternate
name: integer-digits -- the number of concrete digit-value representations
it take to represent the polynomial coefficient values in the mathematical
polynomial series.
I should update [1] to reflect what I am saying here to remove complaints
about integer-length 0 etc and talk about integer-digits (or maybe
rational-digits or even numeric-digits?)
I think scheme's integer-length basically solves for minimum L in
in a mapping of rational numbers (limited to integers in its case)
for + and minus like
[0..2**L) for positive and [-2**L..0) for negative.
Those half-open sets correspond, so we can just use the absolute value
like abslen here:
--8<---------------cut here---------------start------------->8---
#!/usr/bin/env -S guile --no-auto-compile -e main -s
!#
(use-modules (ice-9 format))
(define (abslen absint)
(begin
(let*((absval absint)
(lm (lambda (aval)
(begin
(let inner ((n 0) (av aval))
(begin
(if
(< (integer-expt 2 n) av)
(inner (+ 1 n) av)
n)))))))
(lm absval))))
(define (main args)
(begin
(or
(false-if-exception
(begin
(display (abslen (abs (string->number (cadr args)))))
(newline)))
(begin
(format #t "\nUsage: ~a NUM -- where NUM is [+ - ] POSITIVE_INTEGER\n" (car args)))
(newline))))
--8<---------------cut here---------------end--------------->8---
You might want to call the above something other than integer-length,
but it should compute the same result (modulo very limited testing :).
As mentioned in Tom's reply to [1], zero makes for a special problem
in the general mathematical case, where I think you have to special-case
which set of points it should belong to.
In the general case numbers map into half-open annuli in the complex plane,
where inside and outside the unit circle corresponds to x and 1/x, and 1/0
has to be special-cased. The annulus edge circles are at powers of a rational
base, 2 in the binary case, but 4/3 can work. Just not irrationals.
(Maybe as named unit values though?)
Conventional signed number mappings split an annulus in two to map them,
with positives < the splitting circle and negatives >=
Something analogous to abslen can be done to find the power of the base
that will be the diameter of a circle containing (> not >=) both parts
of the split annulus. I haven't done it yet :)
Complex numbers have both cartesian and polar representations, so that
brings in interesting stuff too. The negative of a complex number as
a point in the complex plane is diametrically opposite the origin, but
zero has no direction to an opposite of itself :)
Defining -0 to be 0 has consequences. (Note that fp hardware does
represent -0 :)
You might find it amusing to play with the scheme program
included in [1] (after you inspect it -- no warranties :).
--
Regards,
Bengt Richter
PS. Shouldn't euclidean-quotient always produce an exact integer?
(Inexactness if any can be carried by the remainder)
This bug report was last modified 3 years and 323 days ago.
Previous Next
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.