Repository: numba/numba
Pull request: Fixes issue 5448
Fixes #5448 

The fix requires verification on 32-bit Windows platform.

<!--

Thanks for wanting to contribute to Numba :)

First, if you need some help or want to chat to the core developers, please
visit https://gitter.im/numba/numba for real time chat or post to the Numba
mailing list https://groups.google.com/a/continuum.io/forum/#!forum/numba-users.

Here's some guidelines to help the review process go smoothly.

0. Please write a description in this text box of the changes that are being
   made.

1. Please ensure that you have written units tests for the changes made/features
   added.

2. If you are closing an issue please use one of the automatic closing words as
   noted here: https://help.github.com/articles/closing-issues-using-keywords/

3. If your pull request is not ready for review but you want to make use of the
   continuous integration testing facilities please label it with `[WIP]` and
   then remove the label when you'd like it to be reviewed.

4. Once review has taken place please do not add features or make changes out of
   the scope of those requested by the reviewer (doing this just add delays as
   already reviewed code ends up having to be re-reviewed/it is hard to tell
   what is new etc!). Further, please do not rebase your branch on master/force
   push/rewrite history, doing any of these causes the context of any comments
   made by reviewers to be lost. If conflicts occur against master they should
   be resolved by merging master into the branch used for making the pull
   request.

Many thanks in advance for your cooperation!

-->


Problem statement:
0.49rc1 fail 1 test on windows
```pytb
ERROR: test_wrapper_address_protocol_libm (numba.tests.test_function_type.TestFunctionTypeExtensions)
Call cos and sinf from standard math library.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\Users\ci\32\Miniconda3\envs\testenv_fbf4b59a-0935-4a9d-8efb-05e471655d84\lib\site-packages\numba\tests\test_function_type.py", line 617, in test_wrapper_address_protocol_libm
    mysin = LibM('sinf')
  File "C:\Users\ci\32\Miniconda3\envs\testenv_fbf4b59a-0935-4a9d-8efb-05e471655d84\lib\site-packages\numba\tests\test_function_type.py", line 598, in __init__
    addr = ctypes.cast(self.lib.sinf, ctypes.c_voidp).value
  File "C:\Users\ci\32\Miniconda3\envs\testenv_fbf4b59a-0935-4a9d-8efb-05e471655d84\lib\ctypes\__init__.py", line 361, in __getattr__
    func = self.__getitem__(name)
  File "C:\Users\ci\32\Miniconda3\envs\testenv_fbf4b59a-0935-4a9d-8efb-05e471655d84\lib\ctypes\__init__.py", line 366, in __getitem__
    func = self._FuncPtr((name_or_ordinal, self))
AttributeError: function 'sinf' not found

----------------------------------------------------------------------
```

Hints from issue discussion:
We'll need to skip/fix this test before 0.49 release
note this is failing on win-32.  It looks like win-64 is fine.
```
winedump -j export msvcrt.dll
```
shows that `sinf` is available only in 64-bit DLL. The 32-bit DLL contains only `sin`.

Suggest skipping the `sinf` test on 32-bit Windows systems but keep the `cos` test.
It is possible that on the 32-bit Windows `sin` is for 32-bit float inputs. If this is the case, then changing conditionally `self.lib.sinf` to `self.lib.sin` might work. Also, the `cos` test requires adjustment as well on the 32-bit Windows platform.
@sklam please see a possible fix in #5459. I cannot verify the fix myself as I don't have immediate access to the 32-bit Windows platform.

Commit message: Disable double-precision cos test on 32-bit Windows.

Patch to review:
diff --git a/numba/tests/test_function_type.py b/numba/tests/test_function_type.py
index a9739100a41..2a48888ae87 100644
--- a/numba/tests/test_function_type.py
+++ b/numba/tests/test_function_type.py
@@ -1,5 +1,6 @@
 import types as pytypes
 from numba import jit, njit, cfunc, types, int64, float64, float32, errors
+from numba.core.config import IS_32BITS, IS_WIN32
 import ctypes
 import warnings
 
@@ -567,13 +568,12 @@ def test_wrapper_address_protocol_libm(self):
         """Call cos and sinf from standard math library.
 
         """
-        import os
         import ctypes.util
 
         class LibM(types.WrapperAddressProtocol):
 
             def __init__(self, fname):
-                if os.name == 'nt':
+                if IS_WIN32:
                     lib = ctypes.cdll.msvcrt
                 else:
                     libpath = ctypes.util.find_library('m')
@@ -581,10 +581,26 @@ def __init__(self, fname):
                 self.lib = lib
                 self._name = fname
                 if fname == 'cos':
-                    addr = ctypes.cast(self.lib.cos, ctypes.c_voidp).value
-                    signature = float64(float64)
+                    # test for double-precision math function
+                    if IS_WIN32 and IS_32BITS:
+                        # 32-bit Windows math library does not provide
+                        # a double-precision cos function, so
+                        # disabling the function
+                        signature = None
+                    else:
+                        addr = ctypes.cast(self.lib.cos, ctypes.c_voidp).value
+                        signature = float64(float64)
                 elif fname == 'sinf':
-                    addr = ctypes.cast(self.lib.sinf, ctypes.c_voidp).value
+                    # test for single-precision math function
+                    if IS_WIN32 and IS_32BITS:
+                        # 32-bit Windows math library provides sin
+                        # (instead of sinf) that is a single-precision
+                        # sin function
+                        addr = ctypes.cast(self.lib.sin, ctypes.c_voidp).value
+                    else:
+                        # Other 32/64 bit platforms define sinf as the
+                        # single-precision sin function
+                        addr = ctypes.cast(self.lib.sinf, ctypes.c_voidp).value
                     signature = float32(float32)
                 else:
                     raise NotImplementedError(
@@ -613,8 +629,10 @@ def myeval(f, x):
         for jit_opts in [dict(nopython=True)]:
             jit_ = jit(**jit_opts)
             with self.subTest(jit=jit_opts):
-                self.assertEqual(jit_(myeval)(mycos, 0.0), 1.0)
-                self.assertEqual(jit_(myeval)(mysin, float32(0.0)), 0.0)
+                if mycos.signature is not None:
+                    self.assertEqual(jit_(myeval)(mycos, 0.0), 1.0)
+                if mysin.signature is not None:
+                    self.assertEqual(jit_(myeval)(mysin, float32(0.0)), 0.0)
 
     def test_compilation_results(self):
         """Turn the existing compilation results of a dispatcher instance to


Code review comments:
diff_hunk: @@ -613,8 +629,10 @@ def myeval(f, x):
         for jit_opts in [dict(nopython=True)]:
             jit_ = jit(**jit_opts)
             with self.subTest(jit=jit_opts):
-                self.assertEqual(jit_(myeval)(mycos, 0.0), 1.0)
-                self.assertEqual(jit_(myeval)(mysin, float32(0.0)), 0.0)
+                if mycos.signature is not None:
+                    self.assertEqual(jit_(myeval)(mycos, 0.0), 1.0)
+                if mysin.signature is not None:
path: numba/tests/test_function_type.py
text: @user1:
```suggestion
                if mysin.signature() is not None:
```

@author:
Right, my bad. Fixed.

diff_hunk: @@ -613,8 +629,10 @@ def myeval(f, x):
         for jit_opts in [dict(nopython=True)]:
             jit_ = jit(**jit_opts)
             with self.subTest(jit=jit_opts):
-                self.assertEqual(jit_(myeval)(mycos, 0.0), 1.0)
-                self.assertEqual(jit_(myeval)(mysin, float32(0.0)), 0.0)
+                if mycos.signature is not None:
path: numba/tests/test_function_type.py
text: @user1:
```suggestion
                if mycos.signature() is not None:
```

@author:
Fixed.