init: initial commit

This commit is contained in:
2024-11-21 22:22:14 +01:00
commit b5868dfdec
8 changed files with 467 additions and 0 deletions

51
include/screen.hpp Normal file
View File

@@ -0,0 +1,51 @@
#pragma once
#include <cstddef>
#include <cstdlib>
#include <cstdio>
#include <unistd.h>
#include <termios.h>
struct Screen {
char *buf;
std::size_t w, h;
float dx = 0, dy = 0;
float sx = 1, sy = 1;
void draw();
void clear();
char &at(std::size_t n);
char &at(std::size_t x, std::size_t y);
void resize(std::size_t n);
void resize(std::size_t x, std::size_t y);
Screen(std::size_t n) : buf(nullptr) { resize(n); }
Screen(std::size_t x, std::size_t y) : buf(nullptr) { resize(x, y); }
~Screen() { delete[] buf; }
private:
char _dummy;
static inline void gotoxy(int x, int y)
{
std::printf("\033[%d;%dH", y, x);
}
};
static termios old, current;
static inline void enter_noncanonical_mode(void)
{
tcgetattr(STDIN_FILENO, &old);
current = old;
current.c_lflag &= ~ICANON; /* disable buffered i/o */
current.c_lflag &= ~ECHO; /* set no echo mode */
current.c_cc[VMIN] = 0;/* no wait */
current.c_cc[VTIME] = 0;/* no wait */
tcsetattr(STDIN_FILENO, TCSANOW, &current);
}
static inline void enter_canonical_mode(void){ tcsetattr(0, TCSANOW, &old); }

111
include/swarm.hpp Normal file
View File

@@ -0,0 +1,111 @@
#pragma once
#include <cstddef>
#include <functional>
#include <utility>
#include <vec.hpp>
#include <vector>
template<typename T>
struct Agent {
using F = std::function<float(T)>;
virtual void move(float dt) = 0;
virtual void step(float dt) = 0;
virtual std::pair<float, T> best() const = 0;
Agent(F f) : f(f) {}
protected:
F f;
};
template<std::size_t N>
struct Particle : public Agent<vec<N>> {
std::pair<float, vec<N>> best() const override { return {pb, pb_pos}; };
void move(float dt=1) override { position = position + velocity * dt; }
void step(float dt=1) override {
velocity = kviscosity * velocity
+ knostalgia * (pb_pos - position)
+ kpeer_pressure * (peer.best().second - position);
float y = f(position);
if(y < pb) {
pb = y;
pb_pos = position;
}
};
float kviscosity = 0.9f;
float knostalgia = 2.5f;
float kpeer_pressure = 0.5f;
Particle(Agent<vec<N>>::F f, const Agent<vec<N>>& peer,
vec<N> position, vec<N> velocity)
: Agent<vec<N>>(f), position(position), velocity(velocity),
pb_pos(position), peer(peer) {
pb = f(position);
}
const vec<N> &get_position() const { return position; };
private:
vec<N> position;
vec<N> velocity;
vec<N> pb_pos;
float pb;
const Agent<vec<N>>& peer;
};
template <std::size_t N>
struct Swarm : public Agent<vec<N>> {
std::pair<float, vec<N>> best() const override { return {best_val, best_pos}; }
void move(float dt=1) override {
for(auto &p : particles)
p.move(dt);
}
void step(float dt=1) override {
if(particles.empty()) return;
// find best before step() on each particle
// otherwise, if this were in best(), each p.step() would update it
const Particle<N> *b = &particles[0];
for(const auto &p : particles) {
if(b->best().first > p.best().first) b = &p;
}
best_val = b->best().first;
best_pos = b->best().second;
for(auto &p : particles)
p.step(dt);
}
void add_particle(std::size_t n=1) {
for(std::size_t i=0; i <= n; ++i)
particles.push_back(
Particle<N>(this->_f, *this, vec<N>(0), vec<N>(10))
);
}
void add_particle(const vec<N> &pos, const vec<N> &vel) {
particles.push_back(
Particle<N>(this->f, *this, pos, vel)
);
}
const std::vector<Particle<N>>& get_particles() { return particles; };
Swarm(Agent<vec<N>>::F f) : Agent<vec<N>>(f) {}
private:
vec<N> best_pos;
float best_val;
std::vector<Particle<N>> particles;
};

153
include/vec.hpp Normal file
View File

