Re: [PHP-DEV] Add bcdivmod() to BCMath

2024-06-26 Thread Saki Takamachi
Hi Marco, Benjamin,

> As for tuple vs reference, I think the general direction is to move away from 
> references as much as possible, and AFAIK references actually make things 
> harder for IDEs and static analysis tools, whereas the tuple syntax 
> array{string, string} is well understood at least by PhpStorm, Psalm and 
> PHPStan, which can correctly type the function's return value in their stubs.

I see, I agree. This problem seems to be solved by using PHPDoc.

> I'm wondering if an array vs an object allocation makes a difference here, or 
> if the amount of `bcdivmod()` execution dwarfs this sort of concern?
> 
> Thinking:
> 
> ```php
> $result = \bcdivmod('123', '2');
> 
> echo $result->quotient; // '61'
> echo $result->remainder; // '1'
> ```
> 
> No idea if that's relevant, so I'm throwing it in the room.

BCMath is significantly faster in master, so its cost may have a significant 
impact.

For reference, here is a speed comparison with 8.3 on my env. The benchmark 
used is the code from ext-decimal, which is often introduced in the context of 
"BCMath is slow”. The unit of all measurement results is "seconds".
https://php-decimal.github.io/#performance

8.3
- add int: 3.7771
- add string: 3.0387
- sub int: 3.491
- sub string: 3.0248
- mul int: 5.3318
- mul string: 5.7315
- div int: 10.6659
- div string: 25.762

Master
- add int: 1.72
- add string: 1.
- sub int: 1.763
- sub string: 1.4745
- mul int: 2.2038
- mul string: 2.0621
- div int: 2.8515
- div string: 2.9411

Regards,

Saki

Re: [PHP-DEV] Add bcdivmod() to BCMath

2024-06-25 Thread Marco Pivetta
Hey Benjamin,

On Tue, 25 Jun 2024 at 22:24, Benjamin Morel 
wrote:

>
> I predicted this would probably be on the agenda. Another idea is to pass
>> arguments by reference, like in `exec()`.
>>
>> Personally, I find something like a tuple easier to use. However, without
>> generics, all we know is that the return type is an array, which may be
>> inconvenient in terms of IDE completion, etc.
>>
>
> As for tuple vs reference, I think the general direction is to move away
> from references as much as possible, and AFAIK references actually make
> things harder for IDEs and static analysis tools, whereas the tuple syntax
> array{string, string} is well understood at least by PhpStorm, Psalm and
> PHPStan, which can correctly type the function's return value in their
> stubs.
>

Full ack on this.

I'm wondering if an array vs an object allocation makes a difference here,
or if the amount of `bcdivmod()` execution dwarfs this sort of concern?

Thinking:

```php
$result = \bcdivmod('123', '2');

echo $result->quotient; // '61'
echo $result->remainder; // '1'
```

No idea if that's relevant, so I'm throwing it in the room.

Marco Pivetta

https://mastodon.social/@ocramius

https://ocramius.github.io/


Re: [PHP-DEV] Add bcdivmod() to BCMath

2024-06-25 Thread Benjamin Morel
>
> I see, I understand.
>
> But I don't think that's wise. For example, if we reversed the order of
> the div and mod, there would be no cache and we wouldn't get the speed
> boost. (Or does it cache the quotient as well?)
>

I don't think the cache is a good idea either, for the reasons you
mentioned.

I predicted this would probably be on the agenda. Another idea is to pass
> arguments by reference, like in `exec()`.
>
> Personally, I find something like a tuple easier to use. However, without
> generics, all we know is that the return type is an array, which may be
> inconvenient in terms of IDE completion, etc.
>

As for tuple vs reference, I think the general direction is to move away
from references as much as possible, and AFAIK references actually make
things harder for IDEs and static analysis tools, whereas the tuple syntax
array{string, string} is well understood at least by PhpStorm, Psalm and
PHPStan, which can correctly type the function's return value in their
stubs.

— Benjamin


Re: [PHP-DEV] Add bcdivmod() to BCMath

2024-06-25 Thread Saki Takamachi
Hi Barney,

> If anything I was thinking of recording the remainder in the the original 
> number object, not the one returned (or possibly in something like a WeakMap 
> keyed to it). So it does increase state and makes it technically no longer 
> immutable, but that change in state would not be detectable from outside 
> except by profiling performance. It's state that would have to be ignored in 
> the equality check.

I see, I understand.

But I don't think that's wise. For example, if we reversed the order of the div 
and mod, there would be no cache and we wouldn't get the speed boost. (Or does 
it cache the quotient as well?)

Also, even if the order is as expected, if another division is performed in 
between, the cache will be overwritten and it will become meaningless.

The main concern is the cost of having to mod data during division for the 
surplus that we may never use.

There is the issue of data capacity, but the extra processing such as memory 
allocation will inevitably occur, so for those who don't need mod, the change 
will make slow down.

Regards,

Saki

Re: [PHP-DEV] Add bcdivmod() to BCMath

2024-06-25 Thread Barney Laurance




  On Tue, 25 Jun 2024 17:29:58 +0100  Saki Takamachi  wrote --- 
 > 
 > Also, it is not practical to record the remainder in the Number object 
 > resulting from the division. This is because there can be objects whose 
 > division results are equal but whose remainders are different.
 > 
 > In the discussion of the Number class, it was argued that objects should not 
 > have too much state. 
 > 
 > Increasing the state of surplus is not desirable in this respect, as it 
 > contradicts the previous argument.

If anything I was thinking of recording the remainder in the the original 
number object, not the one returned (or possibly in something like a WeakMap 
keyed to it). So it does increase state and makes it technically no longer 
immutable, but that change in state would not be detectable from outside except 
by profiling performance. It's state that would have to be ignored in the 
equality check.


Re: [PHP-DEV] Add bcdivmod() to BCMath

2024-06-25 Thread Saki Takamachi
Thanks all,

