| 1527 | } |
| 1528 | |
| 1529 | void HFactor::ftranL(HVector& rhs, const double expected_density, |
| 1530 | HighsTimerClock* factor_timer_clock_pointer) const { |
| 1531 | FactorTimer factor_timer; |
| 1532 | factor_timer.start(FactorFtranLower, factor_timer_clock_pointer); |
| 1533 | if (update_method == kUpdateMethodApf) { |
| 1534 | assert(!(update_method == kUpdateMethodApf)); |
| 1535 | factor_timer.start(FactorFtranLowerAPF, factor_timer_clock_pointer); |
| 1536 | rhs.tight(); |
| 1537 | rhs.pack(); |
| 1538 | ftranAPF(rhs); |
| 1539 | factor_timer.stop(FactorFtranLowerAPF, factor_timer_clock_pointer); |
| 1540 | rhs.tight(); |
| 1541 | } |
| 1542 | |
| 1543 | // Determine style of solve |
| 1544 | double current_density = 1.0 * rhs.count * inv_num_row; |
| 1545 | const bool sparse_solve = rhs.count < 0 || current_density > kHyperCancel || |
| 1546 | expected_density > kHyperFtranL; |
| 1547 | if (sparse_solve) { |
| 1548 | factor_timer.start(FactorFtranLowerSps, factor_timer_clock_pointer); |
| 1549 | // Alias to RHS |
| 1550 | HighsInt* rhs_index = rhs.index.data(); |
| 1551 | double* rhs_array = rhs.array.data(); |
| 1552 | // Alias to factor L |
| 1553 | const HighsInt* l_start = this->l_start.data(); |
| 1554 | const HighsInt* l_index = this->l_index.data(); |
| 1555 | const double* l_value = this->l_value.data(); |
| 1556 | // Local accumulation of RHS count |
| 1557 | HighsInt rhs_count = 0; |
| 1558 | // Transform |
| 1559 | for (HighsInt i = 0; i < num_row; i++) { |
| 1560 | HighsInt pivotRow = l_pivot_index[i]; |
| 1561 | const double pivot_multiplier = rhs_array[pivotRow]; |
| 1562 | if (fabs(pivot_multiplier) > kHighsTiny) { |
| 1563 | rhs_index[rhs_count++] = pivotRow; |
| 1564 | const HighsInt start = l_start[i]; |
| 1565 | const HighsInt end = l_start[i + 1]; |
| 1566 | for (HighsInt k = start; k < end; k++) |
| 1567 | rhs_array[l_index[k]] -= pivot_multiplier * l_value[k]; |
| 1568 | } else |
| 1569 | rhs_array[pivotRow] = 0; |
| 1570 | } |
| 1571 | // Save the count |
| 1572 | rhs.count = rhs_count; |
| 1573 | factor_timer.stop(FactorFtranLowerSps, factor_timer_clock_pointer); |
| 1574 | } else { |
| 1575 | // Hyper-sparse solve |
| 1576 | factor_timer.start(FactorFtranLowerHyper, factor_timer_clock_pointer); |
| 1577 | const HighsInt* l_index = this->l_index.data(); |
| 1578 | const double* l_value = this->l_value.data(); |
| 1579 | solveHyper(num_row, l_pivot_lookup.data(), l_pivot_index.data(), 0, |
| 1580 | l_start.data(), &l_start[1], &l_index[0], &l_value[0], &rhs); |
| 1581 | factor_timer.stop(FactorFtranLowerHyper, factor_timer_clock_pointer); |
| 1582 | } |
| 1583 | factor_timer.stop(FactorFtranLower, factor_timer_clock_pointer); |
| 1584 | } |
| 1585 | |
| 1586 | void HFactor::btranL(HVector& rhs, const double expected_density, |