This will generate the operators to apply the shape transformation that is represented by this class. This is the order of operators that will be generated if needed: 1. Reshape/unsqueeze 2. Transpose 3. Broadcast 4. Reshape/squeeze 5. Broadcast This will generate operators backwards starting at 5 and going up. Steps 1-3 are generated from the subdimensions and steps 4-5 are generated with the d
| 1610 | // are generated from the subdimensions and steps 4-5 are generated with the |
| 1611 | // dimensions. |
| 1612 | std::vector<operation> |
| 1613 | shape_transform_descriptor::generate(const std::vector<std::size_t>& input_dims, |
| 1614 | bool no_broadcast) const |
| 1615 | { |
| 1616 | operation_list result; |
| 1617 | std::vector<dimension> new_dims = |
| 1618 | input_dims.empty() ? dimensions : this->rebase(input_dims).dimensions; |
| 1619 | assert(input_dims.empty() or not new_dims.empty()); |
| 1620 | if(no_broadcast) |
| 1621 | { |
| 1622 | for_each_subdimension(new_dims, &flatten_broadcasted_dim); |
| 1623 | } |
| 1624 | else |
| 1625 | { |
| 1626 | // Need broadcast |
| 1627 | if(std::any_of(new_dims.begin(), new_dims.end(), &is_broadcast_dim)) |
| 1628 | { |
| 1629 | std::vector<std::size_t> out_lens; |
| 1630 | std::transform(new_dims.begin(), |
| 1631 | new_dims.end(), |
| 1632 | std::back_inserter(out_lens), |
| 1633 | [](const dimension& d) { return d.len(); }); |
| 1634 | auto startb = std::find_if_not(new_dims.begin(), new_dims.end(), &has_no_axes); |
| 1635 | auto trailb = std::find_if_not(startb, new_dims.end(), &has_axes); |
| 1636 | auto axis = std::distance(new_dims.begin(), startb); |
| 1637 | auto extra_dims = axis + std::distance(trailb, new_dims.end()); |
| 1638 | // Use broadcast instead of multibroadcast |
| 1639 | if(std::all_of(trailb, new_dims.end(), &has_no_axes) and extra_dims > 0 and |
| 1640 | axis < new_dims.size()) |
| 1641 | { |
| 1642 | result.push_back(make_op("broadcast", {{"axis", axis}, {"out_lens", out_lens}})); |
| 1643 | new_dims.erase(trailb, new_dims.end()); |
| 1644 | new_dims.erase(new_dims.begin(), new_dims.begin() + axis); |
| 1645 | } |
| 1646 | else |
| 1647 | { |
| 1648 | result.push_back(make_op("multibroadcast", {{"out_lens", out_lens}})); |
| 1649 | } |
| 1650 | } |
| 1651 | // If all the dimensions have no axes then there isnt anthing else to do |
| 1652 | // so just clear the new_dims |
| 1653 | if(std::all_of(new_dims.begin(), new_dims.end(), &has_no_axes)) |
| 1654 | new_dims.clear(); |
| 1655 | // Flatten broadcasted dimensions |
| 1656 | for(auto& d : new_dims) |
| 1657 | { |
| 1658 | if(d.subdimensions.size() != 1) |
| 1659 | continue; |
| 1660 | flatten_broadcasted_dim(d.subdimensions.front()); |
| 1661 | } |
| 1662 | } |
| 1663 | // Need squeeze reshape |
| 1664 | if(std::any_of(new_dims.begin(), new_dims.end(), [](const dimension& d) { |
| 1665 | if(d.subdimensions.size() != 1) |
| 1666 | return true; |
| 1667 | return is_broadcast_dim(d); |
| 1668 | })) |
| 1669 | { |
no test coverage detected