From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.ciao.gmane.io!not-for-mail From: Bengt Richter Newsgroups: gmane.lisp.guile.bugs Subject: bug#40855: integer-length 0 should be 1 Date: Sat, 25 Apr 2020 23:15:40 +0200 Message-ID: <20200425211540.GA10315@LionPure> Reply-To: Bengt Richter Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Injection-Info: ciao.gmane.io; posting-host="ciao.gmane.io:159.69.161.202"; logging-data="15097"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Mutt/1.10.1 (2018-07-13) To: 40855@debbugs.gnu.org Original-X-From: bug-guile-bounces+guile-bugs=m.gmane-mx.org@gnu.org Sat Apr 25 23:17:10 2020 Return-path: Envelope-to: guile-bugs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1jSSAf-0003ou-CE for guile-bugs@m.gmane-mx.org; Sat, 25 Apr 2020 23:17:09 +0200 Original-Received: from localhost ([::1]:47720 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jSSAe-0003S7-6n for guile-bugs@m.gmane-mx.org; Sat, 25 Apr 2020 17:17:08 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:51792) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jSSAZ-0003RX-Nk for bug-guile@gnu.org; Sat, 25 Apr 2020 17:17:04 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.90_1) (envelope-from ) id 1jSSAY-00081p-Dn for bug-guile@gnu.org; Sat, 25 Apr 2020 17:17:03 -0400 Original-Received: from debbugs.gnu.org ([209.51.188.43]:48946) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1jSSAX-00080k-Tz for bug-guile@gnu.org; Sat, 25 Apr 2020 17:17:02 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1jSSAX-0007Ys-O7 for bug-guile@gnu.org; Sat, 25 Apr 2020 17:17:01 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Bengt Richter Original-Sender: "Debbugs-submit" Resent-CC: bug-guile@gnu.org Resent-Date: Sat, 25 Apr 2020 21:17:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 40855 X-GNU-PR-Package: guile X-Debbugs-Original-To: bug-guile@gnu.org Original-Received: via spool by submit@debbugs.gnu.org id=B.158784936828995 (code B ref -1); Sat, 25 Apr 2020 21:17:01 +0000 Original-Received: (at submit) by debbugs.gnu.org; 25 Apr 2020 21:16:08 +0000 Original-Received: from localhost ([127.0.0.1]:60492 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1jSS9f-0007Xa-W2 for submit@debbugs.gnu.org; Sat, 25 Apr 2020 17:16:08 -0400 Original-Received: from lists.gnu.org ([209.51.188.17]:39670) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1jSS9d-0007XQ-V0 for submit@debbugs.gnu.org; Sat, 25 Apr 2020 17:16:06 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:51614) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jSS9d-0003NO-5E for bug-guile@gnu.org; Sat, 25 Apr 2020 17:16:05 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.90_1) (envelope-from ) id 1jSS9c-0007kL-20 for bug-guile@gnu.org; Sat, 25 Apr 2020 17:16:04 -0400 Original-Received: from imta-37.everyone.net ([216.200.145.37]:52510 helo=imta-38.everyone.net) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jSS9b-0007gP-BF for bug-guile@gnu.org; Sat, 25 Apr 2020 17:16:03 -0400 Original-Received: from pps.filterd (localhost.localdomain [127.0.0.1]) by imta-38.everyone.net (8.16.0.27/8.16.0.27) with SMTP id 03PLEpsE025276 for ; Sat, 25 Apr 2020 14:15:54 -0700 X-Eon-Originating-Account: GvtrA4CWB31DKDYPaXpK0cj_iskPsz-TZpyEirsFbqk X-Eon-Dm: m0116293.ppops.net Original-Received: by m0116293.mta.everyone.net (EON-AUTHRELAY2 - 5a81c6e6) id m0116293.5e67f91c.41853c for ; Sat, 25 Apr 2020 14:15:52 -0700 X-Eon-Sig: AQMHrIJepKiIKitHjAIAAAAB,25c1be2c3116f6932bf29f64b4041e7a X-Eip: zypbXhRl0sG6PksXuoQmZDY18vZjJBQ87PQLQfYDzM8 Content-Disposition: inline X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.138, 18.0.676 definitions=2020-04-25_13:2020-04-24, 2020-04-25 signatures=0 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 priorityscore=1501 malwarescore=0 suspectscore=1 phishscore=0 bulkscore=0 spamscore=0 clxscore=1034 lowpriorityscore=0 mlxscore=0 impostorscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-2002250000 definitions=main-2004250186 Received-SPF: pass client-ip=216.200.145.37; envelope-from=bokr@oz.net; helo=imta-38.everyone.net X-detected-operating-system: by eggs.gnu.org: First seen = 2020/04/25 17:15:54 X-ACL-Warn: Detected OS = Linux 3.x [generic] X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-Received-From: 209.51.188.43 X-BeenThere: bug-guile@gnu.org List-Id: "Bug reports for GUILE, GNU's Ubiquitous Extension Language" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-guile-bounces+guile-bugs=m.gmane-mx.org@gnu.org Original-Sender: "bug-guile" Xref: news.gmane.io gmane.lisp.guile.bugs:9733 Archived-At: I'm hoping this is the right place to report this bug :) To reproduce, guile -c '(format #t "~s\n" (integer-length 0))' Expected result if correct: 1 Observed result: 0 The following is to support the opinion that 1 is the correct result, and to explore how integer "length" generalizes to other radixes and also signed number writing other than sign-magnitude. Feel free to skip the following if of no interest :) 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..}. 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 (sgnstr (match:prefix matstr)) ;; [] (absstr (match:substring matstr)) ;; [] [] (matst2 (string-match "[0-9]+" (match:suffix matstr))) ;; demo radix (spec in decimal) [] [] (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)) ;; [] (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