Skip to content

Instantly share code, notes, and snippets.

@AliceLR
Last active June 30, 2021 08:39
Show Gist options
  • Save AliceLR/42dcea80facac4f5efc76f34a36b8fc3 to your computer and use it in GitHub Desktop.
Save AliceLR/42dcea80facac4f5efc76f34a36b8fc3 to your computer and use it in GitHub Desktop.
#if 0
g++ -O3 -g -Wall -Wextra anticlick.cpp -oanticlick
exit 0
#endif
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <chrono>
#include <vector>
#define EXEC_TIMES 100000
#define BUFFERSIZE 1024
static void get_smpl(int32_t &left, int32_t &right)
{
static int16_t smpl_left = (rand() - (RAND_MAX / 2));
static int16_t smpl_right = (rand() - (RAND_MAX / 2));
if(smpl_left >= -8192 && smpl_left <= 8192)
smpl_left = (int16_t)(60659);
if(smpl_right >= -8192 && smpl_right <= 8192)
smpl_right = (int16_t)(-60659);
left = smpl_left;
right = smpl_right;
}
static void old_algorithm(int32_t *buf, int count)
{
int32_t left, right;
get_smpl(left, right);
int max_x2 = count * count;
while(count--)
{
*buf++ += (count * (left >> 10) / max_x2 * count) << 10;
*buf++ += (count * (right >> 10) / max_x2 * count) << 10;
}
}
static void floating_point(int32_t *buf, int count)
{
int32_t left, right;
get_smpl(left, right);
float max_x2 = (float)count * (float)count;
while(count--)
{
float coef = (float)count * (float)count / max_x2;
*buf++ += (int32_t)(left * coef);
*buf++ += (int32_t)(right * coef);
}
}
static void double_floating_point(int32_t *buf, int count)
{
int32_t left, right;
get_smpl(left, right);
double max_x2 = (double)count * (double)count;
while(count--)
{
double coef = (double)count * (double)count / max_x2;
*buf++ += (int32_t)(left * coef);
*buf++ += (int32_t)(right * coef);
}
}
static void fixed_point(int32_t *buf, int count)
{
int32_t left, right;
get_smpl(left, right);
static constexpr int FPSHIFT = 10;
int tickval = (1 << FPSHIFT) / count;
if(tickval < 1)
tickval = 1;
int tickmul = tickval * count;
#define DO_MULT(x) (tickmul * ((x) >> FPSHIFT))
while((tickmul -= tickval))
{
*buf++ += DO_MULT(DO_MULT(left));
*buf++ += DO_MULT(DO_MULT(right));
}
}
static void fixed_point64(int32_t *buf, int count)
{
int32_t left, right;
get_smpl(left, right);
static constexpr uint64_t FPSHIFT = 20;
int32_t tickval = (1 << FPSHIFT) / count;
if(tickval < 1)
tickval = 1;
int32_t tickmul = tickval * count;
while((tickmul -= tickval))
{
*buf++ += (tickmul * (int64_t)tickmul * (int64_t)(left >> 8)) >> (FPSHIFT * 2 - 8);
*buf++ += (tickmul * (int64_t)tickmul * (int64_t)(right >> 8)) >> (FPSHIFT * 2 - 8);
}
}
static void fixed_point_hybrid(int32_t *buf, int count)
{
int32_t left, right;
get_smpl(left, right);
static constexpr uint32_t FPSHIFT = 24;
int32_t tickval = (1 << FPSHIFT) / count;
if(tickval < 1)
tickval = 1;
int32_t tickmul = tickval * count;
uint32_t tickmul_sq;
while((tickmul -= tickval))
{
/* Truncate to 16-bits of precision so the product is 32-bits. */
tickmul_sq = tickmul >> (FPSHIFT - 16);
tickmul_sq *= tickmul_sq;
*buf++ += (tickmul_sq * (int64_t)left) >> 32;
*buf++ += (tickmul_sq * (int64_t)right) >> 32;
}
}
template<void (*TESTFN)(int32_t *buf, int count)>
__attribute__((noinline))
static void do_test(const char *name, std::vector<int32_t> &buf, const std::vector<int32_t> &compare)
{
auto start_time = std::chrono::steady_clock::now();
for(size_t i = 0; i < EXEC_TIMES; i++)
TESTFN(buf.data(), buf.size() / 2);
auto end_time = std::chrono::steady_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end_time - start_time);
printf("%-25s: %.3f ms\n", name, (double)duration.count() / 1000.0);
// Verify output.
std::vector<int32_t> verify(compare.size());
TESTFN(verify.data(), verify.size() / 2);
FILE *fp = fopen(name, "wb");
fputs("[ ", fp);
// static constexpr int32_t THRESHOLD = (1 << 8);
// size_t errcount = 0;
for(size_t i = 0; i < buf.size(); i += 2)
{
if(i == 0)
fprintf(fp, "[ %6d, %6d ]", verify[i], verify[i+1]);
else
fprintf(fp, ",\n [ %6d, %6d ]", verify[i], verify[i+1]);
/*
// Allow slight error...
int32_t diff = verify[i] - compare[i];
if(diff >= THRESHOLD || diff <= -THRESHOLD)
errcount++;
diff = verify[i+1] - compare[i+1];
if(diff >= THRESHOLD || diff <= -THRESHOLD)
errcount++;
*/
}
// if(errcount)
// printf(" found %zu samples with error of >=%d\n", errcount, THRESHOLD);
fflush(stdout);
fputs(" ];", fp);
fclose(fp);
}
int main()
{
std::vector<int32_t> old_output(BUFFERSIZE * 2);
std::vector<int32_t> buf(BUFFERSIZE * 2);
old_algorithm(old_output.data(), old_output.size() / 2);
do_test<old_algorithm>("Old algorithm", buf, old_output);
do_test<floating_point>("Single precision floats", buf, old_output);
do_test<double_floating_point>("Double precision floats", buf, old_output);
do_test<fixed_point>("Fixed point", buf, old_output);
do_test<fixed_point64>("Fixed point 64-bit", buf, old_output);
do_test<fixed_point_hybrid>("Fixed point hybrid", buf, old_output);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment