protected static function equal($a, $b, $aStack, $bStack)
    {
        // Unwrap any wrapped object.
        $a instanceof self && $a = $a->_wrapped;
        $b instanceof self && $b = $b->_wrapped;

        if ($a === null && $b === null)
            return true;

        // Two resources are always considered different since there is no way to compare them
        if (is_resource($a) && is_resource($b))
            return false;

        // Perform classic scalar comparison.
        if (is_scalar($a) && is_scalar($b))
            return $a == $b;

        // Assume equality for cyclic structures. The algorithm for detecting cyclic structures is adapted from
        // ES 5.1 section 15.12.3, abstract operation JO.
        $length = count($aStack);
        while ($length--)
            if ($aStack[$length] == $a)
                return $bStack[$length] == $b;

        // Add the first object to the stack of traversed objects.
        $aStack[] = $a;
        $bStack[] = $b;

        $result = true;
        $size = 0;

        if (static::isTraversable($a) && static::isTraversable($b)) {
            // Try to deep compare sequences.
            static::each($a, function ($item, $key) use (& $a, & $b, & $aStack, & $bStack, & $size, & $result) {
                $size++;

                $result = static::has($b, $key) && static::equal(
                    static::get($a, $key),
                    static::get($b, $key),
                    $aStack,
                    $bStack
                );

                if (!$result)
                    return static::BREAKER;
            });

            if ($size != static::size($b))
                $result = false;
        }
        else {
            // Last hope comparison.
            $result = $a == $b;
        }

        // Remove the first object from the stack of traversed objects.
        array_pop($aStack);
        array_pop($aStack);

        return $result;
    }
protected static function equal($a, $b, $aStack, $bStack)
    {
        // Unwrap any wrapped object.
        $a instanceof self && $a = $a->_wrapped;
        $b instanceof self && $b = $b->_wrapped;

        if ($a === null && $b === null)
            return true;

        // Two resources are always considered different since there is no way to compare them
        if (is_resource($a) && is_resource($b))
            return false;

        // Perform classic scalar comparison.
        if (is_scalar($a) && is_scalar($b))
            return $a == $b;

        // Assume equality for cyclic structures. The algorithm for detecting cyclic structures is adapted from
        // ES 5.1 section 15.12.3, abstract operation JO.
        $length = count($aStack);
        while ($length--)
            if ($aStack[$length] == $a)
                return $bStack[$length] == $b;

        // Add the first object to the stack of traversed objects.
        $aStack[] = $a;
        $bStack[] = $b;

        $result = true;
        $size = 0;

        if (static::isTraversable($a) && static::isTraversable($b)) {
            // Try to deep compare sequences.
            static::each($a, function ($item, $key) use (& $a, & $b, & $aStack, & $bStack, & $size, & $result) {
                $size++;

                $result = static::has($b, $key) && static::equal(
                    static::get($a, $key),
                    static::get($b, $key),
                    $aStack,
                    $bStack
                );

                if (!$result)
                    return static::BREAKER;
            });

            if ($size != static::size($b))
                $result = false;
        }
        else {
            // Last hope comparison.
            $result = $a == $b;
        }

        // Remove the first object from the stack of traversed objects.
        array_pop($aStack);
        array_pop($aStack);

        return $result;
    }
protected static function equal ( $ a , $ b , $ aStack , $ bStack ) { // Unwrap any wrapped object.
 $ a instanceof self && $ a = $ a -> _wrapped ; $ b instanceof self && $ b = $ b -> _wrapped ; if ( $ a === null && $ b === null ) return true ; // Two resources are always considered different since there is no way to compare them
 if ( is_resource ( $ a ) && is_resource ( $ b ) ) return false ; // Perform classic scalar comparison.
 if ( is_scalar ( $ a ) && is_scalar ( $ b ) ) return $ a == $ b ; // Assume equality for cyclic structures. The algorithm for detecting cyclic structures is adapted from
 // ES 5.1 section 15.12.3, abstract operation JO.
 $ length = count ( $ aStack ) ; while ( $ length -- ) if ( $ aStack [ $ length ] == $ a ) return $ bStack [ $ length ] == $ b ; // Add the first object to the stack of traversed objects.
 $ aStack [ ] = $ a ; $ bStack [ ] = $ b ; $ result = true ; $ size = 0 ; if ( static :: isTraversable ( $ a ) && static :: isTraversable ( $ b ) ) { // Try to deep compare sequences.
 static :: each ( $ a , function ( $ item , $ key ) use ( & $ a , & $ b , & $ aStack , & $ bStack , & $ size , & $ result ) { $ size ++ ; $ result = static :: has ( $ b , $ key ) && static :: equal ( static :: get ( $ a , $ key ) , static :: get ( $ b , $ key ) , $ aStack , $ bStack ) ; if ( ! $ result ) return static :: BREAKER ; } ) ; if ( $ size != static :: size ( $ b ) ) $ result = false ; } else { // Last hope comparison.
 $ result = $ a == $ b ; } // Remove the first object from the stack of traversed objects.
 array_pop ( $ aStack ) ; array_pop ( $ aStack ) ; return $ result ; }
Tells if two objects are equals.

@category Internal Functions

@param mixed $a the first value
@param mixed $b the second $value
@param array $aStack the first recursion stack
@param array $bStack the second recursion stack

@return bool
Tells if two objects are equals .