Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2024-05-05 Thread Rowan Tommins [IMSoP]



On 30 April 2024 11:16:20 GMT-07:00, Arvids Godjuks  
wrote:
>I think setting some expectations in the proper context is warranted here.
>
>1. Would a native decimal type be good for the language? I would say we
>probably are not going to find many if any people who would be against it.

As I said earlier, I don't think that's the right question, because "adding a 
native type" isn't a defined process. Better questions are: Should a decimal 
type be always available? Does a decimal type need special features to maximise 
performance? Should we have special syntax for a decimal type? What functions 
should support a decimal type, or have versions which do?


>2. Is there a need for it? Well, the whole world of e-commerce, accounting
>and all kinds of business systems that deal with money in PHP world do not
>leave any room for doubt - https://packagist.org/?query=money . The use
>case is right there :)

That's a great example - would a decimal type make those libraries redundant? 
Probably not - they provide currency and rounding facilities beyond basic 
maths. Would those libraries benefit from an always-available, high-performance 
native type? Certainly. 

Would they benefit from it having strong integration into the syntax and 
standard library of the language? Not really; there's a small amount of actual 
code dealing with the values.


>4. Is it a lot of engine work?

Only if we go for the maximum ambition, highly integrated into the language. 


> Is it worth it? 

I'm actually not convinced.


>5. But BCMath/GMP/etc!!! Well, extensions are optional.

Extensions are only optional if we decide they are. ext/json used to be 
optional, but now it's always-on.


> They are also not as fast and they deal with strings.

Not as fast as what? If someone wants to make an extension around a faster 
library, they can. And only BCMath acts directly on strings; other libraries 
use text input to create a value in memory - whether that's a PHP string or a 
literal provided by the compiler doesn't make much difference.



I absolutely think there are use cases for decimal types and functions; but "I 
want a faster implementation" and "I want to add a new fundamental type to the 
language, affecting every corner of the engine" are very different things.

Regards,
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2024-04-30 Thread Arvids Godjuks
On Tue, 30 Apr 2024 at 09:19, Rowan Tommins [IMSoP] 
wrote:

>
>
> On 28 April 2024 07:47:40 GMT-07:00, Robert Landers <
> landers.rob...@gmail.com> wrote:
>
> >I'm not so sure this could be implemented as an extension, there just
> >isn't the right hooks for it.
>
> The whole point of my email was that "this" is not one single feature, but
> a whole series of them. Some of them can be implemented as an extension
> right now; some could be implemented as an extension by adding more hooks
> which would also be useful for other extensions; some would need changes to
> the core of the language.
>
> If the aim is "everything you could possibly want in a decimal type", it
> certainly can't be an extension; if the aim is "better support for
> decimals", then it possibly can.
>
> Regards,
> Rowan Tommins
> [IMSoP]
>

I think setting some expectations in the proper context is warranted here.

1. Would a native decimal type be good for the language? I would say we
probably are not going to find many if any people who would be against it.
2. Is there a need for it? Well, the whole world of e-commerce, accounting
and all kinds of business systems that deal with money in PHP world do not
leave any room for doubt - https://packagist.org/?query=money . The use
case is right there :)
3. In most cases people need decimal precision math in the bounds of what
the decimal128 standard provides. Most of us just do not want the float
drift and while a signed 64-bit integer is big, it has it's limitations and
a need for edge layer transformations be it presentation, API endpoints or
storing it in the database or other storage mediums.
4. Is it a lot of engine work? Yes, yes it is. Is it worth it? I think yes,
especially if we get buying from most of the active maintainers and get a
project going for it. This is not going to be the first or last big engine
project. But this might warrant a PHP 9 release in the end :)
5. But BCMath/GMP/etc!!! Well, extensions are optional. They are also not
as fast and they deal with strings. They are not as fast and you will have
to rely on that extension's methods that most math functions are
implemented and all that stuff. Frankly, I never had a use case where
BCMath was not an overkill. And doing number crunching with BCMath is just
slow due to them being strings internally. The use cases are just
different. They solve a different problem than a decimal128 does for the
language.

I think all the discussions on the subject have shown that BCMath RFC is
it's own thing and adding a decimal type to the PHP language/engine is it's
own thing. They are not mutually exclusive and solve different problems.

-- 

Arvīds Godjuks
+371 26 851 664
arvids.godj...@gmail.com
Telegram: @psihius https://t.me/psihius


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2024-04-30 Thread Rowan Tommins [IMSoP]



On 28 April 2024 07:47:40 GMT-07:00, Robert Landers  
wrote:

>I'm not so sure this could be implemented as an extension, there just
>isn't the right hooks for it.

The whole point of my email was that "this" is not one single feature, but a 
whole series of them. Some of them can be implemented as an extension right 
now; some could be implemented as an extension by adding more hooks which would 
also be useful for other extensions; some would need changes to the core of the 
language.

If the aim is "everything you could possibly want in a decimal type", it 
certainly can't be an extension; if the aim is "better support for decimals", 
then it possibly can.

Regards,
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2024-04-28 Thread Robert Landers
On Sun, Apr 28, 2024 at 11:36 AM Rowan Tommins [IMSoP]
 wrote:
>
>
>
> On 28 April 2024 07:02:22 BST, Alexander Pravdin  
> wrote:
> >Hello everyone. To continue the discussion, I'm suggesting an updated
> >version of my proposal.
>
>
> This all sounds very useful ... but it also sounds like several months of 
> full-time expert development.
>
> Before you begin, I think it will be really important to define clearly what 
> use cases you are trying to cater for, and who your audience is. Only then 
> can you define a minimum set of requirements and goals.
>
> It seems to me that the starting point would be an extension with a decimal 
> type as an object, and implementations for all the operations you want to 
> support. You'll probably want to define that more clearly than "anything in 
> the language which takes a float".
>
> What might seem like it would be the next step is converting the object to a 
> "native type", by adding a new case to the zval struct. Not only would this 
> require a large amount of work to start with, it would have an ongoing impact 
> on everyone working with the internals.
>
> I think a lot of the benefits could actually be delivered without it, and as 
> separate projects:
>
> - Optimising the memory performance of the type, using copy-on-write 
> semantics rather than eager cloning. See Gina's recent thread about "data 
> classes".
>
> - Overloading existing functions which accept floats with decimal 
> implementations. Could potentially be done in a similar way to operator 
> overloads and special interfaces like Countable.
>
> - Convenient syntax for creating decimal values, such as 0.2d, 
> declare(default_decimal), or having (decimal) casts affecting the tree of 
> operations below them rather than just the result. This just needs the type 
> to be available to the compiler, not a new zval type - for instance, 
> anonymous function syntax creates a Closure object.
>
> There may be other parts I've not mentioned, but hopefully this illustrates 
> the idea that "a native decimal type" doesn't have to be one all-or-nothing 
> project.
>
> Regards,
> Rowan Tommins
> [IMSoP]

I'm not so sure this could be implemented as an extension, there just
isn't the right hooks for it.

Robert Landers
Software Engineer
Utrecht NL


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2024-04-28 Thread Rowan Tommins [IMSoP]



On 28 April 2024 07:02:22 BST, Alexander Pravdin  wrote:
>Hello everyone. To continue the discussion, I'm suggesting an updated
>version of my proposal.


This all sounds very useful ... but it also sounds like several months of 
full-time expert development.

Before you begin, I think it will be really important to define clearly what 
use cases you are trying to cater for, and who your audience is. Only then can 
you define a minimum set of requirements and goals.

It seems to me that the starting point would be an extension with a decimal 
type as an object, and implementations for all the operations you want to 
support. You'll probably want to define that more clearly than "anything in the 
language which takes a float".

What might seem like it would be the next step is converting the object to a 
"native type", by adding a new case to the zval struct. Not only would this 
require a large amount of work to start with, it would have an ongoing impact 
on everyone working with the internals.

I think a lot of the benefits could actually be delivered without it, and as 
separate projects: 

- Optimising the memory performance of the type, using copy-on-write semantics 
rather than eager cloning. See Gina's recent thread about "data classes".

- Overloading existing functions which accept floats with decimal 
implementations. Could potentially be done in a similar way to operator 
overloads and special interfaces like Countable.

- Convenient syntax for creating decimal values, such as 0.2d, 
declare(default_decimal), or having (decimal) casts affecting the tree of 
operations below them rather than just the result. This just needs the type to 
be available to the compiler, not a new zval type - for instance, anonymous 
function syntax creates a Closure object. 

There may be other parts I've not mentioned, but hopefully this illustrates the 
idea that "a native decimal type" doesn't have to be one all-or-nothing project.

Regards,
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2024-04-28 Thread Jordan LeDoux
On Sat, Apr 27, 2024 at 11:04 PM Alexander Pravdin 
wrote:

>
> All builtin functions that currently accept float also accept decimal.
> So users don't need to care about separate function sets, and PHP
> developers don't need to maintain separate sets of functions. If any
> of the parameters is decimal, they return decimal. Float parameters
> are converted to decimals implicitly according to the conversion rules
> mentioned above.
>
>
So, as I mentioned months ago, this is the reason that having actually
looked into implementing things like this, I was interested in using a
library. Proposing this is fine. But doing a fully custom implementation
that includes this? You're going to implement `sin` and `cos` and `atan`
for 128-bit decimals? When we could use an open source library that has a
compatible license instead and is proven to work for these already instead,
likely with better performance as well?

This is likely to be more work than doing a type backed by a library while
also being less capable.

I know that your shift in proposal here is not aimed at me, and also I'm
not a voter so in that sense it doesn't matter. But if this is what the
proposal ends up being, I'll probably just continue on the research for an
actual arbitrary precision implementation based on MPFR instead of helping
with this implementation.

Jordan


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2024-04-28 Thread Alexander Pravdin
Hello everyone. To continue the discussion, I'm suggesting an updated
version of my proposal. The main change is: to use decimal128 as the
backend for native decimals, so no 3rd-party libraries are required.
Even if adopting a library, it looks like it'll be much easier than
the previous proposal. Also, the principle "if any operand is decimal,
the result is decimal" is adopted, and conversion requirements are
relaxed and more specific.



Decimal values can be created from literals by specifying a modifier
or using the (decimal) typecast:

$v = 0.2d;
$v = (decimal) 0.2; // Creates a decimal value without intermediary float

Native decimals are backed by 128-bit decimals according to IEEE
754-2008. Point to discuss: can we use 128-bit zvals or transpile
decimals into a pair of 64-bit zvals representing lo and hi portions?


Decimal to float conversion is allowed and smooth:

function f (float $value) {}
f(0.2);
f(0.2d); // allowed with no warnings or errors


Function "str_to_decimal" added to convert from string representation
of numbers to decimals.

Typecast from string to decimal works the same as the "str_to_decimal" function.

The function "float_to_decimal" is added to explicitly convert floats
to decimals. Internally, it performs explicit float to string
conversions using existing defaults and also accepts an optional
parameter to define the number of fractional digits to round to. After
converting a float to a string, it converts the string to a decimal.
Since the main problem of float to decimal conversion is that we don't
know the exact result until we use some rounding when transforming it
to a human-readable format, it looks like the step of the conversion
to a string is inevitable. Any optimized algorithms are welcome.

Explicit type cast "(decimal) float" is the same as using
float_to_decimal with defaults.

Implicit conversion from float to decimal with type juggling works the
same as "float_to_decimal" with defaults but throws a warning to
encourage users to use explicit conversion instead: "Implicit float to
decimal conversion may cause unexpected results due to possible
rounding errors".

With strict types, implicit conversion is not possible and generates a
TypeError.

Literal numbers in the code are compiled to floats by default. If
prepended by the "(decimal)" typecast, or the "d" modifier is used
(0.2d) the decimal is produced by the compiler without an intermediary
float or string.

New declare directive "default_decimal" is added. When used, literals
and math operations return decimal by default instead of float. This
is to simplify creating source files working with decimals only. With
default_decimal, fractional string literals are compiled into
decimals.

Without default_decimal:
$var = 5 / 2; // returns float 2.5
$a = 3.02; // compiled to float

With default_decimal:
$var = 5 / 2; // returns decimal 2.5
$a = 3.02; // compiled to decimal

I understand that this point is controversial, so it can be postponed
and decided later.


The (decimal) typecast applied to a math operation produces a decimal
result without intermediary float by converting all operands to
decimals before calculating:

$var = 5 / 2; // returns float 2.5
$var = (decimal)(5 / 2); // returns decimal 2.5
$a = 5;
$b = 2;
$var = (decimal)($a / $b); // returns decimal 2.5


If any of the math operation operands are decimal, the result is
decimal. Floats are converted to decimals with implicit conversion
rules mentioned above:

Without strict types:
$f = (float) 0.2;
$d = (decimal) 0.2;
$r = $f + $d; // produces a warning about implicit conversion, returns decimal
$r = (decimal)$f + $d; // works with no warnings

With strict types:
$f = (float) 0.2;
$d = (decimal) 0.2;
$r = $f + $d; // produces TypeError
$r = (decimal)$f + $d; // works with no warnings


All builtin functions that currently accept float also accept decimal.
So users don't need to care about separate function sets, and PHP
developers don't need to maintain separate sets of functions. If any
of the parameters is decimal, they return decimal. Float parameters
are converted to decimals implicitly according to the conversion rules
mentioned above.


I hope this version of the design is closer to being accepted by the
community. Please share your thoughts.

--
Best,
Alexander

--
Best regards,
Alex Pravdin
Interico


On Wed, Apr 10, 2024 at 12:55 AM Alexander Pravdin
 wrote:
>
> On Tue, Apr 9, 2024 at 7:52 PM Derick Rethans  wrote:
>
> > Adding a new native type to PHP will create a large change. Not only is
> > it "just" adding a new native type, it also means all of the conversions
> > between types need to be added. This is not a small task.
>
> I understand this :)
>
>
> > If you want to use arbitrary precision natives, then a precision and
> > scale as defined in php.ini defeats the purpose. Every installation can
> > then potentially calculate things in a different way.
> >
> > The only way how to prevent that, is to have *actual* Decimal type, such

Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2024-04-09 Thread Alexander Pravdin
On Tue, Apr 9, 2024 at 7:52 PM Derick Rethans  wrote:

> Adding a new native type to PHP will create a large change. Not only is
> it "just" adding a new native type, it also means all of the conversions
> between types need to be added. This is not a small task.

I understand this :)


> If you want to use arbitrary precision natives, then a precision and
> scale as defined in php.ini defeats the purpose. Every installation can
> then potentially calculate things in a different way.
>
> The only way how to prevent that, is to have *actual* Decimal type, such
> as the Decimal type in MongoDB uses (the IEEE 754 decimal128 type):
>
> - 
> https://www.mongodb.com/docs/mongodb-shell/reference/data-types/#std-label-shell-type-decimal
> - https://en.wikipedia.org/wiki/Decimal128_floating-point_format

If PHP core experts think that 128-bit decimal will cover the vast
majority of cases and is worth implementing, I'm totally for it. If we
can implement something standardized then fine. The current thread is
not an RFC candidate, but a kinda discussion board to formulate the
design principles and strategy.

On another note, is it possible to make zval variable size - 64 or 128
bits? So the 128-bit decimal can be a struct that will be held in the
stack instead of pointer manipulations. Can it be achieved with the
help of macroses?

-- 
Best, Alexander


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2024-04-09 Thread Derick Rethans
On Wed, 3 Apr 2024, Jordan LeDoux wrote:

> On Mon, Mar 18, 2024 at 1:35 PM Rowan Tommins [IMSoP] 
> wrote:
> 
> >
> > Where things get more complicated is with *fixed-precision* decimals,
> > which is what is generally wanted for something like money. What is the
> > correct result of decimal(1.03, precision: 2) / 2 - decimal(0.515, 3)?
> > decimal(0.51, 2)? decimal (0.52, 2)? an error? And what about decimal(10) /
> > 3?
> >
> > If you stick to functions / methods, this is slightly less of an issue,
> > because you can have decimal(1.03, 2)->dividedBy(2, RoundingMode::DOWN) ==
> > decimal(0.51, 2); or decimal(1.03, 2)->split(2) == [ decimal(0.52, 2),
> > decimal(0.51, 2) ] Example names taken directly from the brick/money
> > package.
> >
> > At that point, backwards compatibility is less of an issue as well: make
> > the new functions convenient to use, but distinct from the existing ones
> >
> I came back to this discussion after my last reply on the BCMath as an
> object thread, because we went through a very similar discussion there with
> regard to operators.
> 
> I think that, roughly, the fixed precision should be defined on the scalar
> itself:
> 
> 1.234_d3
> 
> 1.234 is the value, _d makes it a decimal type, and 3 shows that this value
> has a precision of 3. (Actually, it has a SCALE of 3, since precision is
> significant digits, and also includes the integer portion). But when it
> comes to fixed-precision values, it should follow rules very similar to
> those we discussed in the BCMath thread:

Woound't it be much better to capture this complex information in an 
Object, and then allow operators on this? Like... Saki was pretty much 
suggesting with her BCMatch/Number class RFC?

I can't imagine people looking at code understanding a syntax like this 
right away, let alone of what it all means.

cheers,
Derick

-- 
https://derickrethans.nl | https://xdebug.org | https://dram.io

Author of Xdebug. Like it? Consider supporting me: https://xdebug.org/support

mastodon: @derickr@phpc.social @xdebug@phpc.social

Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2024-04-09 Thread Derick Rethans
On Thu, 7 Dec 2023, Alex Pravdin wrote:

> Accounting for all of the above, I suggest adding a native numeric 
> scalar arbitrary precision type called "decimal". Below are the 
> preliminary requirements for implementation.

Adding a new native type to PHP will create a large change. Not only is 
it "just" adding a new native type, it also means all of the conversions 
between types need to be added. This is not a small task.

> Decimal values can be created from literals by specifying a modifier or using
> the (decimal) typecast:
> 
> $v = 0.2d;
> $v = (decimal) 0.2; // Creates a decimal value without intermediary float
> 
> It uses the precision and scale defined in php.ini.

If you want to use arbitrary precision natives, then a precision and 
scale as defined in php.ini defeats the purpose. Every installation can 
then potentially calculate things in a different way.

The only way how to prevent that, is to have *actual* Decimal type, such 
as the Decimal type in MongoDB uses (the IEEE 754 decimal128 type):

- 
https://www.mongodb.com/docs/mongodb-shell/reference/data-types/#std-label-shell-type-decimal
- https://en.wikipedia.org/wiki/Decimal128_floating-point_format

cheers,
Derick

-- 
https://derickrethans.nl | https://xdebug.org | https://dram.io

Author of Xdebug. Like it? Consider supporting me: https://xdebug.org/support

mastodon: @derickr@phpc.social @xdebug@phpc.social


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2024-04-08 Thread Alexander Pravdin
On Tue, Mar 19, 2024 at 5:35 AM Rowan Tommins [IMSoP]
 wrote:

> I think a reasonable number of people do share the sentiment that having two 
> separate modes was a mistake; and neither mode is actually perfect. It's not 
> about "making it on by default", it's about coming up with a unified 
> behaviour that makes the setting redundant.

This is off-topic, but just to conclude: as a user, I personally would
love to see strict_types to be always enabled eventually.


> I don't think choice is really what you want: if you were designing a 
> language from scratch, I doubt you would say "let's give the user a choice of 
> what type 1 / 10 returns". What it's actually about is *backwards 
> compatibility*: what will happen to code that expects 1/10 to give a float, 
> if it suddenly starts giving a decimal.

> In short, the best way of avoiding declare() directives is not to replace 
> them with something else, but to choose a design where nobody feels the need 
> for them.

I understand your point and it is completely valid. But I'm speaking
from a different angle. There are obviously two opposite areas of
calculations, two "modes": "I don't care much about the performance,
give me precise results" and "I don't care about rounding errors, give
me the fastest results". I can't imagine a way of joining them and
unifying the work with them until a completely new CPU architecture is
invented. It makes me think "how can we make both types of users
happy"? I would like to see native and intuitive support for both of
the "modes". So "declare(default_decimal)" seems to be a good option.
Users already know what is "declare" so it will be not a problem to
start using another option. Again, I'm not trying to replace float
calculations with decimals due to performance and backward
compatibility. My goal is to invent a way to make two "modes"
convenient without bandaids.


> For most cases, I think the rule can be as simple as "decimal in means 
> decimal out". What's maybe not as obvious at first sight is that that can 
> apply to operators as functions, and already does: 100 / 10 gives int(10), 
> but 100.0 / 10  gives float(10.0), as do 100 / 10.0  and 100.0 / 10.0

I agree that if one of the operands is decimal then the result should
be decimal. The "declare(default_decimal)" is suggested specifically
for the cases when it is unclear what result we should return and to
not introduce monstrous syntax with a lot of typecast or special
syntax.


> By the same logic, decimal(1) / 10 can produce decimal(0.1) instead of 
> float(0.1), and we don't need any fancy directives. Even better if we can 
> introduce a shorter syntax for decimal literals, so that it becomes 1_d / 10

With "declare(default_decimal)" there's no need to introduce new
syntax for numbers. I personally would prefer to work with "normal"
number literals and let PHP decide (under my guidance) how to
represent them internally - as floats or as decimals.


> Where things get more complicated is with *fixed-precision* decimals, which 
> is what is generally wanted for something like money. What is the correct 
> result of decimal(1.03, precision: 2) / 2 - decimal(0.515, 3)? decimal(0.51, 
> 2)? decimal (0.52, 2)? an error? And what about decimal(10) / 3?

As a user, I see it as we store a decimal number internally with the
maximum number of fractional digits and let the user choose how to
represent it only when converting it from decimal to something else.
Only at this moment, some rounding will happen and we may give users
the proper tools for this. When it comes to 1/3, we may hardcode some
specific rounding mode when it exceeds the internal limit of
fractional digits. In my view, this limit will be more than enough for
99.9% of so they will be able to apply their own rounding mode to 0 or
2 or 10 fractional digits with no issues.


> If you stick to functions / methods, this is slightly less of an issue, 
> because you can have decimal(1.03, 2)->dividedBy(2, RoundingMode::DOWN) == 
> decimal(0.51, 2); or decimal(1.03, 2)->split(2) == [ decimal(0.52, 2), 
> decimal(0.51, 2) ] Example names taken directly from the brick/money package.

Yes, but the whole point of my suggestion is to go away from the
object syntax :) My goal is not to make the future implementation
simpler but to lift the PHP language to the next level even if will
cost much more effort in total.

And just to clarify. I'm not a big expert in decimal calculations, my
proposal is still not so specific and I may have a lack of knowledge
in some terms or details and may need help from more experienced
people. I'm discussing possible ways of the implementation and I would
like to help the community to develop some design that will make
future development aligned with some principles and eventually achieve
the final goal. I understand the complexity of the proposal so I'm not
standing on the implementation as a whole by some PHP version. But I
would be more than happy to know that the language is 

Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2024-04-08 Thread Saki Takamachi
Hi Rowan,

> Again, I don't think "has more than one attribute" is the same as "feel 
> almost like objects". But we're just getting further away from the current 
> discussion, I think.

> The proposed class is called BCMath\Number, which implies that every instance 
> of that class represents a number, just as every instance of a class called 
> DateTime represents a date and time.
> 
> In the end, a class is just a type definition. In pure OOP, it defines the 
> type by its behaviour (methods / messages); in practice, it also defines the 
> properties that each value of the type needs.
> 
> So I am saying that if you were designing a class to represent numbers, you 
> would start by saying "what properties does every number value have?" I don't 
> think "rounding mode" would be on that list, so I don't think it belongs on a 
> class called Number.

We should cool down for now. At the very least, this is the place to discuss 
Alex's proposal, not to comment on my RFC.

If a deeper discussion is needed, we can do that in a new thread.

Regards.

Saki

Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2024-04-08 Thread Rowan Tommins [IMSoP]



On 8 April 2024 10:12:31 BST, Saki Takamachi  wrote:
>
>I don't see any point in "scalar types" that feel almost like objects, because 
>it just feels like you're manipulating objects with procedural functions. Why 
>not just use objects instead?

Again, I don't think "has more than one attribute" is the same as "feel almost 
like objects". But we're just getting further away from the current discussion, 
I think.


>Sorry, but I have no idea what you mean by "numbers have rounding modes". 
>Numbers are just numbers, and if there's something other than numbers in 
>there, then to me it's an object.

The proposed class is called BCMath\Number, which implies that every instance 
of that class represents a number, just as every instance of a class called 
DateTime represents a date and time.

In the end, a class is just a type definition. In pure OOP, it defines the type 
by its behaviour (methods / messages); in practice, it also defines the 
properties that each value of the type needs.

So I am saying that if you were designing a class to represent numbers, you 
would start by saying "what properties does every number value have?" I don't 
think "rounding mode" would be on that list, so I don't think it belongs on a 
class called Number.

Regards,
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2024-04-08 Thread Alexander Pravdin
On Mon, Apr 8, 2024 at 5:06 PM Rowan Tommins [IMSoP]
 wrote:

> If we ever do want to make decimals a native type, we would need some way to 
> initialise a decimal value, since 1.2 will initialise a float.

My original suggestion was:

- Add "default decimal" mode with the "declare" statement in the
beginning of the file. With this statement, all decimal literals like
1.2 will compile to decimals internally, not to floats.
- Add "(decimal) 1.2" typecast that will compile to a decimal number
representation when there's no "default decimal" statement in the
file.

So users will be able to switch contexts explicitly and always know
what they're dealing with.

--
Best, Alexander.


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2024-04-08 Thread Saki Takamachi
Hi Rowan,

> Again, that only seems related to objects because that's what you're used to 
> in PHP, and even then you're overlooking an obvious exception: array(1, 2)


Arrays are a bad example here because their contents are themselves values. For 
example, it would make sense as an example if the third value in the array was 
a flag that controlled the mode in which array_merge operates, but in reality 
it is not.


> If we ever do want to make decimals a native type, we would need some way to 
> initialise a decimal value, since 1.2 will initialise a float. One of the 
> most obvious options is a function-like syntax, decimal(1.2). If we do want 
> numbers to carry extra information in each value, it will be no problem at 
> all to support that.

I don't see any point in "scalar types" that feel almost like objects, because 
it just feels like you're manipulating objects with procedural functions. Why 
not just use objects instead?


> On the other side, just because something's easy doesn't mean it's the right 
> solution. We could make an object which contained a number and an operation, 
> and write this:
> 
> $a = new NumberOp(42, 'add');
> $b = $a->exec(15);
> $c = $b->withOperation('mul');
> $d = $c->exec(2);
> 
> I'm sure you'd agree that would be a bad design.

Yeah, I agree that this is a terrible example. But it's easy to come up with 
terrible examples like this. Shouldn't you use the original decimal class as an 
example for comparison?


> So, again, I urge you to forget about it being easy to stick an extra 
> property on an object, and think in the abstract: does it make sense to say 
> "this number has a preferred rounding mode", rather than "this operation has 
> a preferred rounding mode".

Sorry, but I have no idea what you mean by "numbers have rounding modes". 
Numbers are just numbers, and if there's something other than numbers in there, 
then to me it's an object.

As you can see from the discussion so far, my idea of ​​what a native type is 
and your idea of ​​what a native type is are probably different.

At least between the two of us, we may need to first have a discussion about 
what the native type should be.

Regards.

Saki


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2024-04-08 Thread Rowan Tommins [IMSoP]



On 8 April 2024 01:34:45 BST, Saki Takamachi  wrote:
>
> I'm making these opinions from an API design perspective. How the data is 
> held internally is irrelevant. zval has a lot of data other than values. What 
> I want to say is that if multiple types of parameters are required for 
> initialization, they may only serve as a substitute for object for the user.

Again, that only seems related to objects because that's what you're used to in 
PHP, and even then you're overlooking an obvious exception: array(1, 2)

If we ever do want to make decimals a native type, we would need some way to 
initialise a decimal value, since 1.2 will initialise a float. One of the most 
obvious options is a function-like syntax, decimal(1.2). If we do want numbers 
to carry extra information in each value, it will be no problem at all to 
support that.

On the other side, just because something's easy doesn't mean it's the right 
solution. We could make an object which contained a number and an operation, 
and write this: 

$a = new NumberOp(42, 'add');
$b = $a->exec(15);
$c = $b->withOperation('mul');
$d = $c->exec(2);

I'm sure you'd agree that would be a bad design.

So, again, I urge you to forget about it being easy to stick an extra property 
on an object, and think in the abstract: does it make sense to say "this number 
has a preferred rounding mode", rather than "this operation has a preferred 
rounding mode".

Regards,
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2024-04-07 Thread Saki Takamachi
Hi Rowan

> As I replied to Jordan, I don't see why this is connected to "scalar" vs 
> "object" types at all. An object - particularly an immutable one - is just a 
> way of declaring a type, and some syntax for operations on that type. There's 
> really no difference at all between these:
> 
> $half = $whole / 2;
> $half = numeric_div($whole, 2);
> $half = $whole->div(2);
> 
> In PHP, right now, the last one is only available on objects, but there have 
> been proposals in the past to change that; it's just syntax.
> 
> For rounding, the first one is the real problem, because there's nowhere to 
> put an extra operand. That problem is the same for a class with an overloaded 
> "/" operator, and a "scalar" type which has a definition of "/" in the engine.
> 
> Maybe it feels more obvious that an object can carry extra state in private 
> properties, but internal types don't actually need private properties at all. 
> PHP's "array" type has a bunch of different state without being an object (a 
> linked list of items, a hashtable for random access, an iteration pointer, 
> etc); and SimpleXMLElement and DOMNode are exposed in PHP as separate 
> classes, but actually store state in the same C struct provided by libxml2.
> 
> So I see it just as an API design decision: do we specify the rounding mode 
> of numeric division a) on every operation; b) on every value; c) in a runtime 
> setting (ini_set); d) in a lexically scoped setting (declare)?
> 
> My vote is for (a), maybe with (d) as a fallback.

There is no difference in how the data is held. Agree. What I'm referring to is 
how to initialize the value. If the user has to specify some parameters, or can 
specify them as options, that is already the behavior of the object.

 I'm making these opinions from an API design perspective. How the data is held 
internally is irrelevant. zval has a lot of data other than values. What I want 
to say is that if multiple types of parameters are required for initialization, 
they may only serve as a substitute for object for the user.

