1 /** Predicate extensions to std.algorithm. 2 Copyright: Per Nordlöw 2022-. 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.range.primitives : ElementType; 9 10 // ============================================================================================== 11 12 import std.range: isInputRange; 13 14 /** Returns: `true` iff all elements in range are equal (or range is empty). 15 http://stackoverflow.com/questions/19258556/equality-of-all-elements-in-a-range/19292822?noredirect=1#19292822 16 17 Possible alternatives or aliases: allElementsEqual, haveEqualElements 18 */ 19 bool allEqual(R)(R range) 20 if (isInputRange!R) 21 { 22 import std.algorithm: findAdjacent; 23 import std.range: empty; 24 return range.findAdjacent!("a != b").empty; 25 } 26 pure nothrow @safe unittest { assert([11, 11].allEqual); } 27 pure nothrow @safe unittest { assert(![11, 12].allEqual); } 28 pure nothrow @safe unittest { int[] x; assert(x.allEqual); } 29 30 /* See_Also: http://forum.dlang.org/thread/febepworacvbapkpozjl@forum.dlang.org#post-gbqvablzsbdowqoijxpn:40forum.dlang.org */ 31 /* import std.range: InputRange; */ 32 /* bool allEqual_(T)(InputRange!T range) @safe pure nothrow */ 33 /* { */ 34 /* import std.algorithm: findAdjacent; */ 35 /* import std.range: empty; */ 36 /* return range.findAdjacent!("a != b").empty; */ 37 /* } */ 38 /* pure nothrow @safe unittest { assert([11, 11].allEqual_); } */ 39 /* pure nothrow @safe unittest { assert(![11, 12].allEqual_); } */ 40 /* pure nothrow @safe unittest { int[] x; assert(x.allEqual_); } */ 41 42 /** Returns: `true` iff all elements in range are equal (or range is empty) to $(D element). 43 44 Possible alternatives or aliases: allElementsEqualTo 45 */ 46 bool allEqualTo(R, E)(R range, E element) 47 if (isInputRange!R && 48 is(ElementType!R == E)) 49 { 50 import std.algorithm: all; 51 return range.all!(a => a == element); 52 } 53 54 /// 55 pure nothrow @safe unittest { 56 assert([42, 42].allEqualTo(42)); 57 } 58 59 // ============================================================================================== 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 (is(T == struct) || is(T == class)) 65 { 66 foreach (const ref elt; x.tupleof) 67 if (!elt.allZero) 68 return false; 69 return true; 70 } 71 else 72 { 73 import std.traits : isIterable; 74 static if (useStatic && __traits(isStaticArray, T)) 75 { 76 static foreach (ix; 0 .. x.length) /+ TODO: do we need static iota here? +/ 77 if (!x[ix].allZero) 78 return false; // make use of iota? 79 return true; 80 } 81 else static if (isIterable!T) 82 { 83 foreach (const ref elt; x) 84 if (!elt.allZero) 85 return false; 86 return true; 87 } 88 else 89 return x == 0; 90 } 91 } 92 /// ditto 93 alias zeroed = allZero; 94 95 /// 96 pure nothrow @safe unittest { 97 ubyte[20] d; 98 assert(d.allZero); // note that [] is needed here 99 100 ubyte[2][2] zeros = [ [0, 0], 101 [0, 0] ]; 102 assert(zeros.allZero); 103 104 ubyte[2][2] one = [ [0, 1], 105 [0, 0] ]; 106 assert(!one.allZero); 107 108 ubyte[2][2] ones = [ [1, 1], 109 [1, 1] ]; 110 assert(!ones.allZero); 111 112 ubyte[2][2][2] zeros3d = [ [ [0, 0], 113 [0, 0] ], 114 [ [0, 0], 115 [0, 0] ] ]; 116 assert(zeros3d.allZero); 117 118 ubyte[2][2][2] ones3d = [ [ [1, 1], 119 [1, 1] ], 120 [ [1, 1], 121 [1, 1] ] ]; 122 assert(!ones3d.allZero); 123 } 124 125 /// 126 pure nothrow @safe unittest { 127 struct Vec { real x, y; } 128 const v0 = Vec(0, 0); 129 assert(v0.zeroed); 130 const v1 = Vec(1, 1); 131 assert(!v1.zeroed); 132 } 133 134 /// 135 pure nothrow @safe unittest { 136 class Vec 137 { 138 this(real x, real y) { this.x = x; this.y = y; } 139 real x, y; 140 } 141 const v0 = new Vec(0, 0); 142 assert(v0.zeroed); 143 const v1 = new Vec(1, 1); 144 assert(!v1.zeroed); 145 }