OLD | NEW |
1 /* Implementation of the MAXLOC intrinsic | 1 /* Implementation of the MAXLOC intrinsic |
2 Copyright 2002, 2007, 2009 Free Software Foundation, Inc. | 2 Copyright 2002, 2007, 2009 Free Software Foundation, 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 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
48 GFC_INTEGER_4 * restrict dest; | 48 GFC_INTEGER_4 * restrict dest; |
49 index_type rank; | 49 index_type rank; |
50 index_type n; | 50 index_type n; |
51 | 51 |
52 rank = GFC_DESCRIPTOR_RANK (array); | 52 rank = GFC_DESCRIPTOR_RANK (array); |
53 if (rank <= 0) | 53 if (rank <= 0) |
54 runtime_error ("Rank of array needs to be > 0"); | 54 runtime_error ("Rank of array needs to be > 0"); |
55 | 55 |
56 if (retarray->data == NULL) | 56 if (retarray->data == NULL) |
57 { | 57 { |
58 retarray->dim[0].lbound = 0; | 58 GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1); |
59 retarray->dim[0].ubound = rank-1; | |
60 retarray->dim[0].stride = 1; | |
61 retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1; | 59 retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1; |
62 retarray->offset = 0; | 60 retarray->offset = 0; |
63 retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_4) * rank); | 61 retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_4) * rank); |
64 } | 62 } |
65 else | 63 else |
66 { | 64 { |
67 if (unlikely (compile_options.bounds_check)) | 65 if (unlikely (compile_options.bounds_check)) |
68 » { | 66 » bounds_iforeach_return ((array_t *) retarray, (array_t *) array, |
69 » int ret_rank; | 67 » » » » "MAXLOC"); |
70 » index_type ret_extent; | |
71 | |
72 » ret_rank = GFC_DESCRIPTOR_RANK (retarray); | |
73 » if (ret_rank != 1) | |
74 » runtime_error ("rank of return array in MAXLOC intrinsic" | |
75 » » » " should be 1, is %ld", (long int) ret_rank); | |
76 | |
77 » ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; | |
78 » if (ret_extent != rank) | |
79 » runtime_error ("Incorrect extent in return value of" | |
80 » » » " MAXLOC intrnisic: is %ld, should be %ld", | |
81 » » » (long int) ret_extent, (long int) rank); | |
82 » } | |
83 } | 68 } |
84 | 69 |
85 dstride = retarray->dim[0].stride; | 70 dstride = GFC_DESCRIPTOR_STRIDE(retarray,0); |
86 dest = retarray->data; | 71 dest = retarray->data; |
87 for (n = 0; n < rank; n++) | 72 for (n = 0; n < rank; n++) |
88 { | 73 { |
89 sstride[n] = array->dim[n].stride; | 74 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n); |
90 extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound; | 75 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n); |
91 count[n] = 0; | 76 count[n] = 0; |
92 if (extent[n] <= 0) | 77 if (extent[n] <= 0) |
93 { | 78 { |
94 /* Set the return value. */ | 79 /* Set the return value. */ |
95 for (n = 0; n < rank; n++) | 80 for (n = 0; n < rank; n++) |
96 dest[n * dstride] = 0; | 81 dest[n * dstride] = 0; |
97 return; | 82 return; |
98 } | 83 } |
99 } | 84 } |
100 | 85 |
101 base = array->data; | 86 base = array->data; |
102 | 87 |
103 /* Initialize the return value. */ | 88 /* Initialize the return value. */ |
104 for (n = 0; n < rank; n++) | 89 for (n = 0; n < rank; n++) |
105 dest[n * dstride] = 0; | 90 dest[n * dstride] = 1; |
106 { | 91 { |
107 | 92 |
108 GFC_REAL_4 maxval; | 93 GFC_REAL_4 maxval; |
| 94 #if defined(GFC_REAL_4_QUIET_NAN) |
| 95 int fast = 0; |
| 96 #endif |
109 | 97 |
110 maxval = -GFC_REAL_4_HUGE; | 98 #if defined(GFC_REAL_4_INFINITY) |
111 | 99 maxval = -GFC_REAL_4_INFINITY; |
| 100 #else |
| 101 maxval = -GFC_REAL_4_HUGE; |
| 102 #endif |
112 while (base) | 103 while (base) |
113 { | 104 { |
114 { | 105 do |
115 /* Implementation start. */ | 106 » { |
| 107 » /* Implementation start. */ |
116 | 108 |
117 if (*base > maxval || !dest[0]) | 109 #if defined(GFC_REAL_4_QUIET_NAN) |
118 { | 110 » } |
119 maxval = *base; | 111 while (0); |
120 for (n = 0; n < rank; n++) | 112 if (unlikely (!fast)) |
121 dest[n * dstride] = count[n] + 1; | 113 » { |
122 } | 114 » do |
123 /* Implementation end. */ | 115 » { |
124 } | 116 » if (*base >= maxval) |
125 /* Advance to the next element. */ | 117 » » { |
126 count[0]++; | 118 » » fast = 1; |
127 base += sstride[0]; | 119 » » maxval = *base; |
| 120 » » for (n = 0; n < rank; n++) |
| 121 » » dest[n * dstride] = count[n] + 1; |
| 122 » » break; |
| 123 » » } |
| 124 » base += sstride[0]; |
| 125 » } |
| 126 » while (++count[0] != extent[0]); |
| 127 » if (likely (fast)) |
| 128 » continue; |
| 129 » } |
| 130 else do |
| 131 » { |
| 132 #endif |
| 133 » if (*base > maxval) |
| 134 » { |
| 135 » maxval = *base; |
| 136 » for (n = 0; n < rank; n++) |
| 137 » » dest[n * dstride] = count[n] + 1; |
| 138 » } |
| 139 » /* Implementation end. */ |
| 140 » /* Advance to the next element. */ |
| 141 » base += sstride[0]; |
| 142 » } |
| 143 while (++count[0] != extent[0]); |
128 n = 0; | 144 n = 0; |
129 while (count[n] == extent[n]) | 145 do |
130 { | 146 » { |
131 /* When we get to the end of a dimension, reset it and increment | 147 » /* When we get to the end of a dimension, reset it and increment |
132 the next dimension. */ | 148 » the next dimension. */ |
133 count[n] = 0; | 149 » count[n] = 0; |
134 /* We could precalculate these products, but this is a less | 150 » /* We could precalculate these products, but this is a less |
135 frequently used path so probably not worth it. */ | 151 » frequently used path so probably not worth it. */ |
136 base -= sstride[n] * extent[n]; | 152 » base -= sstride[n] * extent[n]; |
137 n++; | 153 » n++; |
138 if (n == rank) | 154 » if (n == rank) |
139 { | 155 » { |
140 /* Break out of the loop. */ | 156 » /* Break out of the loop. */ |
141 base = NULL; | 157 » base = NULL; |
142 break; | 158 » break; |
143 } | 159 » } |
144 else | 160 » else |
145 { | 161 » { |
146 count[n]++; | 162 » count[n]++; |
147 base += sstride[n]; | 163 » base += sstride[n]; |
148 } | 164 » } |
149 } | 165 » } |
| 166 while (count[n] == extent[n]); |
150 } | 167 } |
151 } | 168 } |
152 } | 169 } |
153 | 170 |
154 | 171 |
155 extern void mmaxloc0_4_r4 (gfc_array_i4 * const restrict, | 172 extern void mmaxloc0_4_r4 (gfc_array_i4 * const restrict, |
156 gfc_array_r4 * const restrict, gfc_array_l1 * const restrict); | 173 gfc_array_r4 * const restrict, gfc_array_l1 * const restrict); |
157 export_proto(mmaxloc0_4_r4); | 174 export_proto(mmaxloc0_4_r4); |
158 | 175 |
159 void | 176 void |
(...skipping 12 matching lines...) Expand all Loading... |
172 int rank; | 189 int rank; |
173 index_type n; | 190 index_type n; |
174 int mask_kind; | 191 int mask_kind; |
175 | 192 |
176 rank = GFC_DESCRIPTOR_RANK (array); | 193 rank = GFC_DESCRIPTOR_RANK (array); |
177 if (rank <= 0) | 194 if (rank <= 0) |
178 runtime_error ("Rank of array needs to be > 0"); | 195 runtime_error ("Rank of array needs to be > 0"); |
179 | 196 |
180 if (retarray->data == NULL) | 197 if (retarray->data == NULL) |
181 { | 198 { |
182 retarray->dim[0].lbound = 0; | 199 GFC_DIMENSION_SET(retarray->dim[0], 0, rank - 1, 1); |
183 retarray->dim[0].ubound = rank-1; | |
184 retarray->dim[0].stride = 1; | |
185 retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1; | 200 retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1; |
186 retarray->offset = 0; | 201 retarray->offset = 0; |
187 retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_4) * rank); | 202 retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_4) * rank); |
188 } | 203 } |
189 else | 204 else |
190 { | 205 { |
191 if (unlikely (compile_options.bounds_check)) | 206 if (unlikely (compile_options.bounds_check)) |
192 { | 207 { |
193 int ret_rank, mask_rank; | |
194 index_type ret_extent; | |
195 int n; | |
196 index_type array_extent, mask_extent; | |
197 | 208 |
198 » ret_rank = GFC_DESCRIPTOR_RANK (retarray); | 209 » bounds_iforeach_return ((array_t *) retarray, (array_t *) array, |
199 » if (ret_rank != 1) | 210 » » » » "MAXLOC"); |
200 » runtime_error ("rank of return array in MAXLOC intrinsic" | 211 » bounds_equal_extents ((array_t *) mask, (array_t *) array, |
201 » » » " should be 1, is %ld", (long int) ret_rank); | 212 » » » » "MASK argument", "MAXLOC"); |
202 | |
203 » ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; | |
204 » if (ret_extent != rank) | |
205 » runtime_error ("Incorrect extent in return value of" | |
206 » » » " MAXLOC intrnisic: is %ld, should be %ld", | |
207 » » » (long int) ret_extent, (long int) rank); | |
208 » | |
209 » mask_rank = GFC_DESCRIPTOR_RANK (mask); | |
210 » if (rank != mask_rank) | |
211 » runtime_error ("rank of MASK argument in MAXLOC intrnisic" | |
212 » "should be %ld, is %ld", (long int) rank, | |
213 » » » (long int) mask_rank); | |
214 | |
215 » for (n=0; n<rank; n++) | |
216 » { | |
217 » array_extent = array->dim[n].ubound + 1 - array->dim[n].lbound; | |
218 » mask_extent = mask->dim[n].ubound + 1 - mask->dim[n].lbound; | |
219 » if (array_extent != mask_extent) | |
220 » » runtime_error ("Incorrect extent in MASK argument of" | |
221 » » » " MAXLOC intrinsic in dimension %ld:" | |
222 » » » " is %ld, should be %ld", (long int) n + 1, | |
223 » » » (long int) mask_extent, (long int) array_extent); | |
224 » } | |
225 } | 213 } |
226 } | 214 } |
227 | 215 |
228 mask_kind = GFC_DESCRIPTOR_SIZE (mask); | 216 mask_kind = GFC_DESCRIPTOR_SIZE (mask); |
229 | 217 |
230 mbase = mask->data; | 218 mbase = mask->data; |
231 | 219 |
232 if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8 | 220 if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8 |
233 #ifdef HAVE_GFC_LOGICAL_16 | 221 #ifdef HAVE_GFC_LOGICAL_16 |
234 || mask_kind == 16 | 222 || mask_kind == 16 |
235 #endif | 223 #endif |
236 ) | 224 ) |
237 mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind); | 225 mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind); |
238 else | 226 else |
239 runtime_error ("Funny sized logical array"); | 227 runtime_error ("Funny sized logical array"); |
240 | 228 |
241 dstride = retarray->dim[0].stride; | 229 dstride = GFC_DESCRIPTOR_STRIDE(retarray,0); |
242 dest = retarray->data; | 230 dest = retarray->data; |
243 for (n = 0; n < rank; n++) | 231 for (n = 0; n < rank; n++) |
244 { | 232 { |
245 sstride[n] = array->dim[n].stride; | 233 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n); |
246 mstride[n] = mask->dim[n].stride * mask_kind; | 234 mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n); |
247 extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound; | 235 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n); |
248 count[n] = 0; | 236 count[n] = 0; |
249 if (extent[n] <= 0) | 237 if (extent[n] <= 0) |
250 { | 238 { |
251 /* Set the return value. */ | 239 /* Set the return value. */ |
252 for (n = 0; n < rank; n++) | 240 for (n = 0; n < rank; n++) |
253 dest[n * dstride] = 0; | 241 dest[n * dstride] = 0; |
254 return; | 242 return; |
255 } | 243 } |
256 } | 244 } |
257 | 245 |
258 base = array->data; | 246 base = array->data; |
259 | 247 |
260 /* Initialize the return value. */ | 248 /* Initialize the return value. */ |
261 for (n = 0; n < rank; n++) | 249 for (n = 0; n < rank; n++) |
262 dest[n * dstride] = 0; | 250 dest[n * dstride] = 0; |
263 { | 251 { |
264 | 252 |
265 GFC_REAL_4 maxval; | 253 GFC_REAL_4 maxval; |
| 254 int fast = 0; |
266 | 255 |
267 maxval = -GFC_REAL_4_HUGE; | 256 #if defined(GFC_REAL_4_INFINITY) |
268 | 257 maxval = -GFC_REAL_4_INFINITY; |
| 258 #else |
| 259 maxval = -GFC_REAL_4_HUGE; |
| 260 #endif |
269 while (base) | 261 while (base) |
270 { | 262 { |
271 { | 263 do |
272 /* Implementation start. */ | 264 » { |
| 265 » /* Implementation start. */ |
273 | 266 |
274 if (*mbase && (*base > maxval || !dest[0])) | 267 » } |
275 { | 268 while (0); |
276 maxval = *base; | 269 if (unlikely (!fast)) |
277 for (n = 0; n < rank; n++) | 270 » { |
278 dest[n * dstride] = count[n] + 1; | 271 » do |
279 } | 272 » { |
280 /* Implementation end. */ | 273 » if (*mbase) |
281 } | 274 » » { |
282 /* Advance to the next element. */ | 275 #if defined(GFC_REAL_4_QUIET_NAN) |
283 count[0]++; | 276 » » if (unlikely (dest[0] == 0)) |
284 base += sstride[0]; | 277 » » for (n = 0; n < rank; n++) |
285 mbase += mstride[0]; | 278 » » dest[n * dstride] = count[n] + 1; |
| 279 » » if (*base >= maxval) |
| 280 #endif |
| 281 » » { |
| 282 » » fast = 1; |
| 283 » » maxval = *base; |
| 284 » » for (n = 0; n < rank; n++) |
| 285 » » » dest[n * dstride] = count[n] + 1; |
| 286 » » break; |
| 287 » » } |
| 288 » » } |
| 289 » base += sstride[0]; |
| 290 » mbase += mstride[0]; |
| 291 » } |
| 292 » while (++count[0] != extent[0]); |
| 293 » if (likely (fast)) |
| 294 » continue; |
| 295 » } |
| 296 else do |
| 297 » { |
| 298 » if (*mbase && *base > maxval) |
| 299 » { |
| 300 » maxval = *base; |
| 301 » for (n = 0; n < rank; n++) |
| 302 » » dest[n * dstride] = count[n] + 1; |
| 303 » } |
| 304 » /* Implementation end. */ |
| 305 » /* Advance to the next element. */ |
| 306 » base += sstride[0]; |
| 307 » mbase += mstride[0]; |
| 308 » } |
| 309 while (++count[0] != extent[0]); |
286 n = 0; | 310 n = 0; |
287 while (count[n] == extent[n]) | 311 do |
288 { | 312 » { |
289 /* When we get to the end of a dimension, reset it and increment | 313 » /* When we get to the end of a dimension, reset it and increment |
290 the next dimension. */ | 314 » the next dimension. */ |
291 count[n] = 0; | 315 » count[n] = 0; |
292 /* We could precalculate these products, but this is a less | 316 » /* We could precalculate these products, but this is a less |
293 frequently used path so probably not worth it. */ | 317 » frequently used path so probably not worth it. */ |
294 base -= sstride[n] * extent[n]; | 318 » base -= sstride[n] * extent[n]; |
295 mbase -= mstride[n] * extent[n]; | 319 » mbase -= mstride[n] * extent[n]; |
296 n++; | 320 » n++; |
297 if (n == rank) | 321 » if (n == rank) |
298 { | 322 » { |
299 /* Break out of the loop. */ | 323 » /* Break out of the loop. */ |
300 base = NULL; | 324 » base = NULL; |
301 break; | 325 » break; |
302 } | 326 » } |
303 else | 327 » else |
304 { | 328 » { |
305 count[n]++; | 329 » count[n]++; |
306 base += sstride[n]; | 330 » base += sstride[n]; |
307 mbase += mstride[n]; | 331 » mbase += mstride[n]; |
308 } | 332 » } |
309 } | 333 » } |
| 334 while (count[n] == extent[n]); |
310 } | 335 } |
311 } | 336 } |
312 } | 337 } |
313 | 338 |
314 | 339 |
315 extern void smaxloc0_4_r4 (gfc_array_i4 * const restrict, | 340 extern void smaxloc0_4_r4 (gfc_array_i4 * const restrict, |
316 gfc_array_r4 * const restrict, GFC_LOGICAL_4 *); | 341 gfc_array_r4 * const restrict, GFC_LOGICAL_4 *); |
317 export_proto(smaxloc0_4_r4); | 342 export_proto(smaxloc0_4_r4); |
318 | 343 |
319 void | 344 void |
(...skipping 12 matching lines...) Expand all Loading... |
332 return; | 357 return; |
333 } | 358 } |
334 | 359 |
335 rank = GFC_DESCRIPTOR_RANK (array); | 360 rank = GFC_DESCRIPTOR_RANK (array); |
336 | 361 |
337 if (rank <= 0) | 362 if (rank <= 0) |
338 runtime_error ("Rank of array needs to be > 0"); | 363 runtime_error ("Rank of array needs to be > 0"); |
339 | 364 |
340 if (retarray->data == NULL) | 365 if (retarray->data == NULL) |
341 { | 366 { |
342 retarray->dim[0].lbound = 0; | 367 GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1); |
343 retarray->dim[0].ubound = rank-1; | |
344 retarray->dim[0].stride = 1; | |
345 retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1; | 368 retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1; |
346 retarray->offset = 0; | 369 retarray->offset = 0; |
347 retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_4) * rank); | 370 retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_4) * rank); |
348 } | 371 } |
349 else | 372 else if (unlikely (compile_options.bounds_check)) |
350 { | 373 { |
351 if (unlikely (compile_options.bounds_check)) | 374 bounds_iforeach_return ((array_t *) retarray, (array_t *) array, |
352 » { | 375 » » » "MAXLOC"); |
353 » int ret_rank; | |
354 » index_type ret_extent; | |
355 | |
356 » ret_rank = GFC_DESCRIPTOR_RANK (retarray); | |
357 » if (ret_rank != 1) | |
358 » runtime_error ("rank of return array in MAXLOC intrinsic" | |
359 » » » " should be 1, is %ld", (long int) ret_rank); | |
360 | |
361 » ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; | |
362 » if (ret_extent != rank) | |
363 » runtime_error ("dimension of return array incorrect"); | |
364 » } | |
365 } | 376 } |
366 | 377 |
367 dstride = retarray->dim[0].stride; | 378 dstride = GFC_DESCRIPTOR_STRIDE(retarray,0); |
368 dest = retarray->data; | 379 dest = retarray->data; |
369 for (n = 0; n<rank; n++) | 380 for (n = 0; n<rank; n++) |
370 dest[n * dstride] = 0 ; | 381 dest[n * dstride] = 0 ; |
371 } | 382 } |
372 #endif | 383 #endif |
OLD | NEW |