Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:112932 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 8735 invoked from network); 19 Jan 2021 18:08:35 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 19 Jan 2021 18:08:35 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id C1FBA1804A7 for ; Tue, 19 Jan 2021 09:48:20 -0800 (PST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,HTML_MESSAGE, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE, SPF_PASS autolearn=no autolearn_force=no version=3.4.2 X-Spam-Virus: No X-Envelope-From: Received: from mail-ej1-f51.google.com (mail-ej1-f51.google.com [209.85.218.51]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Tue, 19 Jan 2021 09:48:20 -0800 (PST) Received: by mail-ej1-f51.google.com with SMTP id 6so29739775ejz.5 for ; Tue, 19 Jan 2021 09:48:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to; bh=n3dTKqomEHgVrzNrjKnkOqxkQXrlx8bM+pRsBbQbTqo=; b=kC80yVw4rJJcdnUGgecWbQ2zNJ9Xv/RC5v96yqq9IsSBEVeFYNoEEMsvM116DRZLrS kXAlMbSj9GBlnNwko56hpIsb9FqpmGlCoLpP/CscJWl0QYAQoGg3Vn+ssP5uLGKSEf1n 6cxc4o1oFERaQEmyUtKw2q8Lujoy2RYRKr0M5OKlXZtbHenI+Vqz3wXnwNSFuOYUOpMe 68tYwHfnkv7OunZ9U18XxGorE404RMPZxBqqxv4xpQq5bbyjIXarG1LAQK7Ey4veHf2q mxnQHjOgp4tHFOnvPqhriyiGEuUYAptmPbvP8Kz715n4SLS2wrtDvXa5CJBtjkqKmGB3 JsHg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to; bh=n3dTKqomEHgVrzNrjKnkOqxkQXrlx8bM+pRsBbQbTqo=; b=rZU2Te3GyDrXk1nfQMthrp/q+T7xMvAI0O0jYvGXmR83f2fpDl/ojoy8v5ywQ0uy0b litr6uZYr2bbbmm0u4uFgwj23wajmKpFtr6IRsnmV7rIEo1JopEWBTpwT202DhMfCgnd X9VfO4xVw9cElHZ4honDGZK5z5pHKqFmjPTsFtu1cnSm4gocu5KhtD7eZ2cWt0fviO78 WxjzlOou5tyU8NZn2CnquEwExOoF1XQ7C+2dPLgW1QwMmx5Y39m/oScG8Yqom3R6At6F YsddKTNjEyHy4414GKZycAfMKWnE3RtZ1KBV8iX1VyZJAAYtX2bveacZxXCK774zQpuU PHpA== X-Gm-Message-State: AOAM530SoG6ymiBHf3xras3iU3uy14c5L3HquwmW5bLPM/OWpVW3GAJd q/fuoQ8G/v+jEL0O5/WCUMAKt51lV0jCYpe+W4GmyaK1gpOJ7w== X-Google-Smtp-Source: ABdhPJzWR/aehEPwz74ajSZq4bFjmg12Vfo/BxuqD8FlEZsrtr2M+DOnU/JuSI0bdoty8fbBPSmey4uP3Y4EUXG031A= X-Received: by 2002:a17:906:2681:: with SMTP id t1mr3698112ejc.29.1611078496046; Tue, 19 Jan 2021 09:48:16 -0800 (PST) MIME-Version: 1.0 References: In-Reply-To: Date: Wed, 20 Jan 2021 02:48:05 +0900 Message-ID: To: internals@lists.php.net Content-Type: multipart/alternative; boundary="00000000000076540505b9447148" Subject: Re: [PHP-DEV] Re: [RFC] Object-scope RNG implementation From: zeriyoshi@gmail.com (Go Kudo) --00000000000076540505b9447148 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable > 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 >=3D 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 =3D true): int` `rng_next64(RNG\RNGInterface $rng, bool $unsigned =3D 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 =3D $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=E5=B9=B41=E6=9C=8820=E6=97=A5(=E6=B0=B4) 1:19 Nikita Popov : > On Mon, Jan 18, 2021 at 5:29 PM Go Kudo 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 t= he >> 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() =3D=3D=3D 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=E5=B9=B41=E6=9C=8817=E6=97=A5(=E6=97=A5) 20:02 Go Kudo : >> >> > 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. U= se >> > 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 mak= e > 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 rang= e > 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 t= o > 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 the= n > the other). Would this make sense to you? > > Regards, > Nikita > --00000000000076540505b9447148--