| 3383 | } |
| 3384 | |
| 3385 | array take( |
| 3386 | const array& a, |
| 3387 | const array& indices, |
| 3388 | int axis, |
| 3389 | StreamOrDevice s /* = {} */) { |
| 3390 | // Check for valid axis |
| 3391 | if (axis + static_cast<int>(a.ndim()) < 0 || |
| 3392 | axis >= static_cast<int>(a.ndim())) { |
| 3393 | std::ostringstream msg; |
| 3394 | msg << "[take] Received invalid axis " << axis << " for array with " |
| 3395 | << a.ndim() << " dimensions."; |
| 3396 | throw std::invalid_argument(msg.str()); |
| 3397 | } |
| 3398 | |
| 3399 | // Check for valid take |
| 3400 | if (a.shape(axis) == 0 && indices.size() != 0) { |
| 3401 | throw std::invalid_argument( |
| 3402 | "[take] Cannot do a non-empty take from an empty axis."); |
| 3403 | } |
| 3404 | |
| 3405 | // Handle negative axis |
| 3406 | axis = axis < 0 ? a.ndim() + axis : axis; |
| 3407 | |
| 3408 | // Make slice sizes to pass to gather |
| 3409 | Shape slice_sizes = a.shape(); |
| 3410 | slice_sizes[axis] = 1; |
| 3411 | |
| 3412 | auto out = gather(a, indices, axis, slice_sizes, s); |
| 3413 | |
| 3414 | // Transpose indices dimensions to axis dimension |
| 3415 | if (axis != 0) { |
| 3416 | std::vector<int> t_axes(out.ndim()); |
| 3417 | std::iota(t_axes.begin(), t_axes.begin() + axis, indices.ndim()); |
| 3418 | std::iota(t_axes.begin() + axis, t_axes.begin() + axis + indices.ndim(), 0); |
| 3419 | std::iota( |
| 3420 | t_axes.begin() + axis + indices.ndim(), |
| 3421 | t_axes.end(), |
| 3422 | indices.ndim() + axis); |
| 3423 | out = transpose(out, t_axes, s); |
| 3424 | } |
| 3425 | |
| 3426 | // Squeeze the axis we take over |
| 3427 | return squeeze(out, indices.ndim() + axis, s); |
| 3428 | } |
| 3429 | |
| 3430 | array take(const array& a, const array& indices, StreamOrDevice s /* = {} */) { |
| 3431 | return take(flatten(a, s), indices, 0, s); |
no test coverage detected