Regards.

Saki

Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2024-04-07 Thread Rowan Tommins [IMSoP]

On 07/04/2024 14:27, Saki Takamachi wrote:
If we really wanted decimal to be a native type, then the rounding 
mode and scale behavior should be completely fixed and not user 
selectable. If not, decimal should be implemented as a class.



As I replied to Jordan, I don't see why this is connected to "scalar" vs 
"object" types at all. An object - particularly an immutable one - is 
just a way of declaring a type, and some syntax for operations on that 
type. There's really no difference at all between these:


$half = $whole / 2;
$half = numeric_div($whole, 2);
$half = $whole->div(2);

In PHP, right now, the last one is only available on objects, but there 
have been proposals in the past to change that; it's just syntax.


For rounding, the first one is the real problem, because there's nowhere 
to put an extra operand. That problem is the same for a class with an 
overloaded "/" operator, and a "scalar" type which has a definition of 
"/" in the engine.


Maybe it feels more obvious that an object can carry extra state in 
private properties, but internal types don't actually need private 
properties at all. PHP's "array" type has a bunch of different state 
without being an object (a linked list of items, a hashtable for random 
access, an iteration pointer, etc); and SimpleXMLElement and DOMNode are 
exposed in PHP as separate classes, but actually store state in the same 
C struct provided by libxml2.


So I see it just as an API design decision: do we specify the rounding 
mode of numeric division a) on every operation; b) on every value; c) in 
a runtime setting (ini_set); d) in a lexically scoped setting (declare)?


My vote is for (a), maybe with (d) as a fallback.

Regards,

--
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2024-04-07 Thread Saki Takamachi
Hi,
> What I'm saying is that $x / 2 doesn't have a good answer if $x is a 
> fixed-precision number which can't be divided by 2 without exceeding that 
> precision. You need a third operand, the rounding mode, so you can't write it 
> as a binary operator, and need some kind of function like decimal_div(decimal 
> $dividend, int|decimal $divisor, RoundingMode $roundingMode). How you 
> implement "decimal" doesn't change that at all.
> 

IMHO, if need a parameter that is anything other than a pure value, it's a bad 
fit for a native type. It's just a different notation for creating instances.

If we really wanted decimal to be a native type, then the rounding mode and 
scale behavior should be completely fixed and not user selectable. If not, 
decimal should be implemented as a class. In fact, php's float will round 
values ​​that are too fine, and cannot specify how it will round them. (This 
involves CPU floating point modes, but I wanted to keep it consistent so I just 
gave it as an example.)

Regards.

Saki

Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2024-04-05 Thread Rowan Tommins [IMSoP]

On 04/04/2024 23:31, Jordan LeDoux wrote:


Well, firstly most of the financial applications that I've worked in 
(I work for a firm that writes accounting software right now) do not 
calculate intermediate steps like this with fixed precision, or even 
have an interest in doing so.



My background is in e-commerce (specifically, travel) rather than 
finance. In that context, it's common to have a single-step operation 
like "per_person_price equals total_price divided by number of 
passengers" where both per_person_price and total_price are going to be 
expressed with the same accuracy.


The top two results for "money" on Packagist are 
https://www.moneyphp.org/ and https://github.com/brick/money both of 
which take this general model: the scale of values is fixed, and every 
operation that might produce fractions of that requires a rounding mode.



Truly "fixed-precision" is not something that decimal should even try 
to be, in my opinion. The use cases where you CANNOT simply round the 
result at the end to fit your display output or your storage location 
are very minimal.



In that case, why do we need to think about the scale or precision of a 
decimal at all? What would the syntax 1.234_d3 do differently from 1.234_d?



I mean, what you are describing is how such OBJECTS are designed in 
other languages like Python, but not scalars.



I don't see any connection at all between what I'm describing and 
objects. I'm talking about what operations make sense on a particular 
data type, regardless of how that data type is implemented.


To be honest, I'm not really sure what "scalar" means in this context. 
In PHP, we call strings "scalars" because they're neither "arrays" nor 
"objects"; but none of those have definitions which are universal to 
other languages.



This kind of precision restriction isn't something you would place on 
an individual value, it's something you would place on all 
calculations. That's why in Python this is done with a global runtime 
setting using `getContext().perc` and `getContext().rounding`. A 
particular value having a precision of X doesn't imply anything 
concrete about a calculation that uses that value necessarily.



Global settings avoid needing extra parameters to each operation, but 
don't really work for the use case I'm describing: different currencies 
have different "natural" scale, e.g. Japanese Yen have a scale of 0 (no 
fractional Yen), Bitcoin has a scale of 8 (100 million satoshis in 1 
bitcoin).  A program dealing with multiple currencies will want to 
assign a different scale to different values.



Maybe we're just not understanding each other. Are you opposed to the 
idea of doing this as a scalar?



Not at all; my first examples used method syntax, because I was basing 
them on https://github.com/brick/money In my last e-mail, I also gave 
examples using normal function syntax.


What I'm saying is that $x / 2 doesn't have a good answer if $x is a 
fixed-precision number which can't be divided by 2 without exceeding 
that precision. You need a third operand, the rounding mode, so you 
can't write it as a binary operator, and need some kind of function like 
decimal_div(decimal $dividend, int|decimal $divisor, RoundingMode 
$roundingMode). How you implement "decimal" doesn't change that at all.



Regards,

--
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2024-04-04 Thread Jordan LeDoux
On Thu, Apr 4, 2024 at 2:28 PM Rowan Tommins [IMSoP] 
wrote:

>
>
> I haven't followed the discussion in the other thread, but I'm not sure
> what the use case would be for a "fixed scale decimal" that followed
> those rules.
>
> As mentioned before, the use case I've encountered is money
> calculations, where what people want to fix is the smallest unit of
> account - e.g. €0.01 for practical currency, or €0.0001 for detailed
> accounting / trading.
>
> If I write $total = 1.03_d2; $perPerson = $total / 2; I want a result of
> 0.51_d2 or 0.52_d2 - that's why I specified a scale of 2 in the first
> place.
>

Well, firstly most of the financial applications that I've worked in (I
work for a firm that writes accounting software right now) do not calculate
intermediate steps like this with fixed precision, or even have an interest
in doing so. They generally want maximum precision that is computationally
reasonable, and then round it according to their preferred method at the
end. Doing the calculations as you are suggesting would introduce a maximum
error of several cents/pence/etc. after only two or three calculations,
which is utterly useless for most applications that deal with money.

Truly "fixed-precision" is not something that decimal should even try to
be, in my opinion. The use cases where you CANNOT simply round the result
at the end to fit your display output or your storage location are very
minimal.


> If I want an accurate result of 0.515_d3, I would just specify 1.03_d,
> since the scale hasn't had any effect on the result.
>
> If I want a lossless split into [0.51_d2, 0.52_d2] I still need a
> function to exist somewhere, whether you spell that $total->split(2), or
> decimal_split($total, 2), etc. So it seems safer to also have
> $total->div(2, Round::DOWN) or decimal_div($total, 2, Round::DOWN) and
> have $total / 2 give an error.
>

I mean, what you are describing is how such OBJECTS are designed in other
languages like Python, but not scalars. Python also has (almost completely
unrestricted) userland operator overloading, which PHP does not, which
further makes the comparison a little murky.

This kind of precision restriction isn't something you would place on an
individual value, it's something you would place on all calculations.
That's why in Python this is done with a global runtime setting using
`getContext().perc` and `getContext().rounding`. A particular value having
a precision of X doesn't imply anything concrete about a calculation that
uses that value necessarily.


> Possibly, it could only error if the result doesn't fit in the scale, so
> that this would be fine: $total = 11.00_d2; $perPerson = $total / 2;
> assert($perPerson === 5.50_d2)
>
> Or possibly, it would just be an error to perform division on a fixed
> scale decimal, but allowed on a variable-fixed scale decimal.
>

Maybe we're just not understanding each other. Are you opposed to the idea
of doing this as a scalar? It certainly feels that way. This feels more
like an argument in favor of doing object-like numerics for this. I suppose
that isn't really that strange either, because as I noted such a value will
almost certainly need to be refcounted because it will not fit into the 64
bits available for a zval no matter what underlying library is used to
perform the math.

Jordan


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2024-04-04 Thread Rowan Tommins [IMSoP]

On 04/04/2024 02:29, Jordan LeDoux wrote:
But when it comes to fixed-precision values, it should follow rules very 
similar to those we discussed in the BCMath thread:


- Addition and subtraction should return a value that is the largest 
scale/precision of any operands in the calculation.
- Division and multiplication should return a value that is the sum of 
the scale/precision of any operands + 2 or a default (perhaps 
configurable) value if the sum is small, to ensure that rounding occurs 
correctly. Near zero, floats have about 12-ish decimal digits of 
accuracy, and will return their full accuracy for example.



I haven't followed the discussion in the other thread, but I'm not sure 
what the use case would be for a "fixed scale decimal" that followed 
those rules.


As mentioned before, the use case I've encountered is money 
calculations, where what people want to fix is the smallest unit of 
account - e.g. €0.01 for practical currency, or €0.0001 for detailed 
accounting / trading.


If I write $total = 1.03_d2; $perPerson = $total / 2; I want a result of 
0.51_d2 or 0.52_d2 - that's why I specified a scale of 2 in the first place.


If I want an accurate result of 0.515_d3, I would just specify 1.03_d, 
since the scale hasn't had any effect on the result.


If I want a lossless split into [0.51_d2, 0.52_d2] I still need a 
function to exist somewhere, whether you spell that $total->split(2), or 
decimal_split($total, 2), etc. So it seems safer to also have 
$total->div(2, Round::DOWN) or decimal_div($total, 2, Round::DOWN) and 
have $total / 2 give an error.


Possibly, it could only error if the result doesn't fit in the scale, so 
that this would be fine: $total = 11.00_d2; $perPerson = $total / 2; 
assert($perPerson === 5.50_d2)


Or possibly, it would just be an error to perform division on a fixed 
scale decimal, but allowed on a variable-fixed scale decimal.


Regards,
--
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2024-04-03 Thread Jordan LeDoux
On Mon, Mar 18, 2024 at 1:35 PM Rowan Tommins [IMSoP] 
wrote:

>
> Where things get more complicated is with *fixed-precision* decimals,
> which is what is generally wanted for something like money. What is the
> correct result of decimal(1.03, precision: 2) / 2 - decimal(0.515, 3)?
> decimal(0.51, 2)? decimal (0.52, 2)? an error? And what about decimal(10) /
> 3?
>
> If you stick to functions / methods, this is slightly less of an issue,
> because you can have decimal(1.03, 2)->dividedBy(2, RoundingMode::DOWN) ==
> decimal(0.51, 2); or decimal(1.03, 2)->split(2) == [ decimal(0.52, 2),
> decimal(0.51, 2) ] Example names taken directly from the brick/money
> package.
>
> At that point, backwards compatibility is less of an issue as well: make
> the new functions convenient to use, but distinct from the existing ones
>
I came back to this discussion after my last reply on the BCMath as an
object thread, because we went through a very similar discussion there with
regard to operators.

I think that, roughly, the fixed precision should be defined on the scalar
itself:

1.234_d3

1.234 is the value, _d makes it a decimal type, and 3 shows that this value
has a precision of 3. (Actually, it has a SCALE of 3, since precision is
significant digits, and also includes the integer portion). But when it
comes to fixed-precision values, it should follow rules very similar to
those we discussed in the BCMath thread:

- Addition and subtraction should return a value that is the largest
scale/precision of any operands in the calculation.
- Division and multiplication should return a value that is the sum of the
scale/precision of any operands + 2 or a default (perhaps configurable)
value if the sum is small, to ensure that rounding occurs correctly. Near
zero, floats have about 12-ish decimal digits of accuracy, and will return
their full accuracy for example.
- Pow is extremely difficult to work with if you allow a decimal in the
exponent. The libraries we have discussed previously handle this
difficulty, but the precision needed often depends on what the calculation
is for, so I'm not entirely sure what the best way to handle this with
operators would be. Minimally, probably the same as division and
multiplication.

But if we have scalar decimal types, we need something like that _d12 to
denote a decimal scalar with a scale/precision of 12.

Jordan


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2024-03-18 Thread Rowan Tommins [IMSoP]

On 18/03/2024 04:39, Alexander Pravdin wrote:

I'm not in the context of the core team plans regarding "strict
types". Could you share some details here? What is the current plan
regarding it? To make strict types on by default eventually? Or
something else?



PHP doesn't really have a defined "core team". There are contributors 
who are particularly active at a given time (sometimes, but far from 
always, because someone is paying them), contributors who are 
particularly long-standing and respected, contributors who throw 
themselves into a pet project and make it happen, and so on.


Partly as a consequence of this, it's often hard to pin down any 
long-term plan about anything, outside of what particular people would 
like to see. So Gina's opinion (it was suffixed "IMHO") that strict 
types was a mistake shouldn't be read as "we have a solid plan for what 
is going to replace strict_types which everyone is on board with".


I think a reasonable number of people do share the sentiment that having 
two separate modes was a mistake; and neither mode is actually perfect. 
It's not about "making it on by default", it's about coming up with a 
unified behaviour that makes the setting redundant.



All of which is something of a diversion from the topic at hand, which 
is this:



How can we introduce the ability to write user code in default
decimals and at the same time keep the old way of working as it was
before, to not introduce any troubles into the existing code and not
introduce performance issues? As a user, I would like to have a
choice.




I don't think choice is really what you want: if you were designing a 
language from scratch, I doubt you would say "let's give the user a 
choice of what type 1 / 10 returns". What it's actually about is 
*backwards compatibility*: what will happen to code that expects 1/10 to 
give a float, if it suddenly starts giving a decimal.


For most cases, I think the rule can be as simple as "decimal in means 
decimal out". What's maybe not as obvious at first sight is that that 
can apply to operators as functions, and already does: 100 / 10 gives 
int(10), but 100.0 / 10  gives float(10.0), as do 100 / 10.0  and 100.0 
/ 10.0


By the same logic, decimal(1) / 10 can produce decimal(0.1) instead of 
float(0.1), and we don't need any fancy directives. Even better if we 
can introduce a shorter syntax for decimal literals, so that it becomes 
1_d / 10



Where things get more complicated is with *fixed-precision* decimals, 
which is what is generally wanted for something like money. What is the 
correct result of decimal(1.03, precision: 2) / 2 - decimal(0.515, 3)? 
decimal(0.51, 2)? decimal (0.52, 2)? an error? And what about 
decimal(10) / 3?


If you stick to functions / methods, this is slightly less of an issue, 
because you can have decimal(1.03, 2)->dividedBy(2, RoundingMode::DOWN) 
== decimal(0.51, 2); or decimal(1.03, 2)->split(2) == [ decimal(0.52, 
2), decimal(0.51, 2) ] Example names taken directly from the brick/money 
package.


At that point, backwards compatibility is less of an issue as well: make 
the new functions convenient to use, but distinct from the existing ones.



In short, the best way of avoiding declare() directives is not to 
replace them with something else, but to choose a design where nobody 
feels the need for them.


Regards,

--
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2024-03-17 Thread Alexander Pravdin
Sorry for the so late reply, but I would like to continue the
discussion on this topic.