@@ -0,0 +1,153 @@
#pragma once
#include <cstddef>
#include <math.h>
#define do_op(o, r, i) \
inline void operator o##= (const r & rhs) { for(unsigned n=0; n<(i); n++) c[n] o##= rhs.c[n]; } \
inline void operator o##= (T d) { for(unsigned n=0; n<(i); n++) c[n] o##= d; } \
inline r operator o (const r & rhs) const { r tmp(*this); tmp o##= rhs; return tmp; } \
inline r operator o (T d) const { r tmp(*this); tmp o##= d; return tmp; }
#define do_ops(c, i) \
do_op(*, c, i); \
do_op(/, c, i); \
do_op(+, c, i); \
do_op(-, c, i);
template <std::size_t n, std::floating_point T = float>
struct vec {
T c[n];
};
template <std::size_t n, std::floating_point T>
vec<n, T> operator*(const T lhs, const vec<n, T>& rhs)
{ return rhs * lhs; }
template<std::floating_point T>
struct vec<2, T> {
union {
T c[2];
struct {
T x, y;
};
};
vec(T x, T y) : c{x,y} {}
vec(T f) : vec(f,f) {}
vec() : vec(0,0) {}
do_ops(vec, 2);
inline vec<2,T> operator-(void) const { return {-x, -y}; }
inline T operator^(const vec<2,T>& rhs) const
{ return x * rhs.x + y * rhs.y; }
/* Return normalised (unit) vector. */
inline vec<2,T> norm() const
{ return *this / len(); }
inline T len() const
{ return sqrtf(x*x + y*y); }
inline T lensquared() const
{ return x*x + y*y; }
/* Return vector reflected around `n'. Expects `this' and `n' to be unit. */
inline vec<2,T> ref(const vec<2,T>& n) const
{ return n * ((*this ^ n) * 2) - *this;}
inline vec<2,T> refract(const vec<2,T>& n, T ior_ratio) const
{
return n * sqrtf(1 - powf(ior_ratio, 2) * (1 - powf(*this ^ n, 2))) + (*this - n * (*this ^ n)) * ior_ratio;
}
inline vec<2,T> refract(const vec<2,T>& n, T ior_incident, T ior_refract) const
{ return refract(n, ior_incident / ior_refract); }
inline vec<2,T> clamp(const vec<2,T>& from, const vec<2,T>& to) const
{ return { fmin(fmax(x, from.x), to.x),
fmin(fmax(y, from.y), to.y) }; }
inline vec<2,T> exp() const
{ return { ::exp(x), ::exp(y) }; }
inline vec<2,T> htan(T exposure = 0) const
{
return { powf((tanh(x + exposure) + 1) / 2, 2.2), powf((tanh(y + exposure) + 1) / 2, 2.2) };
return { tanh(x + exposure), tanh(y + exposure) };
}
};
template<std::floating_point T>
struct vec<3, T> {
union {
T c[3];
struct {
T x, y, z;
};
};
vec(T x, T y, T z) : c{x,y,z} {}
vec(T f) : vec(f,f,f) {}
vec() : vec(0,0,0) {}
do_ops(vec, 3);
inline vec<3,T> operator-(void) const { return {-x, -y, -z}; }
inline T operator^(const vec& rhs) const
{ return x * rhs.x + y * rhs.y + z * rhs.z; }
/* Return normalised (unit) vector. */
inline vec<3,T> norm() const
{ return *this / len(); }
inline T len() const
{ return sqrtf(x*x + y*y + z*z); }
inline T lensquared() const
{ return x*x + y*y + z*z; }
/* Return vec<3,T>tor reflected around `n'. Expects `this' and `n' to be unit. */
inline vec<3,T> ref(const vec<3,T>& n) const
{ return n * ((*this ^ n) * 2) - *this;}
/* Cross product. */
inline vec<3,T> cross(const vec<3,T>& b) const
{ return { y*b.z - z*b.y,
x*b.z - z*b.x,
x*b.y - y*b.x }; }
inline vec<3,T> refract(const vec<3,T>& n, T ior_ratio) const
{
return n * sqrtf(1 - powf(ior_ratio, 2) * (1 - powf(*this ^ n, 2))) + (*this - n * (*this ^ n)) * ior_ratio;
}
inline vec<3,T> refract(const vec<3,T>& n, T ior_incident, T ior_refract) const
{ return refract(n, ior_incident / ior_refract); }
inline vec<3,T> clamp(const vec<3,T>& from, const vec<3,T>& to) const
{ return { fmin(fmax(x, from.x), to.x),
fmin(fmax(y, from.y), to.y),
fmin(fmax(z, from.z), to.z) }; }
inline vec<3,T> exp() const
{ return { ::exp(x), ::exp(y), ::exp(z) }; }
inline vec<3,T> htan(T exposure = 0) const
{
return { powf((tanh(x + exposure) + 1) / 2, 2.2), powf((tanh(y + exposure) + 1) / 2, 2.2), powf((tanh(z + exposure) + 1) / 2, 2.2) };
return { tanh(x + exposure), tanh(y + exposure), tanh(z + exposure) };
}
};
#undef do_ops
#undef do_op
#define V3_FMT "v3(%.2f, %.2f, %.2f)"
#define V3_ARG(v) (v).x, (v).y, (v).z
#define V2_FMT "v2(%.2f, %.2f)"
#define V2_ARG(v) (v).x, (v).y