cqframework / cql-engine

Clinical Quality Language Evaluation Engine

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Power operator is inexact in cases where it should be exact

duncand opened this issue · comments

While in the general case, the result of a decimal number exponentiated to a decimal exponent might be irrational, it is well known that the result of a decimal exponentiated to an integer is rational, and in particular an integer exponentiated to an integer does nothing but possibly move the decimal point.

Therefore, when Power() is called on two Decimal arguments (directly or indirectly via casting), and we know that both arguments are logical integers, we expect that the result should be exact and identical to the first argument but for a possibly shifted decimal point.

Run the following CQL:

define x1: 1000000000000000000000000000.00000000
define x2: Power(10.0,27.0)
define x3: Power(10.0,23.0)
define x4: Power(10.0,22.0)
define x5: Power(10.0,-8.0)
define x6: 0.00000001

Actual result:

>> x1 [1:1] 1000000000000000000000000000.00000000
>> x2 [2:1] 1000000000000000013287555072.00000000
>> x3 [3:1] 100000000000000008388608.00000000
>> x4 [4:1] 10000000000000000000000.00000000
>> x5 [5:1] 1E-8
>> x6 [6:1] 1E-8

The expected result is that x2 is exactly the same exact power of 10 as x1, and that x3 is also an exact power of 10.

CQL officially supports Decimal values up to magnitude 10^28 minus one step size of 10^-8, but specifying larger magnitude numbers tersely in the current CQL Engine using Power() is only precise up to about 10^22 while above that it becomes inexact. This is because the current CQL Engine always implements Power() by way of 2 floating-point data types even when it doesn't need to.

This behaviour goes against user expectations, and can cause errors.

The task of this ticket is to make Power() exact at least when both arguments are integers. Making it exact at other times when logically possible is an option.