diff --git a/src/glop/lp_data.cc b/src/glop/lp_data.cc index 7faefd57b1..97cb644bbd 100644 --- a/src/glop/lp_data.cc +++ b/src/glop/lp_data.cc @@ -22,8 +22,8 @@ namespace { // This should be the same as DCHECK(AreBoundsValid()), but the DCHECK() are // split to give more meaningful information to the user in case of failure. void DebugCheckBoundsValid(Fractional lower_bound, Fractional upper_bound) { - DCHECK(!std::isnan(lower_bound)); - DCHECK(!std::isnan(upper_bound)); + DCHECK(!isnan(lower_bound)); + DCHECK(!isnan(upper_bound)); DCHECK(!(lower_bound == kInfinity && upper_bound == kInfinity)); DCHECK(!(lower_bound == -kInfinity && upper_bound == -kInfinity)); DCHECK_LE(lower_bound, upper_bound); diff --git a/src/glop/lp_solver.cc b/src/glop/lp_solver.cc index e92af3d590..8b229c9272 100644 --- a/src/glop/lp_solver.cc +++ b/src/glop/lp_solver.cc @@ -70,50 +70,6 @@ void DumpLinearProgramIfRequiredByFlags(const LinearProgram& linear_program, } } -// ScopedFloatingPointEnv is used to easily enable Floating-point exceptions. -// The initial state is automatically restored when the object is deleted. -// -// Note(user): For some reason, this causes an FPE exception to be triggered for -// unknown reasons when compiled in 32 bits. Because of this, we do not turn -// on FPE exception if ARCH_K8 is not defined. -// -// TODO(user): Make it work on 32 bits. -// TODO(user): Move to ../util/fp_utils.h -class ScopedFloatingPointEnv { - public: - ScopedFloatingPointEnv() -#if defined(ARCH_K8) && defined(__GNUC__) && !defined(__APPLE__) - : initial_excepts_(fegetexcept()), current_excepts_(0) {} -#else - : initial_excepts_(0), current_excepts_(0) {} -#endif - - - ~ScopedFloatingPointEnv() { -#if defined(ARCH_K8) && defined(__GNUC__) && !defined(__APPLE__) - if (FLAGS_lp_solver_enable_fp_exceptions) { - // Enabled exceptions have to be disabled because feenableexcept acts as - // a bit-or. - fedisableexcept(current_excepts_); - feenableexcept(initial_excepts_); - } -#endif - } - - void FeEnableExcept(int excepts) { -#if defined(ARCH_K8) && defined(__GNUC__) && !defined(__APPLE__) - if (FLAGS_lp_solver_enable_fp_exceptions) { - current_excepts_ |= excepts; - feenableexcept(current_excepts_); - } -#endif - } - - private: - const int initial_excepts_; - int current_excepts_; -}; - } // anonymous namespace // -------------------------------------------------------- @@ -155,7 +111,9 @@ ProblemStatus LPSolver::Solve(const LinearProgram& lp) { // that the program is valid. This way, if we have input NaNs, we will not // crash. ScopedFloatingPointEnv scoped_fenv; - scoped_fenv.FeEnableExcept(FE_DIVBYZERO | FE_INVALID); + if (FLAGS_lp_solver_enable_fp_exceptions) { + scoped_fenv.EnableExceptions(FE_DIVBYZERO | FE_INVALID); + } // Make an internal copy of the problem for the preprocessing. VLOG(1) << "Initial problem: " << lp.GetDimensionString(); diff --git a/src/glop/lp_types.h b/src/glop/lp_types.h index 058cfc25c8..047ca62962 100644 --- a/src/glop/lp_types.h +++ b/src/glop/lp_types.h @@ -247,7 +247,7 @@ class StrictITIVector : public ITIVector { typedef ITIVector ParentType; // This allows for brace initialization, which is really useful in tests. // It is not 'explicit' by design, so one can do vector = {...}; -#if !defined(__ANDROID__) && !defined(_MSC_VER) +#if !defined(__ANDROID__) || !defined(_MSC_VER) || (_MSC_VER >= 1800) StrictITIVector(std::initializer_list init_list) // NOLINT : ParentType(init_list.begin(), init_list.end()) {} #endif diff --git a/src/glop/markowitz.cc b/src/glop/markowitz.cc index 4270350b13..49014e9482 100644 --- a/src/glop/markowitz.cc +++ b/src/glop/markowitz.cc @@ -185,6 +185,8 @@ struct MatrixEntry { RowIndex row; ColIndex col; Fractional coefficient; + MatrixEntry(RowIndex r, ColIndex c, Fractional coeff) + : row(r), col(c), coefficient(coeff) {} bool operator<(const MatrixEntry& o) const { return (row == o.row) ? col < o.col : row < o.row; } @@ -202,8 +204,8 @@ void Markowitz::ExtractSingletonColumns(const MatrixView& basis_matrix, for (ColIndex col(0); col < num_cols; ++col) { const SparseColumn& column = basis_matrix.column(col); if (column.num_entries().value() == 1) { - singleton_entries.push_back( - {column.GetFirstRow(), col, column.GetFirstCoefficient()}); + singleton_entries.push_back(MatrixEntry( + column.GetFirstRow(), col, column.GetFirstCoefficient())); } } diff --git a/src/glop/preprocessor.cc b/src/glop/preprocessor.cc index 1d270a3edf..14a0460fa1 100644 --- a/src/glop/preprocessor.cc +++ b/src/glop/preprocessor.cc @@ -1130,7 +1130,7 @@ namespace { struct ColWithDegree { ColIndex col; EntryIndex num_entries; - + ColWithDegree(ColIndex c, EntryIndex n) : col(c), num_entries(n) {} bool operator<(const ColWithDegree& other) const { if (num_entries == other.num_entries) { return col < other.col; @@ -1201,7 +1201,7 @@ bool ImpliedFreePreprocessor::Run(LinearProgram* lp) { std::vector col_by_degree; for (ColIndex col(0); col < num_cols; ++col) { col_by_degree.push_back( - ColWithDegree{col, lp->GetSparseColumn(col).num_entries()}); + ColWithDegree(col, lp->GetSparseColumn(col).num_entries())); } std::sort(col_by_degree.begin(), col_by_degree.end()); @@ -2585,25 +2585,25 @@ bool DoubletonEqualityRowPreprocessor::Run(LinearProgram* lp) { } if (carried_over_lb <= lb) { // Default (and simplest) case: the lower bound didn't change. - r.bound_backtracking_at_lower_bound = { - MODIFIED, VariableStatus::AT_LOWER_BOUND, lb}; + r.bound_backtracking_at_lower_bound = RestoreInfo::ColChoiceAndStatus( + MODIFIED, VariableStatus::AT_LOWER_BOUND, lb); } else { lb = carried_over_lb; - r.bound_backtracking_at_lower_bound = { + r.bound_backtracking_at_lower_bound = RestoreInfo::ColChoiceAndStatus( DELETED, carry_over_factor > 0 ? VariableStatus::AT_LOWER_BOUND : VariableStatus::AT_UPPER_BOUND, - carry_over_factor > 0 ? r.lb[DELETED] : r.ub[DELETED]}; + carry_over_factor > 0 ? r.lb[DELETED] : r.ub[DELETED]); } if (carried_over_ub >= ub) { // Default (and simplest) case: the upper bound didn't change. - r.bound_backtracking_at_upper_bound = { - MODIFIED, VariableStatus::AT_UPPER_BOUND, ub}; + r.bound_backtracking_at_upper_bound = RestoreInfo::ColChoiceAndStatus( + MODIFIED, VariableStatus::AT_UPPER_BOUND, ub); } else { ub = carried_over_ub; - r.bound_backtracking_at_upper_bound = { + r.bound_backtracking_at_upper_bound = RestoreInfo::ColChoiceAndStatus( DELETED, carry_over_factor > 0 ? VariableStatus::AT_UPPER_BOUND : VariableStatus::AT_LOWER_BOUND, - carry_over_factor > 0 ? r.ub[DELETED] : r.lb[DELETED]}; + carry_over_factor > 0 ? r.ub[DELETED] : r.lb[DELETED]); } // 3) If the new bounds are fixed (the domain is a singleton) or // infeasible, then we let the diff --git a/src/glop/preprocessor.h b/src/glop/preprocessor.h index 03541355d8..1afec8bd69 100644 --- a/src/glop/preprocessor.h +++ b/src/glop/preprocessor.h @@ -741,6 +741,9 @@ class DoubletonEqualityRowPreprocessor : public Preprocessor { ColChoice col_choice; VariableStatus status; Fractional value; + ColChoiceAndStatus() : col_choice(), status(), value(0.0) {} + ColChoiceAndStatus(ColChoice c, VariableStatus s, Fractional v) + : col_choice(c), status(s), value(v) {} }; ColChoiceAndStatus bound_backtracking_at_lower_bound; ColChoiceAndStatus bound_backtracking_at_upper_bound; diff --git a/src/glop/sparse.cc b/src/glop/sparse.cc index 9db54907f5..4f52e3ec27 100644 --- a/src/glop/sparse.cc +++ b/src/glop/sparse.cc @@ -71,6 +71,7 @@ Fractional ComputeInfinityNormTemplate(const Matrix& matrix) { // -------------------------------------------------------- SparseMatrix::SparseMatrix() : columns_(), num_rows_(0) {} +#if !defined(__ANDROID__) || !defined(_MSC_VER) || (_MSC_VER >= 1800) SparseMatrix::SparseMatrix( std::initializer_list> init_list) { ColIndex num_cols(0); @@ -89,6 +90,7 @@ SparseMatrix::SparseMatrix( ++row; } } +#endif void SparseMatrix::Clear() { columns_.clear(); diff --git a/src/glop/sparse.h b/src/glop/sparse.h index f9700e498d..10501ff6cd 100644 --- a/src/glop/sparse.h +++ b/src/glop/sparse.h @@ -49,11 +49,10 @@ class SparseMatrix { // {1, 2, 3}, // {4, 5, 6}, // {7, 8, 9}}; -#if !defined(_MSC_VER) +#if !defined(__ANDROID__) || !defined(_MSC_VER) || (_MSC_VER >= 1800) explicit SparseMatrix( std::initializer_list> init_list); #endif - // Clears internal data structure, i.e. erases all the columns and set // the number of rows to zero. void Clear(); diff --git a/src/glop/sparse_vector.h b/src/glop/sparse_vector.h index 9d20affc93..888d933beb 100644 --- a/src/glop/sparse_vector.h +++ b/src/glop/sparse_vector.h @@ -265,7 +265,10 @@ class SparseVector { Fractional coefficient; // TODO(user): Evaluate the impact of having padding (12 bytes struct when // Fractional is a double). - + // Note(user): The two constructors below are not needed when we switch + // to initializer lists. + InternalEntry() : index(0), coefficient(0.0) {} + InternalEntry(Index i, Fractional c) : index(i), coefficient(c) {} bool operator<(const InternalEntry& other) const { return index < other.index; } @@ -468,7 +471,9 @@ bool SparseVector::CheckNoDuplicates() const { template void SparseVector::SetCoefficient(Index index, Fractional value) { DCHECK_GE(index, 0); - entry_.push_back({index, value}); + // TODO(user): when we drop MSVC2012 in the open-source project, + // use initializer list-based idiom: entry_.push_back({index, value}); + entry_.push_back(InternalEntry(index, value)); may_contain_duplicates_ = true; }