> but I don't think rng_rand() should support calling without arguments.
This is a backwards-compatibility leftover in mt_rand() and we should not
carry it over into a new API.

While this is true, the current implementation of MT in PHP relies on
global state, and I believe that having a compatible implementation that
can eliminate this is a good option.
If PHP supports some parallel implementation in the future, and
`mt_srand()` and `mt_rand()` are deprecated, it may be useful as an
alternative method.

> You should probably mention that the classes can be serialized in the
RFC.
I had forgotten about this one. I've added it. Thanks.

> Naming
I think this needs to be discussed further.

The name RNG\RNGInterface is a compromise at this point, and is mainly
based on the PSR conventions. However, PSR is only a userland convention
and I am not sure if the core should take this into account.
However, we also believe that the name is easy to understand, although it
is somewhat redundant.

> 64-bit
I've been thinking for a while about what to do since then, and I think
your suggestion is probably the most appropriate.
That is, remove the `RNG64Interface` and the `next64()` method, and use the
`rng_range()` function to generate random numbers beyond 32 bits.

However, there is a concern. RNG implementations will no longer be able to
return native 64-bit random numbers for seed values.
Given the class name `XorShift128Plus` , users might expect to return the
number `6233086606872742541` when `12345` is the seed value.

On the other hand, it is possible to pseudo-generate 64-bit random numbers
by bit-shifting even for 32-bit RNGs.
I thought of using this to include `next64()` in the `RNGInterface` itself,
but then the problem of userland implementation comes into play.
Originally, the `next64()` method should always throw an exception if
`PHP_INT_SIZE >= 8`, but if you allow userland implementation, it is
implementation dependent.

To solve these problems, how about adding a function like the following? It
doesn't seem like a very good idea, but...

`rng_next(RNG\RNGInterface $rng, bool $unsigned = true): int`
`rng_next64(RNG\RNGInterface $rng, bool $unsigned = true): int`

These will do a bit shift and return an unsigned integer if `$unsigned` is
true. Otherwise, they return the value as generated by the RNG.

Of course, if `rng_next64()` is called in a 32bit environment, it will
throw a `ValueError` exception.

In this case, however, the interface is no longer an interface. Perhaps it
should be an abstract class, like this

```php
abstract class AbstractRNG
{
    abstract protected function next(): int;
    abstract protected function next64(): int;
}
```

It may also be useful to have a trait like this

```php
trait RNG64Support
{
    abstract function next(): int;
    protected function next64(): int
    {
        $ret = $this->next();
        return $ret << 32 | $this->ret();
    }
}
```

It's pretty "exotic" for a core implementation. :o

Does anyone have any good ideas?



After all this time, I'm not good at English, and I apologize if this is
inappropriate.

Regards,
Go Kudo

2021年1月20日(水) 1:19 Nikita Popov <nikita....@gmail.com>:

> On Mon, Jan 18, 2021 at 5:29 PM Go Kudo <zeriyo...@gmail.com> wrote:
>
>> RFC and implementation updated.
>>
>> https://wiki.php.net/rfc/object_scope_prng
>> https://github.com/php/php-src/pull/6568
>>
>> > MT19937 returns a signed 32bit number as a result of the `next()`
>> method;
>> the mt_rand() function returns a bit-shifted unsigned 31bit number, so the
>> results are not identical.
>>
>> The `rng_range()` function has been renamed to `rng_rand()` and returns an
>> unsigned 31-bit integer like the `mt_rand()` function if only the $rng
>> argument is received.
>>
>> ```php
>> mt_srand(1234);
>> mt_rand() === rng_rand(new \RNG\MT19937(1234)); // true
>> ```
>>
>> This allows to completely replace the `mt_rand()` function with the
>> RNG\MT19937.
>>
>> I said I wanted to initiate a vote, but there seems to be too much
>> discussion missing for that.
>> I'd like to wait and see for a while.
>>
>> Regards,
>> Go Kudo
>>
>> 2021年1月17日(日) 20:02 Go Kudo <zeriyo...@gmail.com>:
>>
>> > Updated the RFC and fixed the implementation.
>> > Also made some additions to the RFC about when this feature might be
>> > useful.
>> >
>> > RFC: https://wiki.php.net/rfc/object_scope_prng
>> > Implementation PR: https://github.com/php/php-src/pull/6568 (All CI
>> > passed)
>> >
>> > The main points are as follows:
>> >
>> > - The implementation now meets all requirements. (maybe)
>> > - Implemented MT19937, which is compatible with PHP standard MT. The
>> > consistency of these is ensured by tests.
>> > - The implementation is now what we used to call TypeII.
>> > - All RNG implementations can now be inherited like regular classes. Use
>> > faster calls only if the class is an internal class.
>> > - The implementation has been heavily modified and the quality of the
>> code
>> > has been improved.
>> >
>> > Currently, there are a few concerns:
>> >
>> > - MT19937 returns a signed 32bit number as a result of the `next()`
>> > method; the mt_rand() function returns a bit-shifted unsigned 31bit
>> number,
>> > so the results are not identical.
>> >     - You can get the equivalent result with `$rng->next() << 1 &
>> > PHP_INT_MAX`, but maybe you should have a `nextUnsigned31()` method.
>> >     - Currently, the test uses `$rng->next() << 1 & PHP_INT_MAX`.
>> > - The implementation of MT19937 is redundant. This can be merged.
>> >
>> > Anyway, I think the code is finally ready for review.
>> > Once that is done, we will start voting on RFCs.
>> >
>> > Regards,
>> > Go Kudo
>>
>
> Overall I like the proposal. Some notes:
>
> * I know you only just changed it, but I don't think rng_rand() should
> support calling without arguments. This is a backwards-compatibility
> leftover in mt_rand() and we should not carry it over into a new API.
>
> * You should probably mention that the classes can be serialized in the
> RFC. Maybe you want to write out all the methods so it's also visible how
> the constructors for the classes look like.
>
> * Naming: RNG\RNGInterface seems a bit redundant. Of course, we can't make
> it RNG\Interface. RNG\Generator would be an option. I'm not sure about
> this. Maybe RNG\RNGInterface is fine.
>
> * 64-bit: I looked over your implementation, and I think your approach to
> handling 64-bits is correct. You only call next64() if the requested range
> is larger than 32-bit, and that can only happen on 64-bit systems, thus
> guaranteeing consistency of results (where they can be consistent at all).
> What I'm unsure about is the way this gets exposed to userland via next()
> and next64() methods. I think fetching of 64-bit values is mainly
> interesting as an internal optimization, and not so much important to be
> part of the RNGInterface API. The user is intended to get numbers via
> rng_rand(), not by directly calling next(). A possibility here would be to
> drop the RNG64Interface and next64() method, have next() always return
> 32-bit, but retain the internal next64 API. For this to make sense, we'd
> need two subsequent internal next() calls to return the same data as a
> single next64() call (i.e. store the result and first return one half then
> the other). Would this make sense to you?
>
> Regards,
> Nikita
>

Reply via email to