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 }