1 /*************************** 2 * D programming language http://www.digitalmars.com/d/ 3 * Runtime support for double array operations. 4 * Placed in public domain. 5 */ 6 7 module rt.compiler.gdc.rt.arrayreal; 8 9 import CPUid = rt.compiler.util.cpuid; 10 11 debug(UnitTest) 12 { 13 private extern(C) int printf(char*,...); 14 /* This is so unit tests will test every CPU variant 15 */ 16 int cpuid; 17 const int CPUID_MAX = 1; 18 bool mmx() { return cpuid == 1 && CPUid.mmx(); } 19 bool sse() { return cpuid == 2 && CPUid.sse(); } 20 bool sse2() { return cpuid == 3 && CPUid.sse2(); } 21 bool amd3dnow() { return cpuid == 4 && CPUid.amd3dnow(); } 22 } 23 else 24 { 25 alias CPUid.mmx mmx; 26 alias CPUid.sse sse; 27 alias CPUid.sse2 sse2; 28 alias CPUid.amd3dnow amd3dnow; 29 } 30 31 //version = log; 32 33 bool disjoint(T)(T[] a, T[] b) 34 { 35 return (a.ptr + a.length <= b.ptr || b.ptr + b.length <= a.ptr); 36 } 37 38 alias real T; 39 40 extern (C): 41 42 /* ======================================================================== */ 43 44 /*********************** 45 * Computes: 46 * a[] = b[] + c[] 47 */ 48 49 T[] _arraySliceSliceAddSliceAssign_r(T[] a, T[] c, T[] b) 50 in 51 { 52 assert(a.length == b.length && b.length == c.length); 53 assert(disjoint(a, b)); 54 assert(disjoint(a, c)); 55 assert(disjoint(b, c)); 56 } 57 body 58 { 59 for (int i = 0; i < a.length; i++) 60 a[i] = b[i] + c[i]; 61 return a; 62 } 63 64 unittest 65 { 66 printf("_arraySliceSliceAddSliceAssign_r unittest\n"); 67 for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) 68 { 69 version (log) printf(" cpuid %d\n", cpuid); 70 71 for (int j = 0; j < 2; j++) 72 { 73 const int dim = 67; 74 T[] a = new T[dim + j]; // aligned on 16 byte boundary 75 a = a[j .. dim + j]; // misalign for second iteration 76 T[] b = new T[dim + j]; 77 b = b[j .. dim + j]; 78 T[] c = new T[dim + j]; 79 c = c[j .. dim + j]; 80 81 for (int i = 0; i < dim; i++) 82 { a[i] = cast(T)i; 83 b[i] = cast(T)(i + 7); 84 c[i] = cast(T)(i * 2); 85 } 86 87 c[] = a[] + b[]; 88 89 for (int i = 0; i < dim; i++) 90 { 91 if (c[i] != cast(T)(a[i] + b[i])) 92 { 93 printf("[%d]: %Lg != %Lg + %Lg\n", i, c[i], a[i], b[i]); 94 assert(0); 95 } 96 } 97 } 98 } 99 } 100 101 /* ======================================================================== */ 102 103 /*********************** 104 * Computes: 105 * a[] = b[] - c[] 106 */ 107 108 T[] _arraySliceSliceMinSliceAssign_r(T[] a, T[] c, T[] b) 109 in 110 { 111 assert(a.length == b.length && b.length == c.length); 112 assert(disjoint(a, b)); 113 assert(disjoint(a, c)); 114 assert(disjoint(b, c)); 115 } 116 body 117 { 118 for (int i = 0; i < a.length; i++) 119 a[i] = b[i] - c[i]; 120 return a; 121 } 122 123 124 unittest 125 { 126 printf("_arraySliceSliceMinSliceAssign_r unittest\n"); 127 for (cpuid = 0; cpuid < CPUID_MAX; cpuid++) 128 { 129 version (log) printf(" cpuid %d\n", cpuid); 130 131 for (int j = 0; j < 2; j++) 132 { 133 const int dim = 67; 134 T[] a = new T[dim + j]; // aligned on 16 byte boundary 135 a = a[j .. dim + j]; // misalign for second iteration 136 T[] b = new T[dim + j]; 137 b = b[j .. dim + j]; 138 T[] c = new T[dim + j]; 139 c = c[j .. dim + j]; 140 141 for (int i = 0; i < dim; i++) 142 { a[i] = cast(T)i; 143 b[i] = cast(T)(i + 7); 144 c[i] = cast(T)(i * 2); 145 } 146 147 c[] = a[] - b[]; 148 149 for (int i = 0; i < dim; i++) 150 { 151 if (c[i] != cast(T)(a[i] - b[i])) 152 { 153 printf("[%d]: %Lg != %Lg - %Lg\n", i, c[i], a[i], b[i]); 154 assert(0); 155 } 156 } 157 } 158 } 159 } 160 161 /* ======================================================================== */ 162 163 /*********************** 164 * Computes: 165 * a[] -= b[] * value 166 */ 167 168 T[] _arraySliceExpMulSliceMinass_r(T[] a, T value, T[] b) 169 { 170 return _arraySliceExpMulSliceAddass_r(a, -value, b); 171 } 172 173 /*********************** 174 * Computes: 175 * a[] += b[] * value 176 */ 177 178 T[] _arraySliceExpMulSliceAddass_r(T[] a, T value, T[] b) 179 in 180 { 181 assert(a.length == b.length); 182 assert(disjoint(a, b)); 183 } 184 body 185 { 186 auto aptr = a.ptr; 187 auto aend = aptr + a.length; 188 auto bptr = b.ptr; 189 190 // Handle remainder 191 while (aptr < aend) 192 *aptr++ += *bptr++ * value; 193 194 return a; 195 } 196 197 unittest 198 { 199 printf("_arraySliceExpMulSliceAddass_r unittest\n"); 200 201 cpuid = 1; 202 { 203 version (log) printf(" cpuid %d\n", cpuid); 204 205 for (int j = 0; j < 1; j++) 206 { 207 const int dim = 67; 208 T[] a = new T[dim + j]; // aligned on 16 byte boundary 209 a = a[j .. dim + j]; // misalign for second iteration 210 T[] b = new T[dim + j]; 211 b = b[j .. dim + j]; 212 T[] c = new T[dim + j]; 213 c = c[j .. dim + j]; 214 215 for (int i = 0; i < dim; i++) 216 { a[i] = cast(T)i; 217 b[i] = cast(T)(i + 7); 218 c[i] = cast(T)(i * 2); 219 } 220 221 b[] = c[]; 222 c[] += a[] * 6; 223 224 for (int i = 0; i < dim; i++) 225 { 226 //printf("[%d]: %Lg ?= %Lg + %Lg * 6\n", i, c[i], b[i], a[i]); 227 if (c[i] != cast(T)(b[i] + a[i] * 6)) 228 { 229 printf("[%d]: %Lg ?= %Lg + %Lg * 6\n", i, c[i], b[i], a[i]); 230 assert(0); 231 } 232 } 233 } 234 } 235 }