This commit is contained in:
Charlotte 🦝 Delenk 2023-02-23 14:57:36 +01:00
parent cc1cee0045
commit 1f8595e2c8
3 changed files with 263 additions and 94 deletions

BIN
a.out

Binary file not shown.

View file

@ -25,6 +25,12 @@
#define LEADER_NO_TIMEOUT
#define DOUBLE_TAP_SHIFT_TURNS_ON_CAPS_WORD
// Required for calculator
#ifdef PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS
# undef PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS
# define PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS 1
#endif
/*
* Feature disable options
* These options are also useful to firmware size reduction.

View file

@ -3,6 +3,7 @@
#include <quantum.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
struct StackElement {
double x;
@ -34,9 +35,9 @@ static void pushNoPrint(double x, int ent_len) {
static void push(double x) {
char buf[32];
memset(buf, 0, sizeof(buf));
int real_length = snprintf(buf, sizeof(buf), "%f", x);
int real_length = snprintf(buf, sizeof(buf), "%.16g", x);
send_unicode_string(buf);
tap_code(KC_SPACE);
send_unicode_string(" ");
pushNoPrint(x, real_length);
}
@ -53,12 +54,20 @@ static int pop_(double *x, int *ent_len) {
return 1;
}
static void backspace(void) {
tap_code(KC_BACKSPACE);
}
static void backspace_n(int n) {
for (int i = 0; i < n; i++) {
backspace();
}
}
static int pop(double *x) {
int ent_len;
if (pop_(x, &ent_len)) {
while (ent_len--) {
tap_code(KC_BACKSPACE);
}
backspace_n(ent_len + 1);
return 1;
}
return 0;
@ -137,8 +146,9 @@ static char enabled = 0;
#define def_primop(name, op) \
static void run_##name(void) { \
double a, b; \
if (!pop(&a)) return; \
backspace(); \
if (!pop(&b)) return; \
if (!pop(&a)) return; \
push(a op b); \
}
@ -146,7 +156,16 @@ def_primop(add, +);
def_primop(sub, -);
def_primop(mul, *);
def_primop(div, /);
/*
static void run_swap(void) {
double a, b;
backspace();
if (!pop(&b)) return;
if (!pop(&a)) return;
push(a);
push(b);
}
#define def_unop(name) \
static void run_##name(void) { \
double a; \
@ -157,25 +176,41 @@ def_primop(div, /);
#define def_binop(name) \
static void run_##name(void) { \
double a, b; \
if (!pop(&a)) return; \
if (!pop(&b)) return; \
if (!pop(&a)) return; \
push((name)(a, b)); \
}
def_unop(cos);
def_unop(sin);
def_unop(tan);
def_unop(acos);
def_unop(acosh);
def_unop(asin);
def_unop(asinh);
def_unop(atan);
def_binop(atan2);
def_unop(cosh);
def_unop(sinh);
def_unop(tanh);
def_unop(acosh);
def_unop(asinh);
def_unop(atanh);
def_unop(cbrt);
def_unop(ceil);
def_binop(copysign);
def_unop(cos);
def_unop(cosh);
def_unop(erf);
def_unop(erfc);
def_unop(exp);
def_unop(exp2);
def_unop(expm1);
def_unop(fabs);
def_binop(fdim);
def_unop(floor);
static void run_fma(void) {
double a, b, c;
if (!pop(&c)) return;
if (!pop(&b)) return;
if (!pop(&a)) return;
push(fma(a, b, c));
}
def_binop(fmax);
def_binop(fmin);
def_binop(fmod);
static void run_frexp(void) {
double a;
int b;
@ -184,50 +219,26 @@ static void run_frexp(void) {
push(a);
push(b);
}
def_binop(hypot);
def_unop(ilogb);
def_binop(ldexp);
def_unop(lgamma);
def_unop(log);
def_unop(log10);
static void modf(void) {
def_unop(log1p);
def_unop(log2);
def_unop(logb);
static void run_modf(void) {
double a, b;
if (!pop(&a)) return;
a = modf(a, &b);
push(a);
push(b);
}
def_unop(exp2);
def_unop(expm1);
def_unop(ilogb);
def_unop(log1p);
def_unop(log2);
def_unop(logb);
static void run_scalbn(void) {
double a, b;
if (!pop(&a)) return;
if (!pop(&b)) return;
push(scalbn(a, (int)b));
}
def_binop(pow);
def_unop(sqrt);
def_unop(cbrt);
def_binop(hypot);
def_unop(erf);
def_unop(erfc);
def_unop(tgamma);
def_unop(lgamma);
def_unop(ceil);
def_unop(floor);
def_binop(fmod);
def_unop(trunc);
def_unop(round);
def_unop(rint);
def_unop(nearbyint);
def_binop(nextafter);
def_binop(pow);
def_binop(remainder);
static void run_remquo(void) {
double a, b;
int c;
@ -237,35 +248,53 @@ static void run_remquo(void) {
push(a);
push(c);
}
def_binop(copysign);
def_binop(nextafter);
def_binop(fdim);
def_binop(fmax);
def_binop(fmin);
def_monop(fabs);
static void run_fma(void) {
double a, b, c;
def_unop(rint);
def_unop(round);
static void run_scalbn(void) {
double a, b;
if (!pop(&a)) return;
if (!pop(&b)) return;
if (!pop(&c)) return;
push(fma(a, b, c));
}*/
push(scalbn(a, (int)b));
}
def_unop(sin);
def_unop(sinh);
def_unop(sqrt);
def_unop(tan);
def_unop(tanh);
def_unop(tgamma);
def_unop(trunc);
void calculator_process_backspace(void) {
double x;
if (number_read_state != NUMBER_READ_STATE_INITIAL) {
finish_number();
}
if (!pop(&x)) {
calculator_disable();
}
#define def_constop(name, constant) \
static void run_##name(void) { \
push(constant); \
}
void calculator_disable(void) {
enabled = 0;
}
def_constop(EPSILON, 2.2204460492503131E-16);
def_constop(MIN, -1.7976931348623157E+308);
def_constop(MIN_POSITIVE, 2.2250738585072014E-308);
def_constop(MAX, 1.7976931348623157E+308);
def_constop(NAN, NAN);
def_constop(INFINITY, INFINITY);
def_constop(NEG_INFINITY, -INFINITY);
def_constop(E, 2.71828182845904523536028747135266250);
def_constop(FRAC_1_PI, 0.318309886183790671537767526745028724);
def_constop(FRAC_1_SQRT_2, 0.707106781186547524400844362104849039);
def_constop(FRAC_2_PI, 0.636619772367581343075535053490057448);
def_constop(FRAC_2_SQRT_PI, 1.12837916709551257389615890312154517);
def_constop(FRAC_PI_2, 1.57079632679489661923132169163975144);
def_constop(FRAC_PI_3, 1.04719755119659774615421446109316763);
def_constop(FRAC_PI_4, 0.785398163397448309615660845819875721);
def_constop(FRAC_PI_6, 0.52359877559829887307710723054658381);
def_constop(FRAC_PI_8, 0.39269908169872415480783042290993786);
def_constop(LN_2, 0.693147180559945309417232121458176568);
def_constop(LN_10, 2.30258509299404568401799145468436421);
def_constop(LOG2_10, 3.32192809488736234787031942948939018);
def_constop(LOG2_E, 1.44269504088896340735992468100189214);
def_constop(LOG10_2, 0.301029995663981195213738894724493027);
def_constop(LOG10_E, 0.434294481903251827651128918916605082);
def_constop(PI, 3.14159265358979323846264338327950288);
def_constop(SQRT_2, 1.41421356237309504880168872420969808);
def_constop(TAU, 6.28318530717958647692528676655900577);
void calculator_enable(void) {
enabled = 1;
@ -275,7 +304,125 @@ int calculator_is_active(void) {
return enabled;
}
static char fn_buf[17];
int fn_pos = 0;
static void reset_fn_buf_state(void) {
memset(fn_buf, 0, sizeof(fn_buf));
fn_pos = 0;
}
void calculator_process_backspace(void) {
double x;
if (number_read_state != NUMBER_READ_STATE_INITIAL) {
finish_number();
}
if (fn_pos > 0) {
backspace_n(fn_pos);
} else if (!pop(&x)) {
calculator_disable();
}
}
void calculator_disable(void) {
double x;
int ent_len;
enabled = 0;
if (number_read_state != NUMBER_READ_STATE_INITIAL) {
finish_number();
}
while (pop_(&x, &ent_len))
;
reset_fn_buf_state();
}
static void try_run_op(void) {
backspace_n(fn_pos + 1);
// Why do kmp when you can do this?
#define CASE(name) else if (strcmp(fn_buf, #name) == 0) run_##name();
if (0) {
}
CASE(acosh)
CASE(acos)
CASE(asinh)
CASE(asin)
CASE(atanh)
CASE(atan2)
CASE(atan)
CASE(cbrt)
CASE(ceil)
CASE(copysign)
CASE(cosh)
CASE(cos)
CASE(erfc)
CASE(erf)
CASE(exp2)
CASE(expm1)
CASE(exp)
CASE(fabs)
CASE(fdim)
CASE(floor)
CASE(fma)
CASE(fmax)
CASE(fmin)
CASE(fmod)
CASE(frexp)
CASE(hypot)
CASE(ilogb)
CASE(ldexp)
CASE(lgamma)
CASE(log10)
CASE(log1p)
CASE(log2)
CASE(logb)
CASE(log)
CASE(modf)
CASE(nearbyint)
CASE(nextafter)
CASE(pow)
CASE(remainder)
CASE(remquo)
CASE(rint)
CASE(round)
CASE(scalbn)
CASE(sinh)
CASE(sin)
CASE(sqrt)
CASE(tanh)
CASE(tan)
CASE(tgamma)
CASE(trunc)
CASE(EPSILON)
CASE(MIN)
CASE(MIN_POSITIVE)
CASE(MAX)
CASE(NAN)
CASE(INFINITY)
CASE(NEG_INFINITY)
CASE(E)
CASE(FRAC_1_PI)
CASE(FRAC_1_SQRT_2)
CASE(FRAC_2_PI)
CASE(FRAC_2_SQRT_PI)
CASE(FRAC_PI_2)
CASE(FRAC_PI_3)
CASE(FRAC_PI_4)
CASE(FRAC_PI_6)
CASE(FRAC_PI_8)
CASE(LN_2)
CASE(LN_10)
CASE(LOG2_10)
CASE(LOG2_E)
CASE(LOG10_2)
CASE(LOG10_E)
CASE(PI)
CASE(SQRT_2)
CASE(TAU)
reset_fn_buf_state();
}
void calculator_process_char(char c) {
if (fn_pos == 0) {
if ((number_read_state != NUMBER_READ_STATE_INITIAL) || (c >= '0' && c <= '9')) {
parse_number(c);
return;
@ -283,7 +430,7 @@ void calculator_process_char(char c) {
switch (c) {
case '+':
run_add();
break;
return;
case '-':
run_sub();
break;
@ -295,5 +442,21 @@ void calculator_process_char(char c) {
case '/':
run_div();
break;
case '%':
run_swap();
break;
}
if (!isalnum(c)) return;
}
if (!isalnum(c)) {
try_run_op();
return;
}
fn_buf[fn_pos++] = c;
if (fn_pos == 16) {
try_run_op();
}
}