| 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 |