floor関数
from マルチサイクル RISC-V CPU を作成したい
floor って to_i と一緒じゃない?と思ったけど、ちょっと違った。
code:ruby
irb(main):001:0> 1.234.floor
=> 1
irb(main):002:0> 1.234.to_i
=> 1
irb(main):003:0> -1.234.to_i
=> -1
irb(main):004:0> -1.234.floor
=> -2
MinCaml で floor 関数を実装した。
code:diff
diff --git a/Makefile b/Makefile
index fbeacbc..43a239b 100644
--- a/Makefile
+++ b/Makefile
@@ -64,7 +64,7 @@ firmware/firmware.hex:
# riscv64-unknown-elf-objcopy -O verilog --verilog-data-width 4 firmware/firmware.elf firmware/firmware.hex
# MinCaml のプログラムをビルド
-FIRMWARE_TARGET = test/sqrt
+FIRMWARE_TARGET = test/floor
firmware/firmware.hex: Makefile firmware/$(FIRMWARE_TARGET).ml firmware/libmincaml.S firmware/stub.S
firmware/bin/min-caml firmware/${FIRMWARE_TARGET}
riscv64-unknown-elf-gcc -nostdlib -march=rv32if -mabi=ilp32f -Wl,-Tfirmware/custom.ld firmware/stub.S firmware/${FIRMWARE_TARGET}.s firmware/libmincaml.S -o firmware/firmware.elf
diff --git a/firmware/libmincaml.S b/firmware/libmincaml.S
index 44b50e4..fb979a9 100644
--- a/firmware/libmincaml.S
+++ b/firmware/libmincaml.S
@@ -449,24 +449,6 @@ min_caml_print_newline:
addi s10, s10, -4
ret
-//---------------------------------------------------------
-// min_caml_sqrt (float -> float)
-//---------------------------------------------------------
- .text
- .globl min_caml_sqrt
-min_caml_sqrt:
- // TODO: あとで実装する
- ret
-
-//---------------------------------------------------------
-// min_caml_floor (float -> float)
-//---------------------------------------------------------
- .text
- .globl min_caml_floor
-min_caml_floor:
- // TODO: あとで実装する
- ret
-
//---------------------------------------------------------
// min_caml_abs_float (float -> float)
//---------------------------------------------------------
diff --git a/firmware/min-rt/min-rt.ml b/firmware/min-rt/min-rt.ml
index 74f8c09..478353b 100644
--- a/firmware/min-rt/min-rt.ml
+++ b/firmware/min-rt/min-rt.ml
@@ -80,6 +80,27 @@ let rec sqrt s =
loop x last_x s
in
+(* floor 関数 *)
+(*
+ floor(0.0) -> 0.0
+ floor(1.0) -> 1.0
+ floor(1.1) -> 1.0
+ floor(1.9) -> 1.0
+ floor(2.1) -> 2.0
+ floor(-1.0) -> -1.0
+ floor(-1.1) -> -2.0
+ floor(-1.9) -> -2.0
+*)
+let rec floor x =
+ if x >= 0.0 then
+ float_of_int (int_of_float x)
+ else
+ if x = float_of_int (int_of_float x) then
+ x
+ else
+ float_of_int (int_of_float (x -. 1.0))
+in
+
(**************** ユーティリティー関数 ****************)
(* データ構造へのアクセス関数 *)
diff --git a/firmware/test/floor.ml b/firmware/test/floor.ml
new file mode 100644
index 0000000..6808115
--- /dev/null
+++ b/firmware/test/floor.ml
@@ -0,0 +1,46 @@
+(* floor関数のテスト *)
+
+(* floor 関数 *)
+(*
+ floor(0.0) -> 0.0
+ floor(1.0) -> 1.0
+ floor(1.1) -> 1.0
+ floor(1.9) -> 1.0
+ floor(2.1) -> 2.0
+ floor(-1.0) -> -1.0
+ floor(-1.1) -> -2.0
+ floor(-1.9) -> -2.0
+*)
+let rec floor x =
+ if x >= 0.0 then
+ float_of_int (int_of_float x)
+ else
+ if x = float_of_int (int_of_float x) then
+ x
+ else
+ float_of_int (int_of_float (x -. 1.0))
+in
+(* floor(0.0) = 0.0 *)
+print_int (int_of_float (floor 0.0 *. 1000.0));
+print_newline ();
+(* floor(1.0) = 1.0 *)
+print_int (int_of_float (floor 1.0 *. 1000.0));
+print_newline ();
+(* floor(1.1) = 1.0 *)
+print_int (int_of_float (floor 1.1 *. 1000.0));
+print_newline ();
+(* floor(1.9) = 1.0 *)
+print_int (int_of_float (floor 1.9 *. 1000.0));
+print_newline ();
+(* floor(2.1) = 2.0 *)
+print_int (int_of_float (floor 2.1 *. 1000.0));
+print_newline ();
+(* floor(-1.0) = -1.0 *)
+print_int (int_of_float (floor (-1.0) *. 1000.0));
+print_newline ();
+(* floor(-1.1) = -2.0 *)
+print_int (int_of_float (floor (-1.1) *. 1000.0));
+print_newline ();
+(* floor(-1.9) = -2.0 *)
+print_int (int_of_float (floor (-1.9) *. 1000.0));
+print_newline ()