task: metadata: install: pip install -e .[dev]
patch: diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 5bcd1f9..71b07ba 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -32,6 +32,7 @@ New regions
 Bug Fixes
 ~~~~~~~~~
 
+- Ensure correct masks are created for `float32` coordinates (:issue:`489`, :pull:`493`).
 - Fixed the default value of ``overlap`` of :py:func:`from_geopandas` to ``None`` (:issue:`453`, :pull:`470`).
 
 Docs
diff --git a/regionmask/core/mask.py b/regionmask/core/mask.py
index cf1f85e..eba2571 100644
--- a/regionmask/core/mask.py
+++ b/regionmask/core/mask.py
@@ -204,8 +204,8 @@ def _mask(
                 "be converted to degree?"
             )
 
-    lon_arr = np.asarray(lon)
-    lat_arr = np.asarray(lat)
+    lon_arr = np.asarray(lon, dtype=float)
+    lat_arr = np.asarray(lat, dtype=float)
 
     # automatically detect whether wrapping is necessary
     if wrap_lon is None:

problem_statement: lon/ lat offset too small for float32 coordinates?
We add a tiny lon and lat offset to get a consistent edge behaviour for all mask backends:

https://github.com/regionmask/regionmask/blob/ca12afe5924f563b1f3650377718406b97bd6485/regionmask/core/mask.py#L626-L627

However, the offset is _too small_ for `float32` coordinates, which will lead to wrong treatment of borderpoints :-1:

- We can fix this by (1) fiddling around with the offsets (e.g. using `np.spacing(lon).max()`) or (2) converting the coords to `float64`. I suggest to do (2).
- This is less bad if the mask is created with rasterio.


```python
import regionmask
import shapely
import numpy as np

r = regionmask.Regions([shapely.Polygon([[-180, -90], [-180, 90], [180, 90], [180, -90]])])

lon32 = np.arange(-180, 180, dtype=np.float32)
lat32 = np.arange(90, -91, -1, dtype=np.float32)

lon64 = np.arange(-180, 180, dtype=float)
lat64 = np.arange(90, -91, -1, dtype=float)

mask32 = r.mask(lon32, lat32, method="shapely")
mask64 = r.mask(lon64, lat64, method="shapely")

np.testing.assert_equal(mask64.values, mask32.values)

f, axs = plt.subplots(1, 2)
```

```python-traceback
AssertionError
```

```python
f, axs = plt.subplots(1, 2)

mask64.plot(ax=axs[0], add_colorbar=False)
mask32.plot(ax=axs[1], add_colorbar=False)

axs[0].set_title("float64 coords")
axs[1].set_title("float32 coords")

for ax in axs:
    ax.set_aspect("equal")
    ax.set_xlabel("")
    ax.set_ylabel("")
    ax.set_xticks([])
    ax.set_yticks([])
```



![offset_float32](https://github.com/regionmask/regionmask/assets/10194086/11cc77c6-4864-4ff5-ad0c-01892cad3db6)


repo: regionmask/regionmask
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/regionmask/tests/test_mask.py b/regionmask/tests/test_mask.py
index 8996f0e..b279a1c 100644
--- a/regionmask/tests/test_mask.py
+++ b/regionmask/tests/test_mask.py
@@ -964,12 +964,29 @@ def test_mask_whole_grid(method, regions, lon):
     mask = regions.mask(lon, lat, method=method)
 
     assert (mask == 0).all()
+    assert mask.lon.dtype == int
+    assert mask.lat.dtype == int
 
     # with wrap_lon=False the edges are not masked
     mask = regions.mask(lon, lat, method=method, wrap_lon=False)
     assert mask.sel(lat=-90).isnull().all()
 
 
+@pytest.mark.parametrize("method", MASK_METHODS)
+@pytest.mark.parametrize("regions", [r_GLOB_180, r_GLOB_360])
+@pytest.mark.parametrize("lon", [lon180, lon360])
+def test_mask_whole_grid_float32(method, regions, lon):
+
+    lat = np.arange(90, -91, -10, dtype=np.float32)
+    lon = lon.astype(np.float32)  # creates a copy
+    mask = regions.mask(lon, lat, method=method)
+
+    assert (mask == 0).all()
+
+    assert mask.lon.dtype == np.float32
+    assert mask.lat.dtype == np.float32
+
+
 @pytest.mark.parametrize("regions", [r_GLOB_180, r_GLOB_360])
 @pytest.mark.parametrize("lon", [lon180, lon360])
 def test_mask_whole_grid_nan_lon(regions, lon):