X-Git-Url: http://nitlanguage.org diff --git a/lib/core/math.nit b/lib/core/math.nit index c08c735..a7eefbe 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` # @@ -126,9 +126,9 @@ redef class Int # Is self a prime number ? # - # assert 3.is_prime - # assert not 1.is_prime - # assert not 12.is_prime + # assert 3.is_prime + # assert not 1.is_prime + # assert not 15.is_prime fun is_prime: Bool do if self == 2 then @@ -136,7 +136,7 @@ redef class Int else if self <= 1 or self.is_even then return false end - for i in [3..self.sqrt[ do + for i in [3..self.sqrt] do if self % i == 0 then return false end return true @@ -169,13 +169,23 @@ redef class Int end return res end + + # Is `self` a power of two ? + # + # ~~~nit + # assert not 3.is_pow2 + # assert 2.is_pow2 + # assert 1.is_pow2 + # assert not 0.is_pow2 + # ~~~ + fun is_pow2: Bool do return self != 0 and (self & self - 1) == 0 end 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` # @@ -242,15 +252,15 @@ redef class Float # Returns `self` raised at `e` power. # - # #assert 2.0.pow(0.0) == 1.0 - # #assert 2.0.pow(3.0) == 8.0 - # #assert 0.0.pow(9.0) == 0.0 + # assert 2.0.pow(0.0) == 1.0 + # assert 2.0.pow(3.0) == 8.0 + # assert 0.0.pow(9.0) == 0.0 fun pow(e: Float): Float `{ return pow(self, e); `} # Natural logarithm of `self`. # # assert 0.0.log.is_inf == -1 - # #assert 1.0.log == 0.0 + # assert 1.0.log == 0.0 fun log: Float `{ return log(self); `} # Logarithm of `self` to base `base`. @@ -410,6 +420,17 @@ fun inf: Float do return 1.0 / 0.0 # ~~~ fun nan: Float do return 0.0 / 0.0 +redef class Comparable + # Constraint `self` within `[min..max]` + # + # assert 1.clamp(5, 10) == 5 + # assert 7.clamp(5, 10) == 7 + # assert 15.clamp(5, 10) == 10 + # assert 1.5.clamp(1.0, 2.0) == 1.5 + # assert "a".clamp("b", "c") == "b" + fun clamp(min, max: OTHER): OTHER do return self.max(min).min(max) +end + redef class Collection[ E ] # Return a random element form the collection # There must be at least one element in the collection @@ -442,6 +463,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] @@ -490,11 +545,11 @@ redef class Sys end end -# Computes the arc tangent given `x` and `y`. +# Computes the arc tangent given `y` and `x`. # # assert atan2(-0.0, 1.0) == -0.0 # assert atan2(0.0, 1.0) == 0.0 -fun atan2(x: Float, y: Float): Float `{ return atan2(x, y); `} +fun atan2(y: Float, x: Float): Float `{ return atan2(y, x); `} # Approximate value of **pi**. fun pi: Float do return 3.14159265 @@ -511,9 +566,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)); `}