Topic: Defect report [N2134]: Missing IO roundtrip for random number engines
Author: "=?iso-8859-1?q?Daniel_Kr=FCgler?=" <daniel.kruegler@googlemail.com>
Date: Thu, 8 Mar 2007 12:56:20 CST Raw View
Table 98 and para 5 in [rand.req.eng]-26.4.1.3 specify
the IO insertion and extraction semantic of random
number engines. It can be shown, v.i., that the specification
of the extractor cannot guarantee to fulfill the requirement
from para 5:
"If a textual representation written via os << x was
subsequently read via is >> v, then x == v provided that
there have been no intervening invocations of x or of v."
The problem is, that the extraction process described in
table 98 misses to specify that it will initially set the
if.fmtflags to ios_base::dec, see table 104:
"dec: converts integer input or generates integer output
in decimal base"
Proof: The following small program demonstrates the violation
of requirements (exception safety not fulfilled):
#include <cassert>
#include <ostream>
#include <iostream>
#include <iomanip>
#include <sstream>
class RanNumEngine {
int state;
public:
RanNumEngine() : state(42) {}
bool operator==(RanNumEngine other) const {
return state == other.state;
}
template <typename Ch, typename Tr>
friend std::basic_ostream<Ch, Tr>& operator<<(std::basic_ostream<Ch,
Tr>& os, RanNumEngine engine) {
Ch old = os.fill(os.widen(' ')); // Sets space character
std::ios_base::fmtflags f = os.flags();
os << std::dec << std::left << engine.state; // Adds ios_base::dec|
ios_base::left
os.fill(old); // Undo
os.flags(f);
return os;
}
template <typename Ch, typename Tr>
friend std::basic_istream<Ch, Tr>& operator>>(std::basic_istream<Ch,
Tr>& is, RanNumEngine& engine) {
// Uncomment only for the fix.
//std::ios_base::fmtflags f = is.flags();
//is >> std::dec;
is >> engine.state;
//is.flags(f);
return is;
}
};
int main() {
std::stringstream s;
s << std::setfill('#'); // No problem
s << std::oct; // Yikes!
// Here starts para 5 requirements:
RanNumEngine x;
s << x;
RanNumEngine v;
s >> v;
assert(x == v); // Fails: 42 == 34
}
A second, minor issue seems to be, that the insertion
description from table 98 unnecessarily requires the
addition of ios_base::fixed (which only influences floating-point
numbers). Its not entirely clear to me whether the proposed
standard does require that the state of random number engines
is stored in integral types or not, but I have the impression
that this is the indent, see e.g. p. 3
"The specification of each random number engine defines the
size of its state in multiples of the size of its result_type".
If other types than integrals are supported, then I wonder why
no requirements are specified for the precision of the stream.
Proposed resolution:
1) In table 98 from 26.4.1.3 in column "pre/post-condition",
row expression "is >> x" change
"Sets v's state as determined by
reading its textual representation
from is.[..]"
to
"Sets v's state as determined by
reading its textual representation
with is.fmtflags set to ios_base::dec
from is.[..]"
2) In table 98 from 26.4.1.3 in column "pre/post-condition",
row expression "os << x" change
"With os.fmtflags set to
ios_base::dec|ios_base::
fixed|ios_base::left and[..]"
to
"With os.fmtflags set to
ios_base::dec|ios_base::
left and[..]"
Greetings from Bremen,
Daniel Kr gler
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: sachs@fnal.gov ("David Sachs")
Date: Mon, 12 Mar 2007 18:32:40 GMT Raw View
The IO operators for random number objects are allowed to alter the=20
characteristics of the stream as needed during the input or output of the=
=20
object, and restore the stream state after the IO. The base implementatio=
n=20
for the new random libraries does just that.
"Daniel Kr=FCgler" <daniel.kruegler@googlemail.com> wrote in message=20
news:1173313685.446786.44770@n33g2000cwc.googlegroups.com...
> Table 98 and para 5 in [rand.req.eng]-26.4.1.3 specify
> the IO insertion and extraction semantic of random
> number engines. It can be shown, v.i., that the specification
> of the extractor cannot guarantee to fulfill the requirement
> from para 5:
>
> "If a textual representation written via os << x was
> subsequently read via is >> v, then x =3D=3D v provided that
> there have been no intervening invocations of x or of v."
>
> The problem is, that the extraction process described in
> table 98 misses to specify that it will initially set the
> if.fmtflags to ios_base::dec, see table 104:
>
> "dec: converts integer input or generates integer output
> in decimal base"
>
> Proof: The following small program demonstrates the violation
> of requirements (exception safety not fulfilled):
>
> #include <cassert>
> #include <ostream>
> #include <iostream>
> #include <iomanip>
> #include <sstream>
>
> class RanNumEngine {
> int state;
> public:
> RanNumEngine() : state(42) {}
>
> bool operator=3D=3D(RanNumEngine other) const {
> return state =3D=3D other.state;
> }
>
> template <typename Ch, typename Tr>
> friend std::basic_ostream<Ch, Tr>& operator<<(std::basic_ostream<Ch,
> Tr>& os, RanNumEngine engine) {
> Ch old =3D os.fill(os.widen(' ')); // Sets space character
> std::ios_base::fmtflags f =3D os.flags();
> os << std::dec << std::left << engine.state; // Adds ios_base::dec|
> ios_base::left
> os.fill(old); // Undo
> os.flags(f);
> return os;
> }
>
> template <typename Ch, typename Tr>
> friend std::basic_istream<Ch, Tr>& operator>>(std::basic_istream<Ch,
> Tr>& is, RanNumEngine& engine) {
> // Uncomment only for the fix.
>
> //std::ios_base::fmtflags f =3D is.flags();
> //is >> std::dec;
> is >> engine.state;
> //is.flags(f);
> return is;
> }
> };
>
> int main() {
> std::stringstream s;
> s << std::setfill('#'); // No problem
> s << std::oct; // Yikes!
> // Here starts para 5 requirements:
> RanNumEngine x;
> s << x;
> RanNumEngine v;
> s >> v;
> assert(x =3D=3D v); // Fails: 42 =3D=3D 34
> }
>
> A second, minor issue seems to be, that the insertion
> description from table 98 unnecessarily requires the
> addition of ios_base::fixed (which only influences floating-point
> numbers). Its not entirely clear to me whether the proposed
> standard does require that the state of random number engines
> is stored in integral types or not, but I have the impression
> that this is the indent, see e.g. p. 3
>
> "The specification of each random number engine defines the
> size of its state in multiples of the size of its result_type".
>
> If other types than integrals are supported, then I wonder why
> no requirements are specified for the precision of the stream.
>
> Proposed resolution:
>
> 1) In table 98 from 26.4.1.3 in column "pre/post-condition",
> row expression "is >> x" change
>
> "Sets v's state as determined by
> reading its textual representation
> from is.[..]"
>
> to
>
> "Sets v's state as determined by
> reading its textual representation
> with is.fmtflags set to ios_base::dec
> from is.[..]"
>
> 2) In table 98 from 26.4.1.3 in column "pre/post-condition",
> row expression "os << x" change
>
> "With os.fmtflags set to
> ios_base::dec|ios_base::
> fixed|ios_base::left and[..]"
>
> to
>
> "With os.fmtflags set to
> ios_base::dec|ios_base::
> left and[..]"
>
> Greetings from Bremen,
>
> Daniel Kr=FCgler
>
>
> ---
> [ comp.std.c++ is moderated. To submit articles, try just posting with=
]
> [ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu =
]
> [ --- Please see the FAQ before posting. --- =
]
> [ FAQ: http://www.comeaucomputing.com/csc/faq.html =
]
>=20
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "=?iso-8859-1?q?Daniel_Kr=FCgler?=" <daniel.kruegler@googlemail.com>
Date: Mon, 12 Mar 2007 15:34:29 CST Raw View
"David Sachs" schrieb:
> The IO operators for random number objects are allowed to alter the
> characteristics of the stream as needed during the input or output of the
> object, and restore the stream state after the IO. The base implementation
> for the new random libraries does just that.
What do you mean by: "Can alter the characteristics of the stream"?
Table 98 make huge efforts to explain in which way the data has to
be written into the stream. Actually it's nearly perfect to persist
and
recover the data independent from user changes of the stream flags.
I just demonstrated that there exists a tiny but important loophole
in
these specs. If your reasoning is supposed to mean that the user
can arbitrarily modify the stream flags to control the output format
of
random number engines then we have actually two defects:
1) The explicit specification of stream flags should be removed, this
is similar to the output specification of e.g. std::complex, which
totally relies on user flags (except for the surrounding parentheses).
2) If this is done this way, an explicit specification of the streamed
data is necessary, otherwise the user cannot know, *what* she
actually modifies and it makes no sense to do so.
So either way: A proper specification (as already attempted in the
current proposal) is indeed reasonable and necessary, it only
needs a fix in the specs, AFAIS.
> "Daniel Kr gler" <daniel.kruegler@googlemail.com> wrote in message
> news:1173313685.446786.44770@n33g2000cwc.googlegroups.com...
Regrettably this link goes nowhere - can you provide
another one?
Greetings from Bremen,
Daniel Kr gler
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]