Acho as funções matemáticas básicas como pow
, e outras extremamente ineficientes, então decidi implementar minhas próprias versões delas, que são precisas e eficientes exp
. E eu fiz.log
cmath
Eu uso aproximações polinomiais de 9ª ordem no intervalo [1, 2) ou [0, 1) para aproximar as funções, usei numpy.polyfit
para obter os polinômios e apliquei os polinômios usando std::index_sequence
which é incrivelmente rápido e, embora meus métodos não sejam tão precisos quanto os da biblioteca, posso obter pelo menos 13 casas decimais corretas com fp:precise
, e meus métodos fornecem a mesma precisão que o código da biblioteca com fp:fast
.
E agora quero uma função para medir o tempo de execução das funções e determinar a precisão delas.
Anteriormente, eu apenas copiava e colava as mesmas linhas de código para cada nova função que desejo avaliar, e isso não é muito organizado e está sujeito a erros.
Minhas funções são simples, todas retornam um número de ponto flutuante, um valor único, que é float
ou double
. E eles pegam um ou dois argumentos, o segundo argumento é um número, pode ser int
, float
ou double
e seu tipo não faz diferença. O tipo do primeiro argumento é importante, porém, pode ser float
ou double
, seu tipo é igual ao tipo de retorno da função e seu tipo deve corresponder exatamente ao que está declarado na função, porque eu uso std::bit_cast
.
Como exemplo, o seguinte é o que eu criei para medir o tempo de execução de uma função que recebe um único float
parâmetro e retorna a float
:
#include <chrono>
#include <functional>
#include <vector>
using std::chrono::steady_clock;
using std::chrono::duration;
using std::vector;
using std::function;
double timeit(const function<float(float)>& func, const vector<float>& values, int runs = 1048576){
auto start = steady_clock::now();
size_t len = values.size();
for (int64_t i = 0; i < runs; i++) {
func(values[i % len]);
}
auto end = steady_clock::now();
duration<double, std::nano> time = end - start;
return time.count() / runs;
}
Ainda não adicionei a verificação, mas adicionarei mais tarde.
Quero saber como posso reutilizar a mesma função para avaliar uma função que retorna a double
? Eu sei da sobrecarga de funções, mas isso significaria uma função com o mesmo corpo da função, apenas com uma lista de parâmetros diferente. Acho que terei que usar outra função para os dois argumentos, mas não quero usar sobrecarga para funções com um argumento.
Eu sei, std::variant
mas quero comparar os valores e, pelo que sei, não oferece suporte à comparação com tipos constituintes.
Como resolver isso?
Use uma função de modelo, por exemplo,
Ou ainda:
Se necessário, você pode usar SFINAE ou conceitos para restringir o tipo de dados do elemento apenas aos tipos desejados.
Acho que o modelo de função pode funcionar, você também pode usar o conceito (não lembro o nome claramente) para verificar o parâmetro. Na minha opinião, se você precisar adicionar mais tipos de argumento, o modelo de função + conceito será sua melhor escolha .