@@ -609,6 +609,137 @@ range_contains(rangeobject *r, PyObject *ob)
609609 PY_ITERSEARCH_CONTAINS );
610610}
611611
612+ /* Compare two range objects. Return 1 for equal, 0 for not equal
613+ and -1 on error. The algorithm is roughly the C equivalent of
614+
615+ if r0 is r1:
616+ return True
617+ if len(r0) != len(r1):
618+ return False
619+ if not len(r0):
620+ return True
621+ if r0.start != r1.start:
622+ return False
623+ if len(r0) == 1:
624+ return True
625+ return r0.step == r1.step
626+ */
627+ static int
628+ range_equals (rangeobject * r0 , rangeobject * r1 )
629+ {
630+ int cmp_result ;
631+ PyObject * one ;
632+
633+ if (r0 == r1 )
634+ return 1 ;
635+ cmp_result = PyObject_RichCompareBool (r0 -> length , r1 -> length , Py_EQ );
636+ /* Return False or error to the caller. */
637+ if (cmp_result != 1 )
638+ return cmp_result ;
639+ cmp_result = PyObject_Not (r0 -> length );
640+ /* Return True or error to the caller. */
641+ if (cmp_result != 0 )
642+ return cmp_result ;
643+ cmp_result = PyObject_RichCompareBool (r0 -> start , r1 -> start , Py_EQ );
644+ /* Return False or error to the caller. */
645+ if (cmp_result != 1 )
646+ return cmp_result ;
647+ one = PyLong_FromLong (1 );
648+ if (!one )
649+ return -1 ;
650+ cmp_result = PyObject_RichCompareBool (r0 -> length , one , Py_EQ );
651+ Py_DECREF (one );
652+ /* Return True or error to the caller. */
653+ if (cmp_result != 0 )
654+ return cmp_result ;
655+ return PyObject_RichCompareBool (r0 -> step , r1 -> step , Py_EQ );
656+ }
657+
658+ static PyObject *
659+ range_richcompare (PyObject * self , PyObject * other , int op )
660+ {
661+ int result ;
662+
663+ if (!PyRange_Check (other ))
664+ Py_RETURN_NOTIMPLEMENTED ;
665+ switch (op ) {
666+ case Py_NE :
667+ case Py_EQ :
668+ result = range_equals ((rangeobject * )self , (rangeobject * )other );
669+ if (result == -1 )
670+ return NULL ;
671+ if (op == Py_NE )
672+ result = !result ;
673+ if (result )
674+ Py_RETURN_TRUE ;
675+ else
676+ Py_RETURN_FALSE ;
677+ case Py_LE :
678+ case Py_GE :
679+ case Py_LT :
680+ case Py_GT :
681+ Py_RETURN_NOTIMPLEMENTED ;
682+ default :
683+ PyErr_BadArgument ();
684+ return NULL ;
685+ }
686+ }
687+
688+ /* Hash function for range objects. Rough C equivalent of
689+
690+ if not len(r):
691+ return hash((len(r), None, None))
692+ if len(r) == 1:
693+ return hash((len(r), r.start, None))
694+ return hash((len(r), r.start, r.step))
695+ */
696+ static Py_hash_t
697+ range_hash (rangeobject * r )
698+ {
699+ PyObject * t ;
700+ Py_hash_t result = -1 ;
701+ int cmp_result ;
702+
703+ t = PyTuple_New (3 );
704+ if (!t )
705+ return -1 ;
706+ Py_INCREF (r -> length );
707+ PyTuple_SET_ITEM (t , 0 , r -> length );
708+ cmp_result = PyObject_Not (r -> length );
709+ if (cmp_result == -1 )
710+ goto end ;
711+ if (cmp_result == 1 ) {
712+ Py_INCREF (Py_None );
713+ Py_INCREF (Py_None );
714+ PyTuple_SET_ITEM (t , 1 , Py_None );
715+ PyTuple_SET_ITEM (t , 2 , Py_None );
716+ }
717+ else {
718+ PyObject * one ;
719+ Py_INCREF (r -> start );
720+ PyTuple_SET_ITEM (t , 1 , r -> start );
721+ one = PyLong_FromLong (1 );
722+ if (!one )
723+ goto end ;
724+ cmp_result = PyObject_RichCompareBool (r -> length , one , Py_EQ );
725+ Py_DECREF (one );
726+ if (cmp_result == -1 )
727+ goto end ;
728+ if (cmp_result == 1 ) {
729+ Py_INCREF (Py_None );
730+ PyTuple_SET_ITEM (t , 2 , Py_None );
731+ }
732+ else {
733+ Py_INCREF (r -> step );
734+ PyTuple_SET_ITEM (t , 2 , r -> step );
735+ }
736+ }
737+ result = PyObject_Hash (t );
738+ end :
739+ Py_DECREF (t );
740+ return result ;
741+ }
742+
612743static PyObject *
613744range_count (rangeobject * r , PyObject * ob )
614745{
@@ -763,7 +894,7 @@ PyTypeObject PyRange_Type = {
763894 0 , /* tp_as_number */
764895 & range_as_sequence , /* tp_as_sequence */
765896 & range_as_mapping , /* tp_as_mapping */
766- 0 , /* tp_hash */
897+ ( hashfunc ) range_hash , /* tp_hash */
767898 0 , /* tp_call */
768899 0 , /* tp_str */
769900 PyObject_GenericGetAttr , /* tp_getattro */
@@ -773,7 +904,7 @@ PyTypeObject PyRange_Type = {
773904 range_doc , /* tp_doc */
774905 0 , /* tp_traverse */
775906 0 , /* tp_clear */
776- 0 , /* tp_richcompare */
907+ range_richcompare , /* tp_richcompare */
777908 0 , /* tp_weaklistoffset */
778909 range_iter , /* tp_iter */
779910 0 , /* tp_iternext */
0 commit comments