On Tue, Dec 12, 2023 at 10:04 PM G. P. B.  wrote:

>> I didn't know that the strict types directive was a mistake. My intention is 
>> to be able to write clean all-decimal units of code and not break the 
>> backward compatibility. The old code should work as it was before. At the 
>> same time, there are use cases when the whole class/project should be 
>> written with decimals only. As a user, I want to do that without complex 
>> language structures and excessive typehints or explicit conversions. The 
>> all-decimal code  should be as clean as it is now with floats. This is why I 
>> proposed this directive. Can you suggest something better to achieve the 
>> same?
>
>
> The issue is that I don't think having arbitrary precision decimals as a core 
> language feature is a necessity compared to rational types.
> A cast from rational to float wouldn't produce a large round trip, whereas 
> trying to figure out arbitrary precision is more difficult.
> But in any case, having a declare/INI or whatever that changes the behaviour 
> of the engine/language is not a good design choice.

How can we introduce the ability to write user code in default
decimals and at the same time keep the old way of working as it was
before, to not introduce any troubles into the existing code and not
introduce performance issues? As a user, I would like to have a
choice. When I need speed and I don't care about rounding errors, I
will use default floats. When I need precise calculations and can
sacrifice some performance, I will use default decimals. And I would
like to be able to switch between these modes selectively, not
app-wide. Just give me a choice and inform me in the documentation
about the differences and pros/cons of both types.


I'm not in the context of the core team plans regarding "strict
types". Could you share some details here? What is the current plan
regarding it? To make strict types on by default eventually? Or
something else?



>> If you can suggest a better way of working with fractional numbers - please 
>> do :) But IMO limiting the language by 64 bits is not a good way. It is more 
>> easy to go over the limit than you may think :) Especially in some 
>> intermediary values while performing complex calculations. I could be wrong, 
>> but fractional numbers limited to 64 bits sound like a bandaid. The language 
>> will tell users "hey, you can do something general, but if you want 
>> something else please don't use me at all or involve bandaids with 
>> extensions". My key point is not only to allow working with decimals, but 
>> also to make all the alternatives useless, cover their functionality by 
>> builtin tools, to free users from thinking about workarounds and bandaids. 
>> From my POV, introducing a new decimal type that does not cover the 
>> GMP/bcmath/ext-decimal functionality is pointless and a waste of time.
>
>
> Again, the use cases for arbitrary precision numbers seems rather limited, 
> and having this as an extension does not seem problematic at all.
> My current issue is that there is no way to represent "small" numbers such as 
> 0.1 or 5.8 exactly.
> Arbitrary precision is a totally different ballpark, be that for integers 
> and/or fractional values and makes everything slow, just look at Python who 
> is *finally* investing time and money to make the most common numbers (those 
> that fit in a machine word) not be abysmally slow.

Honestly speaking, my current pain point is that I need to work with
precise money calculations in business automation and accounting
fields. I would like to see a good tool in the PHP language to do
that. As an engineer, I understand that it should be fast enough. I
suggested mpdecimal as a good enough option. If you could suggest
something else that would fit the majority of user needs, I'm totally
for it.



>> How quickly you would be able to read something like this: 
>> gmp_add(gmp_mul(gmp_div(gmp_sub($value, $add), $value2, $factor, 
>> gmp_sin($value3), gmp_intval($value))) ?
>>
>> This absence of intuitive readability makes the development and support 
>> difficult and it's better to choose another language. This is what I want to 
>> change and make PHP powerful enough for this kind of applications.
>
> GMP supports operator overloading, so you do not need to write this, and as 
> far as I see, ext/decimal *also* supports operator overloading so you can 
> just write it using the normal arithmetic operations.
> Moreover, it supports type casts so you can just do (int) $GMP instead of 
> gmp_intval($GMP);
> And it also supports using the comparisons operatos on it instead of using 
> gmp_cmp()
>
> The only thing that is, currently, not possible to do is a cast _to_ GMP 
> using (GMP), but maybe that's something that could be added to the engine for 
> internal objects, but I'm not sure about this.

If GMP can be converted to a scalar builtin language 

Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2023-12-15 Thread Jordan LeDoux
On Fri, Dec 15, 2023 at 12:59 PM Arvids Godjuks 
wrote:

>
>
> On Fri, 15 Dec 2023 at 22:32, Jordan LeDoux 
> wrote:
>
>> On Fri, Dec 15, 2023 at 12:14 AM Robert Landers > >
>> wrote:
>>
>> >
>> > nobody will likely ever try this again, at least in the foreseeable
>> > future. With comments like that, there is simply no way forward.
>> > There's no convincing (at least via email) and by that point, it's too
>> > late anyway, they already voted but didn't even show up for the
>> > discussion that happened for weeks. Literally wasting everyone's time.
>> > The only way we'd ever get something like this passed is if someone
>> > proposes an RFC that prevents people from voting based on
>> > political/personal reasons and restricts voting "no" to technical
>> > reasons only; or some voters reopen one of the original RFC's for a
>> > revote and leave it in the "Pending Implementation" section as needing
>> > an implementation.
>> >
>> > The fact that people can and do vote "no" for no other reason than
>> > they "don't like it" or they "don't want to use it" leaves a bad taste
>> > in my mouth.
>> >
>>
>> Okay, so I'm probably the most affected by this, considering we're
>> discussing my proposal which was declined and I spent over 400 hours of
>> work on it prior to the vote. So please understand where I'm coming from
>> when I say this: I firmly believe that people should be allowed to vote no
>> on an RFC simply because they feel that it "doesn't belong in PHP". That
>> is
>> a voter taking a position on what the language is for, how it should be
>> designed from a more broad perspective, and I think it's important to have
>> that in order to maintain a productive language that does its job well.
>>
>> The main issue I have discovered through this experience is that some
>> people have difficulty or lack the experience necessary to separate an
>> opinion about the language design philosophy from what would be personally
>> useful to *them*. That is a problem, but it's a problem that is just part
>> of working collaboratively with humans. It's not unique to this group, to
>> PHP, or to this situation.
>>
>> The reason, for everyone else reading, that this is relevant to the
>> current
>> discussion about a scalar decimal type is that this is likely to face some
>> similar pushback. This email will go out to hundreds of people, but only a
>> few are going to reply, and most of the people currently participating in
>> this discussion do not have voting rights, so this RFC if it's worked on
>> will have to be developed without the feedback of the people who actually
>> decide whether it goes into the language.
>>
>> A scalar decimal type will be extremely useful for certain types of
>> applications, foundationally critical to other types of applications, and
>> completely unused for others. A big part of writing this RFC would be
>> explaining to the people who do not work on any applications that benefit
>> why it would be good to include it in the language anyway.
>>
>> A scalar decimal type would create a hard dependency on libmpdec, which I
>> also expect to be something that needs to be addressed. MPDec is licensed
>> under the Simplified BSD License. I *think* it could be bundled if needed,
>> but it couldn't be relicensed with the PHP License itself.
>>
>> Jordan
>>
>
> Jordan has highlighted good points that probably should be addressed and
> in general, I think, this project will take a while, so I would settle in
> for the long haul here and think things through and reach out to people who
> actively work and maintain the PHP core. There have been recent instances
> of people fitting in and passing things and then regretting the way it was
> done (*cought* readonly rfc *cought* ).
>
> As for the idea itself - I fully support it. A decimal type would be
> invaluable in quite a lot of places and a lot of PHP apps are handling
> money and other precise numbers that really would benefit from a proper
> decimal type (right now in most cases people just do it with integers or
> use libraries like brick/money, but that's only a subset covered).
> This is really adding a new type into the engine, so this is going to be a
> big undertaking and this probably will require the work to go into PHP 9
> because extensions probably are going to be affected and will need to be
> upgraded to handle the new type. Especially PDO and database drivers. This
> is far from a small project.
>
>
Here's the research that I did into this subject when I was considering
making my own decimal scalar proposal about a year ago.

MPDec: This is used by ext-decimal. It's licensed with the Simplified BSD
License. It has functions for basic arithmetic (add, subtract, multiply,
divide), as well as logarithmic functions (ln, log10, exp, power, square
root). It does not have functions for trigonometric operations, and has
some limitations for where arbitrary precision numbers can be used (for
instance with pow).

GMP: This is the underlying 

Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2023-12-15 Thread Arvids Godjuks
On Fri, 15 Dec 2023 at 22:32, Jordan LeDoux  wrote:

> On Fri, Dec 15, 2023 at 12:14 AM Robert Landers 
> wrote:
>
> >
> > nobody will likely ever try this again, at least in the foreseeable
> > future. With comments like that, there is simply no way forward.
> > There's no convincing (at least via email) and by that point, it's too
> > late anyway, they already voted but didn't even show up for the
> > discussion that happened for weeks. Literally wasting everyone's time.
> > The only way we'd ever get something like this passed is if someone
> > proposes an RFC that prevents people from voting based on
> > political/personal reasons and restricts voting "no" to technical
> > reasons only; or some voters reopen one of the original RFC's for a
> > revote and leave it in the "Pending Implementation" section as needing
> > an implementation.
> >
> > The fact that people can and do vote "no" for no other reason than
> > they "don't like it" or they "don't want to use it" leaves a bad taste
> > in my mouth.
> >
>
> Okay, so I'm probably the most affected by this, considering we're
> discussing my proposal which was declined and I spent over 400 hours of
> work on it prior to the vote. So please understand where I'm coming from
> when I say this: I firmly believe that people should be allowed to vote no
> on an RFC simply because they feel that it "doesn't belong in PHP". That is
> a voter taking a position on what the language is for, how it should be
> designed from a more broad perspective, and I think it's important to have
> that in order to maintain a productive language that does its job well.
>
> The main issue I have discovered through this experience is that some
> people have difficulty or lack the experience necessary to separate an
> opinion about the language design philosophy from what would be personally
> useful to *them*. That is a problem, but it's a problem that is just part
> of working collaboratively with humans. It's not unique to this group, to
> PHP, or to this situation.
>
> The reason, for everyone else reading, that this is relevant to the current
> discussion about a scalar decimal type is that this is likely to face some
> similar pushback. This email will go out to hundreds of people, but only a
> few are going to reply, and most of the people currently participating in
> this discussion do not have voting rights, so this RFC if it's worked on
> will have to be developed without the feedback of the people who actually
> decide whether it goes into the language.
>
> A scalar decimal type will be extremely useful for certain types of
> applications, foundationally critical to other types of applications, and
> completely unused for others. A big part of writing this RFC would be
> explaining to the people who do not work on any applications that benefit
> why it would be good to include it in the language anyway.
>
> A scalar decimal type would create a hard dependency on libmpdec, which I
> also expect to be something that needs to be addressed. MPDec is licensed
> under the Simplified BSD License. I *think* it could be bundled if needed,
> but it couldn't be relicensed with the PHP License itself.
>
> Jordan
>

Jordan has highlighted good points that probably should be addressed and in
general, I think, this project will take a while, so I would settle in for
the long haul here and think things through and reach out to people who
actively work and maintain the PHP core. There have been recent instances
of people fitting in and passing things and then regretting the way it was
done (*cought* readonly rfc *cought* ).

As for the idea itself - I fully support it. A decimal type would be
invaluable in quite a lot of places and a lot of PHP apps are handling
money and other precise numbers that really would benefit from a proper
decimal type (right now in most cases people just do it with integers or
use libraries like brick/money, but that's only a subset covered).
This is really adding a new type into the engine, so this is going to be a
big undertaking and this probably will require the work to go into PHP 9
because extensions probably are going to be affected and will need to be
upgraded to handle the new type. Especially PDO and database drivers. This
is far from a small project.


-- 

Arvīds Godjuks
+371 26 851 664
arvids.godj...@gmail.com
Telegram: @psihius https://t.me/psihius


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2023-12-15 Thread Jordan LeDoux
On Fri, Dec 15, 2023 at 12:14 AM Robert Landers 
wrote:

>
> nobody will likely ever try this again, at least in the foreseeable
> future. With comments like that, there is simply no way forward.
> There's no convincing (at least via email) and by that point, it's too
> late anyway, they already voted but didn't even show up for the
> discussion that happened for weeks. Literally wasting everyone's time.
> The only way we'd ever get something like this passed is if someone
> proposes an RFC that prevents people from voting based on
> political/personal reasons and restricts voting "no" to technical
> reasons only; or some voters reopen one of the original RFC's for a
> revote and leave it in the "Pending Implementation" section as needing
> an implementation.
>
> The fact that people can and do vote "no" for no other reason than
> they "don't like it" or they "don't want to use it" leaves a bad taste
> in my mouth.
>

Okay, so I'm probably the most affected by this, considering we're
discussing my proposal which was declined and I spent over 400 hours of
work on it prior to the vote. So please understand where I'm coming from
when I say this: I firmly believe that people should be allowed to vote no
on an RFC simply because they feel that it "doesn't belong in PHP". That is
a voter taking a position on what the language is for, how it should be
designed from a more broad perspective, and I think it's important to have
that in order to maintain a productive language that does its job well.

The main issue I have discovered through this experience is that some
people have difficulty or lack the experience necessary to separate an
opinion about the language design philosophy from what would be personally
useful to *them*. That is a problem, but it's a problem that is just part
of working collaboratively with humans. It's not unique to this group, to
PHP, or to this situation.

The reason, for everyone else reading, that this is relevant to the current
discussion about a scalar decimal type is that this is likely to face some
similar pushback. This email will go out to hundreds of people, but only a
few are going to reply, and most of the people currently participating in
this discussion do not have voting rights, so this RFC if it's worked on
will have to be developed without the feedback of the people who actually
decide whether it goes into the language.

A scalar decimal type will be extremely useful for certain types of
applications, foundationally critical to other types of applications, and
completely unused for others. A big part of writing this RFC would be
explaining to the people who do not work on any applications that benefit
why it would be good to include it in the language anyway.

A scalar decimal type would create a hard dependency on libmpdec, which I
also expect to be something that needs to be addressed. MPDec is licensed
under the Simplified BSD License. I *think* it could be bundled if needed,
but it couldn't be relicensed with the PHP License itself.

Jordan


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2023-12-15 Thread Robert Landers
On Fri, Dec 15, 2023 at 2:10 AM G. P. B.  wrote:
>
> On Tue, 12 Dec 2023 at 21:00, Robert Landers  wrote:
>>
>> On Tue, Dec 12, 2023 at 2:04 PM G. P. B.  wrote:
>> > GMP supports operator overloading
>>
>> GMP kinda-sorta-most-of-the-time supports operator overloading.
>> Sometimes ... it doesn't. I implemented a field library in PHP (for
>> work a couple of years ago) and occasionally, overloading would cast
>> things back to float/int and break the math. I don't have access to
>> that code, so I don't have any examples readily available (and the
>> fact that an extension can do overloading but we can't in user-land is
>> a whole different can of worms which made this library ridiculously
>> hard to work with -- we rewrote everything in Scala and never looked
>> back). Needless to say, if I were to go into a project that required
>> GMP, I wouldn't trust the overloading.

Hey Gina,

> I have no idea how _this_ is possible considering GMP will happily throw type 
> errors left and right even in cases when it shouldn't.
> If you encountered this, you should have submitted a bug report.
> Because, using a potential bug as an excuse for not doing this is... weird?

The issue should have been reproducible on a smaller scale, but it
wasn't, thereby hinting that we were hitting some extremely rare edge
case that may not be easily testable. The fact that we hit it,
couldn't create a simple reproduction for reporting a bug, and you
should, theoretically, be able to rely on your software to compute
math correctly made that one person's argument: "Why don't we rewrite
this in X?" that much more persuasive...

> I have come around userland operator overloading with the proposal from 
> Jordan, but considering this hasn't passed it might take a while before 
> someone gives it a crack at it again.
> And it has _always_ been a thing that the engine, and internal extensions, 
> can do more things than userland.
> Especially nonsensical stuff like variadic parameters not at the end...

Considering operator overloading has been declined twice (in 2021:
https://wiki.php.net/rfc/user_defined_operator_overloads, and 2020
https://wiki.php.net/rfc/userspace_operator_overloading) for "reasons"
has me thinking it probably won't be proposed again. With comments
like:

> it is not your implementation proposal,
> but rather the concept per-se that IMO shouldn't land in the language

nobody will likely ever try this again, at least in the foreseeable
future. With comments like that, there is simply no way forward.
There's no convincing (at least via email) and by that point, it's too
late anyway, they already voted but didn't even show up for the
discussion that happened for weeks. Literally wasting everyone's time.
The only way we'd ever get something like this passed is if someone
proposes an RFC that prevents people from voting based on
political/personal reasons and restricts voting "no" to technical
reasons only; or some voters reopen one of the original RFC's for a
revote and leave it in the "Pending Implementation" section as needing
an implementation.

The fact that people can and do vote "no" for no other reason than
they "don't like it" or they "don't want to use it" leaves a bad taste
in my mouth.

Robert Landers
Software Engineer
Utrecht NL

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2023-12-14 Thread G. P. B.
On Wed, 13 Dec 2023 at 09:29, Alexander Pravdin 
wrote:

> On Wed, Dec 13, 2023 at 6:11 PM Robert Landers 
> wrote:
>
> I just ran `apt install php8.3-decimal` and tried this:
> >
> > $a = new Decimal\Decimal("1", 2);
> > $b = $a + $a;
> > PHP Warning:  Uncaught TypeError: Unsupported operand types:
> > Decimal\Decimal + Decimal\Decimal in
> >
> > So, it appears not.
> >
>
> I've pointed out this issue earlier in the discussion and Gina P. Banyard
> has replied that this can be a PHP 8.3 bug and he will look into it.
>
> BTW, my main concern is that this amazing extension doesn't look like it is
> actively maintained and I'm worrying if I will be able to maintain my
> projects that depend on it in the future.
>

Hot take, why not fund the maintainer (or someone else to fork and pick up
the work) to work on this extension?
It is not like most bundled extension within php-src are truly actively
maintained.
So why would integrating ext/decimal mean it will be maintained?
Just have a look at all the XML/DOM related extensions that were riddled
with bugs and unmaintained until Nils decided to pick up the work to
scratch an itch.

Moreover, being separate from "core" is frankly a benefit, and I very much
dislike the current status of having so many bundled extensions that cannot
improve at their own pace.
Having extensions not be tied to php-src's release cycle means they can
move more quickly, fix bugs faster, evolve more easily, etc.
Just look at ext/curl, being stuck at a certain level of support for
libcurl because it *must* be tied to the annual PHP release cycle.

Best regards,

Gina P. Banyard

PS: My pronouns are she/her


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2023-12-14 Thread G. P. B.
On Tue, 12 Dec 2023 at 21:00, Robert Landers 
wrote:

> On Tue, Dec 12, 2023 at 2:04 PM G. P. B.  wrote:
> > GMP supports operator overloading
>
> GMP kinda-sorta-most-of-the-time supports operator overloading.
> Sometimes ... it doesn't. I implemented a field library in PHP (for
> work a couple of years ago) and occasionally, overloading would cast
> things back to float/int and break the math. I don't have access to
> that code, so I don't have any examples readily available (and the
> fact that an extension can do overloading but we can't in user-land is
> a whole different can of worms which made this library ridiculously
> hard to work with -- we rewrote everything in Scala and never looked
> back). Needless to say, if I were to go into a project that required
> GMP, I wouldn't trust the overloading.
>

I have no idea how _this_ is possible considering GMP will happily throw
type errors left and right even in cases when it shouldn't.
If you encountered this, you should have submitted a bug report.
Because, using a potential bug as an excuse for not doing this is... weird?

I have come around userland operator overloading with the proposal from
Jordan, but considering this hasn't passed it might take a while before
someone gives it a crack at it again.
And it has _always_ been a thing that the engine, and internal extensions,
can do more things than userland.
Especially nonsensical stuff like variadic parameters not at the end...

Gina P. Banyard


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2023-12-13 Thread Alexander Pravdin
On Wed, Dec 13, 2023 at 6:11 PM Robert Landers 
wrote:

I just ran `apt install php8.3-decimal` and tried this:
>
> $a = new Decimal\Decimal("1", 2);
> $b = $a + $a;
> PHP Warning:  Uncaught TypeError: Unsupported operand types:
> Decimal\Decimal + Decimal\Decimal in
>
> So, it appears not.
>

I've pointed out this issue earlier in the discussion and Gina P. Banyard
has replied that this can be a PHP 8.3 bug and he will look into it.

BTW, my main concern is that this amazing extension doesn't look like it is
actively maintained and I'm worrying if I will be able to maintain my
projects that depend on it in the future.

Best,
Alex


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2023-12-13 Thread Robert Landers
On Wed, Dec 13, 2023 at 9:37 AM Stephen Reay  wrote:
>
>
>
> > On 7 Dec 2023, at 13:36, Alex Pravdin  wrote:
> >
> > Hello internals,
> >
> >
> > This is the second round of the discussion regarding arbitrary precision 
> > scalar type integration into PHP. The previous part: 
> > https://marc.info/?l=php-internals=168250492216838=2 was initiated by 
> > me before deep diving into the work with decimals in PHP. After 6 months of 
> > working, I would like to update my proposal taking into account my 
> > experience and the previous discussion.
> >
> > Today's alternatives and their problems are the following.
> >
> > bcmath:
> > - Workaround: using string type.
> > - Unintuitive function calls instead of regular math operations.
> > - Unintuitive strings instead of numbers. People want to work with numbers.
> > - Can not use proper type-hinting.
> > - Can use PHP's basic type coercions.
> >
> > Ext-decimal:
> > - Third-party extension.
> > - Workaround: implements the Decimal class that allows basic regular math 
> > operations.
> > - Requires using class methods for the rest of math operations.
> > - The latest release was in 2019 and there's a danger that it will be 
> > unmaintained and not compatible with the future PHP releases.
> > - The php-decimal documentation website is currently down.
> > - Since objects are always casted to true when not null, "(bool) 
> > Decimal(0)" will equal to true which is not intuitive.
> > - IDEs are often confused when you use math operations on objects while the 
> > code works fine.
> >
> > GMP:
> > - Workaround: implements the GMP class that allows basic math operations.
> > - Requires using separate functions for the rest of operations.
> >
> > - Objects are always casted to true, GMP(0) will equal to true.
> >
> >
> > Accounting for all of the above, I suggest adding a native numeric scalar 
> > arbitrary precision type called "decimal". Below are the preliminary 
> > requirements for implementation.
> >
> >
> > Decimal values can be created from literals by specifying a modifier or 
> > using the (decimal) typecast:
> >
> > $v = 0.2d;
> > $v = (decimal) 0.2; // Creates a decimal value without intermediary float
> >
> > It uses the precision and scale defined in php.ini.
> >
> > The "decimal" typehint allows to define custom precision and scale: 
> > decimal(20,5). It accepts regular expressions returning ints in the 
> > execution context. It accepts int constants and literals in class field and 
> > function argument definitions.
> >
> > New functions added: get_scale and get_precision to return corresponding 
> > values about a decimal value.
> >
> > If decimal value with different scale and precision is going to be assigned 
> > to a variable or parameter with smaller scale or precision, it first tries 
> > to convert the value. If it's not possible, then an exception is thrown 
> > like "Can not convert decimal (a, b) x. to decimal(c, d)". If 
> > possible, it performs the conversion and generates a warning like 
> > "Assigning decimal(a, b) to decimal(c, d) may be not possible with some 
> > values".
> >
> > It works the same as "float" in terms of its usage and type casting except 
> > for one thing. Float value can be passed to a decimal argument or 
> > typecasted with a warning like "Float to decimal conversion may incur 
> > unexpected results".
> >
> > Decimal to float conversion is allowed and smooth:
> >
> > function f (float $value) {}
> >
> > f(0.2);
> >
> > f(0.2d); // allowed with no warnings
> >
> >
> > Function "str_to_decimal" added to convert string representation of numbers 
> > to decimals.
> >
> >
> > Typecast from string to decimal works the same as the "str_to_decimal" 
> > function.
> >
> > Function "float_to_decimal" added to explicitly convert floats to decimals. 
> > It performs float to string conversions using php.ini settings as defaults 
> > but also accepts parameters to configure the conversion. Then, it converts 
> > string to decimal. Since the main problem of float to decimal conversion is 
> > that we don't know the exact result until we use some rounding when 
> > transforming it to a human-readable format, it looks like the step of the 
> > conversion to a string is inevitable. Any more optimized algorithms are 
> > welcome.
> >
> > Explicit typecast from float to decimal works the same as 
> > "float_to_decimal" function with all default values but also throws a 
> > warning. This is to encourage users to use explicit conversion with the 
> > "float_to_decimal" function and control the results.
> >
> > Literal numbers in the code are converted to floats by default. If 
> > prepended by the "(decimal)" typecast, the decimal result is produced 
> > without an intermediary float.
> >
> > New declare directive "default_decimal" is added. When used, literals and 
> > math operations return decimal by default instead of float. This is to 
> > simplify creating source files working with decimals only.
> >
> > New 

Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2023-12-13 Thread Stephen Reay


> On 7 Dec 2023, at 13:36, Alex Pravdin  wrote:
> 
> Hello internals,
> 
> 
> This is the second round of the discussion regarding arbitrary precision 
> scalar type integration into PHP. The previous part: 
> https://marc.info/?l=php-internals=168250492216838=2 was initiated by me 
> before deep diving into the work with decimals in PHP. After 6 months of 
> working, I would like to update my proposal taking into account my experience 
> and the previous discussion.
> 
> Today's alternatives and their problems are the following.
> 
> bcmath:
> - Workaround: using string type.
> - Unintuitive function calls instead of regular math operations.
> - Unintuitive strings instead of numbers. People want to work with numbers.
> - Can not use proper type-hinting.
> - Can use PHP's basic type coercions.
> 
> Ext-decimal:
> - Third-party extension.
> - Workaround: implements the Decimal class that allows basic regular math 
> operations.
> - Requires using class methods for the rest of math operations.
> - The latest release was in 2019 and there's a danger that it will be 
> unmaintained and not compatible with the future PHP releases.
> - The php-decimal documentation website is currently down.
> - Since objects are always casted to true when not null, "(bool) Decimal(0)" 
> will equal to true which is not intuitive.
> - IDEs are often confused when you use math operations on objects while the 
> code works fine.
> 
> GMP:
> - Workaround: implements the GMP class that allows basic math operations.
> - Requires using separate functions for the rest of operations.
> 
> - Objects are always casted to true, GMP(0) will equal to true.
> 
> 
> Accounting for all of the above, I suggest adding a native numeric scalar 
> arbitrary precision type called "decimal". Below are the preliminary 
> requirements for implementation.
> 
> 
> Decimal values can be created from literals by specifying a modifier or using 
> the (decimal) typecast:
> 
> $v = 0.2d;
> $v = (decimal) 0.2; // Creates a decimal value without intermediary float
> 
> It uses the precision and scale defined in php.ini.
> 
> The "decimal" typehint allows to define custom precision and scale: 
> decimal(20,5). It accepts regular expressions returning ints in the execution 
> context. It accepts int constants and literals in class field and function 
> argument definitions.
> 
> New functions added: get_scale and get_precision to return corresponding 
> values about a decimal value.
> 
> If decimal value with different scale and precision is going to be assigned 
> to a variable or parameter with smaller scale or precision, it first tries to 
> convert the value. If it's not possible, then an exception is thrown like 
> "Can not convert decimal (a, b) x. to decimal(c, d)". If possible, it 
> performs the conversion and generates a warning like "Assigning decimal(a, b) 
> to decimal(c, d) may be not possible with some values".
> 
> It works the same as "float" in terms of its usage and type casting except 
> for one thing. Float value can be passed to a decimal argument or typecasted 
> with a warning like "Float to decimal conversion may incur unexpected 
> results".
> 
> Decimal to float conversion is allowed and smooth:
> 
> function f (float $value) {}
> 
> f(0.2);
> 
> f(0.2d); // allowed with no warnings
> 
> 
> Function "str_to_decimal" added to convert string representation of numbers 
> to decimals.
> 
> 
> Typecast from string to decimal works the same as the "str_to_decimal" 
> function.
> 
> Function "float_to_decimal" added to explicitly convert floats to decimals. 
> It performs float to string conversions using php.ini settings as defaults 
> but also accepts parameters to configure the conversion. Then, it converts 
> string to decimal. Since the main problem of float to decimal conversion is 
> that we don't know the exact result until we use some rounding when 
> transforming it to a human-readable format, it looks like the step of the 
> conversion to a string is inevitable. Any more optimized algorithms are 
> welcome.
> 
> Explicit typecast from float to decimal works the same as "float_to_decimal" 
> function with all default values but also throws a warning. This is to 
> encourage users to use explicit conversion with the "float_to_decimal" 
> function and control the results.
> 
> Literal numbers in the code are converted to floats by default. If prepended 
> by the "(decimal)" typecast, the decimal result is produced without an 
> intermediary float.
> 
> New declare directive "default_decimal" is added. When used, literals and 
> math operations return decimal by default instead of float. This is to 
> simplify creating source files working with decimals only.
> 
> New language construct "as_decimal()" is added to produce decimal math 
> results for literals and math operations instead of float without 
> intermediary float:
> 
> $var = 5 / 2; // returns float 2.5
> $var = as_decimal(5 / 2); // returns decimal 2.5
> 
> This is 

Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2023-12-12 Thread Jordan LeDoux
On Tue, Dec 12, 2023 at 4:29 PM Jordan LeDoux 
wrote:

>
>
> On Tue, Dec 12, 2023 at 3:05 PM Erick de Azevedo Lima <
> ericklima.c...@gmail.com> wrote:
>
>> Oh, I just realized that I used the wrong word, so let me rephrase that:
>>
>> What's the name of the library you're talking about? Maybe the *pros* of a
>> core implementation can be highlighted if we can see the limitations of a
>> user-land approach.
>>
>> Best,
>> Erick
>>
>>
> My library is Fermat: https://github.com/JordanRL/Fermat
>
> Mine is the ONLY one that I'm aware of that even attempts to support
> complex mathematical operations in PHP. However, there are other arbitrary
> precision math libraries that are more limited in scope.
>
> Other similar math libraries:
>
> markrogoyski/math-php: The closest in terms of features compared to Fermat
> brick/math: The most widely installed PHP math library on Packagist (due
> to being a dependency of several other widely used packages). Has extremely
> limited features for complex arbitrary precision functions.
>
> MPDecimal (the underlying C library that we have discussed using here) has
> extensions and functions for things like sine and cosine. Even just
> exposing those would make writing algorithms for things like 3i^(2+5i)
> much, much faster.
>
> The problem is that there's no point in using arbitrary precision numbers
> unless you're using the spaces after the decimal. I think we can all agree
> on that. No matter how good the implementation, floats are always going to
> be faster if you're unconcerned about rounding errors and such.
>
> So if you're writing an arbitrary precision library and you want to
> support the next obvious operation beyond add, subtract, multiply, and
> divide, you probably naturally choose exponents. Except, calculating A^B
> where both A and B have *arbitrary precision* and where the result will
> also have *arbitrary precision* means that you cannot rely on things like
> the `pow()` function. So you have to implement your own. Except
> implementing decimal exponents means you *really* need to implement `exp()`
> first, since all of the efficient algorithms rely on transforming A^B into
> C*e^D. Except the most efficient ways of doing *that* really work best if
> you have access to trig functions. And *ALL* your calculations in the
> middle can't be losing precision, otherwise there's no point in doing your
> own implementation, so that means all of these functions need to have
> implementations as well.
>
> This rabbit hole is *so* insidious that the BCMath library simple says
> "fuck it" and limits you to only using integers for your exponents. That's
> basically pointless though if the reason you need arbitrary precision
> numbers is something like a statistics application for instance, which PHP
> *also* lacks support for since the one extension that used to provide
> statistics functions is no longer maintained and hasn't been updated since
> I think 7.4.
>
> If we get scalar decimals that only support add, subtract, multiply, and
> divide, that's a huge improvement. But if we can take this opportunity to
> tackle *at least* the trig functions as well, that will enable a LOT of new
> userland code that is very messy and very slow right now.
>
> Jordan
>

Apologies, I just realized that you were asking about the libraries that
implemented rationals with complex operations. I don't have THOSE libraries
handy unfortunately. Even my library converts to decimal first.

Jordan


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2023-12-12 Thread Jordan LeDoux
On Tue, Dec 12, 2023 at 3:05 PM Erick de Azevedo Lima <
ericklima.c...@gmail.com> wrote:

> Oh, I just realized that I used the wrong word, so let me rephrase that:
>
> What's the name of the library you're talking about? Maybe the *pros* of a
> core implementation can be highlighted if we can see the limitations of a
> user-land approach.
>
> Best,
> Erick
>
>
My library is Fermat: https://github.com/JordanRL/Fermat

Mine is the ONLY one that I'm aware of that even attempts to support
complex mathematical operations in PHP. However, there are other arbitrary
precision math libraries that are more limited in scope.

Other similar math libraries:

markrogoyski/math-php: The closest in terms of features compared to Fermat
brick/math: The most widely installed PHP math library on Packagist (due to
being a dependency of several other widely used packages). Has extremely
limited features for complex arbitrary precision functions.

MPDecimal (the underlying C library that we have discussed using here) has
extensions and functions for things like sine and cosine. Even just
exposing those would make writing algorithms for things like 3i^(2+5i)
much, much faster.

The problem is that there's no point in using arbitrary precision numbers
unless you're using the spaces after the decimal. I think we can all agree
on that. No matter how good the implementation, floats are always going to
be faster if you're unconcerned about rounding errors and such.

So if you're writing an arbitrary precision library and you want to support
the next obvious operation beyond add, subtract, multiply, and divide, you
probably naturally choose exponents. Except, calculating A^B where both A
and B have *arbitrary precision* and where the result will also have
*arbitrary precision* means that you cannot rely on things like the `pow()`
function. So you have to implement your own. Except implementing decimal
exponents means you *really* need to implement `exp()` first, since all of
the efficient algorithms rely on transforming A^B into C*e^D. Except the
most efficient ways of doing *that* really work best if you have access to
trig functions. And *ALL* your calculations in the middle can't be losing
precision, otherwise there's no point in doing your own implementation, so
that means all of these functions need to have implementations as well.

This rabbit hole is *so* insidious that the BCMath library simple says
"fuck it" and limits you to only using integers for your exponents. That's
basically pointless though if the reason you need arbitrary precision
numbers is something like a statistics application for instance, which PHP
*also* lacks support for since the one extension that used to provide
statistics functions is no longer maintained and hasn't been updated since
I think 7.4.

If we get scalar decimals that only support add, subtract, multiply, and
divide, that's a huge improvement. But if we can take this opportunity to
tackle *at least* the trig functions as well, that will enable a LOT of new
userland code that is very messy and very slow right now.

Jordan


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2023-12-12 Thread Erick de Azevedo Lima
Oh, I just realized that I used the wrong word, so let me rephrase that:

What's the name of the library you're talking about? Maybe the *pros* of a
core implementation can be highlighted if we can see the limitations of a
user-land approach.

Best,
Erick

Em ter., 12 de dez. de 2023 às 18:52, Erick de Azevedo Lima <
ericklima.c...@gmail.com> escreveu:

> Hi Jordan.
>
> What's the name of the library you're talking about? Maybe the cons of a
> core implementation can be highlighted if we can see the limitations of a
> user-land approach.
>
> Best,
> Erick
>
> Em ter., 12 de dez. de 2023 às 18:35, Jordan LeDoux <
> jordan.led...@gmail.com> escreveu:
>
>> On Tue, Dec 12, 2023 at 1:26 PM Larry Garfield 
>> wrote:
>>
>> > On Tue, Dec 12, 2023, at 1:03 PM, G. P. B. wrote:
>> >
>> > > The issue is that I don't think having arbitrary precision decimals
>> as a
>> > > core language feature is a necessity compared to rational types.
>> > > A cast from rational to float wouldn't produce a large round trip,
>> > whereas
>> > > trying to figure out arbitrary precision is more difficult.
>> > > But in any case, having a declare/INI or whatever that changes the
>> > > behaviour of the engine/language is not a good design choice.
>> >
>> > I don't have strong feelings about arbitrary precision decimals either
>> > way, but I do strongly agree with this point.  Having the language
>> behavior
>> > (including the precision of numbers) change with an ini setting is
>> > long-understood to be a bad idea, and we've been trying to phase it
>> out.  A
>> > decimal feature that relies on a language-affecting ini setting is just
>> not
>> > going to fly these days, IMO, and rightly so.
>> >
>> > I am curious, GB, if you're proposing an actual `rational` type, which
>> > stores values internally as just numerator and denominator separately
>> until
>> > some point when it renders down to a float (eg, on print)?  That sounds
>> > neat, though I am nowhere near expert enough in that area to say what
>> ugly
>> > edge cases that might run into.
>> >
>> > --Larry Garfield
>> >
>>
>> I agree that an INI setting or declare is wrong for this.
>>
>> The ugly edge cases on a native rational type tend to be in complex
>> algorithms, which many libraries deal with by converting the rational to a
>> float or decimal for those complex algorithms and just avoiding the issue.
>> (Algorithms like `sin()`, `atan()`, or `exp()`). It's not an unsolveable
>> problem if you really want rational types. There are libraries that do it.
>> But unless there's someone here volunteering, it's probably a non-starter,
>> as that's something I won't touch.
>>
>> Jordan
>>
>


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2023-12-12 Thread Erick de Azevedo Lima
Hi Jordan.

What's the name of the library you're talking about? Maybe the cons of a
core implementation can be highlighted if we can see the limitations of a
user-land approach.

Best,
Erick

Em ter., 12 de dez. de 2023 às 18:35, Jordan LeDoux 
escreveu:

> On Tue, Dec 12, 2023 at 1:26 PM Larry Garfield 
> wrote:
>
> > On Tue, Dec 12, 2023, at 1:03 PM, G. P. B. wrote:
> >
> > > The issue is that I don't think having arbitrary precision decimals as
> a
> > > core language feature is a necessity compared to rational types.
> > > A cast from rational to float wouldn't produce a large round trip,
> > whereas
> > > trying to figure out arbitrary precision is more difficult.
> > > But in any case, having a declare/INI or whatever that changes the
> > > behaviour of the engine/language is not a good design choice.
> >
> > I don't have strong feelings about arbitrary precision decimals either
> > way, but I do strongly agree with this point.  Having the language
> behavior
> > (including the precision of numbers) change with an ini setting is
> > long-understood to be a bad idea, and we've been trying to phase it
> out.  A
> > decimal feature that relies on a language-affecting ini setting is just
> not
> > going to fly these days, IMO, and rightly so.
> >
> > I am curious, GB, if you're proposing an actual `rational` type, which
> > stores values internally as just numerator and denominator separately
> until
> > some point when it renders down to a float (eg, on print)?  That sounds
> > neat, though I am nowhere near expert enough in that area to say what
> ugly
> > edge cases that might run into.
> >
> > --Larry Garfield
> >
>
> I agree that an INI setting or declare is wrong for this.
>
> The ugly edge cases on a native rational type tend to be in complex
> algorithms, which many libraries deal with by converting the rational to a
> float or decimal for those complex algorithms and just avoiding the issue.
> (Algorithms like `sin()`, `atan()`, or `exp()`). It's not an unsolveable
> problem if you really want rational types. There are libraries that do it.
> But unless there's someone here volunteering, it's probably a non-starter,
> as that's something I won't touch.
>
> Jordan
>


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2023-12-12 Thread Jordan LeDoux
On Tue, Dec 12, 2023 at 1:26 PM Larry Garfield 
wrote:

> On Tue, Dec 12, 2023, at 1:03 PM, G. P. B. wrote:
>
> > The issue is that I don't think having arbitrary precision decimals as a
> > core language feature is a necessity compared to rational types.
> > A cast from rational to float wouldn't produce a large round trip,
> whereas
> > trying to figure out arbitrary precision is more difficult.
> > But in any case, having a declare/INI or whatever that changes the
> > behaviour of the engine/language is not a good design choice.
>
> I don't have strong feelings about arbitrary precision decimals either
> way, but I do strongly agree with this point.  Having the language behavior
> (including the precision of numbers) change with an ini setting is
> long-understood to be a bad idea, and we've been trying to phase it out.  A
> decimal feature that relies on a language-affecting ini setting is just not
> going to fly these days, IMO, and rightly so.
>
> I am curious, GB, if you're proposing an actual `rational` type, which
> stores values internally as just numerator and denominator separately until
> some point when it renders down to a float (eg, on print)?  That sounds
> neat, though I am nowhere near expert enough in that area to say what ugly
> edge cases that might run into.
>
> --Larry Garfield
>

I agree that an INI setting or declare is wrong for this.

The ugly edge cases on a native rational type tend to be in complex
algorithms, which many libraries deal with by converting the rational to a
float or decimal for those complex algorithms and just avoiding the issue.
(Algorithms like `sin()`, `atan()`, or `exp()`). It's not an unsolveable
problem if you really want rational types. There are libraries that do it.
But unless there's someone here volunteering, it's probably a non-starter,
as that's something I won't touch.

Jordan


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2023-12-12 Thread Jordan LeDoux
On Tue, Dec 12, 2023 at 1:00 PM Robert Landers 
wrote:

>
> Hey Gina,
>
> > GMP supports operator overloading
>
> GMP kinda-sorta-most-of-the-time supports operator overloading.
> Sometimes ... it doesn't. I implemented a field library in PHP (for
> work a couple of years ago) and occasionally, overloading would cast
> things back to float/int and break the math. I don't have access to
> that code, so I don't have any examples readily available (and the
> fact that an extension can do overloading but we can't in user-land is
> a whole different can of worms which made this library ridiculously
> hard to work with -- we rewrote everything in Scala and never looked
> back). Needless to say, if I were to go into a project that required
> GMP, I wouldn't trust the overloading.
>
> Just my 2¢
>

I tried not to bring that up in this discussion because it would probably
sound bitter/unhelpful, but the lack of userland operator overloading is
definitely something that makes a native decimal scalar more necessary.
Voters have repeatedly rejected userland operator overloads. The last
proposal was mine, and most of the people who voted not told me that they
didn't have any real problems with the design, they just don't like
operator overloads.

Things like ext-decimal and GMP are always going to be clunky and annoying
to use without them though. It's one of the reasons I considered writing my
own implementation of a decimal scalar for core after my operator overload
RFC was declined. The use case for a scalar decimal type is much stronger
since nothing like it can be remotely implemented in userland at all. (I
know from experience, I wrote from scratch the most comprehensive arbitrary
precision math library in PHP.)

Jordan


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2023-12-12 Thread Larry Garfield
On Tue, Dec 12, 2023, at 1:03 PM, G. P. B. wrote:

> The issue is that I don't think having arbitrary precision decimals as a
> core language feature is a necessity compared to rational types.
> A cast from rational to float wouldn't produce a large round trip, whereas
> trying to figure out arbitrary precision is more difficult.
> But in any case, having a declare/INI or whatever that changes the
> behaviour of the engine/language is not a good design choice.

I don't have strong feelings about arbitrary precision decimals either way, but 
I do strongly agree with this point.  Having the language behavior (including 
the precision of numbers) change with an ini setting is long-understood to be a 
bad idea, and we've been trying to phase it out.  A decimal feature that relies 
on a language-affecting ini setting is just not going to fly these days, IMO, 
and rightly so.

I am curious, GB, if you're proposing an actual `rational` type, which stores 
values internally as just numerator and denominator separately until some point 
when it renders down to a float (eg, on print)?  That sounds neat, though I am 
nowhere near expert enough in that area to say what ugly edge cases that might 
run into.

