| 1641 | } |
| 1642 | |
| 1643 | void HFactor::ftranU(HVector& rhs, const double expected_density, |
| 1644 | HighsTimerClock* factor_timer_clock_pointer) const { |
| 1645 | assert(rhs.count >= 0); |
| 1646 | FactorTimer factor_timer; |
| 1647 | factor_timer.start(FactorFtranUpper, factor_timer_clock_pointer); |
| 1648 | // The update part |
| 1649 | if (update_method == kUpdateMethodFt) { |
| 1650 | factor_timer.start(FactorFtranUpperFT, factor_timer_clock_pointer); |
| 1651 | ftranFT(rhs); |
| 1652 | rhs.tight(); |
| 1653 | rhs.pack(); |
| 1654 | factor_timer.stop(FactorFtranUpperFT, factor_timer_clock_pointer); |
| 1655 | } else if (update_method == kUpdateMethodMpf) { |
| 1656 | assert(!(update_method == kUpdateMethodMpf)); |
| 1657 | factor_timer.start(FactorFtranUpperMPF, factor_timer_clock_pointer); |
| 1658 | ftranMPF(rhs); |
| 1659 | rhs.tight(); |
| 1660 | rhs.pack(); |
| 1661 | factor_timer.stop(FactorFtranUpperMPF, factor_timer_clock_pointer); |
| 1662 | } |
| 1663 | |
| 1664 | // The regular part |
| 1665 | // |
| 1666 | // Determine style of solve |
| 1667 | const double current_density = 1.0 * rhs.count * inv_num_row; |
| 1668 | const bool sparse_solve = rhs.count < 0 || current_density > kHyperCancel || |
| 1669 | expected_density > kHyperFtranU; |
| 1670 | if (sparse_solve) { |
| 1671 | const bool report_ftran_upper_sparse = |
| 1672 | false; // current_density < kHyperCancel; |
| 1673 | HighsInt use_clock; |
| 1674 | if (current_density < 0.1) |
| 1675 | use_clock = FactorFtranUpperSps2; |
| 1676 | else if (current_density < 0.5) |
| 1677 | use_clock = FactorFtranUpperSps1; |
| 1678 | else |
| 1679 | use_clock = FactorFtranUpperSps0; |
| 1680 | factor_timer.start(use_clock, factor_timer_clock_pointer); |
| 1681 | // Alias to non constant |
| 1682 | double rhs_synthetic_tick = 0; |
| 1683 | // Alias to RHS |
| 1684 | HighsInt* rhs_index = rhs.index.data(); |
| 1685 | double* rhs_array = rhs.array.data(); |
| 1686 | // Alias to factor U |
| 1687 | const HighsInt* u_start = this->u_start.data(); |
| 1688 | const HighsInt* u_end = this->u_last_p.data(); |
| 1689 | const HighsInt* u_index = this->u_index.data(); |
| 1690 | const double* u_value = this->u_value.data(); |
| 1691 | // Local accumulation of RHS count |
| 1692 | HighsInt rhs_count = 0; |
| 1693 | // Transform |
| 1694 | HighsInt u_pivot_count = u_pivot_index.size(); |
| 1695 | for (HighsInt i_logic = u_pivot_count - 1; i_logic >= 0; i_logic--) { |
| 1696 | // Skip void |
| 1697 | if (u_pivot_index[i_logic] == -1) continue; |
| 1698 | // Normal part |
| 1699 | const HighsInt pivotRow = u_pivot_index[i_logic]; |
| 1700 | double pivot_multiplier = rhs_array[pivotRow]; |