shithub: rgbds

Download patch

ref: 425339ccf62192b1666a522099b979ca3963598b
parent: 1a1f1365e66e17610aaf65d73ce974b0fb556396
author: Rangi <[email protected]>
date: Sat Aug 27 08:40:55 EDT 2022

Implement `FMOD` function for fixed-point modulo

Fixes #1021

--- a/include/asm/fixpoint.h
+++ b/include/asm/fixpoint.h
@@ -20,6 +20,7 @@
 int32_t fix_ATan(int32_t i);
 int32_t fix_ATan2(int32_t i, int32_t j);
 int32_t fix_Mul(int32_t i, int32_t j);
+int32_t fix_Mod(int32_t i, int32_t j);
 int32_t fix_Div(int32_t i, int32_t j);
 int32_t fix_Pow(int32_t i, int32_t j);
 int32_t fix_Log(int32_t i, int32_t j);
--- a/man/rgbasm.5
+++ b/man/rgbasm.5
@@ -319,6 +319,7 @@
 .It Sy Name Ta Sy Operation
 .It Fn DIV x y Ta $x \[di] y$
 .It Fn MUL x y Ta $x \[mu] y$
+.It Fn FMOD x y Ta $x % y$
 .It Fn POW x y Ta $x$ to the $y$ power
 .It Fn LOG x y Ta Logarithm of $x$ to the base $y$
 .It Fn ROUND x Ta Round $x$ to the nearest integer
--- a/src/asm/fixpoint.c
+++ b/src/asm/fixpoint.c
@@ -120,6 +120,14 @@
 }
 
 /*
+ * Modulo
+ */
+int32_t fix_Mod(int32_t i, int32_t j)
+{
+	return double2fix(fmod(fix2double(i), fix2double(j)));
+}
+
+/*
  * Power
  */
 int32_t fix_Pow(int32_t i, int32_t j)
--- a/src/asm/lexer.c
+++ b/src/asm/lexer.c
@@ -181,6 +181,7 @@
 	{"FLOOR", T_OP_FLOOR},
 	{"DIV", T_OP_FDIV},
 	{"MUL", T_OP_FMUL},
+	{"FMOD", T_OP_FMOD},
 	{"POW", T_OP_POW},
 	{"LOG", T_OP_LOG},
 	{"SIN", T_OP_SIN},
--- a/src/asm/parser.y
+++ b/src/asm/parser.y
@@ -558,6 +558,7 @@
 %token	T_OP_ASIN "ASIN" T_OP_ACOS "ACOS" T_OP_ATAN "ATAN" T_OP_ATAN2 "ATAN2"
 %token	T_OP_FDIV "FDIV"
 %token	T_OP_FMUL "FMUL"
+%token	T_OP_FMOD "FMOD"
 %token	T_OP_POW "POW"
 %token	T_OP_LOG "LOG"
 %token	T_OP_ROUND "ROUND"
@@ -1487,6 +1488,9 @@
 		}
 		| T_OP_FMUL T_LPAREN const T_COMMA const T_RPAREN {
 			rpn_Number(&$$, fix_Mul($3, $5));
+		}
+		| T_OP_FMOD T_LPAREN const T_COMMA const T_RPAREN {
+			rpn_Number(&$$, fix_Mod($3, $5));
 		}
 		| T_OP_POW T_LPAREN const T_COMMA const T_RPAREN {
 			rpn_Number(&$$, fix_Pow($3, $5));
--- a/test/asm/math.asm
+++ b/test/asm/math.asm
@@ -23,6 +23,10 @@
 	assert MUL(10.0, 0.5) == 5.0
 	assert MUL(10.0, 0.0) == 0.0
 
+	assert FMOD(5.0, 2.0) == 1.0
+	assert FMOD(-5.0, 2.0) == -1.0
+	assert FMOD(-5.0, 0.0) == $8000_0000
+
 	assert POW(10.0, 2.0) == 100.0
 	assert POW(100.0, 0.5) == 10.0