> My only question is the pseudo-tuple return, which is rarely used in PHP 
> (although I've used it myself, I think exactly once), and I think this would 
> be the first use of it in a built in library.  (I may be wrong on that.)  I 
> don't have a particular alternative to suggest, just flagging that as the 
> main part that could warrant discussion.


> It's actually already used by gmp_div_qr(), so +1 from me.

I predicted this would probably be on the agenda. Another idea is to pass 
arguments by reference, like in `exec()`.

Personally, I find something like a tuple easier to use. However, without 
generics, all we know is that the return type is an array, which may be 
inconvenient in terms of IDE completion, etc.

> I'm wondering whether this needs to be a change to the API, or if it might be 
> better implemented as a purely internal optimisation to BCMath / Number - in 
> some way memoize both the quotient and the remainder when either div or mod 
> is called, and then document for users that calling one after the other will 
> be extremely cheap to run.
> 
> But maybe that brings up too many questions about memory usage - e.g. is the 
> memory for this reserved in advance for each instance of Number, or allocated 
> when one of these functions is called, and should it be freed even while the 
> object remains in scope to avoid using lots of memory if many numbers are 
> divided or modded.

I am considering implementing this not only as a Number class, but also as a 
function.

Also, it is not practical to record the remainder in the Number object 
resulting from the division. This is because there can be objects whose 
division results are equal but whose remainders are different.

In the discussion of the Number class, it was argued that objects should not 
have too much state. 

Increasing the state of surplus is not desirable in this respect, as it 
contradicts the previous argument.

Regards,

Saki

Re: [PHP-DEV] Add bcdivmod() to BCMath

2024-06-25 Thread Barney Laurance


  On Tue, 25 Jun 2024 10:11:10 +0100  Saki Takamachi  wrote --- 
 > Hi internals,
 > 
 > I've been working on improving performance of BCMath lately, and I found 
 > that I can get the div and mod in one calculation. This is obviously faster 
 > than calculating it twice separately.
 > 
 > Do you think there's a demand for this feature?
 > 
 > e.g.
 > ```
 > [$quot, $rem] = bcdivmod('123', '2');
 > // $quot is '61', $rem is '1'
 > ```
 > 
 > The naming and return value scheme is inspired by Python and Ruby.
 > 
 > Of course, if this is added, equivalent functionality will be added to the 
 > Number class.

I'm wondering whether this needs to be a change to the API, or if it might be 
better implemented as a purely internal optimisation to BCMath / Number - in 
some way memoize both the quotient and the remainder when either div or mod is 
called, and then document for users that calling one after the other will be 
extremely cheap to run.

But maybe that brings up too many questions about memory usage - e.g. is the 
memory for this reserved in advance for each instance of Number, or allocated 
when one of these functions is called, and should it be freed even while the 
object remains in scope to avoid using lots of memory if many numbers are 
divided or modded.


Re: [PHP-DEV] Add bcdivmod() to BCMath

2024-06-25 Thread Benjamin Morel
Hi,

I've been working on improving performance of BCMath lately, and I found
> that I can get the div and mod in one calculation. This is obviously faster
> than calculating it twice separately.
>
> Do you think there's a demand for this feature?
>
> e.g.
> ```
> [$quot, $rem] = bcdivmod('123', '2');
> // $quot is '61', $rem is '1'
> ```
>
> The naming and return value scheme is inspired by Python and Ruby.
>
> Of course, if this is added, equivalent functionality will be added to the
> Number class.
>
> Regards,
>
> Saki
>

I would definitely use this in brick/math:

https://github.com/brick/math/blob/0.12.1/src/Internal/Calculator/BcMathCalculator.php#L43-L49


> This isn't something I'm likely to ever use as I don't do complex math
> much, but it seems like a reasonable optimization for those that do.  No
> objection.
>
> My only question is the pseudo-tuple return, which is rarely used in PHP
> (although I've used it myself, I think exactly once), and I think this
> would be the first use of it in a built in library.  (I may be wrong on
> that.)  I don't have a particular alternative to suggest, just flagging
> that as the main part that could warrant discussion.
>
> --Larry Garfield
>

It's actually already used by gmp_div_qr(), so +1 from me.

- Benjamin


Re: [PHP-DEV] Add bcdivmod() to BCMath

2024-06-25 Thread Larry Garfield
On Tue, Jun 25, 2024, at 9:11 AM, Saki Takamachi wrote:
> Hi internals,
>
> I've been working on improving performance of BCMath lately, and I 
> found that I can get the div and mod in one calculation. This is 
> obviously faster than calculating it twice separately.
>
> Do you think there's a demand for this feature?
>
> e.g.
> ```
> [$quot, $rem] = bcdivmod('123', '2');
> // $quot is '61', $rem is '1'
> ```
>
> The naming and return value scheme is inspired by Python and Ruby.
>
> Of course, if this is added, equivalent functionality will be added to 
> the Number class.
>
> Regards,
>
> Saki

This isn't something I'm likely to ever use as I don't do complex math much, 
but it seems like a reasonable optimization for those that do.  No objection.

My only question is the pseudo-tuple return, which is rarely used in PHP 
(although I've used it myself, I think exactly once), and I think this would be 
the first use of it in a built in library.  (I may be wrong on that.)  I don't 
have a particular alternative to suggest, just flagging that as the main part 
that could warrant discussion.

--Larry Garfield


Re: [PHP-DEV] Add bcdivmod() to BCMath

2024-06-25 Thread Morgan

On 2024-06-25 21:11, Saki Takamachi wrote:

Hi internals,

I've been working on improving performance of BCMath lately, and I found that I 
can get the div and mod in one calculation. This is obviously faster than 
calculating it twice separately.

Do you think there's a demand for this feature?

Since, when calculating either the div or the mod you basically get the 
other for free (as you've found), and they often go together in use (I 
have some number of things to distributed among some number of columns: 
I end up with *this many* things in each column and *this many* left 
over) so I can definitely see a convenience in this.


Otherwise, if you want both, you essentially end up doing the same 
computation twice:


$rem = bcmod($number, $modulus);
$quot = bcdiv(bcsub($number, $rem), $modulus);