X-Git-Url: http://nitlanguage.org diff --git a/lib/core/math.nit b/lib/core/math.nit index 50b36e9..bdd7daa 100644 --- a/lib/core/math.nit +++ b/lib/core/math.nit @@ -67,12 +67,12 @@ redef class Int # Returns the result of a binary AND operation on `self` and `i` # # assert 0x10 & 0x01 == 0 - fun &(i: Int): Int `{ return self & i; `} + fun &(i: Int): Int is intern `{ return self & i; `} # Returns the result of a binary OR operation on `self` and `i` # # assert 0x10 | 0x01 == 0x11 - fun |(i: Int): Int `{ return self | i; `} + fun |(i: Int): Int is intern `{ return self | i; `} # Returns the result of a binary XOR operation on `self` and `i` # @@ -175,7 +175,7 @@ redef class Byte # Returns the result of a binary AND operation on `self` and `i` # # assert 0x10u8 & 0x01u8 == 0u8 - fun &(i: Byte): Byte `{ return self & i; `} + fun &(i: Byte): Byte is intern `{ return self & i; `} # Returns the result of a binary OR operation on `self` and `i` # @@ -333,6 +333,45 @@ redef class Float # assert -0.5.lerp(0.0, 128.0) == -64.0 # ~~~ fun lerp(a, b: Float): Float do return (1.0 - self) * a + self * b + + # Quadratic Bézier interpolation between `a` and `b` with an `handle` using `self` as weight + # + # ~~~ + # assert 0.00.qerp(0.0, 32.0, 128.0) == 0.0 + # assert 0.25.qerp(0.0, 32.0, 128.0) == 20.0 + # assert 0.50.qerp(0.0, 32.0, 128.0) == 48.0 + # assert 0.75.qerp(0.0, 32.0, 128.0) == 84.0 + # assert 1.00.qerp(0.0, 32.0, 128.0) == 128.0 + # ~~~ + fun qerp(a, handle, b: Float): Float do + var p = self + var i = 1.0 - p + var r = i*i * a + + 2.0*i*p * handle + + p*p * b + return r + end + + # Cubic Bézier interpolation between `a` and `b` with two handles using `self` as weight + # + # The Cubic Bézier interpolation is the most common one and use two control points. + # + # ~~~ + # assert 0.00.cerp(0.0, 32.0, 128.0, 64.0) == 0.0 + # assert 0.25.cerp(0.0, 32.0, 128.0, 64.0) == 32.5 + # assert 0.50.cerp(0.0, 32.0, 128.0, 64.0) == 68.0 + # assert 0.75.cerp(0.0, 32.0, 128.0, 64.0) == 85.5 + # assert 1.00.cerp(0.0, 32.0, 128.0, 64.0) == 64.0 + # ~~~ + fun cerp(a, a_handle, b_handle, b: Float): Float do + var p = self + var i = 1.0 - p + var r = i*i*i * a + + 3.0*i*i*p * a_handle + + 3.0*i*p*p * b_handle + + p*p*p * b + return r + end end # Positive float infinite (IEEE 754) @@ -403,6 +442,40 @@ redef class Collection[ E ] res.shuffle return res end + + # Return a new array made of (at most) `length` elements randomly chosen. + # + # ~~~ + # var a = [1,2,1].sample(2) + # assert a == [1,1] or a == [1,2] or a == [2,1] + # ~~~ + # + # If there is not enough elements, then the result only contains them in a random order. + # See `to_shuffle`. + # + # ENSURE `result.length == self.length.min(length)` + # + # Note: the default implementation uses the Reservoir Algorithm + fun sample(length: Int): Array[E] + do + if length >= self.length then return to_shuffle + + var res = new Array[E].with_capacity(length) + var it = iterator + for i in [0..length[ do + res[i] = it.item + it.next + end + res.shuffle + for i in [length+1..self.length] do + var j = i.rand + if j < length then + res[j] = it.item + end + it.next + end + return res + end end redef class SequenceRead[E] @@ -472,9 +545,9 @@ fun pi: Float do return 3.14159265 # assert 10.rand == a # assert 100.rand == b # ~~~~ -fun srand_from(x: Int) `{ nit_rand_seeded = 1; nit_rand_seed = x; `} +fun srand_from(x: Int) `{ nit_rand_seeded = 1; nit_rand_seed = (unsigned int)x; `} # Reinitialize the pseudo-random generator used by the method `rand` and other. # This method is automatically invoked at the begin of the program, so usually, there is no need to manually invoke it. # The only exception is in conjunction with `srand_from` to reset the pseudo-random generator. -fun srand `{ nit_rand_seeded = 0; srand(time(NULL)); `} +fun srand `{ nit_rand_seeded = 0; srand((unsigned int)time(NULL)); `}