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

[BUG] Cast from string to long should return null if string is not a valid long #5110

Closed
andygrove opened this issue May 6, 2020 · 17 comments
Assignees
Labels
feature request New feature or request Java Affects Java cuDF API. Spark Functionality that helps Spark RAPIDS

Comments

@andygrove
Copy link
Contributor

andygrove commented May 6, 2020

Describe the bug

When casting from string to long (signed 64 bit in Java) I would expect the cast to return null if the provided string is less than Long.MIN_VALUE or greater than Long.MAX_VALUE. Currently, it returns an incorrect value.

For example, casting "9223372036854775808" (Long.MAX_VALUE + 1) to a long returns -9223372036854775808 (Long.MIN_VALUE).

Steps/Code to reproduce bug

Add the following test to ColumnVectorTest.

  @Test
  void testCastStringToLongOverflow() {
    String outOfRangeLong = "9223372036854775808"; // Long.MAX_VALUE + 1
    try (ColumnVector strings = ColumnVector.fromStrings(outOfRangeLong);
         ColumnVector cv = strings.castTo(DType.INT64);
         HostColumnVector longs = cv.copyToHost();) {
      assert(longs.isNull(0));
    }
  }

Expected behavior

Casting a string to long where the string is not a valid long in the range Long.MIN_VALUE to Long.MAX_VALUE should return null rather than overflow.

Environment overview (please complete the following information)

  • Environment location: Bare-metal
  • Method of cuDF install: from source

