allow constants to be combined
diff --git a/aenum/__init__.py b/aenum/__init__.py
index b6b6bd6..4a85617 100644
--- a/aenum/__init__.py
+++ b/aenum/__init__.py
@@ -169,6 +169,11 @@
         if obj is not sentinel:
             return obj
 
+def _value(obj):
+    if isinstance(obj, (auto, constant)):
+        return obj.value
+    else:
+        return obj
 
 ################
 # Constant stuff
@@ -190,6 +195,98 @@
     def __repr__(self):
         return '%s(%r)' % (self.__class__.__name__, self.value)
 
+    def __and__(self, other):
+        return _and_(self.value, _value(other))
+
+    def __rand__(self, other):
+        return _and_(_value(other), self.value)
+
+    def __invert__(self):
+        return _inv_(self.value)
+
+    def __or__(self, other):
+        return _or_(self.value, _value(other))
+
+    def __ror__(self, other):
+        return _or_(_value(other), self.value)
+
+    def __xor__(self, other):
+        return _xor_(self.value, _value(other))
+
+    def __rxor__(self, other):
+        return _xor_(_value(other), self.value)
+
+    def __abs__(self):
+        return _abs_(self.value)
+
+    def __add__(self, other):
+        return _add_(self.value, _value(other))
+
+    def __radd__(self, other):
+        return _add_(_value(other), self.value)
+
+    def __neg__(self):
+        return _neg_(self.value)
+
+    def __pos__(self):
+        return _pos_(self.value)
+
+    if pyver < 3:
+        def __div__(self, other):
+            return _div_(self.value, _value(other))
+
+    def __rdiv__(self, other):
+        return _div_(_value(other), (self.value))
+
+    def __floordiv__(self, other):
+        return _floordiv_(self.value, _value(other))
+
+    def __rfloordiv__(self, other):
+        return _floordiv_(_value(other), self.value)
+
+    def __truediv__(self, other):
+        return _truediv_(self.value, _value(other))
+
+    def __rtruediv__(self, other):
+        return _truediv_(_value(other), self.value)
+
+    def __lshift__(self, other):
+        return _lshift_(self.value, _value(other))
+
+    def __rlshift__(self, other):
+        return _lshift_(_value(other), self.value)
+
+    def __rshift__(self, other):
+        return _rshift_(self.value, _value(other))
+
+    def __rrshift__(self, other):
+        return _rshift_(_value(other), self.value)
+
+    def __mod__(self, other):
+        return _mod_(self.value, _value(other))
+
+    def __rmod__(self, other):
+        return _mod_(_value(other), self.value)
+
+    def __mul__(self, other):
+        return _mul_(self.value, _value(other))
+
+    def __rmul__(self, other):
+        return _mul_(_value(other), self.value)
+
+    def __pow__(self, other):
+        return _pow_(self.value, _value(other))
+
+    def __rpow__(self, other):
+        return _pow_(_value(other), self.value)
+
+    def __sub__(self, other):
+        return _sub_(self.value, _value(other))
+
+    def __rsub__(self, other):
+        return _sub_(_value(other), self.value)
+
+
 
 NamedConstant = None
 
@@ -1261,8 +1358,8 @@
         # (see issue19025).
         if attr in cls._member_map_:
             raise AttributeError(
-                    "%s: cannot delete Enum member %r." % (cls.__name__,
-                    ))
+                    "%s: cannot delete Enum member %r." % (cls.__name__, attr),
+                    )
         if isinstance(_get_attr_from_chain(cls, attr), constant):
             raise AttributeError(
                     "%s: cannot delete constant %r" % (cls.__name__, attr),
diff --git a/aenum/doc/aenum.rst b/aenum/doc/aenum.rst
index 96e6adf..d45cd99 100644
--- a/aenum/doc/aenum.rst
+++ b/aenum/doc/aenum.rst
@@ -859,7 +859,7 @@
     >>> Planet.G = 9
     Traceback (most recent call last):
     ...
-    AttributeError: Cannot rebind constant(6.673e-11)
+    AttributeError: Planet: cannot rebind constant 'G'
 
 skip
 ^^^^
diff --git a/aenum/test.py b/aenum/test.py
index c441a42..28dd82d 100644
--- a/aenum/test.py
+++ b/aenum/test.py
@@ -274,13 +274,75 @@
         # operator.div is gone in 3
         if pyver < 3:
             tester(12, _div_, 12 // 5, 5)
-        # strigs are a pain
+        # strings are a pain
         left = auto()
         right = 'eggs'
         value = _mod_(left, right)
         left.value = 'I see 17 %s!'
         self.assertEqual(value.value, 'I see 17 %s!' % 'eggs')
 
+    def test_constant(self):
+        errors = []
+        def tester(first, op, final, second=None):
+            if second is None:
+                primary = constant(first)
+                secondary = constant(op(primary))
+                if secondary.value != final:
+                    errors.append(
+                        "%s %r -> %r != %r" % (op.__name__, first, secondary.value, final),
+                        )
+            else:
+                left = constant(first)
+                right = second
+                value = op(left, right)
+                if value != final:
+                    errors.append(
+                        "forward: %r %s %r -> %r != %r" % (first, op.__name__, second, value, final),
+                        )
+                left = first
+                right = constant(second)
+                value = op(left, right)
+                if value != final:
+                    errors.append(
+                        "reversed: %r %s %r -> %r != %r" % (second, op.__name__, first, value, final),
+                        )
+        for args in (
+                (1, _abs_, abs(1)),
+                (-3, _abs_, abs(-3)),
+                (1, _add_, 1+2, 2),
+                (25, _floordiv_, 25 // 5, 5),
+                (49, _truediv_, 49 / 9, 9),
+                (6, _mod_, 6 % 9, 9),
+                (5, _lshift_, 5 << 2, 2),
+                (5, _rshift_, 5 >> 2, 2),
+                (3, _mul_, 3 * 6, 6),
+                (5, _neg_, -5),
+                (-4, _pos_, +(-4)),
+                (2, _pow_, 2**5, 5),
+                (7, _sub_, 7 - 10, 10),
+                (1, _or_, 1 | 2, 2),
+                (3, _xor_, 3 ^ 6, 6),
+                (3, _and_, 3 & 6, 6),
+                (7, _inv_, ~7),
+                ('a', _add_, 'a'+'b', 'b'),
+                ('a', _mul_, 'a' * 3, 3),
+                ):
+            tester(*args)
+        # operator.div is gone in 3
+        if pyver < 3:
+            tester(12, _div_, 12 // 5, 5)
+        # strings are a pain
+        left = constant('I see 17 %s!')
+        right = 'eggs'
+        value = _mod_(left, right)
+        if value != 'I see 17 %s!' % 'eggs':
+            errors.append("'I see 17 eggs!' != %r" % value)
+        if errors:
+            print()
+            for error in errors:
+                print(error)
+            self.assertTrue(False)
+
 
 class TestEnum(TestCase):
 
@@ -2221,7 +2283,7 @@
                 elementD = 'd'
         self.assertIs(enumA.enumB, enumA.__dict__['enumB'])
 
-    def test_constantness_in_enum(self):
+    def test_constantness_of_constants(self):
         class Universe(Enum):
             PI = constant(3.141596)
             G = constant(6.67300E-11)
@@ -2229,6 +2291,13 @@
         self.assertRaisesRegex(AttributeError, 'cannot rebind constant', setattr, Universe, 'PI', 9)
         self.assertRaisesRegex(AttributeError, 'cannot delete constant', delattr, Universe, 'PI')
 
+    def test_math_and_stuff_with_constants(self):
+        class Universe(Enum):
+            PI = constant(3.141596)
+            TAU = constant(2 * PI)
+        self.assertEqual(Universe.PI, 3.141596)
+        self.assertEqual(Universe.TAU, 2 * Universe.PI)
+
     if StdlibEnumMeta is not None:
         def test_stdlib_inheritence(self):
             self.assertTrue(isinstance(self.Season, StdlibEnumMeta))