OLD | NEW |
1 /* Specific implementation of the PACK intrinsic | 1 /* Specific implementation of the PACK intrinsic |
2 Copyright (C) 2002, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundati
on, Inc. | 2 Copyright (C) 2002, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundati
on, Inc. |
3 Contributed by Paul Brook <paul@nowt.org> | 3 Contributed by Paul Brook <paul@nowt.org> |
4 | 4 |
5 This file is part of the GNU Fortran 95 runtime library (libgfortran). | 5 This file is part of the GNU Fortran 95 runtime library (libgfortran). |
6 | 6 |
7 Libgfortran is free software; you can redistribute it and/or | 7 Libgfortran is free software; you can redistribute it and/or |
8 modify it under the terms of the GNU General Public | 8 modify it under the terms of the GNU General Public |
9 License as published by the Free Software Foundation; either | 9 License as published by the Free Software Foundation; either |
10 version 3 of the License, or (at your option) any later version. | 10 version 3 of the License, or (at your option) any later version. |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
115 if (mptr) | 115 if (mptr) |
116 mptr = GFOR_POINTER_TO_L1 (mptr, mask_kind); | 116 mptr = GFOR_POINTER_TO_L1 (mptr, mask_kind); |
117 } | 117 } |
118 else | 118 else |
119 runtime_error ("Funny sized logical array"); | 119 runtime_error ("Funny sized logical array"); |
120 | 120 |
121 zero_sized = 0; | 121 zero_sized = 0; |
122 for (n = 0; n < dim; n++) | 122 for (n = 0; n < dim; n++) |
123 { | 123 { |
124 count[n] = 0; | 124 count[n] = 0; |
125 extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound; | 125 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n); |
126 if (extent[n] <= 0) | 126 if (extent[n] <= 0) |
127 zero_sized = 1; | 127 zero_sized = 1; |
128 sstride[n] = array->dim[n].stride; | 128 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n); |
129 mstride[n] = mask->dim[n].stride * mask_kind; | 129 mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n); |
130 } | 130 } |
131 if (sstride[0] == 0) | 131 if (sstride[0] == 0) |
132 sstride[0] = 1; | 132 sstride[0] = 1; |
133 if (mstride[0] == 0) | 133 if (mstride[0] == 0) |
134 mstride[0] = mask_kind; | 134 mstride[0] = mask_kind; |
135 | 135 |
136 if (zero_sized) | 136 if (zero_sized) |
137 sptr = NULL; | 137 sptr = NULL; |
138 else | 138 else |
139 sptr = array->data; | 139 sptr = array->data; |
140 | 140 |
141 if (ret->data == NULL || compile_options.bounds_check) | 141 if (ret->data == NULL || unlikely (compile_options.bounds_check)) |
142 { | 142 { |
143 /* Count the elements, either for allocating memory or | 143 /* Count the elements, either for allocating memory or |
144 for bounds checking. */ | 144 for bounds checking. */ |
145 | 145 |
146 if (vector != NULL) | 146 if (vector != NULL) |
147 { | 147 { |
148 /* The return array will have as many | 148 /* The return array will have as many |
149 elements as there are in VECTOR. */ | 149 elements as there are in VECTOR. */ |
150 » total = vector->dim[0].ubound + 1 - vector->dim[0].lbound; | 150 » total = GFC_DESCRIPTOR_EXTENT(vector,0); |
151 if (total < 0) | 151 if (total < 0) |
152 { | 152 { |
153 total = 0; | 153 total = 0; |
154 vector = NULL; | 154 vector = NULL; |
155 } | 155 } |
156 } | 156 } |
157 else | 157 else |
158 » { | 158 { |
159 » /* We have to count the true elements in MASK. */ | 159 » /* We have to count the true elements in MASK. */ |
160 | 160 » total = count_0 (mask); |
161 » /* TODO: We could speed up pack easily in the case of only | 161 } |
162 » few .TRUE. entries in MASK, by keeping track of where we | |
163 » would be in the source array during the initial traversal | |
164 » of MASK, and caching the pointers to those elements. Then, | |
165 » supposed the number of elements is small enough, we would | |
166 » only have to traverse the list, and copy those elements | |
167 » into the result array. In the case of datatypes which fit | |
168 » in one of the integer types we could also cache the | |
169 » value instead of a pointer to it. | |
170 » This approach might be bad from the point of view of | |
171 » cache behavior in the case where our cache is not big | |
172 » enough to hold all elements that have to be copied. */ | |
173 | |
174 » const GFC_LOGICAL_1 *m = mptr; | |
175 | |
176 » total = 0; | |
177 » if (zero_sized) | |
178 » m = NULL; | |
179 | |
180 » while (m) | |
181 » { | |
182 » /* Test this element. */ | |
183 » if (*m) | |
184 » » total++; | |
185 | |
186 » /* Advance to the next element. */ | |
187 » m += mstride[0]; | |
188 » count[0]++; | |
189 » n = 0; | |
190 » while (count[n] == extent[n]) | |
191 » » { | |
192 » » /* When we get to the end of a dimension, reset it | |
193 » » and increment the next dimension. */ | |
194 » » count[n] = 0; | |
195 » » /* We could precalculate this product, but this is a | |
196 » » less frequently used path so probably not worth | |
197 » » it. */ | |
198 » » m -= mstride[n] * extent[n]; | |
199 » » n++; | |
200 » » if (n >= dim) | |
201 » » { | |
202 » » /* Break out of the loop. */ | |
203 » » m = NULL; | |
204 » » break; | |
205 » » } | |
206 » » else | |
207 » » { | |
208 » » count[n]++; | |
209 » » m += mstride[n]; | |
210 » » } | |
211 » » } | |
212 » } | |
213 » } | |
214 | 162 |
215 if (ret->data == NULL) | 163 if (ret->data == NULL) |
216 { | 164 { |
217 /* Setup the array descriptor. */ | 165 /* Setup the array descriptor. */ |
218 » ret->dim[0].lbound = 0; | 166 » GFC_DIMENSION_SET(ret->dim[0], 0, total-1, 1); |
219 » ret->dim[0].ubound = total - 1; | |
220 » ret->dim[0].stride = 1; | |
221 | 167 |
222 ret->offset = 0; | 168 ret->offset = 0; |
223 if (total == 0) | 169 if (total == 0) |
224 { | 170 { |
225 /* In this case, nothing remains to be done. */ | 171 /* In this case, nothing remains to be done. */ |
226 ret->data = internal_malloc_size (1); | 172 ret->data = internal_malloc_size (1); |
227 return; | 173 return; |
228 } | 174 } |
229 else | 175 else |
230 ret->data = internal_malloc_size (sizeof (GFC_REAL_8) * total); | 176 ret->data = internal_malloc_size (sizeof (GFC_REAL_8) * total); |
231 } | 177 } |
232 else | 178 else |
233 { | 179 { |
234 /* We come here because of range checking. */ | 180 /* We come here because of range checking. */ |
235 index_type ret_extent; | 181 index_type ret_extent; |
236 | 182 |
237 » ret_extent = ret->dim[0].ubound + 1 - ret->dim[0].lbound; | 183 » ret_extent = GFC_DESCRIPTOR_EXTENT(ret,0); |
238 if (total != ret_extent) | 184 if (total != ret_extent) |
239 runtime_error ("Incorrect extent in return value of PACK intrinsic;" | 185 runtime_error ("Incorrect extent in return value of PACK intrinsic;" |
240 " is %ld, should be %ld", (long int) total, | 186 " is %ld, should be %ld", (long int) total, |
241 (long int) ret_extent); | 187 (long int) ret_extent); |
242 } | 188 } |
243 } | 189 } |
244 | 190 |
245 rstride0 = ret->dim[0].stride; | 191 rstride0 = GFC_DESCRIPTOR_STRIDE(ret,0); |
246 if (rstride0 == 0) | 192 if (rstride0 == 0) |
247 rstride0 = 1; | 193 rstride0 = 1; |
248 sstride0 = sstride[0]; | 194 sstride0 = sstride[0]; |
249 mstride0 = mstride[0]; | 195 mstride0 = mstride[0]; |
250 rptr = ret->data; | 196 rptr = ret->data; |
251 | 197 |
252 while (sptr && mptr) | 198 while (sptr && mptr) |
253 { | 199 { |
254 /* Test this element. */ | 200 /* Test this element. */ |
255 if (*mptr) | 201 if (*mptr) |
(...skipping 28 matching lines...) Expand all Loading... |
284 count[n]++; | 230 count[n]++; |
285 sptr += sstride[n]; | 231 sptr += sstride[n]; |
286 mptr += mstride[n]; | 232 mptr += mstride[n]; |
287 } | 233 } |
288 } | 234 } |
289 } | 235 } |
290 | 236 |
291 /* Add any remaining elements from VECTOR. */ | 237 /* Add any remaining elements from VECTOR. */ |
292 if (vector) | 238 if (vector) |
293 { | 239 { |
294 n = vector->dim[0].ubound + 1 - vector->dim[0].lbound; | 240 n = GFC_DESCRIPTOR_EXTENT(vector,0); |
295 nelem = ((rptr - ret->data) / rstride0); | 241 nelem = ((rptr - ret->data) / rstride0); |
296 if (n > nelem) | 242 if (n > nelem) |
297 { | 243 { |
298 sstride0 = vector->dim[0].stride; | 244 sstride0 = GFC_DESCRIPTOR_STRIDE(vector,0); |
299 if (sstride0 == 0) | 245 if (sstride0 == 0) |
300 sstride0 = 1; | 246 sstride0 = 1; |
301 | 247 |
302 sptr = vector->data + sstride0 * nelem; | 248 sptr = vector->data + sstride0 * nelem; |
303 n -= nelem; | 249 n -= nelem; |
304 while (n--) | 250 while (n--) |
305 { | 251 { |
306 *rptr = *sptr; | 252 *rptr = *sptr; |
307 rptr += rstride0; | 253 rptr += rstride0; |
308 sptr += sstride0; | 254 sptr += sstride0; |
309 } | 255 } |
310 } | 256 } |
311 } | 257 } |
312 } | 258 } |
313 | 259 |
314 #endif | 260 #endif |
315 | 261 |
OLD | NEW |