diff --git a/src/io/FilereaderLp.cpp b/src/io/FilereaderLp.cpp index 5de2163359..8a9e0ba988 100644 --- a/src/io/FilereaderLp.cpp +++ b/src/io/FilereaderLp.cpp @@ -216,16 +216,16 @@ FilereaderRetcode FilereaderLp::readModelFromFile(const HighsOptions& options, void FilereaderLp::writeToFile(FILE* file, const char* format, ...) { va_list argptr; va_start(argptr, format); - char stringbuffer[LP_MAX_LINE_LENGTH + 1] = {}; + std::array stringbuffer = {}; HighsInt tokenlength = - vsnprintf(stringbuffer, sizeof stringbuffer, format, argptr); + vsnprintf(stringbuffer.data(), stringbuffer.size(), format, argptr); va_end(argptr); if (this->linelength + tokenlength >= LP_MAX_LINE_LENGTH) { fprintf(file, "\n"); - fprintf(file, "%s", stringbuffer); + fprintf(file, "%s", stringbuffer.data()); this->linelength = tokenlength; } else { - fprintf(file, "%s", stringbuffer); + fprintf(file, "%s", stringbuffer.data()); this->linelength += tokenlength; } } diff --git a/src/io/HMPSIO.cpp b/src/io/HMPSIO.cpp index b6037d3624..014f5716b1 100644 --- a/src/io/HMPSIO.cpp +++ b/src/io/HMPSIO.cpp @@ -78,21 +78,21 @@ FilereaderRetcode readMps( highsLogDev(log_options, HighsLogType::kInfo, "readMPS: Opened file OK\n"); // Input buffer const HighsInt lmax = 128; - char line[lmax]; - char flag[2] = {0, 0}; - double data[3]; + std::array line; + std::array flag = {0, 0}; + std::array data; HighsInt num_alien_entries = 0; HighsVarType integerCol = HighsVarType::kContinuous; // Load NAME - load_mpsLine(file, integerCol, lmax, line, flag, data); + load_mpsLine(file, integerCol, lmax, line.data(), flag.data(), data.data()); highsLogDev(log_options, HighsLogType::kInfo, "readMPS: Read NAME OK\n"); // Load OBJSENSE or ROWS - load_mpsLine(file, integerCol, lmax, line, flag, data); + load_mpsLine(file, integerCol, lmax, line.data(), flag.data(), data.data()); if (flag[0] == 'O') { // Found OBJSENSE - load_mpsLine(file, integerCol, lmax, line, flag, data); + load_mpsLine(file, integerCol, lmax, line.data(), flag.data(), data.data()); std::string sense(&line[2], &line[2] + 3); // the sense must be "MAX" or "MIN" if (sense.compare("MAX") == 0) { @@ -105,7 +105,7 @@ FilereaderRetcode readMps( highsLogDev(log_options, HighsLogType::kInfo, "readMPS: Read OBJSENSE OK\n"); // Load ROWS - load_mpsLine(file, integerCol, lmax, line, flag, data); + load_mpsLine(file, integerCol, lmax, line.data(), flag.data(), data.data()); } row_names.clear(); @@ -113,7 +113,8 @@ FilereaderRetcode readMps( vector rowType; map rowIndex; double objName = 0; - while (load_mpsLine(file, integerCol, lmax, line, flag, data)) { + while (load_mpsLine(file, integerCol, lmax, line.data(), flag.data(), + data.data())) { if (flag[0] == 'N' && (objName == 0 || keep_n_rows == kKeepNRowsDeleteRows)) { // N-row: take the first as the objective and possibly ignore any others @@ -149,7 +150,8 @@ FilereaderRetcode readMps( // line - field 5 non-empty. save_flag1 is used to deduce whether // the row name and value are from fields 5 and 6, or 3 and 4 HighsInt save_flag1 = 0; - while (load_mpsLine(file, integerCol, lmax, line, flag, data)) { + while (load_mpsLine(file, integerCol, lmax, line.data(), flag.data(), + data.data())) { HighsInt iRow = rowIndex[data[2]] - 1; std::string name = ""; if (iRow >= 0) name = row_names[iRow]; @@ -218,7 +220,8 @@ FilereaderRetcode readMps( num_alien_entries = 0; vector RHS(numRow, 0); save_flag1 = 0; - while (load_mpsLine(file, integerCol, lmax, line, flag, data)) { + while (load_mpsLine(file, integerCol, lmax, line.data(), flag.data(), + data.data())) { if (data[2] != objName) { HighsInt iRow = rowIndex[data[2]] - 1; if (iRow >= 0) { @@ -268,7 +271,8 @@ FilereaderRetcode readMps( rowUpper.resize(numRow); if (flag[0] == 'R') { save_flag1 = 0; - while (load_mpsLine(file, integerCol, lmax, line, flag, data)) { + while (load_mpsLine(file, integerCol, lmax, line.data(), flag.data(), + data.data())) { HighsInt iRow = rowIndex[data[2]] - 1; if (iRow >= 0) { if (rowType[iRow] == 'L' || (rowType[iRow] == 'E' && data[0] < 0)) { @@ -338,7 +342,8 @@ FilereaderRetcode readMps( colLower.assign(numCol, 0); colUpper.assign(numCol, kHighsInf); if (flag[0] == 'B') { - while (load_mpsLine(file, integerCol, lmax, line, flag, data)) { + while (load_mpsLine(file, integerCol, lmax, line.data(), flag.data(), + data.data())) { // Find the column index associated with the name "data[2]". If // the name is in colIndex then the value stored is the true // column index plus one. Otherwise 0 will be returned. @@ -389,7 +394,8 @@ FilereaderRetcode readMps( HighsInt previous_col = -1; bool has_diagonal = false; Qstart.clear(); - while (load_mpsLine(file, integerCol, lmax, line, flag, data)) { + while (load_mpsLine(file, integerCol, lmax, line.data(), flag.data(), + data.data())) { HighsInt iCol0 = colIndex[data[1]] - 1; std::string name0 = ""; if (iCol0 >= 0) name0 = col_names[iCol0]; diff --git a/src/io/HighsIO.cpp b/src/io/HighsIO.cpp index b32b5758a5..c1e8ad4195 100644 --- a/src/io/HighsIO.cpp +++ b/src/io/HighsIO.cpp @@ -131,27 +131,31 @@ void highsLogUser(const HighsLogOptions& log_options_, const HighsLogType type, if (flush_streams) fflush(stdout); } } else { - int len = 0; - char msgbuffer[kIoBufferSize] = {}; - if (prefix) - len = snprintf(msgbuffer, sizeof(msgbuffer), "%-9s", - HighsLogTypeTag[(int)type]); - if (len < (int)sizeof(msgbuffer)) - len += - vsnprintf(msgbuffer + len, sizeof(msgbuffer) - len, format, argptr); - if (len >= (int)sizeof(msgbuffer)) { - // Output was truncated: for now just ensure string is null-terminated - msgbuffer[sizeof(msgbuffer) - 1] = '\0'; + size_t len = 0; + std::array msgbuffer = {}; + if (prefix) { + int l = snprintf(msgbuffer.data(), msgbuffer.size(), "%-9s", + HighsLogTypeTag[(int)type]); + // assert that there are no encoding errors + assert(l >= 0); + len = static_cast(l); + } + if (len < msgbuffer.size()) { + int l = vsnprintf(msgbuffer.data() + len, msgbuffer.size() - len, format, + argptr); + // assert that there are no encoding errors + assert(l >= 0); + len += static_cast(l); } if (log_options_.user_log_callback) { - log_options_.user_log_callback(type, msgbuffer, + log_options_.user_log_callback(type, msgbuffer.data(), log_options_.user_log_callback_data); } if (log_options_.user_callback_active) { assert(log_options_.user_callback); HighsCallbackDataOut data_out; data_out.log_type = int(type); - log_options_.user_callback(kCallbackLogging, msgbuffer, &data_out, + log_options_.user_callback(kCallbackLogging, msgbuffer.data(), &data_out, nullptr, log_options_.user_callback_data); } } @@ -199,21 +203,18 @@ void highsLogDev(const HighsLogOptions& log_options_, const HighsLogType type, if (flush_streams) fflush(stdout); } } else { - int len; - char msgbuffer[kIoBufferSize] = {}; - len = vsnprintf(msgbuffer, sizeof(msgbuffer), format, argptr); - if (len >= (int)sizeof(msgbuffer)) { - // Output was truncated: for now just ensure string is null-terminated - msgbuffer[sizeof(msgbuffer) - 1] = '\0'; - } + std::array msgbuffer = {}; + int len = vsnprintf(msgbuffer.data(), msgbuffer.size(), format, argptr); + // assert that there are no encoding errors + assert(len >= 0); if (log_options_.user_log_callback) { - log_options_.user_log_callback(type, msgbuffer, + log_options_.user_log_callback(type, msgbuffer.data(), log_options_.user_log_callback_data); } else if (log_options_.user_callback_active) { assert(log_options_.user_callback); HighsCallbackDataOut data_out; data_out.log_type = int(type); - log_options_.user_callback(kCallbackLogging, msgbuffer, &data_out, + log_options_.user_callback(kCallbackLogging, msgbuffer.data(), &data_out, nullptr, log_options_.user_callback_data); } } @@ -261,16 +262,12 @@ void highsReportLogOptions(const HighsLogOptions& log_options_) { std::string highsFormatToString(const char* format, ...) { va_list argptr; va_start(argptr, format); - int len; - char msgbuffer[kIoBufferSize] = {}; - len = vsnprintf(msgbuffer, sizeof(msgbuffer), format, argptr); - - if (len >= (int)sizeof(msgbuffer)) { - // Output was truncated: for now just ensure string is null-terminated - msgbuffer[sizeof(msgbuffer) - 1] = '\0'; - } + std::array msgbuffer = {}; + int len = vsnprintf(msgbuffer.data(), msgbuffer.size(), format, argptr); + // assert that there are no encoding errors + assert(len >= 0); va_end(argptr); - return std::string(msgbuffer); + return std::string(msgbuffer.data()); } const std::string highsBoolToString(const bool b, const HighsInt field_width) { diff --git a/src/io/HighsIO.h b/src/io/HighsIO.h index b63d47141f..52bf156ff6 100644 --- a/src/io/HighsIO.h +++ b/src/io/HighsIO.h @@ -18,7 +18,7 @@ #include #include "lp_data/HighsCallback.h" -//#include "util/HighsInt.h" +// #include "util/HighsInt.h" class HighsOptions; diff --git a/src/mip/HighsDomain.cpp b/src/mip/HighsDomain.cpp index eb38717812..3fb1950e79 100644 --- a/src/mip/HighsDomain.cpp +++ b/src/mip/HighsDomain.cpp @@ -180,7 +180,7 @@ void HighsDomain::ConflictPoolPropagation::conflictAdded(HighsInt conflict) { } switch (numWatched) { case 0: { - std::pair latestActive[2]; + std::array, 2> latestActive; HighsInt numActive = 0; for (HighsInt i = start; i != end; ++i) { HighsInt pos = conflictEntries[i].boundtype == HighsBoundType::kLower @@ -276,7 +276,7 @@ void HighsDomain::ConflictPoolPropagation::updateActivityUbChange( HighsInt conflict = i >> 1; const HighsDomainChange& domchg = watchedLiterals_[i].domchg; - HighsInt numInactiveDelta = + uint8_t numInactiveDelta = (domchg.boundval < newbound) - (domchg.boundval < oldbound); if (numInactiveDelta != 0) { conflictFlag_[conflict] += numInactiveDelta; @@ -306,7 +306,7 @@ void HighsDomain::ConflictPoolPropagation::propagateConflict( WatchedLiteral* watched = watchedLiterals_.data() + 2 * conflict; - HighsInt inactive[2]; + std::array inactive; HighsInt numInactive = 0; for (HighsInt i = start; i != end; ++i) { if (domain->isActive(entries[i])) continue; diff --git a/src/mip/HighsGFkSolve.h b/src/mip/HighsGFkSolve.h index 75519459de..d483d3bfda 100644 --- a/src/mip/HighsGFkSolve.h +++ b/src/mip/HighsGFkSolve.h @@ -317,7 +317,7 @@ class HighsGFkSolve { // check if a solution exists by scanning the linearly dependent rows for // nonzero right hand sides - bool hasSolution[kNumRhs]; + std::array hasSolution; HighsInt numRhsWithSolution = 0; for (int rhsIndex = 0; rhsIndex < kNumRhs; ++rhsIndex) { hasSolution[rhsIndex] = true; @@ -341,7 +341,7 @@ class HighsGFkSolve { // now iterate a subset of the basic solutions. // When a column leaves the basis we do not allow it to enter again so that // we iterate at most one solution for each nonbasic column - std::vector solution[kNumRhs]; + std::array, kNumRhs> solution; for (int rhsIndex = 0; rhsIndex < kNumRhs; ++rhsIndex) if (hasSolution[rhsIndex]) solution[rhsIndex].reserve(numCol); @@ -384,7 +384,7 @@ class HighsGFkSolve { for (HighsInt i = numFactorRows - 1; i >= 0; --i) { HighsInt row = factorRowPerm[i]; - unsigned int solval[kNumRhs]; + std::array solval; for (int rhsIndex = 0; rhsIndex < kNumRhs; ++rhsIndex) { if (!hasSolution[rhsIndex]) continue; diff --git a/src/mip/HighsImplications.cpp b/src/mip/HighsImplications.cpp index 2c909d9f0d..e625669c22 100644 --- a/src/mip/HighsImplications.cpp +++ b/src/mip/HighsImplications.cpp @@ -79,7 +79,7 @@ bool HighsImplications::computeImplications(HighsInt col, bool val) { pdqsort(implics.begin(), binstart); - HighsCliqueTable::CliqueVar clique[2]; + std::array clique; clique[0] = HighsCliqueTable::CliqueVar(col, val); for (auto i = binstart; i != implics.end(); ++i) { @@ -88,7 +88,7 @@ bool HighsImplications::computeImplications(HighsInt col, bool val) { else clique[1] = HighsCliqueTable::CliqueVar(i->column, 1); - cliquetable.addClique(mipsolver, clique, 2); + cliquetable.addClique(mipsolver, clique.data(), 2); if (globaldomain.infeasible() || globaldomain.isFixed(col)) return true; } @@ -519,8 +519,8 @@ void HighsImplications::separateImpliedBounds( HighsCutPool& cutpool, double feastol) { HighsDomain& globaldomain = mipsolver.mipdata_->domain; - HighsInt inds[2]; - double vals[2]; + std::array inds; + std::array vals; double rhs; HighsInt numboundchgs = 0; @@ -586,7 +586,8 @@ void HighsImplications::separateImpliedBounds( if (infeas) { vals[0] = 1.0; inds[0] = col; - cutpool.addCut(mipsolver, inds, vals, 1, 0.0, false, true, false); + cutpool.addCut(mipsolver, inds.data(), vals.data(), 1, 0.0, false, true, + false); continue; } @@ -621,7 +622,7 @@ void HighsImplications::separateImpliedBounds( if (viol > feastol) { // printf("added implied bound cut to pool\n"); - cutpool.addCut(mipsolver, inds, vals, 2, rhs, + cutpool.addCut(mipsolver, inds.data(), vals.data(), 2, rhs, mipsolver.variableType(implics[i].column) != HighsVarType::kContinuous, false, false, false); @@ -637,7 +638,8 @@ void HighsImplications::separateImpliedBounds( if (infeas) { vals[0] = -1.0; inds[0] = col; - cutpool.addCut(mipsolver, inds, vals, 1, -1.0, false, true, false); + cutpool.addCut(mipsolver, inds.data(), vals.data(), 1, -1.0, false, + true, false); continue; } @@ -671,7 +673,7 @@ void HighsImplications::separateImpliedBounds( if (viol > feastol) { // printf("added implied bound cut to pool\n"); - cutpool.addCut(mipsolver, inds, vals, 2, rhs, + cutpool.addCut(mipsolver, inds.data(), vals.data(), 2, rhs, mipsolver.variableType(implics[i].column) != HighsVarType::kContinuous, false, false, false); diff --git a/src/mip/HighsPathSeparator.cpp b/src/mip/HighsPathSeparator.cpp index 83ab962a3d..0989bd098c 100644 --- a/src/mip/HighsPathSeparator.cpp +++ b/src/mip/HighsPathSeparator.cpp @@ -174,7 +174,7 @@ void HighsPathSeparator::separateLpSolution(HighsLpRelaxation& lpRelaxation, HighsInt currentPath[maxPathLen]; std::vector, std::vector>> aggregatedPath; - double scales[2]; + std::array scales; for (HighsInt i = 0; i != lp.num_row_; ++i) { switch (rowtype[i]) { case RowType::kUnusuable: diff --git a/src/parallel/HighsSplitDeque.h b/src/parallel/HighsSplitDeque.h index c4981f14ae..cdf3831953 100644 --- a/src/parallel/HighsSplitDeque.h +++ b/src/parallel/HighsSplitDeque.h @@ -176,7 +176,7 @@ class HighsSplitDeque { static_assert(sizeof(StealerData) <= 64, "sizeof(StealerData) exceeds cache line size"); static_assert(sizeof(WorkerBunkData) <= 64, - "sizeof(GlobalQueueData) exceeds cache line size"); + "sizeof(WorkerBunkData) exceeds cache line size"); alignas(64) OwnerData ownerData; alignas(64) std::atomic splitRequest; diff --git a/src/util/HighsHashTree.h b/src/util/HighsHashTree.h index c42bc271e9..abd9012bde 100644 --- a/src/util/HighsHashTree.h +++ b/src/util/HighsHashTree.h @@ -113,17 +113,20 @@ class HighsHashTree { // to do a linear scan and key comparisons at all Occupation occupation; int size; - uint64_t hashes[capacity() + 1]; - Entry entries[capacity()]; + std::array hashes; + std::array entries; InnerLeaf() : occupation(0), size(0) { hashes[0] = 0; } template InnerLeaf(InnerLeaf&& other) { assert(other.size <= capacity()); - memcpy((void*)this, (void*)&other, - (char*)&other.hashes[other.size + 1] - (char*)&other); - std::move(&other.entries[0], &other.entries[size], &entries[0]); + occupation = other.occupation; + size = other.size; + std::copy(other.hashes.cbegin(), + std::next(other.hashes.cbegin(), size + 1), hashes.begin()); + std::move(other.entries.begin(), std::next(other.entries.begin(), size), + entries.begin()); } int get_num_entries() const { return size; } @@ -190,7 +193,9 @@ class HighsHashTree { --size; if (pos < size) { - std::move(&entries[pos + 1], &entries[size + 1], &entries[pos]); + std::move(std::next(entries.begin(), pos + 1), + std::next(entries.begin(), size + 1), + std::next(entries.begin(), pos)); memmove(&hashes[pos], &hashes[pos + 1], sizeof(hashes[0]) * (size - pos)); if (get_first_chunk16(hashes[startPos]) != hashChunk) @@ -254,7 +259,9 @@ class HighsHashTree { void move_backward(const int& first, const int& last) { // move elements backwards - std::move_backward(&entries[first], &entries[last], &entries[last + 1]); + std::move_backward(std::next(entries.begin(), first), + std::next(entries.begin(), last), + std::next(entries.begin(), last + 1)); memmove(&hashes[first + 1], &hashes[first], sizeof(hashes[0]) * (last - first)); } @@ -836,7 +843,7 @@ class HighsHashTree { hash, hashPos + 1, entry); } else { // there are many collisions, determine the exact sizes first - uint8_t sizes[InnerLeaf<4>::capacity() + 1] = {}; + std::array::capacity() + 1> sizes = {}; sizes[occupation.num_set_until(hashChunk) - 1] += 1; for (int i = 0; i < leaf->size; ++i) { int pos =