# New Ticket Created by  Tadeusz SoĊ›nierz 
# Please include the string:  [perl #77204]
# in the subject line of all future correspondence about this issue. 
# <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=77204 >


(1..n) is a common idiom to get a random number between 1 and n.
However, due to Range and .pick complexity it is much slower than
(n.rand + 1). This patch optimizes Range.pick behaviour in a specific
case, when both edges of the Range are Integers. Otherwise, and in case
of using :replace, the Any-List.pm .pick implementation is used.

Kind regards,
Ted
>From 41c37191b4ff458e811e41edadea1912a1657ea3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tadeusz=20So=C5=9Bnierz?= <[email protected]>
Date: Sat, 14 Aug 2010 00:24:14 +0000
Subject: [PATCH] Optimized Range.pick in some special cases

---
 src/core/Range.pm |   15 +++++++++++++++
 1 files changed, 15 insertions(+), 0 deletions(-)

diff --git a/src/core/Range.pm b/src/core/Range.pm
index 0d3a920..6c6f092 100644
--- a/src/core/Range.pm
+++ b/src/core/Range.pm
@@ -58,6 +58,21 @@ class Range is Iterable does Positional {
         $min ~ $emin ~ ".." ~ $emax ~ $max;
     }
 
+    multi method pick() {
+        nextsame unless $.min.isa(Int) and $.max.isa(Int);
+        my $least = $.excludes_min ?? $.min + 1 !! $.min;
+        my $elems = ($.excludes_max ?? $.max - 1 !! $.max) - $least;
+        $elems ?? ($least + $elems.rand.floor) !! Any;
+    }
+
+    multi method pick(Int $n) {
+        nextsame;
+    }
+
+    multi method pick(Int $n, :$replace!) {
+        (1..$n).map: { self.pick }
+    }
+
     multi method fmt($format = '%s', $separator = ' ') {
         self.map({ .fmt($format)}).join($separator);
     }
-- 
1.7.1.1

Reply via email to