Title
Is std::subtract_with_carry_engine<uint16_t> supposed to work?
Status
wp
Section
[rand.eng.sub]
Submitter
Jonathan Wakely

Created on 2022-11-02.00:00:00 last changed 5 months ago

Messages

Date: 2023-11-13.14:08:10

Proposed resolution:

This wording is relative to n4917.

  1. Modify the class synopsis in [rand.eng.sub] as indicated:

    namespace std {
      template<class UIntType, size_t w, size_t s, size_t r>
      class subtract_with_carry_engine {
      public:
        // types
        using result_type = UIntType;
        // engine characteristics
        static constexpr size_t word_size = w;
        static constexpr size_t short_lag = s;
        static constexpr size_t long_lag = r;
        static constexpr result_type min() { return 0; }
        static constexpr result_type max() { return m − 1; }
        static constexpr result_typeuint_least32_t default_seed = 19780503u;
        // constructors and seeding functions
        subtract_with_carry_engine() : subtract_with_carry_engine(default_seed0u) {}
        explicit subtract_with_carry_engine(result_type value);
        template<class Sseq> explicit subtract_with_carry_engine(Sseq& q);
        void seed(result_type value = default_seed0u);
        template<class Sseq> void seed(Sseq& q);
    
  2. Modify [rand.eng.sub] p7 as indicated:

    explicit subtract_with_carry_engine(result_type value);

    -7- Effects: Sets the values of X r , , X 1 , in that order, as specified below. If X 1 is then 0 , sets c to 1 ; otherwise sets c to 0 .

         To set the values X k , first construct e, a linear_congruential_engine object, as if by the following definition:

    linear_congruential_engine<result_typeuint_least32_t,
                               40014u,0u,2147483563u> e(value == 0u ? default_seed : value);
    

         Then, to set each X k , obtain new values z 0 , , z n 1 from n = w 32 successive invocations of e. Set X k to ( j = 0 n 1 z j 2 32 j ) mod m .

Date: 2023-11-11.00:00:00

[ 2023-11-11 Approved at November 2023 meeting in Kona. Status changed: Voting → WP. ]

Date: 2023-11-07.20:53:14

[ 2023-05; reflector poll ]

Status to Tentatively Ready after six votes in favour.

Date: 2022-11-25.15:40:55

[ Kona 2022-11-25; Jonathan provides wording ]

Date: 2022-11-12.01:08:30

[ Kona 2022-11-12; Set priority to 3 ]

Date: 2022-11-02.00:00:00

The standard requires subtract_with_carry_engine<T> to use:

linear_congruential_engine<T, 40014u, 0u, 2147483563u>

where each of those values is converted to T.

This appears to mean subtract_with_carry_engine cannot be used with uint16_t, because 2147483563u cannot be converted to uint16_t without narrowing.

What is the intention here? Should it be ill-formed? Should the seed engine be linear_congruential_engine<uint_least32_t, …> instead? The values from the linear_congruential_engine are used modulo 2^32 so getting 64-bit values from it is pointless, and getting 16-bit values from it doesn't compile.

History
Date User Action Args
2023-11-13 14:08:10adminsetmessages: + msg13839
2023-11-13 14:08:10adminsetstatus: voting -> wp
2023-11-07 21:41:54adminsetstatus: ready -> voting
2023-11-07 20:53:14adminsetmessages: + msg13824
2023-11-07 20:53:14adminsetstatus: new -> ready
2022-11-25 15:40:55adminsetmessages: + msg13114
2022-11-25 15:40:55adminsetmessages: + msg13113
2022-11-12 01:08:30adminsetmessages: + msg13035
2022-11-02 00:00:00admincreate