@@ -886,6 +886,123 @@ namespace Microsoft.FSharp.Core
886886
887887 module HashCompare =
888888
889+ //-------------------------------------------------------------------------
890+ // LanguagePrimitives.HashCompare : HASHING.
891+ //-------------------------------------------------------------------------
892+
893+ let defaultHashNodes = 18
894+
895+ /// The implementation of IEqualityComparer , using depth - limited for hashing and PER semantics for NaN equality.
896+ type CountLimitedHasherPER ( sz : int ) =
897+ [< DefaultValue >]
898+ val mutable nodeCount : int
899+
900+ member x.Fresh () =
901+ if ( System.Threading.Interlocked.CompareExchange (&( x.nodeCount ), sz , 0 ) = 0 ) then
902+ x
903+ else
904+ new CountLimitedHasherPER ( sz )
905+
906+ interface IEqualityComparer
907+
908+ /// The implementation of IEqualityComparer , using unlimited depth for hashing and ER semantics for NaN equality.
909+ type UnlimitedHasherER () =
910+ interface IEqualityComparer
911+
912+ /// The implementation of IEqualityComparer , using unlimited depth for hashing and PER semantics for NaN equality.
913+ type UnlimitedHasherPER () =
914+ interface IEqualityComparer
915+
916+
917+ /// The unique object for unlimited depth for hashing and ER semantics for equality.
918+ let fsEqualityComparerUnlimitedHashingER = UnlimitedHasherER ()
919+
920+ /// The unique object for unlimited depth for hashing and PER semantics for equality.
921+ let fsEqualityComparerUnlimitedHashingPER = UnlimitedHasherPER ()
922+
923+ let inline HashCombine nr x y = ( x <<< 1 ) + y + 631 * nr
924+
925+ let GenericHashObjArray ( iec : IEqualityComparer ) ( x : obj array ) : int =
926+ let len = x.Length
927+ let mutable i = len - 1
928+ if i > defaultHashNodes then i < - defaultHashNodes // limit the hash
929+ let mutable acc = 0
930+ while ( i >= 0 ) do
931+ // NOTE: GenericHash* call decreases nr
932+ acc <- HashCombine i acc ( iec.GetHashCode( x.GetValue( i)));
933+ i <- i - 1
934+ acc
935+
936+ // optimized case - byte arrays
937+ let GenericHashByteArray ( x : byte array ) : int =
938+ let len = length x
939+ let mutable i = len - 1
940+ if i > defaultHashNodes then i <- defaultHashNodes // limit the hash
941+ let mutable acc = 0
942+ while ( i >= 0 ) do
943+ acc <- HashCombine i acc ( intOfByte ( get x i));
944+ i <- i - 1
945+ acc
946+
947+ // optimized case - int arrays
948+ let GenericHashInt32Array ( x : int array ) : int =
949+ let len = length x
950+ let mutable i = len - 1
951+ if i > defaultHashNodes then i <- defaultHashNodes // limit the hash
952+ let mutable acc = 0
953+ while ( i >= 0 ) do
954+ acc <- HashCombine i acc ( get x i);
955+ i <- i - 1
956+ acc
957+
958+ // optimized case - int arrays
959+ let GenericHashInt64Array ( x : int64 array ) : int =
960+ let len = length x
961+ let mutable i = len - 1
962+ if i > defaultHashNodes then i <- defaultHashNodes // limit the hash
963+ let mutable acc = 0
964+ while ( i >= 0 ) do
965+ acc <- HashCombine i acc ( int32 ( get x i));
966+ i <- i - 1
967+ acc
968+
969+ // special case - arrays do not by default have a decent structural hashing function
970+ let GenericHashArbArray ( iec : IEqualityComparer ) ( x : System.Array ) : int =
971+ match x.Rank with
972+ | 1 ->
973+ let b = x.GetLowerBound( 0 )
974+ let len = x.Length
975+ let mutable i = b + len - 1
976+ if i > b + defaultHashNodes then i <- b + defaultHashNodes // limit the hash
977+ let mutable acc = 0
978+ while ( i >= b) do
979+ // NOTE: GenericHash* call decreases nr
980+ acc <- HashCombine i acc ( iec.GetHashCode( x.GetValue( i)));
981+ i <- i - 1
982+ acc
983+ | _ ->
984+ HashCombine 10 ( x.GetLength( 0 )) ( x.GetLength( 1 ))
985+
986+ // Core implementation of structural hashing, corresponds to pseudo-code in the
987+ // F# Language spec. Searches for the IStructuralHash interface, otherwise uses GetHashCode().
988+ // Arrays are structurally hashed through a separate technique.
989+ //
990+ // "iec" is either fsEqualityComparerUnlimitedHashingER, fsEqualityComparerUnlimitedHashingPER or a CountLimitedHasherPER.
991+ let rec GenericHashParamObj ( iec : IEqualityComparer ) ( x : obj ) : int =
992+ match x with
993+ | null -> 0
994+ | (:? System.Array as a) ->
995+ match a with
996+ | :? ( obj array) as oa -> GenericHashObjArray iec oa
997+ | :? ( byte array) as ba -> GenericHashByteArray ba
998+ | :? ( int array) as ba -> GenericHashInt32Array ba
999+ | :? ( int64 array) as ba -> GenericHashInt64Array ba
1000+ | _ -> GenericHashArbArray iec a
1001+ | :? IStructuralEquatable as a ->
1002+ a.GetHashCode( iec)
1003+ | _ ->
1004+ x.GetHashCode()
1005+
8891006 //-------------------------------------------------------------------------
8901007 // LanguagePrimitives.HashCompare: Physical Equality
8911008 //-------------------------------------------------------------------------
@@ -1663,126 +1780,6 @@ namespace Microsoft.FSharp.Core
16631780 when 'T : decimal = System.Decimal.op_ Equality(( # " " x: decimal #), ( # " " y: decimal #))
16641781 when 'T : DateTime = DateTime.Equals(( # " " x : DateTime #), ( # " " y : DateTime #))
16651782
1666- //-------------------------------------------------------------------------
1667- // LanguagePrimitives.HashCompare: HASHING.
1668- //-------------------------------------------------------------------------
1669-
1670-
1671-
1672- let defaultHashNodes = 18
1673-
1674- /// The implementation of IEqualityComparer, using depth-limited for hashing and PER semantics for NaN equality.
1675- type CountLimitedHasherPER ( sz : int ) =
1676- [<DefaultValue>]
1677- val mutable nodeCount : int
1678-
1679- member x.Fresh () =
1680- if ( System.Threading.Interlocked.CompareExchange(&( x.nodeCount), sz, 0 ) = 0 ) then
1681- x
1682- else
1683- new CountLimitedHasherPER( sz)
1684-
1685- interface IEqualityComparer
1686-
1687- /// The implementation of IEqualityComparer, using unlimited depth for hashing and ER semantics for NaN equality.
1688- type UnlimitedHasherER () =
1689- interface IEqualityComparer
1690-
1691- /// The implementation of IEqualityComparer, using unlimited depth for hashing and PER semantics for NaN equality.
1692- type UnlimitedHasherPER () =
1693- interface IEqualityComparer
1694-
1695-
1696- /// The unique object for unlimited depth for hashing and ER semantics for equality.
1697- let fsEqualityComparerUnlimitedHashingER = UnlimitedHasherER()
1698-
1699- /// The unique object for unlimited depth for hashing and PER semantics for equality.
1700- let fsEqualityComparerUnlimitedHashingPER = UnlimitedHasherPER()
1701-
1702- let inline HashCombine nr x y = ( x <<< 1 ) + y + 631 * nr
1703-
1704- let GenericHashObjArray ( iec : IEqualityComparer ) ( x : obj array ) : int =
1705- let len = x.Length
1706- let mutable i = len - 1
1707- if i > defaultHashNodes then i <- defaultHashNodes // limit the hash
1708- let mutable acc = 0
1709- while ( i >= 0 ) do
1710- // NOTE: GenericHash* call decreases nr
1711- acc <- HashCombine i acc ( iec.GetHashCode( x.GetValue( i)));
1712- i <- i - 1
1713- acc
1714-
1715- // optimized case - byte arrays
1716- let GenericHashByteArray ( x : byte array ) : int =
1717- let len = length x
1718- let mutable i = len - 1
1719- if i > defaultHashNodes then i <- defaultHashNodes // limit the hash
1720- let mutable acc = 0
1721- while ( i >= 0 ) do
1722- acc <- HashCombine i acc ( intOfByte ( get x i));
1723- i <- i - 1
1724- acc
1725-
1726- // optimized case - int arrays
1727- let GenericHashInt32Array ( x : int array ) : int =
1728- let len = length x
1729- let mutable i = len - 1
1730- if i > defaultHashNodes then i <- defaultHashNodes // limit the hash
1731- let mutable acc = 0
1732- while ( i >= 0 ) do
1733- acc <- HashCombine i acc ( get x i);
1734- i <- i - 1
1735- acc
1736-
1737- // optimized case - int arrays
1738- let GenericHashInt64Array ( x : int64 array ) : int =
1739- let len = length x
1740- let mutable i = len - 1
1741- if i > defaultHashNodes then i <- defaultHashNodes // limit the hash
1742- let mutable acc = 0
1743- while ( i >= 0 ) do
1744- acc <- HashCombine i acc ( int32 ( get x i));
1745- i <- i - 1
1746- acc
1747-
1748- // special case - arrays do not by default have a decent structural hashing function
1749- let GenericHashArbArray ( iec : IEqualityComparer ) ( x : System.Array ) : int =
1750- match x.Rank with
1751- | 1 ->
1752- let b = x.GetLowerBound( 0 )
1753- let len = x.Length
1754- let mutable i = b + len - 1
1755- if i > b + defaultHashNodes then i <- b + defaultHashNodes // limit the hash
1756- let mutable acc = 0
1757- while ( i >= b) do
1758- // NOTE: GenericHash* call decreases nr
1759- acc <- HashCombine i acc ( iec.GetHashCode( x.GetValue( i)));
1760- i <- i - 1
1761- acc
1762- | _ ->
1763- HashCombine 10 ( x.GetLength( 0 )) ( x.GetLength( 1 ))
1764-
1765- // Core implementation of structural hashing, corresponds to pseudo-code in the
1766- // F# Language spec. Searches for the IStructuralHash interface, otherwise uses GetHashCode().
1767- // Arrays are structurally hashed through a separate technique.
1768- //
1769- // "iec" is either fsEqualityComparerUnlimitedHashingER, fsEqualityComparerUnlimitedHashingPER or a CountLimitedHasherPER.
1770- let rec GenericHashParamObj ( iec : IEqualityComparer ) ( x : obj ) : int =
1771- match x with
1772- | null -> 0
1773- | (:? System.Array as a) ->
1774- match a with
1775- | :? ( obj array) as oa -> GenericHashObjArray iec oa
1776- | :? ( byte array) as ba -> GenericHashByteArray ba
1777- | :? ( int array) as ba -> GenericHashInt32Array ba
1778- | :? ( int64 array) as ba -> GenericHashInt64Array ba
1779- | _ -> GenericHashArbArray iec a
1780- | :? IStructuralEquatable as a ->
1781- a.GetHashCode( iec)
1782- | _ ->
1783- x.GetHashCode()
1784-
1785-
17861783 /// Fill in the implementation of CountLimitedHasherPER
17871784 type CountLimitedHasherPER with
17881785
0 commit comments