"Fossies" - the Fresh Open Source Software Archive

Member "dmd2/src/druntime/import/core/internal/array/comparison.d" (20 Nov 2020, 7031 Bytes) of package /linux/misc/dmd.2.094.2.linux.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) D source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /**
    2  * This module contains compiler support for comparing dynamic arrays
    3  *
    4  * Copyright: Copyright Digital Mars 2000 - 2019.
    5  * License: Distributed under the
    6  *      $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
    7  *    (See accompanying file LICENSE)
    8  * Source: $(DRUNTIMESRC core/internal/_array/_comparison.d)
    9  */
   10 
   11 module core.internal.array.comparison;
   12 
   13 int __cmp(T)(scope const T[] lhs, scope const T[] rhs) @trusted
   14     if (__traits(isScalar, T))
   15 {
   16     // Compute U as the implementation type for T
   17     static if (is(T == ubyte) || is(T == void) || is(T == bool))
   18         alias U = char;
   19     else static if (is(T == wchar))
   20         alias U = ushort;
   21     else static if (is(T == dchar))
   22         alias U = uint;
   23     else static if (is(T == ifloat))
   24         alias U = float;
   25     else static if (is(T == idouble))
   26         alias U = double;
   27     else static if (is(T == ireal))
   28         alias U = real;
   29     else
   30         alias U = T;
   31 
   32     static if (is(U == char))
   33     {
   34         import core.internal.string : dstrcmp;
   35         return dstrcmp(cast(char[]) lhs, cast(char[]) rhs);
   36     }
   37     else static if (!is(U == T))
   38     {
   39         // Reuse another implementation
   40         return __cmp(cast(U[]) lhs, cast(U[]) rhs);
   41     }
   42     else
   43     {
   44         version (BigEndian)
   45         static if (__traits(isUnsigned, T) ? !is(T == __vector) : is(T : P*, P))
   46         {
   47             if (!__ctfe)
   48             {
   49                 import core.stdc.string : memcmp;
   50                 int c = memcmp(lhs.ptr, rhs.ptr, (lhs.length <= rhs.length ? lhs.length : rhs.length) * T.sizeof);
   51                 if (c)
   52                     return c;
   53                 static if (size_t.sizeof <= uint.sizeof && T.sizeof >= 2)
   54                     return cast(int) lhs.length - cast(int) rhs.length;
   55                 else
   56                     return int(lhs.length > rhs.length) - int(lhs.length < rhs.length);
   57             }
   58         }
   59 
   60         immutable len = lhs.length <= rhs.length ? lhs.length : rhs.length;
   61         foreach (const u; 0 .. len)
   62         {
   63             static if (__traits(isFloating, T))
   64             {
   65                 immutable a = lhs.ptr[u], b = rhs.ptr[u];
   66                 static if (is(T == cfloat) || is(T == cdouble)
   67                     || is(T == creal))
   68                 {
   69                     // Use rt.cmath2._Ccmp instead ?
   70                     auto r = (a.re > b.re) - (a.re < b.re);
   71                     if (!r) r = (a.im > b.im) - (a.im < b.im);
   72                 }
   73                 else
   74                 {
   75                     const r = (a > b) - (a < b);
   76                 }
   77                 if (r) return r;
   78             }
   79             else if (lhs.ptr[u] != rhs.ptr[u])
   80                 return lhs.ptr[u] < rhs.ptr[u] ? -1 : 1;
   81         }
   82         return lhs.length < rhs.length ? -1 : (lhs.length > rhs.length);
   83     }
   84 }
   85 
   86 // This function is called by the compiler when dealing with array
   87 // comparisons in the semantic analysis phase of CmpExp. The ordering
   88 // comparison is lowered to a call to this template.
   89 int __cmp(T1, T2)(T1[] s1, T2[] s2)
   90 if (!__traits(isScalar, T1) && !__traits(isScalar, T2))
   91 {
   92     import core.internal.traits : Unqual;
   93     alias U1 = Unqual!T1;
   94     alias U2 = Unqual!T2;
   95 
   96     static if (is(U1 == void) && is(U2 == void))
   97         static @trusted ref inout(ubyte) at(inout(void)[] r, size_t i) { return (cast(inout(ubyte)*) r.ptr)[i]; }
   98     else
   99         static @trusted ref R at(R)(R[] r, size_t i) { return r.ptr[i]; }
  100 
  101     // All unsigned byte-wide types = > dstrcmp
  102     immutable len = s1.length <= s2.length ? s1.length : s2.length;
  103 
  104     foreach (const u; 0 .. len)
  105     {
  106         static if (__traits(compiles, __cmp(at(s1, u), at(s2, u))))
  107         {
  108             auto c = __cmp(at(s1, u), at(s2, u));
  109             if (c != 0)
  110                 return c;
  111         }
  112         else static if (__traits(compiles, at(s1, u).opCmp(at(s2, u))))
  113         {
  114             auto c = at(s1, u).opCmp(at(s2, u));
  115             if (c != 0)
  116                 return c;
  117         }
  118         else static if (__traits(compiles, at(s1, u) < at(s2, u)))
  119         {
  120             if (at(s1, u) != at(s2, u))
  121                 return at(s1, u) < at(s2, u) ? -1 : 1;
  122         }
  123         else
  124         {
  125             // TODO: fix this legacy bad behavior, see
  126             // https://issues.dlang.org/show_bug.cgi?id=17244
  127             static assert(is(U1 == U2), "Internal error.");
  128             import core.stdc.string : memcmp;
  129             auto c = (() @trusted => memcmp(&at(s1, u), &at(s2, u), U1.sizeof))();
  130             if (c != 0)
  131                 return c;
  132         }
  133     }
  134     return s1.length < s2.length ? -1 : (s1.length > s2.length);
  135 }
  136 
  137 // integral types
  138 @safe unittest
  139 {
  140     void compareMinMax(T)()
  141     {
  142         T[2] a = [T.max, T.max];
  143         T[2] b = [T.min, T.min];
  144 
  145         assert(__cmp(a, b) > 0);
  146         assert(__cmp(b, a) < 0);
  147     }
  148 
  149     compareMinMax!int;
  150     compareMinMax!uint;
  151     compareMinMax!long;
  152     compareMinMax!ulong;
  153     compareMinMax!short;
  154     compareMinMax!ushort;
  155     compareMinMax!byte;
  156     compareMinMax!dchar;
  157     compareMinMax!wchar;
  158 }
  159 
  160 // char types (dstrcmp)
  161 @safe unittest
  162 {
  163     void compareMinMax(T)()
  164     {
  165         T[2] a = [T.max, T.max];
  166         T[2] b = [T.min, T.min];
  167 
  168         assert(__cmp(a, b) > 0);
  169         assert(__cmp(b, a) < 0);
  170     }
  171 
  172     compareMinMax!ubyte;
  173     compareMinMax!bool;
  174     compareMinMax!char;
  175     compareMinMax!(const char);
  176 
  177     string s1 = "aaaa";
  178     string s2 = "bbbb";
  179     assert(__cmp(s2, s1) > 0);
  180     assert(__cmp(s1, s2) < 0);
  181 }
  182 
  183 // fp types
  184 @safe unittest
  185 {
  186     void compareMinMax(T)()
  187     {
  188         T[2] a = [T.max, T.max];
  189         T[2] b = [T.min_normal, T.min_normal];
  190         T[2] c = [T.max, T.min_normal];
  191         T[1] d = [T.max];
  192 
  193         assert(__cmp(a, b) > 0);
  194         assert(__cmp(b, a) < 0);
  195         assert(__cmp(a, c) > 0);
  196         assert(__cmp(a, d) > 0);
  197         assert(__cmp(d, c) < 0);
  198         assert(__cmp(c, c) == 0);
  199     }
  200 
  201     compareMinMax!real;
  202     compareMinMax!float;
  203     compareMinMax!double;
  204     compareMinMax!ireal;
  205     compareMinMax!ifloat;
  206     compareMinMax!idouble;
  207     compareMinMax!creal;
  208     //compareMinMax!cfloat;
  209     compareMinMax!cdouble;
  210 
  211     // qualifiers
  212     compareMinMax!(const real);
  213     compareMinMax!(immutable real);
  214 }
  215 
  216 // void[]
  217 @safe unittest
  218 {
  219     void[] a;
  220     const(void)[] b;
  221 
  222     (() @trusted
  223     {
  224         a = cast(void[]) "bb";
  225         b = cast(const(void)[]) "aa";
  226     })();
  227 
  228     assert(__cmp(a, b) > 0);
  229     assert(__cmp(b, a) < 0);
  230 }
  231 
  232 // arrays of arrays with mixed modifiers
  233 @safe unittest
  234 {
  235     // https://issues.dlang.org/show_bug.cgi?id=17876
  236     bool less1(immutable size_t[][] a, size_t[][] b) { return a < b; }
  237     bool less2(const void[][] a, void[][] b) { return a < b; }
  238     bool less3(inout size_t[][] a, size_t[][] b) { return a < b; }
  239 
  240     immutable size_t[][] a = [[1, 2], [3, 4]];
  241     size_t[][] b = [[1, 2], [3, 5]];
  242     assert(less1(a, b));
  243     assert(less3(a, b));
  244 
  245     auto va = [cast(immutable void[])a[0], a[1]];
  246     auto vb = [cast(void[])b[0], b[1]];
  247     assert(less2(va, vb));
  248 }