Environment details

     
     **git***
     commit e1ec4995aa1df35591c7cd60a0d7863e8202bd87 (HEAD -> branch-0.14, rapids/branch-0.14)
     Merge: b9577a3e6 416ef8ddd
     Author: Devavret Makkar <[email protected]>
     Date:   Tue May 5 02:22:18 2020 +0530
     
     Merge pull request #5022 from hummingtree/hotfix/transform_header
     
     Add timestamp header to transform
     **git submodules***
     b165e1fb11eeea64ccf95053e40f2424312599cc ../thirdparty/cub (v1.7.1)
     e3f867027c1d9603b5a677795900465b9fac9cb8 ../thirdparty/jitify (heads/cudf)
     cdcda484d0c7db114ea29c3b33429de5756ecfd8 ../thirdparty/libcudacxx (0.8.1-99-gcdcda48)
     a97a7380c76346c22bb67b93695bed19592afad2 ../thirdparty/libcudacxx/libcxx (heads/rapidsai-interop)
     
     ***OS Information***
     DISTRIB_ID=Ubuntu
     DISTRIB_RELEASE=18.04
     DISTRIB_CODENAME=bionic
     DISTRIB_DESCRIPTION="Ubuntu 18.04.3 LTS"
     NAME="Ubuntu"
     VERSION="18.04.3 LTS (Bionic Beaver)"
     ID=ubuntu
     ID_LIKE=debian
     PRETTY_NAME="Ubuntu 18.04.3 LTS"
     VERSION_ID="18.04"
     HOME_URL="https://www.ubuntu.com/"
     SUPPORT_URL="https://help.ubuntu.com/"
     BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
     PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
     VERSION_CODENAME=bionic
     UBUNTU_CODENAME=bionic
     Linux andygrove-dt 5.3.0-51-generic #44~18.04.2-Ubuntu SMP Thu Apr 23 14:27:18 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
     
     ***GPU Information***
     Wed May  6 10:54:55 2020
     +-----------------------------------------------------------------------------+
     | NVIDIA-SMI 440.64.00    Driver Version: 440.64.00    CUDA Version: 10.2     |
     |-------------------------------+----------------------+----------------------+
     | GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
     | Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
     |===============================+======================+======================|
     |   0  Quadro RTX 6000     On   | 00000000:17:00.0 Off |                  Off |
     | 33%   32C    P8     3W / 260W |      1MiB / 24220MiB |      0%      Default |
     +-------------------------------+----------------------+----------------------+
     |   1  GeForce GT 710      On   | 00000000:65:00.0 N/A |                  N/A |
     | 50%   49C    P0    N/A /  N/A |    790MiB /  2000MiB |     N/A      Default |
     +-------------------------------+----------------------+----------------------+
     
     +-----------------------------------------------------------------------------+
     | Processes:                                                       GPU Memory |
     |  GPU       PID   Type   Process name                             Usage      |
     |=============================================================================|
     |    1                    Not Supported                                       |
     +-----------------------------------------------------------------------------+
     
     ***CPU***
     Architecture:        x86_64
     CPU op-mode(s):      32-bit, 64-bit
     Byte Order:          Little Endian
     CPU(s):              12
     On-line CPU(s) list: 0-11
     Thread(s) per core:  2
     Core(s) per socket:  6
     Socket(s):           1
     NUMA node(s):        1
     Vendor ID:           GenuineIntel
     CPU family:          6
     Model:               85
     Model name:          Intel(R) Core(TM) i7-7800X CPU @ 3.50GHz
     Stepping:            4
     CPU MHz:             1200.011
     CPU max MHz:         4000.0000
     CPU min MHz:         1200.0000
     BogoMIPS:            6999.82
     Virtualization:      VT-x
     L1d cache:           32K
     L1i cache:           32K
     L2 cache:            1024K
     L3 cache:            8448K
     NUMA node0 CPU(s):   0-11
     Flags:               fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb cat_l3 cdp_l3 invpcid_single pti ssbd mba ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm cqm mpx rdt_a avx512f avx512dq rdseed adx smap clflushopt clwb intel_pt avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts hwp hwp_act_window hwp_epp hwp_pkg_req md_clear flush_l1d
     
     ***CMake***
     /home/andygrove/miniconda2/envs/cudf_dev/bin/cmake
     cmake version 3.17.0
     
     CMake suite maintained and supported by Kitware (kitware.com/cmake).
     
     ***g++***
     /usr/bin/g++
     g++ (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
     Copyright (C) 2017 Free Software Foundation, Inc.
     This is free software; see the source for copying conditions.  There is NO
     warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     
     
     ***nvcc***
     
     ***Python***
     /home/andygrove/miniconda2/envs/cudf_dev/bin/python
     Python 3.7.6
     
     ***Environment Variables***
     PATH                            : /opt/apache-maven-3.6.3/bin:/home/andygrove/miniconda2/envs/cudf_dev/bin:/home/andygrove/miniconda2/condabin:/home/andygrove/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
     LD_LIBRARY_PATH                 :
     NUMBAPRO_NVVM                   :
     NUMBAPRO_LIBDEVICE              :
     CONDA_PREFIX                    : /home/andygrove/miniconda2/envs/cudf_dev
     PYTHON_PATH                     :
     
     ***conda packages***
     /home/andygrove/miniconda2/condabin/conda
     # packages in environment at /home/andygrove/miniconda2/envs/cudf_dev:
     #
     # Name                    Version                   Build  Channel
     _libgcc_mutex             0.1                 conda_forge    conda-forge
     _openmp_mutex             4.5                      1_llvm    conda-forge
     alabaster                 0.7.12                     py_0    conda-forge
     appdirs                   1.4.3                      py_1    conda-forge
     arrow-cpp                 0.15.0           py37h090bef1_2    conda-forge
     attrs                     19.3.0                     py_0    conda-forge
     babel                     2.8.0                      py_0    conda-forge
     backcall                  0.1.0                      py_0    conda-forge
     black                     19.10b0                  py37_0    conda-forge
     bleach                    3.1.4              pyh9f0ad1d_0    conda-forge
     bokeh                     2.0.1            py37hc8dfbb8_0    conda-forge
     boost-cpp                 1.70.0               h8e57a91_2    conda-forge
     brotli                    1.0.7             he1b5a44_1001    conda-forge
     brotlipy                  0.7.0           py37h8f50634_1000    conda-forge
     bzip2                     1.0.8                h516909a_2    conda-forge
     c-ares                    1.15.0            h516909a_1001    conda-forge
     ca-certificates           2020.4.5.1           hecc5488_0    conda-forge
     certifi                   2020.4.5.1       py37hc8dfbb8_0    conda-forge
     cffi                      1.14.0           py37hd463f26_0    conda-forge
     cfgv                      3.1.0                      py_0    conda-forge
     chardet                   3.0.4           py37hc8dfbb8_1006    conda-forge
     click                     7.1.1              pyh8c360ce_0    conda-forge
     cloudpickle               1.3.0                      py_0    conda-forge
     cmake                     3.17.0               h28c56e5_0    conda-forge
     cmake_setuptools          0.1.3                      py_0    rapidsai
     commonmark                0.9.1                      py_0    conda-forge
     cryptography              2.8              py37hb09aad4_2    conda-forge
     cudatoolkit               10.0.130                      0    nvidia
     cudf                      0.14.0a0+3395.gf1dad0783.dirty          pypi_0    pypi
     cudnn                     7.6.0                cuda10.0_0    nvidia
     cupy                      7.3.0            py37h658377b_0    conda-forge
     cython                    0.29.16          py37h3340039_0    conda-forge
     cytoolz                   0.10.1           py37h516909a_0    conda-forge
     dask                      2.14.0+14.g03e9bc99          pypi_0    pypi
     decorator                 4.4.2                      py_0    conda-forge
     defusedxml                0.6.0                      py_0    conda-forge
     distributed               2.14.0+29.g8534e84b          pypi_0    pypi
     dlpack                    0.2                  he1b5a44_1    conda-forge
     docutils                  0.16             py37hc8dfbb8_1    conda-forge
     double-conversion         3.1.5                he1b5a44_2    conda-forge
     editdistance              0.5.3            py37h3340039_0    conda-forge
     entrypoints               0.3             py37hc8dfbb8_1001    conda-forge
     expat                     2.2.9                he1b5a44_2    conda-forge
     fastavro                  0.23.2           py37h8f50634_0    conda-forge
     fastrlock                 0.4             py37h3340039_1001    conda-forge
     flake8                    3.7.9            py37hc8dfbb8_1    conda-forge
     flatbuffers               1.12.0               he1b5a44_0    conda-forge
     freetype                  2.10.1               he06d7ca_0    conda-forge
     fsspec                    0.7.2                      py_0    conda-forge
     future                    0.18.2           py37hc8dfbb8_1    conda-forge
     gflags                    2.2.2             he1b5a44_1002    conda-forge
     glog                      0.4.0                h49b9bf7_3    conda-forge
     gmp                       6.2.0                he1b5a44_2    conda-forge
     grpc-cpp                  1.23.0               h18db393_0    conda-forge
     heapdict                  1.0.1                      py_0    conda-forge
     hypothesis                5.10.0                     py_0    conda-forge
     icu                       64.2                 he1b5a44_1    conda-forge
     identify                  1.4.14             pyh9f0ad1d_0    conda-forge
     idna                      2.9                        py_1    conda-forge
     imagesize                 1.2.0                      py_0    conda-forge
     importlib-metadata        1.6.0            py37hc8dfbb8_0    conda-forge
     importlib_metadata        1.6.0                         0    conda-forge
     ipykernel                 5.2.0            py37h43977f1_1    conda-forge
     ipython                   7.13.0           py37hc8dfbb8_2    conda-forge
     ipython_genutils          0.2.0                      py_1    conda-forge
     isort                     4.3.21           py37hc8dfbb8_1    conda-forge
     jedi                      0.17.0           py37hc8dfbb8_0    conda-forge
     jinja2                    2.11.2             pyh9f0ad1d_0    conda-forge
     jpeg                      9c                h14c3975_1001    conda-forge
     jsonschema                3.2.0            py37hc8dfbb8_1    conda-forge
     jupyter_client            6.1.3                      py_0    conda-forge
     jupyter_core              4.6.3            py37hc8dfbb8_1    conda-forge
     krb5                      1.17.1               h2fd8d38_0    conda-forge
     ld_impl_linux-64          2.34                 h53a641e_0    conda-forge
     libblas                   3.8.0               16_openblas    conda-forge
     libcblas                  3.8.0               16_openblas    conda-forge
     libcurl                   7.69.1               hf7181ac_0    conda-forge
     libedit                   3.1.20170329      hf8c457e_1001    conda-forge
     libevent                  2.1.10               h72c5cf5_0    conda-forge
     libffi                    3.2.1             he1b5a44_1007    conda-forge
     libgcc-ng                 9.2.0                h24d8f2e_2    conda-forge
     libgfortran-ng            7.3.0                hdf63c60_5    conda-forge
     liblapack                 3.8.0               16_openblas    conda-forge
     libllvm8                  8.0.1                hc9558a2_0    conda-forge
     libopenblas               0.3.9                h5ec1e0e_0    conda-forge
     libpng                    1.6.37               hed695b0_1    conda-forge
     libprotobuf               3.8.0                h8b12597_0    conda-forge
     librmm                    0.14.0a200420      cuda10.0_258    rapidsai-nightly
     libsodium                 1.0.17               h516909a_0    conda-forge
     libssh2                   1.8.2                h22169c7_2    conda-forge
     libstdcxx-ng              9.2.0                hdf63c60_2    conda-forge
     libtiff                   4.1.0                hfc65ed5_0    conda-forge
     libuv                     1.34.0               h516909a_0    conda-forge
     llvm-openmp               10.0.0               hc9558a2_0    conda-forge
     llvmlite                  0.31.0           py37h5202443_1    conda-forge
     locket                    0.2.0                      py_2    conda-forge
     lz4-c                     1.8.3             he1b5a44_1001    conda-forge
     markdown                  3.0.1                    pypi_0    pypi
     markupsafe                1.1.1            py37h8f50634_1    conda-forge
     mccabe                    0.6.1                      py_1    conda-forge
     mistune                   0.8.4           py37h8f50634_1001    conda-forge
     more-itertools            8.2.0                      py_0    conda-forge
     msgpack-python            1.0.0            py37h99015e2_1    conda-forge
     mypy_extensions           0.4.3            py37hc8dfbb8_1    conda-forge
     nbconvert                 5.6.1            py37hc8dfbb8_1    conda-forge
     nbformat                  5.0.6                      py_0    conda-forge
     nbsphinx                  0.6.1              pyh9f0ad1d_0    conda-forge
     nccl                      2.4.6.1              cuda10.0_0    nvidia
     ncurses                   6.1               hf484d3e_1002    conda-forge
     nodeenv                   1.3.5                      py_0    conda-forge
     notebook                  6.0.3                    py37_0    conda-forge
     numba                     0.48.0           py37hb3f55d8_0    conda-forge
     numpy                     1.18.1           py37h8960a57_1    conda-forge
     numpydoc                  0.9.2                      py_0    conda-forge
     nvstrings-cudaunknown     0.0.0.dev0               pypi_0    pypi
     olefile                   0.46                       py_0    conda-forge
     openssl                   1.1.1f               h516909a_0    conda-forge
     packaging                 20.1                       py_0    conda-forge
     pandas                    0.25.3           py37hb3f55d8_0    conda-forge
     pandoc                    1.19.2                        0    conda-forge
     pandocfilters             1.4.2                      py_1    conda-forge
     parquet-cpp               1.5.1                         2    conda-forge
     parso                     0.7.0              pyh9f0ad1d_0    conda-forge
     partd                     1.1.0                      py_0    conda-forge
     pathspec                  0.8.0              pyh9f0ad1d_0    conda-forge
     pexpect                   4.8.0            py37hc8dfbb8_1    conda-forge
     pickleshare               0.7.5           py37hc8dfbb8_1001    conda-forge
     pillow                    7.1.1            py37h718be6c_0    conda-forge
     pip                       20.0.2                     py_2    conda-forge
     pluggy                    0.13.0                   py37_0    conda-forge
     pre-commit                2.2.0            py37hc8dfbb8_1    conda-forge
     pre_commit                2.2.0                         1    conda-forge
     prometheus_client         0.7.1                      py_0    conda-forge
     prompt-toolkit            3.0.5                      py_0    conda-forge
     psutil                    5.7.0            py37h8f50634_1    conda-forge
     ptyprocess                0.6.0                   py_1001    conda-forge
     py                        1.8.1                      py_0    conda-forge
     pyarrow                   0.15.0           py37h8b68381_1    conda-forge
     pycodestyle               2.5.0                      py_0    conda-forge
     pycparser                 2.20                       py_0    conda-forge
     pyflakes                  2.1.1                      py_0    conda-forge
     pygments                  2.6.1                      py_0    conda-forge
     pyopenssl                 19.1.0                     py_1    conda-forge
     pyparsing                 2.4.7              pyh9f0ad1d_0    conda-forge
     pyrsistent                0.16.0           py37h8f50634_0    conda-forge
     pysocks                   1.7.1            py37hc8dfbb8_1    conda-forge
     pytest                    5.4.1            py37hc8dfbb8_0    conda-forge
     python                    3.7.6           h8356626_5_cpython    conda-forge
     python-dateutil           2.8.1                      py_0    conda-forge
     python_abi                3.7                     1_cp37m    conda-forge
     pytz                      2019.3                     py_0    conda-forge
     pyyaml                    5.3.1            py37h8f50634_0    conda-forge
     pyzmq                     19.0.0           py37hac76be4_1    conda-forge
     rapidjson                 1.1.0             he1b5a44_1002    conda-forge
     re2                       2020.04.01           he1b5a44_0    conda-forge
     readline                  8.0                  hf8c457e_0    conda-forge
     recommonmark              0.6.0                      py_0    conda-forge
     regex                     2020.4.4         py37h8f50634_0    conda-forge
     requests                  2.23.0             pyh8c360ce_2    conda-forge
     rhash                     1.3.6             h14c3975_1001    conda-forge
     rmm                       0.14.0a200420          py37_258    rapidsai-nightly
     send2trash                1.5.0                      py_0    conda-forge
     setuptools                46.1.3           py37hc8dfbb8_0    conda-forge
     six                       1.14.0                     py_1    conda-forge
     snappy                    1.1.8                he1b5a44_1    conda-forge
     snowballstemmer           2.0.0                      py_0    conda-forge
     sortedcontainers          2.1.0                      py_0    conda-forge
     sphinx                    3.0.2                      py_0    conda-forge
     sphinx-markdown-tables    0.0.12                   pypi_0    pypi
     sphinx_rtd_theme          0.4.3                      py_0    conda-forge
     sphinxcontrib-applehelp   1.0.2                      py_0    conda-forge
     sphinxcontrib-devhelp     1.0.2                      py_0    conda-forge
     sphinxcontrib-htmlhelp    1.0.3                      py_0    conda-forge
     sphinxcontrib-jsmath      1.0.1                      py_0    conda-forge
     sphinxcontrib-qthelp      1.0.3                      py_0    conda-forge
     sphinxcontrib-serializinghtml 1.1.4                      py_0    conda-forge
     sphinxcontrib-websupport  1.2.1              pyh9f0ad1d_0    conda-forge
     sqlite                    3.30.1               hcee41ef_0    conda-forge
     streamz                   0.5.3                    pypi_0    pypi
     tblib                     1.6.0                      py_0    conda-forge
     terminado                 0.8.3            py37hc8dfbb8_1    conda-forge
     testpath                  0.4.4                      py_0    conda-forge
     thrift-cpp                0.12.0            hf3afdfd_1004    conda-forge
     tk                        8.6.10               hed695b0_0    conda-forge
     toml                      0.10.0                     py_0    conda-forge
     toolz                     0.10.0                     py_0    conda-forge
     tornado                   6.0.4            py37h8f50634_1    conda-forge
     traitlets                 4.3.3            py37hc8dfbb8_1    conda-forge
     typed-ast                 1.4.1            py37h516909a_0    conda-forge
     typing_extensions         3.7.4.1          py37hc8dfbb8_3    conda-forge
     uriparser                 0.9.3                he1b5a44_1    conda-forge
     urllib3                   1.25.9                     py_0    conda-forge
     virtualenv                16.7.5                     py_0    conda-forge
     wcwidth                   0.1.9              pyh9f0ad1d_0    conda-forge
     webencodings              0.5.1                      py_1    conda-forge
     wheel                     0.34.2                     py_1    conda-forge
     xz                        5.2.5                h516909a_0    conda-forge
     yaml                      0.2.4                h516909a_0    conda-forge
     zeromq                    4.3.2                he1b5a44_2    conda-forge
     zict                      2.0.0                      py_0    conda-forge
     zipp                      3.1.0                      py_0    conda-forge
     zlib                      1.2.11            h516909a_1006    conda-forge
     zstd                      1.4.3                h3b9ef0a_0    conda-forge

Additional context
None.

@andygrove andygrove added bug Something isn't working Needs Triage Need team to review and classify Java Affects Java cuDF API. labels May 6, 2020
@andygrove andygrove added the Spark Functionality that helps Spark RAPIDS label May 6, 2020
@harrism
Copy link
Member

harrism commented May 7, 2020

When casting from string to long (signed 64 bit in Java) I would expect the cast to return null if the provided string is less than Long.MAX_VALUE or greater than Long.MAX_VALUE

I assume you mean Long.MIN_VALUE for the first use of MAX_VALUE above?

@andygrove
Copy link
Contributor Author

Oops, yes, that is what I meant.

@davidwendt
Copy link
Contributor

This is working as intended and documented here:
https://docs.rapids.ai/api/libcudf/nightly/group__strings__convert.html#gab5c7bb70d5d915636847e0d1831eba3b

Overflow of the resulting integer type is not checked. Each string is converted using an int64 type and then cast to the target integer type before storing it into the output column. If the resulting integer type is too small to hold the value, the stored value will be undefined.

@kkraus14 @harrism should this behavior be changed?

Looks like Pandas throws an exception and does not convert these rows to null:

File "pandas/_libs/lib.pyx", line 547, in pandas._libs.lib.astype_intsafe
OverflowError: Python int too large to convert to C long

We may want to introduce a new parameter for the specific behavior of convert out-of-range values to null.
And possibly add a similar parameter to check for out-of-range in all_integer()/is_integer() as well.

@harrism
Copy link
Member

harrism commented May 15, 2020

I think the last solution David mentions is probably the best way. Similar to @kkraus14 's answer here #5160 (comment)

We can enable users to check that their data is all within range and get a mask of the out of range values. This way, well-formed data doesn't pay the (likely high) performance cost of the checks at cast time.

@harrism harrism added feature request New feature or request and removed Needs Triage Need team to review and classify bug Something isn't working labels May 15, 2020
@andygrove
Copy link
Contributor Author

Thanks for the responses. I think "introduce a new parameter for the specific behavior of convert out-of-range values to null" would be the best option in this case. The existing is_integer code can't be used as-is due to some very specific logic that Spark has when converting strings to integers. For example, it allows for decimal places in the string, but not for exponents, so neither is_integer or is_float would work right now.

@davidwendt
Copy link
Contributor

Passing strings with floating point notation including decimals to a string-to-integer conversion function is not supported in C++, Java, or Python. C++ std::stol, std::stoi, etc will just stop parsing on the first invalid character that is why it may appear to support decimal:

    std::stol( "122.4" ) -> 122
    std::stol( "122e4" ) -> 122
    std::stol( "122 abcdef" ) -> 122

The C++ std behavior is also the behavior of cudf::strings::to_integer().

Python and Java throw exceptions if the decimal or other invalid character is included in the string.
Python:

>>> int("122.4")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: '122.4'

Java:

   Integer.parseInt("122.4") ->
   Exception in thread "main" java.lang.NumberFormatException: For input string: "122.4"

I would recommend using the is_integer() to assign nulls to the row-entries that return false rather than creating a specialized API.

@revans2
Copy link
Contributor

revans2 commented May 16, 2020

Yes, java does not support it directly, but Spark does. Isn't it wonderful? But that is not a big deal we can always run a regexp to strip off the \.[0-9]* from the end of the string. Not super efficient, but only Spark would take the penalty for it.

@davidwendt
Copy link
Contributor

Sounds like you should convert to floats first and then cast to integers. This will likely be less of a penalty then using regex.

@harrism
Copy link
Member

harrism commented May 18, 2020

So @davidwendt what is the decision, or what still needs to be decided?

@ttnghia
Copy link
Contributor

ttnghia commented Mar 10, 2021

To all: I'm working on this.

The current string_to_integer API returns an IntegerType value. Thus, there is no way to know if the input string would generate an invalid return.

I propose to return a pair of return values instead. Similar to many C++ std APIs, I propose to have this API (for individual string row)

std::pair<IntegerType, bool> to_integer(cudf::string_view& str);

In the returning pair, the first value is the parsed integer, while the second value is a boolean indicating whether the parsing was successful or not. We can re-generate null mask for the column base on such boolean values for all rows.

Please let me know if you have any suggestion.

@kkraus14
Copy link
Collaborator

I think previous discussion pointed to the approach in #7080 where we have a is_valid_integer function that gets used to determine where casting cannot be safely done first, which is used to set nulls.

libcudf should not match Spark behavior or Pandas behavior, but instead should provide the necessary primitives for downstream usage to reasonably implement their desired behavior.

@ttnghia
Copy link
Contributor

ttnghia commented Mar 10, 2021

We will have that API separately, just to check if a string is a valid integer. That API is nearly as expensive as parsing an integer.
On the other hand, during parsing a string, we will have the returning validity boolean for free.

@jrhemstad
Copy link
Contributor

jrhemstad commented Mar 10, 2021

We will have that API separately, just to check if a string is a valid integer. That API is nearly as expensive as parsing an integer.
On the other hand, during parsing a string, we will have the returning validity boolean for free.

That complicates the implementation of the existing to_integer function in order to satisfy Spark's unique requirements. We have an explicit policy of not over-fitting implementations to a specific user's needs. The way to achieve Spark's desired behavior is the combination of is_valid_integer + to_integer.

@ttnghia
Copy link
Contributor

ttnghia commented Mar 10, 2021

Thanks, Jake. to achieve Spark's desired behavior---this is understandable. I was trying to satisfy both users' desires and maintainability though (trying to avoid code duplication if we have nearly the same implementation for is_valid_integer and to_integer).

not over-fitting implementations to a specific user's needs---I'm not 100% agree with this. In some cases (such as in this case), if we don't overfit then we will have to have duplicate implementations. I think this is also the reason why C++ STL has many functions that return an additional boolean flag such as std::map::emplace---since such flag is almost zero-cost to have but it can be very useful in many situations.

rapids-bot bot pushed a commit that referenced this issue Mar 24, 2021
…eger conversion (#7642)

This PR addresses #5110, #7080, and rework #7094. It adds the function `cudf::strings::is_integer` that can check if strings can be correctly converted into integer values. Underflow and overflow are also taken into account.

Note that this `cudf::strings::is_integer` is different from the existing `cudf::strings::string::is_integer`, which only checks for pattern and does not care about under/overflow.

Examples:
```
s = { "eee", "-200", "-100", "127", "128", "1.5", NULL}

is_integer(s, INT8) = { 0, 0, 1, 1, 0, 0, NULL}
is_integer(s, INT32) = { 0, 1, 1, 1, 1, 0, NULL}
```

Authors:
  - Nghia Truong (@ttnghia)

Approvers:
  - David (@davidwendt)
  - Jake Hemstad (@jrhemstad)
  - Mark Harris (@harrism)

URL: #7642
@sameerz
Copy link
Contributor

sameerz commented Mar 30, 2021

@andygrove does PR #7642 resolve this issue?

@andygrove
Copy link
Contributor Author

@andygrove does PR #7642 resolve this issue?

Yes, from the plugin we can call the new is_integer method introduced in #7642 and use the result to either throw an exception or replace invalid values with null depending on the use case in Spark. We will need to file an issue against the plugin to implement this if we don't already have one.

@kkraus14
Copy link
Collaborator

Fixed by #7642

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request New feature or request Java Affects Java cuDF API. Spark Functionality that helps Spark RAPIDS
Projects
None yet
Development

No branches or pull requests

8 participants