C++ and MATLAB Simulink tips for HWIL simulation software engineers
Wednesday, September 29, 2021
Safety-Critical System Development
Monday, September 27, 2021
Binary string permutations
Previously, I had solved printing all permutations of a string. As part of a programming contest, I solved binary string permutations using C++. What is interesting in this solution is that is uses a simple for loop and obtains each binary permutation by converting a decimal number to a binary number:
//Print all binary string combinations of length n. | |
//You can think of the strings as binary forms of numbers from 0 to 2^n-1. | |
//Solution of https://www.algoleague.com/contest/algorithm-training-beginner-set/problem/the-pit/detail | |
//Şamil Korkmaz, 27.09.2021 | |
#include <iostream> | |
using namespace std; | |
//Convert decimal number to binary number string | |
void dec2binStr(int dec, const int n) { | |
//printf("-------\n"); | |
char s[n+1]; | |
s[n] = 0; //end of line character | |
for(int i=0; i < n; i++) { | |
//printf("dec = %d\n", dec); | |
int digit = dec & 1; //get rightmost digit | |
dec = dec >> 1; //divide by 2 | |
//printf("digit = %d\n", digit); | |
s[n-1-i] = digit + 48; //ascii '0' = 48 | |
//printf("digit = %d\n", digit); | |
} | |
cout << s << endl; | |
} | |
int main() { | |
int n; cin >> n; | |
//int n = 4; | |
int maxVal = 1 << n; //2^n | |
//printf("maxVal = %d\n", maxVal); | |
for(int i = 0; i < maxVal; i++) { //numbers from 0 to 2^n-1 | |
dec2binStr(i, n); | |
//cout << "s = " << s << endl; | |
} | |
return 0; | |
} |
Sunday, September 12, 2021
Hiding internal details of a C++ library
When you need to provide your simulation as an external library (dll, lib) to someone, you should simplify the API as much as possible so that you are able to provide the minimal amount of header files, without exposing details the user doesn't care about. You can achieve this by hiding all the internal dependencies in the implementation (cpp) file. If the user has to be able to create multiple (concurrent) simulations, you can use a static map to hold each simulation object. Here is an example (C++11):
//Blog post: https://simulinkforsoftwareengineers.blogspot.com/2021/09/hiding-simulation-details-in-c-library.html | |
#include "SimAPI.h" | |
#include<map> | |
using namespace std; | |
#include<SimState.h> //this is internal to simulation, which the library user does not need to know | |
#include<Solver.h> //this is internal to simulation | |
class Simulation { | |
public: | |
State state; //State is defined in SimState.h | |
Solver solver; //Solver is defined in Solver.h | |
}; | |
Simulation* sim; | |
static map<int, Simulation*> sims; | |
SimAPI::SimAPI(int simKey) { | |
if (sims.count(simKey) > 0) throw SimKeyAlreadyExistsException(simKey); | |
sim = new Simulation(); | |
sims.insert({ simKey, sim }); | |
} | |
SimAPI::~SimAPI() {} //Note: The desctructor is called right after constructor when this class is used like SimAPI s = SimAPI(...) due to a temp object being created. It is not the case for SimAPI* s = new SimAPI(...). | |
Outputs SimAPI::runOneStep(int simKey, int timeStep_s) { | |
Simulation* pSim = sims[simKey]; | |
State currentState = pSim->state; | |
State newState = pSim->solver(currentState, timeStep_s); | |
pSim->state = newState; //update simulation state | |
Outputs out = Outputs(); | |
out.time_s = newState.time_s; | |
out.hMSL_m = newState.hMSL_m; | |
return out; | |
} | |
void SimAPI::terminate(int simKey) { | |
sims.erase(simKey); | |
} |
#pragma once | |
#include<exception> | |
#include<stdio.h> | |
class SimKeyAlreadyExistsException : public std::exception { | |
public: | |
SimKeyAlreadyExistsException(int simKey) : existingKey(simKey) {} | |
const char* what() const throw() { | |
char message[200]; | |
sprintf_s(message, "simKey (%d) already exists, please enter a unique simKey!\n", existingKey); | |
return message; | |
} | |
int getExistingKey() { | |
return existingKey; | |
} | |
private: | |
int existingKey; | |
}; | |
class Outputs { | |
public: | |
int time_s; | |
double hMSL_m; | |
}; | |
class SimAPI { | |
public: | |
SimAPI(int simIndex); | |
~SimAPI(); | |
Outputs runOneStep(int simIndex, int timeStep_s); | |
void terminate(int simIndex); | |
}; |