1
0
Fork 0
forked from fun/fun

More math opcode Fun. (0.37.44)

This commit is contained in:
Johannes Findeisen 2026-01-03 04:10:11 +01:00
commit 4a6903e58a
16 changed files with 546 additions and 2 deletions

41
src/vm/math/fmax.c Normal file
View file

@ -0,0 +1,41 @@
/**
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen <you@hanez.org>
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*
* Added: 2026-01-03
*/
/**
* @file fmax.c
* @brief Implements the OP_FMAX opcode using C99 math.h fmax().
* Accepts int or float; follows IEEE-754 NaN handling per fmax.
*/
#include <math.h>
case OP_FMAX: {
Value b = pop_value(vm);
Value a = pop_value(vm);
if (!((a.type == VAL_INT || a.type == VAL_FLOAT) && (b.type == VAL_INT || b.type == VAL_FLOAT))) {
fprintf(stderr, "Runtime type error: FMAX expects numbers, got %s and %s\n",
value_type_name(a.type), value_type_name(b.type));
exit(1);
}
double da = (a.type == VAL_FLOAT) ? a.d : (double)a.i;
double db = (b.type == VAL_FLOAT) ? b.d : (double)b.i;
double r = fmax(da, db);
Value out;
if (!isnan(r) && !isinf(r) && r >= (double)INT64_MIN && r <= (double)INT64_MAX) {
int64_t ii = (int64_t)r;
if ((double)ii == r) out = make_int(ii); else out = make_float(r);
} else {
out = make_float(r);
}
free_value(a); free_value(b);
push_value(vm, out);
break;
}

41
src/vm/math/fmin.c Normal file
View file

@ -0,0 +1,41 @@
/**
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen <you@hanez.org>
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*
* Added: 2026-01-03
*/
/**
* @file fmin.c
* @brief Implements the OP_FMIN opcode using C99 math.h fmin().
* Accepts int or float; follows IEEE-754 NaN handling per fmin.
*/
#include <math.h>
case OP_FMIN: {
Value b = pop_value(vm);
Value a = pop_value(vm);
if (!((a.type == VAL_INT || a.type == VAL_FLOAT) && (b.type == VAL_INT || b.type == VAL_FLOAT))) {
fprintf(stderr, "Runtime type error: FMIN expects numbers, got %s and %s\n",
value_type_name(a.type), value_type_name(b.type));
exit(1);
}
double da = (a.type == VAL_FLOAT) ? a.d : (double)a.i;
double db = (b.type == VAL_FLOAT) ? b.d : (double)b.i;
double r = fmin(da, db);
Value out;
if (!isnan(r) && !isinf(r) && r >= (double)INT64_MIN && r <= (double)INT64_MAX) {
int64_t ii = (int64_t)r;
if ((double)ii == r) out = make_int(ii); else out = make_float(r);
} else {
out = make_float(r);
}
free_value(a); free_value(b);
push_value(vm, out);
break;
}

40
src/vm/math/gcd.c Normal file
View file

@ -0,0 +1,40 @@
/**
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen <you@hanez.org>
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*
* Added: 2026-01-03
*/
/**
* @file gcd.c
* @brief Implements the OP_GCD opcode for greatest common divisor.
*/
case OP_GCD: {
Value vb = pop_value(vm);
Value va = pop_value(vm);
if (!((va.type == VAL_INT) || (va.type == VAL_FLOAT)) ||
!((vb.type == VAL_INT) || (vb.type == VAL_FLOAT))) {
fprintf(stderr, "Runtime type error: GCD expects numbers, got %s and %s\n",
value_type_name(va.type), value_type_name(vb.type));
exit(1);
}
int64_t a = (va.type == VAL_INT) ? va.i : (int64_t)va.d;
int64_t b = (vb.type == VAL_INT) ? vb.i : (int64_t)vb.d;
if (a == INT64_MIN) a = (int64_t)INT64_MAX; else if (a < 0) a = -a;
if (b == INT64_MIN) b = (int64_t)INT64_MAX; else if (b < 0) b = -b;
while (b != 0) {
int64_t t = a % b;
a = b;
b = t;
}
Value res = make_int(a);
free_value(va);
free_value(vb);
push_value(vm, res);
break;
}

47
src/vm/math/isqrt.c Normal file
View file

@ -0,0 +1,47 @@
/**
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen <you@hanez.org>
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*
* Added: 2026-01-03
*/
/**
* @file isqrt.c
* @brief Implements the OP_ISQRT opcode for integer square root (floor).
*/
case OP_ISQRT: {
Value v = pop_value(vm);
if (!((v.type == VAL_INT) || (v.type == VAL_FLOAT))) {
fprintf(stderr, "Runtime type error: ISQRT expects number, got %s\n", value_type_name(v.type));
exit(1);
}
int64_t a = (v.type == VAL_INT) ? v.i : (int64_t)v.d;
if (a <= 0) {
free_value(v);
push_value(vm, make_int(0));
break;
}
/* Binary isqrt inline */
uint64_t n = (uint64_t)a;
uint64_t x = 0;
uint64_t bit = (uint64_t)1 << 62; /* highest even bit set */
while (bit > n) bit >>= 2;
while (bit != 0) {
if (n >= x + bit) {
n -= x + bit;
x = (x >> 1) + bit;
} else {
x >>= 1;
}
bit >>= 2;
}
int64_t r = (int64_t)x;
free_value(v);
push_value(vm, make_int(r));
break;
}

48
src/vm/math/lcm.c Normal file
View file

@ -0,0 +1,48 @@
/**
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen <you@hanez.org>
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*
* Added: 2026-01-03
*/
/**
* @file lcm.c
* @brief Implements the OP_LCM opcode for least common multiple.
*/
case OP_LCM: {
Value vb = pop_value(vm);
Value va = pop_value(vm);
if (!((va.type == VAL_INT) || (va.type == VAL_FLOAT)) ||
!((vb.type == VAL_INT) || (vb.type == VAL_FLOAT))) {
fprintf(stderr, "Runtime type error: LCM expects numbers, got %s and %s\n",
value_type_name(va.type), value_type_name(vb.type));
exit(1);
}
int64_t a = (va.type == VAL_INT) ? va.i : (int64_t)va.d;
int64_t b = (vb.type == VAL_INT) ? vb.i : (int64_t)vb.d;
if (a == INT64_MIN) a = (int64_t)INT64_MAX; else if (a < 0) a = -a;
if (b == INT64_MIN) b = (int64_t)INT64_MAX; else if (b < 0) b = -b;
if (a == 0 || b == 0) {
free_value(va); free_value(vb);
push_value(vm, make_int(0));
break;
}
/* gcd(a,b) */
int64_t x = a, y = b;
while (y != 0) {
int64_t t = x % y; x = y; y = t;
}
int64_t g = x;
/* lcm = (a/g)*b (attempt to reduce overflow) */
int64_t l = (a / g) * b;
Value res = make_int(l);
free_value(va);
free_value(vb);
push_value(vm, res);
break;
}

33
src/vm/math/sign.c Normal file
View file

@ -0,0 +1,33 @@
/**
* This file is part of the Fun programming language.
* https://fun-lang.xyz/
*
* Copyright 2026 Johannes Findeisen <you@hanez.org>
* Licensed under the terms of the Apache-2.0 license.
* https://opensource.org/license/apache-2-0
*
* Added: 2026-01-03
*/
/**
* @file sign.c
* @brief Implements the OP_SIGN opcode returning -1, 0, or 1.
*/
case OP_SIGN: {
Value v = pop_value(vm);
int out = 0;
if (v.type == VAL_INT) {
out = (v.i > 0) - (v.i < 0);
} else if (v.type == VAL_FLOAT) {
if (v.d > 0.0) out = 1;
else if (v.d < 0.0) out = -1;
else out = 0;
} else {
fprintf(stderr, "Runtime type error: SIGN expects number, got %s\n", value_type_name(v.type));
exit(1);
}
free_value(v);
push_value(vm, make_int(out));
break;
}