More math opcode Fun. (0.37.43)
This commit is contained in:
parent
194c06e4aa
commit
c062b685e1
18 changed files with 501 additions and 2 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
cmake_minimum_required(VERSION 3.10)
|
cmake_minimum_required(VERSION 3.10)
|
||||||
project(fun VERSION 0.37.42 LANGUAGES C)
|
project(fun VERSION 0.37.43 LANGUAGES C)
|
||||||
|
|
||||||
set(CMAKE_C_STANDARD 99)
|
set(CMAKE_C_STANDARD 99)
|
||||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||||
|
|
|
||||||
30
examples/math_cos.fun
Normal file
30
examples/math_cos.fun
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
#!/usr/bin/env fun
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Demo of cos(x)
|
||||||
|
|
||||||
|
print("=== math cos demo start ===")
|
||||||
|
|
||||||
|
print("cos(0) -> " + to_string(cos(0)))
|
||||||
|
print("cos(3.14159265359) ~ pi -> " + to_string(cos(3.14159265359)))
|
||||||
|
print("cos(1.57079632679) ~ pi/2 -> " + to_string(cos(1.57079632679)))
|
||||||
|
|
||||||
|
print("=== math cos demo end ===")
|
||||||
|
|
||||||
|
/* Expected output (approximate):
|
||||||
|
=== math cos demo start ===
|
||||||
|
cos(0) -> 1
|
||||||
|
cos(3.14159265359) ~ pi -> -1
|
||||||
|
cos(1.57079632679) ~ pi/2 -> 0
|
||||||
|
=== math cos demo end ===
|
||||||
|
*/
|
||||||
34
examples/math_exp_log.fun
Normal file
34
examples/math_exp_log.fun
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
#!/usr/bin/env fun
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Demo of exp(x), log(x), log10(x)
|
||||||
|
|
||||||
|
print("=== math exp/log demo start ===")
|
||||||
|
|
||||||
|
print("exp(0) -> " + to_string(exp(0)))
|
||||||
|
print("log(1) -> " + to_string(log(1)))
|
||||||
|
print("log10(1) -> " + to_string(log10(1)))
|
||||||
|
print("exp(1) -> " + to_string(exp(1)))
|
||||||
|
print("log(2.71828182846) ~ ln(e) -> " + to_string(log(2.71828182846)))
|
||||||
|
|
||||||
|
print("=== math exp/log demo end ===")
|
||||||
|
|
||||||
|
/* Expected output (approximate):
|
||||||
|
=== math exp/log demo start ===
|
||||||
|
exp(0) -> 1
|
||||||
|
log(1) -> 0
|
||||||
|
log10(1) -> 0
|
||||||
|
exp(1) -> 2.718281828...
|
||||||
|
log(2.71828182846) ~ ln(e) -> 1
|
||||||
|
=== math exp/log demo end ===
|
||||||
|
*/
|
||||||
30
examples/math_sin.fun
Normal file
30
examples/math_sin.fun
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
#!/usr/bin/env fun
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Demo of sin(x)
|
||||||
|
|
||||||
|
print("=== math sin demo start ===")
|
||||||
|
|
||||||
|
print("sin(0) -> " + to_string(sin(0)))
|
||||||
|
print("sin(1.57079632679) ~ pi/2 -> " + to_string(sin(1.57079632679)))
|
||||||
|
print("sin(-1.57079632679) -> " + to_string(sin(-1.57079632679)))
|
||||||
|
|
||||||
|
print("=== math sin demo end ===")
|
||||||
|
|
||||||
|
/* Expected output (approximate):
|
||||||
|
=== math sin demo start ===
|
||||||
|
sin(0) -> 0
|
||||||
|
sin(1.57079632679) ~ pi/2 -> 1
|
||||||
|
sin(-1.57079632679) -> -1
|
||||||
|
=== math sin demo end ===
|
||||||
|
*/
|
||||||
32
examples/math_sqrt.fun
Normal file
32
examples/math_sqrt.fun
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
#!/usr/bin/env fun
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Demo of sqrt(x)
|
||||||
|
|
||||||
|
print("=== math sqrt demo start ===")
|
||||||
|
|
||||||
|
print("sqrt(0) -> " + to_string(sqrt(0)))
|
||||||
|
print("sqrt(9) -> " + to_string(sqrt(9)))
|
||||||
|
print("sqrt(2) -> " + to_string(sqrt(2)))
|
||||||
|
print("sqrt(-1) -> " + to_string(sqrt(-1))) // NaN expected
|
||||||
|
|
||||||
|
print("=== math sqrt demo end ===")
|
||||||
|
|
||||||
|
/* Expected output (approximate):
|
||||||
|
=== math sqrt demo start ===
|
||||||
|
sqrt(0) -> 0
|
||||||
|
sqrt(9) -> 3
|
||||||
|
sqrt(2) -> 1.41421356...
|
||||||
|
sqrt(-1) -> nan
|
||||||
|
=== math sqrt demo end ===
|
||||||
|
*/
|
||||||
28
examples/math_tan.fun
Normal file
28
examples/math_tan.fun
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
#!/usr/bin/env fun
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Demo of tan(x)
|
||||||
|
|
||||||
|
print("=== math tan demo start ===")
|
||||||
|
|
||||||
|
print("tan(0) -> " + to_string(tan(0)))
|
||||||
|
print("tan(0.78539816339) ~ pi/4 -> " + to_string(tan(0.78539816339)))
|
||||||
|
|
||||||
|
print("=== math tan demo end ===")
|
||||||
|
|
||||||
|
/* Expected output (approximate):
|
||||||
|
=== math tan demo start ===
|
||||||
|
tan(0) -> 0
|
||||||
|
tan(0.78539816339) ~ pi/4 -> 1
|
||||||
|
=== math tan demo end ===
|
||||||
|
*/
|
||||||
|
|
@ -193,6 +193,13 @@ static const char *opcode_name(OpCode op) {
|
||||||
case OP_CEIL: return "CEIL";
|
case OP_CEIL: return "CEIL";
|
||||||
case OP_TRUNC: return "TRUNC";
|
case OP_TRUNC: return "TRUNC";
|
||||||
case OP_ROUND: return "ROUND";
|
case OP_ROUND: return "ROUND";
|
||||||
|
case OP_SIN: return "SIN";
|
||||||
|
case OP_COS: return "COS";
|
||||||
|
case OP_TAN: return "TAN";
|
||||||
|
case OP_EXP: return "EXP";
|
||||||
|
case OP_LOG: return "LOG";
|
||||||
|
case OP_LOG10: return "LOG10";
|
||||||
|
case OP_SQRT: return "SQRT";
|
||||||
default: return "???";
|
default: return "???";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -242,7 +242,16 @@ typedef enum {
|
||||||
OP_FLOOR, // pops x (int/float); pushes floor(x) (int if integral else float)
|
OP_FLOOR, // pops x (int/float); pushes floor(x) (int if integral else float)
|
||||||
OP_CEIL, // pops x (int/float); pushes ceil(x) (int if integral else float)
|
OP_CEIL, // pops x (int/float); pushes ceil(x) (int if integral else float)
|
||||||
OP_TRUNC, // pops x (int/float); pushes trunc(x) (int if integral else float)
|
OP_TRUNC, // pops x (int/float); pushes trunc(x) (int if integral else float)
|
||||||
OP_ROUND // pops x (int/float); pushes round(x) (half away from zero)
|
OP_ROUND, // pops x (int/float); pushes round(x) (half away from zero)
|
||||||
|
|
||||||
|
// C99 math.h transcendentals (float-aware)
|
||||||
|
OP_SIN, // pops x (int/float); pushes sin(x)
|
||||||
|
OP_COS, // pops x (int/float); pushes cos(x)
|
||||||
|
OP_TAN, // pops x (int/float); pushes tan(x)
|
||||||
|
OP_EXP, // pops x (int/float); pushes exp(x)
|
||||||
|
OP_LOG, // pops x (int/float); pushes natural log ln(x)
|
||||||
|
OP_LOG10, // pops x (int/float); pushes log10(x)
|
||||||
|
OP_SQRT // pops x (int/float); pushes sqrt(x)
|
||||||
} OpCode;
|
} OpCode;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,9 @@ int main(void) {
|
||||||
int cfn3_2 = bytecode_add_constant(bc, make_float(-3.2));
|
int cfn3_2 = bytecode_add_constant(bc, make_float(-3.2));
|
||||||
int cfn3_5 = bytecode_add_constant(bc, make_float(-3.5));
|
int cfn3_5 = bytecode_add_constant(bc, make_float(-3.5));
|
||||||
int cfn3_8 = bytecode_add_constant(bc, make_float(-3.8));
|
int cfn3_8 = bytecode_add_constant(bc, make_float(-3.8));
|
||||||
|
int cf0 = bytecode_add_constant(bc, make_float(0.0));
|
||||||
|
int cf1 = bytecode_add_constant(bc, make_float(1.0));
|
||||||
|
int c9 = bytecode_add_constant(bc, make_int(9));
|
||||||
|
|
||||||
// ---------- Arithmetic ----------
|
// ---------- Arithmetic ----------
|
||||||
bytecode_add_instruction(bc, OP_LOAD_CONST, c42);
|
bytecode_add_instruction(bc, OP_LOAD_CONST, c42);
|
||||||
|
|
@ -168,6 +171,36 @@ int main(void) {
|
||||||
bytecode_add_instruction(bc, OP_FLOOR, 0);
|
bytecode_add_instruction(bc, OP_FLOOR, 0);
|
||||||
bytecode_add_instruction(bc, OP_PRINT, 0);
|
bytecode_add_instruction(bc, OP_PRINT, 0);
|
||||||
|
|
||||||
|
// ---------- Transcendentals demo ----------
|
||||||
|
// sin(0)=0
|
||||||
|
bytecode_add_instruction(bc, OP_LOAD_CONST, cf0);
|
||||||
|
bytecode_add_instruction(bc, OP_SIN, 0);
|
||||||
|
bytecode_add_instruction(bc, OP_PRINT, 0);
|
||||||
|
// cos(0)=1
|
||||||
|
bytecode_add_instruction(bc, OP_LOAD_CONST, cf0);
|
||||||
|
bytecode_add_instruction(bc, OP_COS, 0);
|
||||||
|
bytecode_add_instruction(bc, OP_PRINT, 0);
|
||||||
|
// tan(0)=0
|
||||||
|
bytecode_add_instruction(bc, OP_LOAD_CONST, cf0);
|
||||||
|
bytecode_add_instruction(bc, OP_TAN, 0);
|
||||||
|
bytecode_add_instruction(bc, OP_PRINT, 0);
|
||||||
|
// exp(0)=1
|
||||||
|
bytecode_add_instruction(bc, OP_LOAD_CONST, cf0);
|
||||||
|
bytecode_add_instruction(bc, OP_EXP, 0);
|
||||||
|
bytecode_add_instruction(bc, OP_PRINT, 0);
|
||||||
|
// log(1)=0
|
||||||
|
bytecode_add_instruction(bc, OP_LOAD_CONST, cf1);
|
||||||
|
bytecode_add_instruction(bc, OP_LOG, 0);
|
||||||
|
bytecode_add_instruction(bc, OP_PRINT, 0);
|
||||||
|
// log10(1)=0
|
||||||
|
bytecode_add_instruction(bc, OP_LOAD_CONST, cf1);
|
||||||
|
bytecode_add_instruction(bc, OP_LOG10, 0);
|
||||||
|
bytecode_add_instruction(bc, OP_PRINT, 0);
|
||||||
|
// sqrt(9)=3
|
||||||
|
bytecode_add_instruction(bc, OP_LOAD_CONST, c9);
|
||||||
|
bytecode_add_instruction(bc, OP_SQRT, 0);
|
||||||
|
bytecode_add_instruction(bc, OP_PRINT, 0);
|
||||||
|
|
||||||
// ---------- HALT ----------
|
// ---------- HALT ----------
|
||||||
bytecode_add_instruction(bc, OP_HALT, 0);
|
bytecode_add_instruction(bc, OP_HALT, 0);
|
||||||
|
|
||||||
|
|
|
||||||
49
src/parser.c
49
src/parser.c
|
|
@ -1786,6 +1786,55 @@ static int emit_primary(Bytecode *bc, const char *src, size_t len, size_t *pos)
|
||||||
free(name);
|
free(name);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
if (strcmp(name, "sin") == 0) {
|
||||||
|
(*pos)++; /* '(' */
|
||||||
|
if (!emit_expression(bc, src, len, pos) || !consume_char(src, len, pos, ')')) { parser_fail(*pos, "sin expects 1 arg"); free(name); return 0; }
|
||||||
|
bytecode_add_instruction(bc, OP_SIN, 0);
|
||||||
|
free(name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (strcmp(name, "cos") == 0) {
|
||||||
|
(*pos)++; /* '(' */
|
||||||
|
if (!emit_expression(bc, src, len, pos) || !consume_char(src, len, pos, ')')) { parser_fail(*pos, "cos expects 1 arg"); free(name); return 0; }
|
||||||
|
bytecode_add_instruction(bc, OP_COS, 0);
|
||||||
|
free(name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (strcmp(name, "tan") == 0) {
|
||||||
|
(*pos)++; /* '(' */
|
||||||
|
if (!emit_expression(bc, src, len, pos) || !consume_char(src, len, pos, ')')) { parser_fail(*pos, "tan expects 1 arg"); free(name); return 0; }
|
||||||
|
bytecode_add_instruction(bc, OP_TAN, 0);
|
||||||
|
free(name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (strcmp(name, "exp") == 0) {
|
||||||
|
(*pos)++; /* '(' */
|
||||||
|
if (!emit_expression(bc, src, len, pos) || !consume_char(src, len, pos, ')')) { parser_fail(*pos, "exp expects 1 arg"); free(name); return 0; }
|
||||||
|
bytecode_add_instruction(bc, OP_EXP, 0);
|
||||||
|
free(name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (strcmp(name, "log") == 0) {
|
||||||
|
(*pos)++; /* '(' */
|
||||||
|
if (!emit_expression(bc, src, len, pos) || !consume_char(src, len, pos, ')')) { parser_fail(*pos, "log expects 1 arg"); free(name); return 0; }
|
||||||
|
bytecode_add_instruction(bc, OP_LOG, 0);
|
||||||
|
free(name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (strcmp(name, "log10") == 0) {
|
||||||
|
(*pos)++; /* '(' */
|
||||||
|
if (!emit_expression(bc, src, len, pos) || !consume_char(src, len, pos, ')')) { parser_fail(*pos, "log10 expects 1 arg"); free(name); return 0; }
|
||||||
|
bytecode_add_instruction(bc, OP_LOG10, 0);
|
||||||
|
free(name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (strcmp(name, "sqrt") == 0) {
|
||||||
|
(*pos)++; /* '(' */
|
||||||
|
if (!emit_expression(bc, src, len, pos) || !consume_char(src, len, pos, ')')) { parser_fail(*pos, "sqrt expects 1 arg"); free(name); return 0; }
|
||||||
|
bytecode_add_instruction(bc, OP_SQRT, 0);
|
||||||
|
free(name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
if (strcmp(name, "pow") == 0) {
|
if (strcmp(name, "pow") == 0) {
|
||||||
(*pos)++; /* '(' */
|
(*pos)++; /* '(' */
|
||||||
if (!emit_expression(bc, src, len, pos) || !consume_char(src, len, pos, ',')) { parser_fail(*pos, "pow expects 2 args"); free(name); return 0; }
|
if (!emit_expression(bc, src, len, pos) || !consume_char(src, len, pos, ',')) { parser_fail(*pos, "pow expects 2 args"); free(name); return 0; }
|
||||||
|
|
|
||||||
7
src/vm.c
7
src/vm.c
|
|
@ -678,6 +678,13 @@ void vm_run(VM *vm, Bytecode *entry) {
|
||||||
#include "vm/math/ceil.c"
|
#include "vm/math/ceil.c"
|
||||||
#include "vm/math/trunc.c"
|
#include "vm/math/trunc.c"
|
||||||
#include "vm/math/round.c"
|
#include "vm/math/round.c"
|
||||||
|
#include "vm/math/sin.c"
|
||||||
|
#include "vm/math/cos.c"
|
||||||
|
#include "vm/math/tan.c"
|
||||||
|
#include "vm/math/exp.c"
|
||||||
|
#include "vm/math/log.c"
|
||||||
|
#include "vm/math/log10.c"
|
||||||
|
#include "vm/math/sqrt.c"
|
||||||
#include "vm/math/random_int.c"
|
#include "vm/math/random_int.c"
|
||||||
#include "vm/math/random_seed.c"
|
#include "vm/math/random_seed.c"
|
||||||
|
|
||||||
|
|
|
||||||
31
src/vm/math/cos.c
Normal file
31
src/vm/math/cos.c
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
/**
|
||||||
|
* 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 cos.c
|
||||||
|
* @brief Implements the OP_COS opcode using C99 math.h cos().
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
case OP_COS: {
|
||||||
|
Value v = pop_value(vm);
|
||||||
|
if (v.type == VAL_INT || v.type == VAL_FLOAT) {
|
||||||
|
double x = (v.type == VAL_FLOAT) ? v.d : (double)v.i;
|
||||||
|
double r = cos(x);
|
||||||
|
push_value(vm, make_float(r));
|
||||||
|
free_value(v);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Runtime type error: COS expects number, got %s\n", value_type_name(v.type));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
31
src/vm/math/exp.c
Normal file
31
src/vm/math/exp.c
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
/**
|
||||||
|
* 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 exp.c
|
||||||
|
* @brief Implements the OP_EXP opcode using C99 math.h exp().
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
case OP_EXP: {
|
||||||
|
Value v = pop_value(vm);
|
||||||
|
if (v.type == VAL_INT || v.type == VAL_FLOAT) {
|
||||||
|
double x = (v.type == VAL_FLOAT) ? v.d : (double)v.i;
|
||||||
|
double r = exp(x);
|
||||||
|
push_value(vm, make_float(r));
|
||||||
|
free_value(v);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Runtime type error: EXP expects number, got %s\n", value_type_name(v.type));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
36
src/vm/math/log.c
Normal file
36
src/vm/math/log.c
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
/**
|
||||||
|
* 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 log.c
|
||||||
|
* @brief Implements the OP_LOG opcode using C99 math.h log() (natural logarithm).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
case OP_LOG: {
|
||||||
|
Value v = pop_value(vm);
|
||||||
|
if (v.type == VAL_INT || v.type == VAL_FLOAT) {
|
||||||
|
double x = (v.type == VAL_FLOAT) ? v.d : (double)v.i;
|
||||||
|
if (x <= 0.0) {
|
||||||
|
/* Domain error: return NaN to signal invalid input */
|
||||||
|
push_value(vm, make_float(NAN));
|
||||||
|
} else {
|
||||||
|
double r = log(x);
|
||||||
|
push_value(vm, make_float(r));
|
||||||
|
}
|
||||||
|
free_value(v);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Runtime type error: LOG expects number, got %s\n", value_type_name(v.type));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
35
src/vm/math/log10.c
Normal file
35
src/vm/math/log10.c
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
/**
|
||||||
|
* 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 log10.c
|
||||||
|
* @brief Implements the OP_LOG10 opcode using C99 math.h log10().
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
case OP_LOG10: {
|
||||||
|
Value v = pop_value(vm);
|
||||||
|
if (v.type == VAL_INT || v.type == VAL_FLOAT) {
|
||||||
|
double x = (v.type == VAL_FLOAT) ? v.d : (double)v.i;
|
||||||
|
if (x <= 0.0) {
|
||||||
|
push_value(vm, make_float(NAN));
|
||||||
|
} else {
|
||||||
|
double r = log10(x);
|
||||||
|
push_value(vm, make_float(r));
|
||||||
|
}
|
||||||
|
free_value(v);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Runtime type error: LOG10 expects number, got %s\n", value_type_name(v.type));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
31
src/vm/math/sin.c
Normal file
31
src/vm/math/sin.c
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
/**
|
||||||
|
* 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 sin.c
|
||||||
|
* @brief Implements the OP_SIN opcode using C99 math.h sin().
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
case OP_SIN: {
|
||||||
|
Value v = pop_value(vm);
|
||||||
|
if (v.type == VAL_INT || v.type == VAL_FLOAT) {
|
||||||
|
double x = (v.type == VAL_FLOAT) ? v.d : (double)v.i;
|
||||||
|
double r = sin(x);
|
||||||
|
push_value(vm, make_float(r));
|
||||||
|
free_value(v);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Runtime type error: SIN expects number, got %s\n", value_type_name(v.type));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
45
src/vm/math/sqrt.c
Normal file
45
src/vm/math/sqrt.c
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
/**
|
||||||
|
* 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 sqrt.c
|
||||||
|
* @brief Implements the OP_SQRT opcode using C99 math.h sqrt().
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
case OP_SQRT: {
|
||||||
|
Value v = pop_value(vm);
|
||||||
|
if (v.type == VAL_INT || v.type == VAL_FLOAT) {
|
||||||
|
double x = (v.type == VAL_FLOAT) ? v.d : (double)v.i;
|
||||||
|
if (x < 0.0) {
|
||||||
|
push_value(vm, make_float(NAN));
|
||||||
|
} else {
|
||||||
|
double r = sqrt(x);
|
||||||
|
/* preserve int if exactly integral */
|
||||||
|
if (r >= (double)INT64_MIN && r <= (double)INT64_MAX) {
|
||||||
|
int64_t ii = (int64_t)r;
|
||||||
|
if ((double)ii == r) {
|
||||||
|
push_value(vm, make_int(ii));
|
||||||
|
} else {
|
||||||
|
push_value(vm, make_float(r));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
push_value(vm, make_float(r));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free_value(v);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Runtime type error: SQRT expects number, got %s\n", value_type_name(v.type));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
31
src/vm/math/tan.c
Normal file
31
src/vm/math/tan.c
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
/**
|
||||||
|
* 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 tan.c
|
||||||
|
* @brief Implements the OP_TAN opcode using C99 math.h tan().
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
case OP_TAN: {
|
||||||
|
Value v = pop_value(vm);
|
||||||
|
if (v.type == VAL_INT || v.type == VAL_FLOAT) {
|
||||||
|
double x = (v.type == VAL_FLOAT) ? v.d : (double)v.i;
|
||||||
|
double r = tan(x);
|
||||||
|
push_value(vm, make_float(r));
|
||||||
|
free_value(v);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Runtime type error: TAN expects number, got %s\n", value_type_name(v.type));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue