React-native-reanimated: Math errors with modulo on iOS

Created on 22 May 2020  路  3Comments  路  Source: software-mansion/react-native-reanimated

Description

When using modulo with certain values, the result appears to be incorrect. I haven't worked out what the pattern is for values that cause this behaviour, and the bug only appears to exist on iOS. Reanimated, Android and Web appear to behave correctly.

As an example, the operation 9999999999 % 10 === 9 in JS. In Reanimated modulo(new Value(9999999999), 10) === 9 on web and Android. However on Reanimated iOS I get a result of 0.

Initially I thought this might have been an issue with being above max 32bit int, but that doesn't appear to be the case as some numbers give the correct result, while some values much smaller than max int do not.

Screenshots

Reanimated Web | Reanimated Android | Reanimated iOS
---|---|---
9 | 9 | 0
image | image | image

GIF from iOS

This GIF shows some of the unusual results that are given from my expo snack. Values appear to be mostly incorrect when the start value is 9999999999 (or a similarly large number) but setting the value to 1234567 and then gradually increasing the value, the result appears to be correct, even when exceeding a value of 9999999999.

The left-hand side is pure JS (value % 10) while the right side is the result from reanimated (modulo(animatedValue, 10)).

RPReplay_Final1590116531

Snack or minimal code example

https://snack.expo.io/@levibuzolic/reanimated-math

import * as React from 'react';
import Animated from 'react-native-reanimated';
import { ReText } from 'react-native-redash';
const { concat, Value, modulo } = Animated;
const { useRef } = React;

export default function App() {
  const { current: animValue } = useRef(new Value(9999999999));
  return <ReText text={concat('', modulo(animValue, 10))} />;
}

Package versions

For the sample app I've tested in Expo 37.0.0 (which I believe uses Reanimated 1.70)

The issue also exists in my current production app running:

  • React: 16.9.0
  • React Native: 0.61.5
  • React Native Reanimated: 1.8.0
馃悶 Bug 馃コcan-repro

Most helpful comment

Hi @lebedev,
thanks for the detailed description.

We use CGFloat in Operator node code and it downcasts to floats as @deecewan mentioned. We should use there plain double like in Android implementation. I'll prepare a PR.

Thanks!

All 3 comments

Looking into this further with the help of @deecewan, it appears to be an issue with using single precision floats as 9999999999 cannot be safely represented as a float, so in iOS 9999999999 will end up being 10000000000 which will fmodf to 0.

This _might_ be an issue specific to targeting non-64-bit architectures as the reanimated code looks to be using doubles, but CGFloat might downcast to a 32-bit float.

yeah, from here it looks like if you're targeting a 32-bit architecture, CGFloat downcasts to a float instead of a double 馃槥

Hi @lebedev,
thanks for the detailed description.

We use CGFloat in Operator node code and it downcasts to floats as @deecewan mentioned. We should use there plain double like in Android implementation. I'll prepare a PR.

Thanks!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mrousavy picture mrousavy  路  3Comments

sa8ab picture sa8ab  路  3Comments

dinhmai74 picture dinhmai74  路  3Comments

ShaMan123 picture ShaMan123  路  3Comments

hosseinmd picture hosseinmd  路  3Comments