1 /** Predicate extensions to std.algorithm. 2 Copyright: Per Nordlöw 2018-. 3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 4 Authors: $(WEB Per Nordlöw) 5 */ 6 module nxt.predicates; 7 8 import std.traits : isIterable; 9 import std.range.primitives : ElementType; 10 11 // ============================================================================================== 12 13 import std.range: isInputRange; 14 15 /** Returns: `true` iff all elements in range are equal (or range is empty). 16 http://stackoverflow.com/questions/19258556/equality-of-all-elements-in-a-range/19292822?noredirect=1#19292822 17 18 Possible alternatives or aliases: allElementsEqual, haveEqualElements 19 */ 20 bool allEqual(R)(R range) 21 if (isInputRange!R) 22 { 23 import std.algorithm: findAdjacent; 24 import std.range: empty; 25 return range.findAdjacent!("a != b").empty; 26 } 27 unittest { assert([11, 11].allEqual); } 28 unittest { assert(![11, 12].allEqual); } 29 unittest { int[] x; assert(x.allEqual); } 30 31 /* See_Also: http://forum.dlang.org/thread/febepworacvbapkpozjl@forum.dlang.org#post-gbqvablzsbdowqoijxpn:40forum.dlang.org */ 32 /* import std.range: InputRange; */ 33 /* bool allEqual_(T)(InputRange!T range) @safe pure nothrow */ 34 /* { */ 35 /* import std.algorithm: findAdjacent; */ 36 /* import std.range: empty; */ 37 /* return range.findAdjacent!("a != b").empty; */ 38 /* } */ 39 /* unittest { assert([11, 11].allEqual_); } */ 40 /* unittest { assert(![11, 12].allEqual_); } */ 41 /* unittest { int[] x; assert(x.allEqual_); } */ 42 43 /** Returns: `true` iff all elements in range are equal (or range is empty) to $(D element). 44 45 Possible alternatives or aliases: allElementsEqualTo 46 */ 47 bool allEqualTo(R, E)(R range, E element) 48 if (isInputRange!R && 49 is(ElementType!R == E)) 50 { 51 import std.algorithm: all; 52 return range.all!(a => a == element); 53 } 54 unittest { assert([42, 42].allEqualTo(42)); } 55 56 // ============================================================================================== 57 58 import nxt.traits_ex: isStruct, isClass; 59 import std.traits: isStaticArray; 60 61 /** Check if all Elements of $(D x) are zero. */ 62 bool allZero(T, bool useStatic = true)(in T x) 63 { 64 static if (isStruct!T || isClass!T) 65 { 66 foreach (const ref elt; x.tupleof) 67 { 68 if (!elt.allZero) { return false; } 69 } 70 return true; 71 } 72 else static if (useStatic && isStaticArray!T) 73 { 74 static foreach (ix; 0 .. x.length) // TODO do we need static iota here? 75 { 76 if (!x[ix].allZero) { return false; } // make use of iota? 77 } 78 return true; 79 } 80 else static if (isIterable!T) 81 { 82 foreach (const ref elt; x) 83 { 84 if (!elt.allZero) { return false; } 85 } 86 return true; 87 } 88 else 89 { 90 return x == 0; 91 } 92 } 93 94 alias zeroed = allZero; 95 96 unittest 97 { 98 ubyte[20] d; 99 assert(d.allZero); // note that [] is needed here 100 101 ubyte[2][2] zeros = [ [0, 0], 102 [0, 0] ]; 103 assert(zeros.allZero); 104 105 ubyte[2][2] one = [ [0, 1], 106 [0, 0] ]; 107 assert(!one.allZero); 108 109 ubyte[2][2] ones = [ [1, 1], 110 [1, 1] ]; 111 assert(!ones.allZero); 112 113 ubyte[2][2][2] zeros3d = [ [ [0, 0], 114 [0, 0] ], 115 [ [0, 0], 116 [0, 0] ] ]; 117 assert(zeros3d.allZero); 118 119 ubyte[2][2][2] ones3d = [ [ [1, 1], 120 [1, 1] ], 121 [ [1, 1], 122 [1, 1] ] ]; 123 assert(!ones3d.allZero); 124 } 125 126 unittest 127 { 128 struct Vec { real x, y; } 129 const v0 = Vec(0, 0); 130 assert(v0.zeroed); 131 const v1 = Vec(1, 1); 132 assert(!v1.zeroed); 133 } 134 135 unittest 136 { 137 class Vec 138 { 139 this(real x, real y) { this.x = x; this.y = y; } 140 real x, y; 141 } 142 const v0 = new Vec(0, 0); 143 assert(v0.zeroed); 144 const v1 = new Vec(1, 1); 145 assert(!v1.zeroed); 146 } 147 148 /** Returns: `true` iff $(D a) is set to the default/initial value of its type $(D T). 149 */ 150 bool isDefaulted(T)(in T a) 151 { 152 import std.traits: isInstanceOf; 153 import std.typecons: Nullable; 154 static if (isInstanceOf!(Nullable, T)) 155 { 156 return a.isNull; 157 } 158 else 159 { 160 return a == T.init; 161 } 162 } 163 alias isUntouched = isDefaulted; 164 alias isInited = isDefaulted;