Repository: Lightning-AI/torchmetrics

Issue:
AUROC for binary task, if thresholds is set, results in an error
## 🐛 Bug

The AUROC metric for a binary task has an optional `thresholds` argument. It documents that if it is set to an int, then that number of bins is set, otherwise if its a List of floats, then the AUROC at those thresholds is calculated. This is so that a faster calculation can occur. However, if the thresholds argument is set to either of those things, then an error occurs:

```python
RuntimeError: "bincount_cuda" not implemented for 'Float'
```

### To Reproduce

Steps to reproduce the behavior...

```python
import torchmetrics
import torch

labels = torch.Tensor([0, 1]).cuda()
probs = torch.Tensor([0.1, 0.9]).cuda()

metric = torchmetrics.AUROC(task="binary", thresholds=20).cuda()
print(metric(probs, labels))
```

of note, removing `.cuda()` also results in an error:

```python
RuntimeError: "bincount_cpu" not implemented for 'Float'
```

### Expected behavior

The AUROC should be calculated along the fast O(n_thresholds) rather than the O(n_samples)

### Environment

Installed from Conda with the following other relevant libraries:

- TorchMetrics 11.4 (and 11.3.1)
- Pytorch 1.13.0
- Python 3.10


Discussion:
Hi! thanks for your contribution!, great first issue!

Resolving patch:
diff --git a/src/torchmetrics/functional/classification/precision_recall_curve.py b/src/torchmetrics/functional/classification/precision_recall_curve.py
--- a/src/torchmetrics/functional/classification/precision_recall_curve.py
+++ b/src/torchmetrics/functional/classification/precision_recall_curve.py
@@ -214,7 +214,7 @@ def _binary_precision_recall_curve_update_vectorized(
     """
     len_t = len(thresholds)
     preds_t = (preds.unsqueeze(-1) >= thresholds.unsqueeze(0)).long()  # num_samples x num_thresholds
-    unique_mapping = preds_t + 2 * target.unsqueeze(-1) + 4 * torch.arange(len_t, device=target.device)
+    unique_mapping = preds_t + 2 * target.long().unsqueeze(-1) + 4 * torch.arange(len_t, device=target.device)
     bins = _bincount(unique_mapping.flatten(), minlength=4 * len_t)
     return bins.reshape(len_t, 2, 2)
 
@@ -469,7 +469,7 @@ def _multiclass_precision_recall_curve_update_vectorized(
     len_t = len(thresholds)
     preds_t = (preds.unsqueeze(-1) >= thresholds.unsqueeze(0).unsqueeze(0)).long()
     target_t = torch.nn.functional.one_hot(target, num_classes=num_classes)
-    unique_mapping = preds_t + 2 * target_t.unsqueeze(-1)
+    unique_mapping = preds_t + 2 * target_t.long().unsqueeze(-1)
     unique_mapping += 4 * torch.arange(num_classes, device=preds.device).unsqueeze(0).unsqueeze(-1)
     unique_mapping += 4 * num_classes * torch.arange(len_t, device=preds.device)
     bins = _bincount(unique_mapping.flatten(), minlength=4 * num_classes * len_t)
@@ -714,7 +714,7 @@ def _multilabel_precision_recall_curve_update(
     len_t = len(thresholds)
     # num_samples x num_labels x num_thresholds
     preds_t = (preds.unsqueeze(-1) >= thresholds.unsqueeze(0).unsqueeze(0)).long()
-    unique_mapping = preds_t + 2 * target.unsqueeze(-1)
+    unique_mapping = preds_t + 2 * target.long().unsqueeze(-1)
     unique_mapping += 4 * torch.arange(num_labels, device=preds.device).unsqueeze(0).unsqueeze(-1)
     unique_mapping += 4 * num_labels * torch.arange(len_t, device=preds.device)
     unique_mapping = unique_mapping[unique_mapping >= 0]


Test patch: