Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Floating point bug in range operation on Apple Silicon hardware #14140

Closed
judahnator opened this issue May 5, 2024 · 17 comments
Closed

Floating point bug in range operation on Apple Silicon hardware #14140

judahnator opened this issue May 5, 2024 · 17 comments
Assignees
Labels

Comments

@judahnator
Copy link

Description

The following code:

<?php
print_r(range(-0.03, 0.03, 0.01));

Resulted in this output:

Array
(
    [0] => -0.03
    [1] => -0.02
    [2] => -0.01
    [3] => 1.7347234759768E-18
    [4] => 0.01
    [5] => 0.02
)

But I expected this output instead:

Array
(
    [0] => -0.03
    [1] => -0.02
    [2] => -0.01
    [3] => 0
    [4] => 0.01
    [5] => 0.02
    [6] => 0.03
)

I tested this on a few devices with my peers. Every x86 processor we tested worked as expected, but reliably got the erroneous result using different Apple M2 devices.

PHP Version

PHP 8.3.6

Operating System

Sonoma 14.4.1

@SakiTakamachi
Copy link
Member

I'll investigate this issue.

@SakiTakamachi SakiTakamachi self-assigned this May 5, 2024
@SakiTakamachi
Copy link
Member

SakiTakamachi commented May 6, 2024

The investigation is complete. This is probably an Apple bug.

The following code:

// double.c
int main(void)
{
    int i = 3;
    double v = 0.03;
    double v2 = 0.01;

    double ret = v - (i * v2);

    return 0;
}

compile:

clang -o double -g double.c

exec:

./double

If this continues, nothing will be output, so debug with gdb:

# gdb ./double

....

(gdb) b main
Breakpoint 1 at 0x724: file double.c, line 4.
(gdb) run

....

Breakpoint 1, main () at double.c:4
4           int i = 3;
(gdb) n
5           double v = 0.03;
(gdb) 
6           double v2 = 0.01;
(gdb) 
8           double ret = v - (i * v2);
(gdb) 
10          return 0;
(gdb) p ret
$1 = -1.7347234759768071e-18
(gdb) p v
$2 = 0.029999999999999999
(gdb) p v2
$3 = 0.01
(gdb) p i
$4 = 3
(gdb) p i * v2
$5 = 0.029999999999999999
(gdb) p v - (i * v2)
$6 = 0

We can see that the calculation result ret is incorrect.

@SakiTakamachi
Copy link
Member

However, I'm just trying to figure out if there's a workaround for this

@devnexen
Copy link
Member

devnexen commented May 6, 2024

If that helps, I have the same issue with my raspberry 4.

@erjotek
Copy link

erjotek commented May 6, 2024

same problem occurred between 5.0 and 5.3.6 checking on 3v4l

@SakiTakamachi
Copy link
Member

Thanks. hmm, then, is this an arm-specific phenomenon? It might be a good idea to push the test code to Circle CI arm.

@SakiTakamachi
Copy link
Member

On a separate matter, I was investigating the behavior when using gcc and arm together.
So I discovered by chance that this only happens when compiled with clang. Compiling with gcc gives normal results.

@youkidearitai
Copy link
Contributor

In M1 MacBook Air is reproduced.

MacBook-Air-2:php-src tekimen$ sapi/cli/php -r 'print_r(range(-0.03, 0.03, 0.01));'
Array
(
    [0] => -0.03
    [1] => -0.02
    [2] => -0.01
    [3] => 1.7347234759768E-18
    [4] => 0.01
    [5] => 0.02
)

In Raspberry Pi 4 (build in GCC), result is bellow:

tekimen@raspberrypi:~/src/php-src $ sapi/cli/php -r 'print_r(range(-0.03, 0.03, 0.01));'
Array
(
    [0] => -0.03
    [1] => -0.02
    [2] => -0.01
    [3] => 0
    [4] => 0.01
    [5] => 0.02
    [6] => 0.03
)

However, In Raspberry Pi 4 (build in clang), result is reproduced:

tekimen@raspberrypi:~/src/php-src $ cat config.nice
#! /bin/sh
#
# Created by configure

CFLAGS='-g' \
LDFLAGS='-v' \
CC='clang' \
'./configure' \
'--enable-debug' \
'--enable-mbstring' \
'--prefix=/home/tekimen/php83' \
"$@"
tekimen@raspberrypi:~/src/php-src $ sapi/cli/php -r 'print_r(range(-0.03, 0.03, 0.01));'
Array
(
    [0] => -0.03
    [1] => -0.02
    [2] => -0.01
    [3] => 1.7347234759768E-18
    [4] => 0.01
    [5] => 0.02
)

@SakiTakamachi
Copy link
Member

The combination of intel and clang works fine.

@SakiTakamachi
Copy link
Member

I reported it
llvm/llvm-project#91224

@SakiTakamachi
Copy link
Member

SakiTakamachi commented May 6, 2024

I was able to get an answer right away. This is a problem with clang's compilation flags, and if -ffp-contract=off is not specified, calculation results may be slightly different from those of gcc etc.

Therefore, if you are building it yourself, please pass CFLAGS='-ffp-contract=off' in ./configure.

@youkidearitai
Copy link
Contributor

I confirmed correct behavior in M1 MacBook Air.

MacBook-Air-2:php-src tekimen$ cat config.nice
#! /bin/sh
#
# Created by configure

CFLAGS='-ffp-contract=off' \
'./configure' \
'--enable-mbstring' \
'--enable-debug' \
'--prefix=/Users/tekimen/php_master' \
'--with-iconv=/opt/homebrew/opt/libiconv' \
'PKG_CONFIG_PATH=/opt/homebrew/opt/icu4c/lib/pkgconfig' \
'--enable-bcmath' \
'--with-zlib' \
'--enable-intl' \
"$@"
MacBook-Air-2:php-src tekimen$ sapi/cli/php -r 'print_r(range(-0.03, 0.03, 0.01));'
Array
(
    [0] => -0.03
    [1] => -0.02
    [2] => -0.01
    [3] => 0
    [4] => 0.01
    [5] => 0.02
    [6] => 0.03
)

Copy link

No feedback was provided. The issue is being suspended because we assume that you are no longer experiencing the problem. If this is not the case and you are able to provide the information that was requested earlier, please do so. Thank you.

@erjotek
Copy link

erjotek commented May 21, 2024

@shivammathur Hi, do you plan to change this flag in yours brew packages?

@SakiTakamachi
Copy link
Member

This issue was resolved by the following PR:

#14162

@shivammathur
Copy link
Member

shivammathur commented May 21, 2024

@erjotek

@shivammathur Hi, do you plan to change this flag in yours brew packages?

Yes, with the next releases.

@judahnator
Copy link
Author

Still having the problem, thanks GitHub actions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

6 participants