Commits

Taku Miyakawa  committed dd0a3ba

Moves CORE.random_number_generator to RANDOM_NUMBER_GENERATOR.new (closing issue #477)

  • Participants
  • Parent commits 59f51ae

Comments (0)

Files changed (6)

File src/main/java/org/kink_lang/kink/internal/Messages.java

     }
 
 
-    public static String seedMustBeStringOrBytesOrIntegral( Value actualValue ) {
-        return String.format( string( "seedMustBeStringOrBytesOrIntegral" ) , actualValue );
-    }
-
-
     public static String nthElement( int index ) {
         return String.format( string( "nthElement" ) , index );
     }

File src/main/java/org/kink_lang/kink/internal/module/Core.java

 import org.kink_lang.kink.Receiver;
 import org.kink_lang.kink.Optional;
 import org.kink_lang.kink.internal.Envs;
-import org.kink_lang.kink.internal.RandomNumbers;
-import org.kink_lang.kink.Numbers;
 import org.kink_lang.kink.internal.Messages;
 
 import java.lang.reflect.Method;
 import java.nio.file.Paths;
 import java.util.List;
 import java.util.ArrayList;
-import java.math.BigInteger;
 
 /** CORE module. */
 public final class Core extends ModuleFactory {
 
 
         @Define
-        public Value random_number_generator( @Optional Value seedVal ) {
-            if ( seedVal == null ) {
-                return Value.value( RandomNumbers.newMersenneTwister() );
-            }
-            Object seed = seedVal.unbox();
-            if ( seed instanceof String ) {
-                return Value.value( RandomNumbers.newMersenneTwister( (String) seed ) );
-            } else if ( seed instanceof byte[] ) {
-                return Value.value( RandomNumbers.newMersenneTwister( (byte[]) seed ) );
-            } else if ( seed instanceof Number && Numbers.isIntegral( (Number) seed ) ) {
-                BigInteger seedBigInteger = Numbers.toBigInteger( (Number) seed );
-                return Value.value( RandomNumbers.newMersenneTwister( seedBigInteger ) );
-            } else {
-                throw new KinkException( Messages.seedMustBeStringOrBytesOrIntegral( seedVal ) );
-            }
-        }
-
-
-        @Define
         public final Value base = Value.base();
 
 

File src/main/kink/RANDOM_NUMBER_GENERATOR.kn

+#!/usr/bin/env kink
+# vim: et sw=4 sts=4 fdm=marker
+
+# Copyright (c) 2013 Miyakawa Taku
+# 
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+use('org.kink_lang.kink.internal.RandomNumbers')
+
+### .new([Seed]) => /random_number_generator
+###
+### SUMMARY
+###     Returns a new random number generator initialized with the seed if specified,
+###     or with an auto generated seed.
+###
+### PARAM Seed
+###     Optional seed, whoes type is /int_num, /str or /bytes.
+###     If the argument is not specified, an auto generated seed is used.
+:new = { (:Seed)
+    # TODO type checking
+    :Seed.exists?.then {
+        RandomNumbers.newMersenneTwister(Seed)
+    } {
+        RandomNumbers.newMersenneTwister
+    }
+}

File src/main/resources/org/kink_lang/kink/message.properties

 tooBigCount=Too big count %s
 cannotExpand=Expansion requires a list, but actually got %s
 upperBoundMustBePositive=Upper bound must be positive (>= 0), but actually was %s
-seedMustBeStringOrBytesOrIntegral=Seed must be a string, an array of bytes or an integral number, but actually was %s
 nthElement=#%d element
 varMissingShouldReturnEmptyOrSingletonList='var_missing' is expected to return [] or [<alternative-value>], but actually returns %s
 noMatchingJavaMethod=%s has no matching Java method %s with arguments %s

File src/test/java/org/kink_lang/kink/internal/module/CoreTest.java

 import org.kink_lang.kink.Modules;
 import org.kink_lang.kink.StubFun;
 import org.kink_lang.kink.internal.Envs;
-import org.kink_lang.kink.internal.RandomNumbers;
 import org.kink_lang.common.Classes;
 import org.kink_lang.common.test.ClassMockery;
 
 import java.util.List;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.Random;
-import java.math.BigInteger;
 
 import org.slf4j.LoggerFactory;
 
 
 
     @Test
-    public void make_rng_with_default_seed() {
-        Random rng = (Random) core.call( new GetSite( "random_number_generator" ) ).unbox();
-        assertThat( rng.nextInt() , is( Integer.class ) );
-        assertThat( rng.nextInt() , is( Integer.class ) );
-        assertThat( rng.nextInt() , is( Integer.class ) );
-    }
-
-
-    @Test
-    public void make_rng_with_integral_seed() {
-        Random actualRng = (Random) core.call( new GetSite( "random_number_generator" )
-                , Value.value( Long.MAX_VALUE ) ).unbox();
-        Random expectedRng
-            = RandomNumbers.newMersenneTwister( BigInteger.valueOf( Long.MAX_VALUE ) );
-        assertThat( actualRng.nextInt() , is( expectedRng.nextInt() ) );
-        assertThat( actualRng.nextInt() , is( expectedRng.nextInt() ) );
-        assertThat( actualRng.nextInt() , is( expectedRng.nextInt() ) );
-    }
-
-
-    @Test
-    public void make_rng_with_bytes_seed() {
-        byte[] seed = { 1 , 2 , 3 };
-        Random actualRng = (Random) core.call( new GetSite( "random_number_generator" )
-                , Value.value( seed ) ).unbox();
-        Random expectedRng = RandomNumbers.newMersenneTwister( seed );
-        assertThat( actualRng.nextInt() , is( expectedRng.nextInt() ) );
-        assertThat( actualRng.nextInt() , is( expectedRng.nextInt() ) );
-        assertThat( actualRng.nextInt() , is( expectedRng.nextInt() ) );
-    }
-
-
-    @Test
-    public void make_rng_with_string_seed() {
-        String seed = "voxxx";
-        Random actualRng = (Random) core.call( new GetSite( "random_number_generator" )
-                , Value.value( seed ) ).unbox();
-        Random expectedRng = RandomNumbers.newMersenneTwister( seed );
-        assertThat( actualRng.nextInt() , is( expectedRng.nextInt() ) );
-        assertThat( actualRng.nextInt() , is( expectedRng.nextInt() ) );
-        assertThat( actualRng.nextInt() , is( expectedRng.nextInt() ) );
-    }
-
-
-    @Test( expected = KinkException.class )
-    public void cannot_make_rng_with_not_integral_number() {
-        core.call( new GetSite( "random_number_generator" ) , Value.value( 1.5 ) );
-    }
-
-
-    @Test( expected = KinkException.class )
-    public void cannot_make_rng_with_not_string_nor_bytes_nor_integral_seed() {
-        core.call( new GetSite( "random_number_generator" ) , Value.value( new Object() ) );
-    }
-
-
-    @Test
     public void show_of_core() {
         assertThat( core.call( new GetSite( "show" ) ).asString( "" ) , is( "CORE" ) );
     }

File src/test/kink/RANDOM_NUMBER_GENERATOR_test.kn

+#!/usr/bin/env kink
+# vim: et sw=4 sts=4 fdm=marker
+
+# Copyright (c) 2013 Miyakawa Taku
+# 
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+use('RANDOM_NUMBER_GENERATOR')
+
+use('TEST.test')
+use('TEST.test_group')
+
+:_10_numbers_below_100_with_seed = { (:Seed)
+    :Rng = RANDOM_NUMBER_GENERATOR.new(Seed)
+    Rng.seq(100).head(10).list
+}
+
+test_group('Random numbers with an integer seed') {
+    use('java.lang.Integer')
+    use('java.lang.Long')
+
+    test('Integer.MIN_VALUE') {
+        _10_numbers_below_100_with_seed(Integer.MIN_VALUE).check([75 80 35 42 77 47 1 41 38 75])
+    }
+
+    test('Integer.MAX_VALUE') {
+        _10_numbers_below_100_with_seed(Integer.MAX_VALUE).check([71 92 38 2 67 61 48 42 57 33])
+    }
+
+    test('Long.MIN_VALUE') {
+        _10_numbers_below_100_with_seed(Long.MIN_VALUE).check([74 84 59 16 73 72 86 10 71 25])
+    }
+
+    test('Long.MAX_VALUE') {
+        _10_numbers_below_100_with_seed(Long.MAX_VALUE).check([67 9 84 93 63 56 47 85 62 68])
+    }
+
+    test('Long.MIN_VALUE - 1') {
+        _10_numbers_below_100_with_seed(Long.MIN_VALUE - 1).check([19 85 34 44 9 19 62 30 28 28])
+    }
+
+    test('Long.MAX_VALUE + 1') {
+        _10_numbers_below_100_with_seed(Long.MAX_VALUE + 1).check([20 9 80 78 16 89 47 88 18 44])
+    }
+}
+
+test_group('Random numbers with a bytes seed') {
+    use('JAVA.byte')
+
+    test('empty bytes') {
+        _10_numbers_below_100_with_seed(byte.array()).check([18 99 78 57 2 46 85 61 97 78])
+    }
+
+    test('byte.array(1 2 3)') {
+        _10_numbers_below_100_with_seed(byte.array(1 2 3)).check([76 84 33 54 51 37 84 64 42 17])
+    }
+}
+
+test_group('Random numbers with a string seed') {
+
+    test('empty string') {
+        _10_numbers_below_100_with_seed('').check([18 99 78 57 2 46 85 61 97 78])
+    }
+
+    test("'hoge'") {
+        _10_numbers_below_100_with_seed('hoge').check([46 63 44 21 21 49 63 84 63 24])
+    }
+}
+
+test('Random numbers with an auto generated seed') {
+    use('COMMON_PATTERN.lt')
+    :Numbers = RANDOM_NUMBER_GENERATOR.new.seq(100).head(10).list
+    Numbers.check([lt(100)] * 10)
+}