From 028c7273f9f9ab5f6dca1ca057d9a47c1b5b6440 Mon Sep 17 00:00:00 2001 From: Maxime Jacquemin <maxime.jacquemin@cea.fr> Date: Wed, 10 Jan 2024 16:20:31 +0100 Subject: [PATCH] [Kernel] Optimizing Nat and Finite Under the hood, it's just int. But only valid nat and finite can be built through the given constructors. --- src/kernel_services/analysis/filter/finite.ml | 40 ++++++------------- src/kernel_services/analysis/filter/nat.ml | 20 ++++------ src/kernel_services/analysis/filter/nat.mli | 2 +- 3 files changed, 21 insertions(+), 41 deletions(-) diff --git a/src/kernel_services/analysis/filter/finite.ml b/src/kernel_services/analysis/filter/finite.ml index 06b52b28a72..0889718c22e 100644 --- a/src/kernel_services/analysis/filter/finite.ml +++ b/src/kernel_services/analysis/filter/finite.ml @@ -23,37 +23,21 @@ open Nat.Types module Types = struct - type 'n formal = First : 'n succ formal | Next : 'n formal -> 'n succ formal - type 'n finite = { value : int ; formal : 'n formal } + type 'n finite = int end open Types -let first = { value = 0 ; formal = First } -let next { value ; formal } = { value = value + 1 ; formal = Next formal } -let to_int { value ; _ } = value -let ( == ) l r = l.value = r.value +let first : type n. n succ finite = 0 +let next : type n. n finite -> n succ finite = fun n -> n + 1 +let weaken : type n. n finite -> n succ finite = fun n -> n +let ( == ) : type n. n finite -> n finite -> bool = fun l r -> l = r +let to_int : type n. n finite -> int = fun n -> n -let rec of_int : type n. n succ nat -> int -> n succ finite = fun limit n -> - match limit with - | Succ Zero -> first - | Succ Succ _ when n <= 0 -> first - | Succ Succ limit -> next (of_int (Succ limit) (n - 1)) +let of_int : type n. n succ nat -> int -> n succ finite = + fun limit n -> min (max 0 n) (Nat.to_int limit) -let rec of_nat : type n. n succ nat -> n succ finite = function - | Succ Zero -> first - | Succ (Succ n) -> next (of_nat (Succ n)) - -(* We use Obj.magic here to avoid the O(n) long but trivial proof *) -let weaken : type n. n finite -> n succ finite = - fun { value ; formal } -> { value ; formal = Obj.magic formal } - -(* Non tail-rec to perform the computation in the natural order *) -let rec fold f n acc = - match n with - | { formal = First ; _ } as n -> f n acc - | { formal = Next formal ; value } as n -> - f n (fold f (weaken { value = value - 1 ; formal }) acc) - -let for_each (type n) acc (n : n nat) (f : n finite -> 'a -> 'a) = - match n with Zero -> acc | Succ _ as n -> fold f (of_nat n) acc +let for_each (type n) acc (limit : n nat) (f : n finite -> 'a -> 'a) = + let acc = ref acc in + for i = 0 to Nat.to_int limit - 1 do acc := f i !acc done ; + !acc diff --git a/src/kernel_services/analysis/filter/nat.ml b/src/kernel_services/analysis/filter/nat.ml index 79e401c8ae9..c85a25a5a47 100644 --- a/src/kernel_services/analysis/filter/nat.ml +++ b/src/kernel_services/analysis/filter/nat.ml @@ -23,29 +23,25 @@ module Types = struct type zero = | type 'n succ = | - type 'n nat = Zero : zero nat | Succ : 'n nat -> 'n succ nat + type 'n nat = int type positive_or_null = PositiveOrNull : 'n nat -> positive_or_null type strictly_positive = StrictlyPositive : 'n succ nat -> strictly_positive end open Types -let zero = Zero -let one = Succ Zero -let succ n = (Succ n) -let prev (Succ n) = n - -let to_int n = - let rec aux : type n. int -> n nat -> int = fun acc -> - function Zero -> acc | Succ n -> aux (acc + 1) n - in aux 0 n +let zero : zero nat = 0 +let one : zero succ nat = 1 +let succ : type n. n nat -> n succ nat = fun n -> n + 1 +let prev : type n. n succ nat -> n nat = fun n -> n - 1 +let to_int : type n. n nat -> int = fun n -> n let of_int n = - let next (PositiveOrNull n) = PositiveOrNull (Succ n) in + let next (PositiveOrNull n) = PositiveOrNull (succ n) in let rec aux acc n = if n <= 0 then acc else aux (next acc) (n - 1) in aux (PositiveOrNull zero) n let of_strictly_positive_int n = - let next (StrictlyPositive n) = StrictlyPositive (Succ n) in + let next (StrictlyPositive n) = StrictlyPositive (succ n) in let rec aux acc n = if n <= 1 then acc else aux (next acc) (n - 1) in aux (StrictlyPositive one) n diff --git a/src/kernel_services/analysis/filter/nat.mli b/src/kernel_services/analysis/filter/nat.mli index 38b41ab0918..4fbc1a1b7c1 100644 --- a/src/kernel_services/analysis/filter/nat.mli +++ b/src/kernel_services/analysis/filter/nat.mli @@ -23,7 +23,7 @@ module Types : sig type zero = | type 'n succ = | - type 'n nat = Zero : zero nat | Succ : 'n nat -> 'n succ nat + type 'n nat type positive_or_null = PositiveOrNull : 'n nat -> positive_or_null type strictly_positive = StrictlyPositive : 'n succ nat -> strictly_positive end -- GitLab