Add faster versions of various runtime-checkable protocols (#146)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index b8d8b62..f117f39 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -49,6 +49,11 @@
   Patch by Alex Waygood.
 - Speedup `isinstance(3, typing_extensions.SupportsIndex)` by >10x on Python
   <3.12. Patch by Alex Waygood.
+- Add `typing_extensions` versions of `SupportsInt`, `SupportsFloat`,
+  `SupportsComplex`, `SupportsBytes`, `SupportsAbs` and `SupportsRound`. These
+  have the same semantics as the versions from the `typing` module, but
+  `isinstance()` checks against the `typing_extensions` versions are >10x faster
+  at runtime on Python <3.12. Patch by Alex Waygood.
 - Add `__orig_bases__` to non-generic TypedDicts, call-based TypedDicts, and
   call-based NamedTuples. Other TypedDicts and NamedTuples already had the attribute.
   Patch by Adrian Garcia Badaracco.
diff --git a/src/test_typing_extensions.py b/src/test_typing_extensions.py
index 7f3c0ef..4a5d3a1 100644
--- a/src/test_typing_extensions.py
+++ b/src/test_typing_extensions.py
@@ -3852,8 +3852,9 @@
             exclude |= {'final', 'Any'}
         if sys.version_info < (3, 12):
             exclude |= {
-                'Protocol', 'runtime_checkable', 'SupportsIndex', 'TypedDict',
-                'is_typeddict', 'NamedTuple',
+                'Protocol', 'runtime_checkable', 'SupportsAbs', 'SupportsBytes',
+                'SupportsComplex', 'SupportsFloat', 'SupportsIndex', 'SupportsInt',
+                'SupportsRound', 'TypedDict', 'is_typeddict', 'NamedTuple',
             }
         for item in typing_extensions.__all__:
             if item not in exclude and hasattr(typing, item):
diff --git a/src/typing_extensions.py b/src/typing_extensions.py
index 2ee36eb..cce31f8 100644
--- a/src/typing_extensions.py
+++ b/src/typing_extensions.py
@@ -46,7 +46,13 @@
     'TypedDict',
 
     # Structural checks, a.k.a. protocols.
+    'SupportsAbs',
+    'SupportsBytes',
+    'SupportsComplex',
+    'SupportsFloat',
     'SupportsIndex',
+    'SupportsInt',
+    'SupportsRound',
 
     # One-off things.
     'Annotated',
@@ -739,9 +745,50 @@
 
 # Our version of runtime-checkable protocols is faster on Python 3.7-3.11
 if sys.version_info >= (3, 12):
+    SupportsInt = typing.SupportsInt
+    SupportsFloat = typing.SupportsFloat
+    SupportsComplex = typing.SupportsComplex
     SupportsIndex = typing.SupportsIndex
+    SupportsAbs = typing.SupportsAbs
+    SupportsRound = typing.SupportsRound
 else:
     @runtime_checkable
+    class SupportsInt(Protocol):
+        """An ABC with one abstract method __int__."""
+        __slots__ = ()
+
+        @abc.abstractmethod
+        def __int__(self) -> int:
+            pass
+
+    @runtime_checkable
+    class SupportsFloat(Protocol):
+        """An ABC with one abstract method __float__."""
+        __slots__ = ()
+
+        @abc.abstractmethod
+        def __float__(self) -> float:
+            pass
+
+    @runtime_checkable
+    class SupportsComplex(Protocol):
+        """An ABC with one abstract method __complex__."""
+        __slots__ = ()
+
+        @abc.abstractmethod
+        def __complex__(self) -> complex:
+            pass
+
+    @runtime_checkable
+    class SupportsBytes(Protocol):
+        """An ABC with one abstract method __bytes__."""
+        __slots__ = ()
+
+        @abc.abstractmethod
+        def __bytes__(self) -> bytes:
+            pass
+
+    @runtime_checkable
     class SupportsIndex(Protocol):
         __slots__ = ()
 
@@ -749,6 +796,28 @@
         def __index__(self) -> int:
             pass
 
+    @runtime_checkable
+    class SupportsAbs(Protocol[T_co]):
+        """
+        An ABC with one abstract method __abs__ that is covariant in its return type.
+        """
+        __slots__ = ()
+
+        @abc.abstractmethod
+        def __abs__(self) -> T_co:
+            pass
+
+    @runtime_checkable
+    class SupportsRound(Protocol[T_co]):
+        """
+        An ABC with one abstract method __round__ that is covariant in its return type.
+        """
+        __slots__ = ()
+
+        @abc.abstractmethod
+        def __round__(self, ndigits: int = 0) -> T_co:
+            pass
+
 
 if sys.version_info >= (3, 12):
     # The standard library TypedDict in Python 3.8 does not store runtime information