--Larry Garfield

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php



Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2023-12-12 Thread Robert Landers
On Tue, Dec 12, 2023 at 2:04 PM G. P. B.  wrote:
>
> On Fri, 8 Dec 2023 at 10:14, Alexander Pravdin 
> wrote:
>
> > On Thu, Dec 7, 2023 at 11:36 PM G. P. B.  wrote:
> >
> > - Objects are always casted to true, GMP(0) will equal to true.
> >>>
> >>
> >> This is incorrect, GMP object do _not_ support casts to bool
> >> See https://3v4l.org/LHpD1
> >>
> >
> > This is weird. Any PHP user would expect that a zero number can be easily
> > casted to boolean false. This is also why I think we need a scalar decimal
> > type.
> >
>
> Internal objects can overload casts, SimpleXML overloads the boolean cast
> already.
> We could add this to GMP to return false for 0.
>
>
> > It works the same as "float" in terms of its usage and type casting except
> >>> for one thing. Float value can be passed to a decimal argument or
> >>> typecasted with a warning like "Float to decimal conversion may incur
> >>> unexpected results".
> >>>
> >>> Decimal to float conversion is allowed and smooth:
> >>>
> >>> function f (float $value) {}
> >>>
> >>> f(0.2);
> >>>
> >>> f(0.2d); // allowed with no warnings
> >>>
> >>
> >> I disagree with this part, floats can not represent decimal values
> >> properly e.g.
> >> $f1 = 0.1;
> >> $f2 = 0.2;
> >> $f3 = 0.3;
> >> var_dump($f1 + $f2 === $f3);
> >>
> > will return false.
> >> As such, floats are not at all compatible with decimals.
> >>
> >
> > Yes, I know that. I mentioned that we can not convert float to decimal
> > without an intermediate value where we apply rounding and get a
> > human-readable value in some representation (string or whatsoever).
> >
> > My intention was to provide implicit conversion with warnings because I
> > guess that the majority of end users will expect that numeric scalar types
> > are interoperable. To not make them scared and point them to issues in
> > their code instead of slapping their hands immediately when they run
> > something that is not so correct.
> >
> >
> >
> >> Moreover, the whole point of adding a warning when implicit conversions
> >> from int to float happen was to be able to warn before elevating the
> >> warning to a TypeError.
> >>
> >
> > Sorry, I'm not aware of issues of converting ints to floats. Are there any
> > issues? I understand the issue of the backward conversion, but not the
> > forward one. Could you add details here?
> >
>
> I meant converting floats to int.
> But you can lose precision when converting an integer to float as there are
> only 53 bits for the coefficient.
>
>
> > Therefore, introducing behaviour that warns instead of throwing a
> >> TypeError is already a no-go from my PoV.
> >>
> >
> > I'm okay with TypeErrors for float to decimal conversions as well. This is
> > not a key point of my proposal. If the community prefers errors instead of
> > warnings - that's also fine.
> >
> >
> > Literal numbers in the code are converted to floats by default. If
> >>> prepended by the "(decimal)" typecast, the decimal result is produced
> >>> without an intermediary float.
> >>>
> >>
> >> This behaviour is rather suboptimal, I'd rather have literals be decimals,
> >> as decimals to floats should always be a reasonable implicit coercion
> >> considering we already do int to float.
> >>
> >
> > Is it optimal to perform conversions on every fractional literal? This is
> > also not a key point for me and I'm okay with any implementation that the
> > internals community prefers.
> >
> >
> >
> >>  New declare directive "default_decimal" is added. When used, literals and
> >>
> >>> math operations return decimal by default instead of float. This is to
> >>> simplify creating source files working with decimals only.
> >>>
> >>
> >> Please no, no new declare directives that affect engine behaviour.
> >> Strict types was already a mistake because of this IMHO.
> >>
> >
> > I didn't know that the strict types directive was a mistake. My intention
> > is to be able to write clean all-decimal units of code and not break the
> > backward compatibility. The old code should work as it was before. At the
> > same time, there are use cases when the whole class/project should be
> > written with decimals only. As a user, I want to do that without complex
> > language structures and excessive typehints or explicit conversions. The
> > all-decimal code  should be as clean as it is now with floats. This is why
> > I proposed this directive. Can you suggest something better to achieve the
> > same?
> >
>
> The issue is that I don't think having arbitrary precision decimals as a
> core language feature is a necessity compared to rational types.
> A cast from rational to float wouldn't produce a large round trip, whereas
> trying to figure out arbitrary precision is more difficult.
> But in any case, having a declare/INI or whatever that changes the
> behaviour of the engine/language is not a good design choice.
>
>
> > [...]
> >
> >  The new type uses libmpdec internally to perform decimal calculations
> >> (same
> >>
> >>> as Python).
> >>>
> >>
> 

Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2023-12-12 Thread G. P. B.
On Fri, 8 Dec 2023 at 10:14, Alexander Pravdin 
wrote:

> On Thu, Dec 7, 2023 at 11:36 PM G. P. B.  wrote:
>
> - Objects are always casted to true, GMP(0) will equal to true.
>>>
>>
>> This is incorrect, GMP object do _not_ support casts to bool
>> See https://3v4l.org/LHpD1
>>
>
> This is weird. Any PHP user would expect that a zero number can be easily
> casted to boolean false. This is also why I think we need a scalar decimal
> type.
>

Internal objects can overload casts, SimpleXML overloads the boolean cast
already.
We could add this to GMP to return false for 0.


> It works the same as "float" in terms of its usage and type casting except
>>> for one thing. Float value can be passed to a decimal argument or
>>> typecasted with a warning like "Float to decimal conversion may incur
>>> unexpected results".
>>>
>>> Decimal to float conversion is allowed and smooth:
>>>
>>> function f (float $value) {}
>>>
>>> f(0.2);
>>>
>>> f(0.2d); // allowed with no warnings
>>>
>>
>> I disagree with this part, floats can not represent decimal values
>> properly e.g.
>> $f1 = 0.1;
>> $f2 = 0.2;
>> $f3 = 0.3;
>> var_dump($f1 + $f2 === $f3);
>>
> will return false.
>> As such, floats are not at all compatible with decimals.
>>
>
> Yes, I know that. I mentioned that we can not convert float to decimal
> without an intermediate value where we apply rounding and get a
> human-readable value in some representation (string or whatsoever).
>
> My intention was to provide implicit conversion with warnings because I
> guess that the majority of end users will expect that numeric scalar types
> are interoperable. To not make them scared and point them to issues in
> their code instead of slapping their hands immediately when they run
> something that is not so correct.
>
>
>
>> Moreover, the whole point of adding a warning when implicit conversions
>> from int to float happen was to be able to warn before elevating the
>> warning to a TypeError.
>>
>
> Sorry, I'm not aware of issues of converting ints to floats. Are there any
> issues? I understand the issue of the backward conversion, but not the
> forward one. Could you add details here?
>

I meant converting floats to int.
But you can lose precision when converting an integer to float as there are
only 53 bits for the coefficient.


> Therefore, introducing behaviour that warns instead of throwing a
>> TypeError is already a no-go from my PoV.
>>
>
> I'm okay with TypeErrors for float to decimal conversions as well. This is
> not a key point of my proposal. If the community prefers errors instead of
> warnings - that's also fine.
>
>
> Literal numbers in the code are converted to floats by default. If
>>> prepended by the "(decimal)" typecast, the decimal result is produced
>>> without an intermediary float.
>>>
>>
>> This behaviour is rather suboptimal, I'd rather have literals be decimals,
>> as decimals to floats should always be a reasonable implicit coercion
>> considering we already do int to float.
>>
>
> Is it optimal to perform conversions on every fractional literal? This is
> also not a key point for me and I'm okay with any implementation that the
> internals community prefers.
>
>
>
>>  New declare directive "default_decimal" is added. When used, literals and
>>
>>> math operations return decimal by default instead of float. This is to
>>> simplify creating source files working with decimals only.
>>>
>>
>> Please no, no new declare directives that affect engine behaviour.
>> Strict types was already a mistake because of this IMHO.
>>
>
> I didn't know that the strict types directive was a mistake. My intention
> is to be able to write clean all-decimal units of code and not break the
> backward compatibility. The old code should work as it was before. At the
> same time, there are use cases when the whole class/project should be
> written with decimals only. As a user, I want to do that without complex
> language structures and excessive typehints or explicit conversions. The
> all-decimal code  should be as clean as it is now with floats. This is why
> I proposed this directive. Can you suggest something better to achieve the
> same?
>

The issue is that I don't think having arbitrary precision decimals as a
core language feature is a necessity compared to rational types.
A cast from rational to float wouldn't produce a large round trip, whereas
trying to figure out arbitrary precision is more difficult.
But in any case, having a declare/INI or whatever that changes the
behaviour of the engine/language is not a good design choice.


> [...]
>
>  The new type uses libmpdec internally to perform decimal calculations
>> (same
>>
>>> as Python).
>>>
>>
>> I really don't think we need arbitrary precision decimals.
>>
> I'm also not convinced using a floating point spec is the most sensible,
>> due to the rounding errors this is going to introduce.
>> The non-arbitrary IEEE 754-2008 specification cannot describe the decimal
>> 123457.1467 exactly, which is 

Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2023-12-08 Thread Alexander Pravdin
On Thu, Dec 7, 2023 at 11:36 PM G. P. B.  wrote:

- Objects are always casted to true, GMP(0) will equal to true.
>>
>
> This is incorrect, GMP object do _not_ support casts to bool
> See https://3v4l.org/LHpD1
>

This is weird. Any PHP user would expect that a zero number can be easily
casted to boolean false. This is also why I think we need a scalar decimal
type.



>
>> It works the same as "float" in terms of its usage and type casting
>> except
>> for one thing. Float value can be passed to a decimal argument or
>> typecasted with a warning like "Float to decimal conversion may incur
>> unexpected results".
>>
>> Decimal to float conversion is allowed and smooth:
>>
>> function f (float $value) {}
>>
>> f(0.2);
>>
>> f(0.2d); // allowed with no warnings
>>
>
> I disagree with this part, floats can not represent decimal values
> properly e.g.
> $f1 = 0.1;
> $f2 = 0.2;
> $f3 = 0.3;
> var_dump($f1 + $f2 === $f3);
>
will return false.
> As such, floats are not at all compatible with decimals.
>

Yes, I know that. I mentioned that we can not convert float to decimal
without an intermediate value where we apply rounding and get a
human-readable value in some representation (string or whatsoever).

My intention was to provide implicit conversion with warnings because I
guess that the majority of end users will expect that numeric scalar types
are interoperable. To not make them scared and point them to issues in
their code instead of slapping their hands immediately when they run
something that is not so correct.



> Moreover, the whole point of adding a warning when implicit conversions
> from int to float happen was to be able to warn before elevating the
> warning to a TypeError.
>

Sorry, I'm not aware of issues of converting ints to floats. Are there any
issues? I understand the issue of the backward conversion, but not the
forward one. Could you add details here?



> Therefore, introducing behaviour that warns instead of throwing a
> TypeError is already a no-go from my PoV.
>

I'm okay with TypeErrors for float to decimal conversions as well. This is
not a key point of my proposal. If the community prefers errors instead of
warnings - that's also fine.


Literal numbers in the code are converted to floats by default. If
>> prepended by the "(decimal)" typecast, the decimal result is produced
>> without an intermediary float.
>>
>
> This behaviour is rather suboptimal, I'd rather have literals be decimals,
> as decimals to floats should always be a reasonable implicit coercion
> considering we already do int to float.
>

Is it optimal to perform conversions on every fractional literal? This is
also not a key point for me and I'm okay with any implementation that the
internals community prefers.



>  New declare directive "default_decimal" is added. When used, literals and
>
>> math operations return decimal by default instead of float. This is to
>> simplify creating source files working with decimals only.
>>
>
> Please no, no new declare directives that affect engine behaviour.
> Strict types was already a mistake because of this IMHO.
>

I didn't know that the strict types directive was a mistake. My intention
is to be able to write clean all-decimal units of code and not break the
backward compatibility. The old code should work as it was before. At the
same time, there are use cases when the whole class/project should be
written with decimals only. As a user, I want to do that without complex
language structures and excessive typehints or explicit conversions. The
all-decimal code  should be as clean as it is now with floats. This is why
I proposed this directive. Can you suggest something better to achieve the
same?



> New language construct "as_decimal()" is added to produce decimal math
>> results for literals and math operations instead of float without
>> intermediary float:
>>
>> $var = 5 / 2; // returns float 2.5
>> $var = as_decimal(5 / 2); // returns decimal 2.5
>>
>> This is a kind of "default_decimal" for a specific operation.
>>
>
> Again, this should return a decimal instead IMHO.
>

While it will work from the logical perspective, additional conversions
from decimal to float may incur performance issues in the existing code
that relies on floats only. Again, my intention here is to not break
backward compatibility and not introduce performance issues to the existing
code.



>
>
>> If mixed float and decimal operands are used in a math operation, decimal
>> is converted to float by default. If "default_decimal" directive or
>> "as_decimal()" construct is used, float is converted to decimal (with a
>> warning):
>>
>> $f = (float) 0.2;
>> $d = (decimal) 0.2;
>>
>> $r = $f + $d; // returns float result by default
>> $r = as_decimal($f + $d); // returns decimal result with a warning about
>> implicit float to decimal conversion
>>
>> All builtin functions that currently accept float also accept decimal. So
>> users don't need to care about separate function sets, and PHP 

Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2023-12-08 Thread Alexander Pravdin
On Thu, Dec 7, 2023 at 11:27 PM Jordan LeDoux 
wrote:

You are going to run into some very difficult corners on this one. For the
> last... 8 years i guess? I have been working on an arbitrary precision
> library for PHP in userland. It utilizes BCMath, ext-decimal, and GMP,
> depending on what is installed and what kind of operation you are
> performing.
>
> So, the functions that currently accept floats include functions such as
> `sin()` or `atan()`. These functions are not at all trivial to do to
> arbitrary precision. In fact, the VAST majority of the work I have done on
> my library has been to handle cases like "What do I do if the user wants
> 2.921 ** 4.293810472934854?" or "How will I guarantee the precision that
> the user requested for `tan()` in an efficient way?"
>
> Now, libmpdec is going to actually have implementations for most of this
> stuff that you can call directly, but if the PHP function `sin()` isn't
> capable of *outputting* a `decimal`, then this isn't really that much of an
> improvement over the current situation. I mean, it's still something I
> would support, but that's the area where some help from the engine goes a
> VERY long way.
>

In my proposal, builtin functions are capable of returning decimals if
they're fed with decimals.


You're probably also going to need a way for a user to grab certain
> constants to a given precision. I would think e and pi at the least.
>
> I have a lot of experience working on this problem space in PHP, and am
> definitely willing to help. I looked into doing a libmpdec PHP integration
> several years ago, but decided that voters were unlikely to give it a fair
> shot, and so decided against it. If you're willing to try and roll the ball
> up the hill though, I'll definitely help you.
>

Unfortunately, I'm not an expert in precise math. I definitely need help
from experts like you. I appreciate your readiness.

I understand that there are a lot of edge cases. I would propose to
implement basics at first and then decide what to do with edge cases.


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2023-12-07 Thread G. P. B.
On Thu, 7 Dec 2023 at 06:36, Alex Pravdin  wrote:

> Hello internals,
> [...]
> GMP:
> - Workaround: implements the GMP class that allows basic math operations.
> - Requires using separate functions for the rest of operations.
>
> - Objects are always casted to true, GMP(0) will equal to true.
>

This is incorrect, GMP object do _not_ support casts to bool
See https://3v4l.org/LHpD1


> It works the same as "float" in terms of its usage and type casting except
> for one thing. Float value can be passed to a decimal argument or
> typecasted with a warning like "Float to decimal conversion may incur
> unexpected results".
>
> Decimal to float conversion is allowed and smooth:
>
> function f (float $value) {}
>
> f(0.2);
>
> f(0.2d); // allowed with no warnings
>

I disagree with this part, floats can not represent decimal values properly
e.g.
$f1 = 0.1;
$f2 = 0.2;
$f3 = 0.3;
var_dump($f1 + $f2 === $f3);

will return false.
As such, floats are not at all compatible with decimals.

Moreover, the whole point of adding a warning when implicit conversions
from int to float happen was to be able to warn before elevating the
warning to a TypeError.
Therefore, introducing behaviour that warns instead of throwing a TypeError
is already a no-go from my PoV.


> [...]
>
> Literal numbers in the code are converted to floats by default. If
> prepended by the "(decimal)" typecast, the decimal result is produced
> without an intermediary float.
>

This behaviour is rather suboptimal, I'd rather have literals be decimals,
as decimals to floats should always be a reasonable implicit coercion
considering we already do int to float.


> New declare directive "default_decimal" is added. When used, literals and
> math operations return decimal by default instead of float. This is to
> simplify creating source files working with decimals only.
>

Please no, no new declare directives that affect engine behaviour.
Strict types was already a mistake because of this IMHO.


> New language construct "as_decimal()" is added to produce decimal math
> results for literals and math operations instead of float without
> intermediary float:
>
> $var = 5 / 2; // returns float 2.5
> $var = as_decimal(5 / 2); // returns decimal 2.5
>
> This is a kind of "default_decimal" for a specific operation.
>

Again, this should return a decimal instead IMHO.


> If mixed float and decimal operands are used in a math operation, decimal
> is converted to float by default. If "default_decimal" directive or
> "as_decimal()" construct is used, float is converted to decimal (with a
> warning):
>
> $f = (float) 0.2;
> $d = (decimal) 0.2;
>
> $r = $f + $d; // returns float result by default
> $r = as_decimal($f + $d); // returns decimal result with a warning about
> implicit float to decimal conversion
>
> All builtin functions that currently accept float also accept decimal. So
> users don't need to care about separate function sets, and PHP developers
> don't need to maintain separate sets of functions. If such functions get
> the decimal parameter, they return decimal. If they have more than one
> float parameter and mixed float and decimal passed, decimals converted to
> float by default. If "default_decimal" or "as_decimal" used, float is
> converted to decimal with the warning.
>

Messing with the return value type has already proved controversial.
And as I said previously, I am dead against having implicit float to
decimal conversions.
Making the functions type generic is something that I am fine, however.


> The new type uses libmpdec internally to perform decimal calculations
> (same
> as Python).
>

I really don't think we need arbitrary precision decimals.
I'm also not convinced using a floating point spec is the most sensible,
due to the rounding errors this is going to introduce.
The non-arbitrary IEEE 754-2008 specification cannot describe the decimal
123457.1467 exactly, which is frankly pointless.

Decimals, or more broadly rational numbers that, outside numerical
computations, that are going to be used are not going to need huge
denominators.

I've been thinking about this for a while, and I personally think that
rational numbers are just better than trying to support only decimals.
And considering we have 64 bits to play with for a new zval type splitting
the bits into a 32-bit unsigned integer for the numerator and an 32-bit
signed integer for the denominator should provide us with enough reasonable
rational numbers.
As any number that do not fit in this structure seems to be something
relegated to the world of numerical computation where floats are what are
mostly used anyway.


> All of the points above are subject to discussions, it is not an RFC
> candidate right now. So please share your opinions.
>
> I know that the implementation of this will require a lot of work. But I
> don't think this is a stopper from formulating the requirements.
> Sometimes,
> any project requires big changes to move forward. I'm pretty sure this
> 

Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2023-12-07 Thread Jordan LeDoux
On Wed, Dec 6, 2023 at 10:36 PM Alex Pravdin  wrote:

> Hello internals,
>
>
> This is the second round of the discussion regarding arbitrary precision
> scalar type integration into PHP. The previous part:
> https://marc.info/?l=php-internals=168250492216838=2 was initiated by
> me before deep diving into the work with decimals in PHP. After 6 months
> of
> working, I would like to update my proposal taking into account my
> experience and the previous discussion.
> All builtin functions that currently accept float also accept decimal. So
> users don't need to care about separate function sets, and PHP developers
> don't need to maintain separate sets of functions. If such functions get
> the decimal parameter, they return decimal. If they have more than one
> float parameter and mixed float and decimal passed, decimals converted to
> float by default. If "default_decimal" or "as_decimal" used, float is
> converted to decimal with the warning.
>
>
You are going to run into some very difficult corners on this one. For the
last... 8 years i guess? I have been working on an arbitrary precision
library for PHP in userland. It utilizes BCMath, ext-decimal, and GMP,
depending on what is installed and what kind of operation you are
performing.

So, the functions that currently accept floats include functions such as
`sin()` or `atan()`. These functions are not at all trivial to do to
arbitrary precision. In fact, the VAST majority of the work I have done on
my library has been to handle cases like "What do I do if the user wants
2.921 ** 4.293810472934854?" or "How will I guarantee the precision that
the user requested for `tan()` in an efficient way?"

Now, libmpdec is going to actually have implementations for most of this
stuff that you can call directly, but if the PHP function `sin()` isn't
capable of *outputting* a `decimal`, then this isn't really that much of an
improvement over the current situation. I mean, it's still something I
would support, but that's the area where some help from the engine goes a
VERY long way.

You're probably also going to need a way for a user to grab certain
constants to a given precision. I would think e and pi at the least.

I have a lot of experience working on this problem space in PHP, and am
definitely willing to help. I looked into doing a libmpdec PHP integration
several years ago, but decided that voters were unlikely to give it a fair
shot, and so decided against it. If you're willing to try and roll the ball
up the hill though, I'll definitely help you.

Jordan


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2023-12-07 Thread Alexander Pravdin
>
> Someone tangential to your proposal, have you given any thought to
> implementing this similar to how Python treats numbers?
>

Unfortunately, I don't know many details of numbers treatment in Python...


In Python, integers have unlimited precision. I’m not sure how they store
> the values internally, but to users of Python, any sequence of numbers is
> an `int`, no matter how long it is.
>
> For example, this multiplies the max 64-bit, signed integer by 2, and the
> result is still an `int`:
>
> >>> i = 9223372036854775807 * 2
> >>> i
> 18446744073709551614
> >>> type(i)
> 
>
> And this is a really, really, really long number that’s still an `int`:
>
> >>> x =
> 9223372036854775807922337203685477580792233720368547758079223372036854775807
> >>> x
>
> 9223372036854775807922337203685477580792233720368547758079223372036854775807
> >>> type(x)
> 
>

I'm not sure about integers, I mostly care about decimals :) Decimals can
hold big rounded ints as well. The limit on the maximum number here will be
the underlying library's limit.


However, if we can achieve arbitrary-length integers, is there a reason we
> couldn’t also have arbitrary length floating point numbers?
>

I'm not familiar with arbitrary-length integers so I don't know what to say
here...



> Below a certain threshold, we could use the system’s native int and double
> for storage and math. Above a certain threshold, we could internally switch
> to a bundled library for handling arbitrary-precision integers and floats,
> and it would be seamless to the user, who would see only `int` and `float`
> types in PHP.
>

I guess this could be a topic of the next step discussion after "decimal"
introduction.


Anyway, this is something I’ve been thinking about for some time, but I
> haven’t taken the time to look into what it might take to implement it. It
> sounds like you have looked into it, so I’m interested to know whether you
> think what I’ve described here is feasible.
>

I was only thinking about decimals and I'm not an expert in low-level
manipulation of numbers.



Best regards,
Alex.


Re: [PHP-DEV] Proposal: Arbitrary precision native scalar type

2023-12-06 Thread Ben Ramsey
> On Dec 7, 2023, at 00:36, Alex Pravdin  wrote:
> 
> Hello internals,
> 
> 
> This is the second round of the discussion regarding arbitrary precision 
> scalar type integration into PHP. The previous part: 
> https://marc.info/?l=php-internals=168250492216838=2 was initiated by me 
> before deep diving into the work with decimals in PHP. After 6 months of 
> working, I would like to update my proposal taking into account my experience 
> and the previous discussion.
> 
> Today's alternatives and their problems are the following.
> 
> bcmath:
> - Workaround: using string type.
> - Unintuitive function calls instead of regular math operations.
> - Unintuitive strings instead of numbers. People want to work with numbers.
> - Can not use proper type-hinting.
> - Can use PHP's basic type coercions.
> 
> Ext-decimal:
> - Third-party extension.
> - Workaround: implements the Decimal class that allows basic regular math 
> operations.
> - Requires using class methods for the rest of math operations.
> - The latest release was in 2019 and there's a danger that it will be 
> unmaintained and not compatible with the future PHP releases.
> - The php-decimal documentation website is currently down.
> - Since objects are always casted to true when not null, "(bool) Decimal(0)" 
> will equal to true which is not intuitive.
> - IDEs are often confused when you use math operations on objects while the 
> code works fine.
> 
> GMP:
> - Workaround: implements the GMP class that allows basic math operations.
> - Requires using separate functions for the rest of operations.
> 
> - Objects are always casted to true, GMP(0) will equal to true.
> 
> 
> Accounting for all of the above, I suggest adding a native numeric scalar 
> arbitrary precision type called "decimal". Below are the preliminary 
> requirements for implementation.
> 
> 
> Decimal values can be created from literals by specifying a modifier or using 
> the (decimal) typecast:
> 
> $v = 0.2d;
> $v = (decimal) 0.2; // Creates a decimal value without intermediary float
> 
> It uses the precision and scale defined in php.ini.
> 
> The "decimal" typehint allows to define custom precision and scale: 
> decimal(20,5). It accepts regular expressions returning ints in the execution 
> context. It accepts int constants and literals in class field and function 
> argument definitions.
> 
> New functions added: get_scale and get_precision to return corresponding 
> values about a decimal value.
> 
> If decimal value with different scale and precision is going to be assigned 
> to a variable or parameter with smaller scale or precision, it first tries to 
> convert the value. If it's not possible, then an exception is thrown like 
> "Can not convert decimal (a, b) x. to decimal(c, d)". If possible, it 
> performs the conversion and generates a warning like "Assigning decimal(a, b) 
> to decimal(c, d) may be not possible with some values".
> 
> It works the same as "float" in terms of its usage and type casting except 
> for one thing. Float value can be passed to a decimal argument or typecasted 
> with a warning like "Float to decimal conversion may incur unexpected 
> results".
> 
> Decimal to float conversion is allowed and smooth:
> 
> function f (float $value) {}
> 
> f(0.2);
> 
> f(0.2d); // allowed with no warnings
> 
> 
> Function "str_to_decimal" added to convert string representation of numbers 
> to decimals.
> 
> 
> Typecast from string to decimal works the same as the "str_to_decimal" 
> function.
> 
> Function "float_to_decimal" added to explicitly convert floats to decimals. 
> It performs float to string conversions using php.ini settings as defaults 
> but also accepts parameters to configure the conversion. Then, it converts 
> string to decimal. Since the main problem of float to decimal conversion is 
> that we don't know the exact result until we use some rounding when 
> transforming it to a human-readable format, it looks like the step of the 
> conversion to a string is inevitable. Any more optimized algorithms are 
> welcome.
> 
> Explicit typecast from float to decimal works the same as "float_to_decimal" 
> function with all default values but also throws a warning. This is to 
> encourage users to use explicit conversion with the "float_to_decimal" 
> function and control the results.
> 
> Literal numbers in the code are converted to floats by default. If prepended 
> by the "(decimal)" typecast, the decimal result is produced without an 
> intermediary float.
> 
> New declare directive "default_decimal" is added. When used, literals and 
> math operations return decimal by default instead of float. This is to 
> simplify creating source files working with decimals only.
> 
> New language construct "as_decimal()" is added to produce decimal math 
> results for literals and math operations instead of float without 
> intermediary float:
> 
> $var = 5 / 2; // returns float 2.5
> $var = as_decimal(5 / 2); // returns decimal 2.5
> 
> This is 

[PHP-DEV] Proposal: Arbitrary precision native scalar type

2023-12-06 Thread Alex Pravdin

Hello internals,


This is the second round of the discussion regarding arbitrary precision 
scalar type integration into PHP. The previous part: 
https://marc.info/?l=php-internals=168250492216838=2 was initiated by 
me before deep diving into the work with decimals in PHP. After 6 months of 
working, I would like to update my proposal taking into account my 
experience and the previous discussion.


Today's alternatives and their problems are the following.

bcmath:
- Workaround: using string type.
- Unintuitive function calls instead of regular math operations.
- Unintuitive strings instead of numbers. People want to work with numbers.
- Can not use proper type-hinting.
- Can use PHP's basic type coercions.

Ext-decimal:
- Third-party extension.
- Workaround: implements the Decimal class that allows basic regular math 
operations.

- Requires using class methods for the rest of math operations.
- The latest release was in 2019 and there's a danger that it will be 
unmaintained and not compatible with the future PHP releases.

- The php-decimal documentation website is currently down.
- Since objects are always casted to true when not null, "(bool) 
Decimal(0)" will equal to true which is not intuitive.
- IDEs are often confused when you use math operations on objects while the 
code works fine.


GMP:
- Workaround: implements the GMP class that allows basic math operations.
- Requires using separate functions for the rest of operations.

- Objects are always casted to true, GMP(0) will equal to true.


Accounting for all of the above, I suggest adding a native numeric scalar 
arbitrary precision type called "decimal". Below are the preliminary 
requirements for implementation.



Decimal values can be created from literals by specifying a modifier or 
using the (decimal) typecast:


$v = 0.2d;
$v = (decimal) 0.2; // Creates a decimal value without intermediary float

It uses the precision and scale defined in php.ini.

The "decimal" typehint allows to define custom precision and scale: 
decimal(20,5). It accepts regular expressions returning ints in the 
execution context. It accepts int constants and literals in class field and 
function argument definitions.


New functions added: get_scale and get_precision to return corresponding 
values about a decimal value.


If decimal value with different scale and precision is going to be assigned 
to a variable or parameter with smaller scale or precision, it first tries 
to convert the value. If it's not possible, then an exception is thrown 
like "Can not convert decimal (a, b) x. to decimal(c, d)". If 
possible, it performs the conversion and generates a warning like 
"Assigning decimal(a, b) to decimal(c, d) may be not possible with some 
values".


It works the same as "float" in terms of its usage and type casting except 
for one thing. Float value can be passed to a decimal argument or 
typecasted with a warning like "Float to decimal conversion may incur 
unexpected results".


Decimal to float conversion is allowed and smooth:

function f (float $value) {}

f(0.2);

f(0.2d); // allowed with no warnings


Function "str_to_decimal" added to convert string representation of numbers 
to decimals.



Typecast from string to decimal works the same as the "str_to_decimal" 
function.


Function "float_to_decimal" added to explicitly convert floats to decimals. 
It performs float to string conversions using php.ini settings as defaults 
but also accepts parameters to configure the conversion. Then, it converts 
string to decimal. Since the main problem of float to decimal conversion is 
that we don't know the exact result until we use some rounding when 
transforming it to a human-readable format, it looks like the step of the 
conversion to a string is inevitable. Any more optimized algorithms are 
welcome.


Explicit typecast from float to decimal works the same as 
"float_to_decimal" function with all default values but also throws a 
warning. This is to encourage users to use explicit conversion with the 
"float_to_decimal" function and control the results.


Literal numbers in the code are converted to floats by default. If 
prepended by the "(decimal)" typecast, the decimal result is produced 
without an intermediary float.


New declare directive "default_decimal" is added. When used, literals and 
math operations return decimal by default instead of float. This is to 
simplify creating source files working with decimals only.


New language construct "as_decimal()" is added to produce decimal math 
results for literals and math operations instead of float without 
intermediary float:


$var = 5 / 2; // returns float 2.5
$var = as_decimal(5 / 2); // returns decimal 2.5

This is a kind of "default_decimal" for a specific operation.

If mixed float and decimal operands are used in a math operation, decimal 
is converted to float by default. If "default_decimal" directive or 
"as_decimal()" construct is used, float is converted to decimal (with