bug#21900: map is not continuation-safe

2015-11-13 Thread Zefram
With Guile 2.0.11:

scheme@(guile-user)> (define cc #f)
scheme@(guile-user)> (map (lambda (v) (if (= v 0) (call/cc (lambda (c) (set! cc 
c) 0)) (+ v 1))) '(10 20 30 0 40 50 60))
$1 = (11 21 31 0 41 51 61)
scheme@(guile-user)> (cc 5)
$2 = (61 51 41 0 31 5 41 51 61)

It worked correctly in Guile 1.8.

-zefram





bug#21901: bit shift wrong on maximal right shift

2015-11-13 Thread Zefram
With Guile 2.0.11:

scheme@(guile-user)> (ash 123 (ash -1 63))
$1 = 123

Correct result would of course be zero.  Problem only occurs for
exactly this shift distance: one bit less produces the right answer.
Problem also occurs on Guile 1.8.8.  Looking at the implementation,
the problem is attributable to the negation of the shift distance,
which in twos-complement fails to produce the expected positive result.

Note the resemblance to bug #14864, fixed in 2.0.10.  This bug is of
very similar form, but is distinct.  The test cases of #14864 pass for
me on the 2.0.11 that shows the problem with a 2^63 bit shift.  My bug
does occur with the rnrs bitwise-arithmetic-shift-right, which was used
in #14864, as well as with ash.

-zefram





bug#21902: doc incorrectly describes Julian Date

2015-11-13 Thread Zefram
The manual says, in the section "SRFI-19 Introduction",

#Also, for those not familiar with the terminology, a "Julian Day" is
# a real number which is a count of days and fraction of a day, in UTC,
# starting from -4713-01-01T12:00:00Z, ie. midday Monday 1 Jan 4713 B.C.

There are two errors in the first statement of the epoch for Julian Date,
in ISO 8601 format.  The JD epoch is noon on 1 January 4713 BC *in the
proleptic Julian calendar*.  The ISO 8601 format is properly never used on
the Julian calendar: ISO 8601 specifies the use of the Gregorian calendar,
including proleptically where necessary (as it most certainly is here).
On the proleptic Gregorian calendar, the JD epoch is noon on 24 November
4714 BC, and so the ISO 8601 expression should have some "-11-24".

The second error is in how the year is expressed in ISO 8601.  The initial
"-" does not mean the BC era, it means that the year number is negative.
ISO 8601 specifies that the AD era is always used, with year numbers
going negative where necessary; this arrangement is commonly known as
"astronomical year numbering".  So "" means 1 BC, "-0001" means 2
BC, and "-4713" means 4714 BC.  So the "-4713" is not correct for the
attempted expression of the Julian calendar date, but happens to be
correct for the Gregorian calendar date.

Putting it together, a correct ISO 8601 expression for the Julian Date
epoch is "-4713-11-24T12:00:00Z".

The word-based statement of the JD epoch is correct as far as it goes,
but would benefit considerably by the addition of a clause stating that
it is in the proleptic Julian calendar.  (Generally, a clarification
of which calendar is being used is helpful with the statement of any
date prior to the UK's switch of calendar in 1752.)  The description of
Modified Julian Date is essentially correct.

However, there's a third problem: misuse of the term "UTC" for historical
times.  The description of Julian Date says it's counted "in UTC",
and the statement of the MJD epoch describes its 1858 time as being
specified in UTC.  UTC is defined entirely by its relationship to TAI,
which is defined by the operation of atomic clocks.  TAI is therefore
only defined for the period since the operation of the first caesium
atomic clock in the middle of 1955.  The UTC<->TAI relationship isn't
actually defined even that far back: UTC begins at the beginning of
1961 (and that was not in the modern form with leap seconds).  It is
therefore incorrect to apply the term "UTC" to any time prior to 1961.
These two references to UTC should instead be to "UT", the wider class
of closely-matching time scales of which UTC is one representative.
Also, in the first sentence of this doc section, the phrase "universal
time (UTC)" should be either "universal time (UT)" or (more likely)
"coordinated universal time (UTC)".

-zefram





bug#21903: date->string duff ISO 8601 negative years

2015-11-13 Thread Zefram
The date->string function from (srfi srfi-19), used on ISO 8601 formats
"~1", "~4" and "~5", for years preceding AD 1, has an off-by-one error:

scheme@(guile-user)> (use-modules (srfi srfi-19))
scheme@(guile-user)> (date->string (julian-day->date 0 0) "~4")
$1 = "-4714-11-24T12:00:00Z"

The date in question, the JD epoch, is 24 November 4714 BC (in the
proleptic Gregorian calendar).  In ISO 8601 format, that year is properly
represented as "-4713", not "-4714", because ISO 8601 uses the AD era
exclusively.  4714 BC = AD -4713.

-zefram





bug#21904: date->string duff ISO 8601 format for non-4-digit years

2015-11-13 Thread Zefram
The date->string function from (srfi srfi-19), used on ISO 8601 formats
"~1", "~4", and "~5", gets the formatting of year numbers wrong when the
year number doesn't have exactly four digits.  There are multiple cases:

scheme@(guile-user)> (date->string (julian-day->date 150 0) "~1")
$1 = "-607-10-04"
scheme@(guile-user)> (date->string (julian-day->date 170 0) "~1")
$2 = "-59-05-05"
scheme@(guile-user)> (date->string (julian-day->date 172 0) "~1")
$3 = "-4-02-05"

For year numbers -999 to -1 inclusive, date->string is using the minimum
number of digits to express the number, but ISO 8601 requires the use
of at least four digits, with zero padding on the left.  So one should
write "-0059" rather than "-59", for example.  Note that this range is
also affected by the off-by-one error in the selection of the year number
that I described in bug #21903, but that's not the subject of the present
bug report.  Here I'm concerned with how the number is represented in
characters, not with how the year is represented numerically.

scheme@(guile-user)> (date->string (julian-day->date 1722000 0) "~1")
$4 = "2-07-29"
scheme@(guile-user)> (date->string (julian-day->date 173 0) "~1")
$5 = "24-06-23"
scheme@(guile-user)> (date->string (julian-day->date 200 0) "~1")
$6 = "763-09-18"

For year numbers 1 to 999 inclusive, again date->string is using the
minimum number of digits to express the number, but ISO 8601 requires the
use of at least four digits.  If no leading "+" sign is used then the
number must be exactly four digits, and that is the appropriate format
to use in this situation.  So one should write "0024" rather than "24",
for example.

The year number 0, representing the year 1 BC, logically also falls into
this group, and should be represented textually as "".  Currently this
case doesn't arise in the function's output, because the off-by-one bug
has it erroneously emit "-1" for that year.

scheme@(guile-user)> (date->string (julian-day->date 1000 0) "~1")
$7 = "22666-12-20"
scheme@(guile-user)> (date->string (julian-day->date 1 0) "~1")
$8 = "269078-08-07"

For year numbers 1 and above, it is necessary to use more than four
digits for the year, and that's permitted, but ISO 8601 requires that
more than four digits are preceded by a sign.  For positive year numbers
the sign must be "+".  So one should write "+22666" rather than "22666",
for example.

The formatting of year numbers for ISO 8601 purposes is currently only
correct for numbers -1000 and lower (though the choice of number is off
by one) and for year numbers 1000 to  inclusive.

-zefram





bug#21906: julian-day->date negative input breakage

2015-11-13 Thread Zefram
scheme@(guile-user)> (use-modules (srfi srfi-19))
scheme@(guile-user)> (julian-day->date 0 0)
$1 = #
scheme@(guile-user)> (julian-day->date -1 0)
$2 = #
scheme@(guile-user)> (julian-day->date -10 0)
$3 = #
scheme@(guile-user)> (julian-day->date -1000 0)
$4 = #

Observe the various erroneous field values: negative hour, negative
day-of-month, zero month.  These occur in general for various negative
JD inputs.  Not only should the conversion not produce these kinds of
values, the date structure type probably ought to reject them if they
get that far.

-zefram





bug#21907: date->string duff ISO 8601 zone format

2015-11-13 Thread Zefram
scheme@(guile-user)> (use-modules (srfi srfi-19))
scheme@(guile-user)> (date->string (julian-day->date 245 3600) "~4")
$1 = "1995-10-09T13:00:00+0100"
scheme@(guile-user)> (date->string (julian-day->date 245 3630) "~4")
$2 = "1995-10-09T13:00:30+0100"

There are two problems here with date->string's representation of zone
offsets for the ISO 8601 formats "~2" and "~4".  Firstly, because the
time-of-day is represented in the extended format with colon separators,
the zone offset must also be represented with colon separators.  So the
first "+0100" above should be "+01:00".

Secondly, the offset is being truncated to an integral minute, so the
output doesn't fully represent the zone offset.  More importantly,
because the local time-of-day isn't being adjusted to match, it's not
accurately representing the point in time.  ISO 8601 doesn't permit
a seconds component in the zone offset, so you have a choice of three
not-entirely-satisfactory options.  Firstly, you could round the zone
offset and adjust the represented local time accordingly, so the 3630
conversion above would yield either "1995-10-09T13:00:00+01:00" or
"1995-10-09T13:01:00+01:01".  Secondly, you could use the obvious
extension of the ISO 8601 format to a seconds component, outputting
"1995-10-09T13:00:30+01:00:30".  Or finally you could signal an error
when trying to represent a zone offset that's not an integral minute.

Incidentally, for offsets of -1 to -59 inclusive, the truncation isn't
clearing the negative sign, so is producing the invalid output "-".
The zero offset is required to be represented with a "+" sign.  If you
take the rounding option described above, anything that rounds to a
zero-minutes offset must yield "+00:00" in the output.

-zefram





bug#21911: TAI-to-UTC conversion leaps at wrong time

2015-11-13 Thread Zefram
Probing the TAI-to-UTC conversion offered by srfi-19's time-tai->date,
in the minutes around the leap second in 2012:

scheme@(guile-user)> (use-modules (srfi srfi-19))
scheme@(guile-user)> (for-each (lambda (d) (write (list d (date->string 
(time-tai->date (add-duration (julian-day->time-tai 2456109) (make-time 
time-duration 0 d)) 0) "~4"))) (newline)) (list 43000 43160 43164 43165 43166 
43167 43199 43200 43201 43202))
(43000 "2012-06-30T23:56:40Z")
(43160 "2012-06-30T23:59:20Z")
(43164 "2012-06-30T23:59:24Z")
(43165 "2012-06-30T23:59:25Z")
(43166 "2012-06-30T23:59:25Z")
(43167 "2012-06-30T23:59:26Z")
(43199 "2012-06-30T23:59:58Z")
(43200 "2012-06-30T23:59:59Z")
(43201 "2012-06-30T23:59:60Z")
(43202 "2012-07-01T00:00:01Z")

The julian-day->time-tai conversion is correct (the JD refers to
2012-06-30T12:00:00 UTC, which is 2012-06-30T12:00:34 TAI), and the
duration addition works in a perfectly regular manner in TAI space.
All the interesting stuff happens in the TAI-to-UTC conversion, between
the time-tai structure and the date structure.  The same thing happens
if the conversion is performed by separate time-tai->time-utc and
time-utc->date calls.  The date->string part is correct and uninteresting.

The conversion is initially correct, minutes before midnight, but a
discontinuity is seen 35 seconds before midnight.  Outputs from then up
to one second after midnight are one second slow.  At one second after
midnight it recovers.  Because 35 seconds happens to be the TAI-UTC
difference prevailing immediately after this leap second, I suspect that
this is down to a time_t value (as used in the time-utc structure) for
the moment of the leap being misinterpreted as a time-tai seconds value.

The UTC-to-TAI conversion is in better shape.  As a result,
time-tai->time-utc and time-utc->time-tai are not inverses during the
35 second erroneous period.  Round-tripping through the two conversions
produces an output not matching the input.

-zefram





bug#21912: TAI<->UTC conversion botches the unknown

2015-11-13 Thread Zefram
Probing the existence of leap seconds on particular days, via srfi-19's
TAI-to-UTC conversion.  The methodology here is to take noon UT on the
day of interest, convert to TAI, add 86400 seconds, then convert to UTC
and display.  The resulting time of day is 11:59:59 if there is a leap
second that day, and 12:00:00 if there is not.

scheme@(guile-user)> (use-modules (srfi srfi-19))
scheme@(guile-user)> (date->string (time-tai->date (add-duration 
(julian-day->time-tai 2455743) (make-time time-duration 0 86400)) 0) "~4")
$1 = "2011-07-01T12:00:00Z"
scheme@(guile-user)> (date->string (time-tai->date (add-duration 
(julian-day->time-tai 2456109) (make-time time-duration 0 86400)) 0) "~4")
$2 = "2012-07-01T11:59:59Z"
scheme@(guile-user)> (date->string (time-tai->date (add-duration 
(julian-day->time-tai 2457204) (make-time time-duration 0 86400)) 0) "~4")
$3 = "2015-07-01T12:00:00Z"
scheme@(guile-user)> (date->string (time-tai->date (add-duration 
(julian-day->time-tai 2457935) (make-time time-duration 0 86400)) 0) "~4")
$4 = "2017-07-01T12:00:00Z"

For 2011-06-30 it is correct that there was not a leap second, and for
2012-06-30 it is correct that there was.  But for 2015-06-30 it says
there was not a leap second, when in fact there was.  For 2017-06-30
it says there will not be a leap second, when in fact it is not yet
determined whether there will be.

Really both of these errors come from the same cause.  At the time
this Guile 2.0.11 was released, the leap status of 2015-06-30 had not
yet been determined.  Both 2015 and 2017 fall within the future period
beyond the scope of this Guile's static leap second knowledge.

The bug is not that Guile doesn't know that there was a leap second
in 2015.  As the 2017 case illustrates, it's impossible for it to
know all the leap second scheduling about which it can be asked.
The bug is that Guile *thinks* it knows about all future leap seconds.
It specifically thinks that there will be no leaps at all beyond the
historically-scheduled ones that it knows about.

Guile ought to be aware of how far its leap table extends, and signal
an error when asked to perform a TAI<->UTC conversion that falls outside
its scope.

-zefram





bug#21915: write inconsistent about #nil

2015-11-13 Thread Zefram
The write function is inconsistent about whether it distinguishes between
#nil and ():

scheme@(guile-user)> '(#nil . a)
$1 = (#nil . a)
scheme@(guile-user)> '(a . #nil)
$2 = (a)

Thee latter behaviour, emitting #nil as if it were (), breaks the usual
write/read round-tripping, and the traditional correspondence between
equal? and matching of written representation.  Admittedly those standards
are not absolute, nor is the extent to which they're expected to hold
documented, but #nil is clearly sufficiently atomic to be the kind of
value to which one would expect them to apply.  For these reasons,
if a consistent behaviour is to be chosen, I think it should be to
consistently distinguish the values.

I think the behaviour should be consistent.  The values should be
distinguished or not without regard to the context in which they arise
within an s-expression.

Whatever is done, even if it's to endorse the inconsistency, the behaviour
should be documented, with rationale.

-zefram





bug#21514: Guile 2.2: Sluggish elf calls, esp around arity / promises / statprof

2015-11-13 Thread Christopher Allan Webber
Here's a fix to this bug.  Tests pass, and performance appears to be
back here.

I've assigned copyright to the FSF for Guile so it should be fine to
commit!

>From 79e3b5286a2699f9b302bd3abf8a6b884b13a4f4 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber 
Date: Fri, 13 Nov 2015 20:42:31 -0600
Subject: [PATCH] Remove thunk / arity check in make-promise

* libguile/promises.c (s_scm_make_promise): Remove arity check in
  make-promise.  This was causing considerably slowdown with the new elf
  code, causing considerable number of bytevector reading calls on
  every call to (make-promise).  Removing this check fixes a performance
  regression in the new compiler.
---
 libguile/promises.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/libguile/promises.c b/libguile/promises.c
index dcd0ac3..858b6f3 100644
--- a/libguile/promises.c
+++ b/libguile/promises.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011
+/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2015
  * Free Software Foundation, Inc.
  * 
  * This library is free software; you can redistribute it and/or
@@ -77,7 +77,6 @@ SCM_DEFINE (scm_make_promise, "make-promise", 1, 0, 0,
 "@end lisp\n")
 #define FUNC_NAME s_scm_make_promise
 {
-  SCM_VALIDATE_THUNK (1, thunk);
   SCM_RETURN_NEWSMOB2 (scm_tc16_promise,
 		   SCM_UNPACK (thunk),
 		   SCM_UNPACK (scm_make_recursive_mutex ()));
-- 
2.1.4