Multiplying large blocks of data?
Started by Andrew on 17-Jun-2017/0:19:38-7:00
Andrew — 17-Jun-2017/0:19:38-7:00
what would be a good way of multiplying a block of numbers 1 - 1,000,000 by 2?
test: [1 2 3...1000000]
test2: []
foreach num test [append test2 num * 2]
that seems to do the trick, but I'm sure there must be another way.
Nick — 17-Jun-2017/1:17:46-7:00
You can do this:
t: [1 2 3 4 5 6]
repeat x length? t [t/(x): t/(x) * 2]
Nick — 17-Jun-2017/1:21:09-7:00
and BTW, to test it with an actually large block:
t: copy [] insert/dup t 1 1000000
repeat x length? t [t/(x): t/(x) * 2]
Nick — 17-Jun-2017/1:27:21-7:00
and also BTW, to create a list of numbers 1-10million, the first option below is much faster:
t: copy [] repeat i 10000000 [insert tail t i]
t: copy [] repeat i 10000000 [append t i]
Geekyi — 18-Jun-2017/8:43:48-7:00
Why not use `map-each`, which is designed for it:
t: [1 2 3 4 5 6]
map-each i t [i * 2]
Well, the times are a bit different:
0:00:11 map-each
0:00:06 foreach Andrew
0:00:04 repeat Nick
Nick — 18-Jun-2017/9:55:56-7:00
Yes, and for 10 million+ values, for example, the delay makes a dramatic difference (seconds rather than minutes).
Endo — 19-Jun-2017/5:11:04-7:00
This worked a bit faster on my PC
t: copy [] insert/dup t 1 1000000
i: 1 until [t/:i: t/:i * 2 tail? t: next t]
Nick — 19-Jun-2017/8:41:57-7:00
Interesting, running on a little Windows 8 tablet with Z3735G 1.33 GHz CPU and 1 GB RAM (w/ Rebol 2.7.8.3.1), my results are the opposite in every case:
>> t: copy [] repeat i 10000000 [insert tail t i]
== []
>> delta-time [i: 1 until [t/:i: t/:i * 2 tail? t: next t]]
== 0:00:21.236
>> t: copy [] repeat i 10000000 [insert tail t i]
== []
>> delta-time [repeat x length? t [t/(x): t/(x) * 2]]
== 0:00:16.228
>> t: copy [] insert/dup t 1 10000000
== []
>> delta-time [i: 1 until [t/:i: t/:i * 2 tail? t: next t]]
== 0:00:22.194
>> t: copy [] insert/dup t 1 10000000
== []
>> delta-time [repeat x length? t [t/(x): t/(x) * 2]]
== 0:00:15.447
What system are you running Endo? I'm really curious about the difference in performance.
Nick — 19-Jun-2017/8:51:20-7:00
Here's the cleaned up copy of the tests - curious to hear results on other platforms:
t: copy [] repeat i 10000000 [insert tail t i]
delta-time [i: 1 until [t/:i: t/:i * 2 tail? t: next t]]
t: copy [] repeat i 10000000 [insert tail t i]
delta-time [repeat x length? t [t/(x): t/(x) * 2]]
t: copy [] insert/dup t 1 10000000
delta-time [i: 1 until [t/:i: t/:i * 2 tail? t: next t]]
t: copy [] insert/dup t 1 10000000
delta-time [repeat x length? t [t/(x): t/(x) * 2]]
Howard — 19-Jun-2017/19:16:53-7:00
t1 14.433255 14.375567 14.562163
t2 10.988527 10.948129 10.986415
t3 14.513004 14.739353 14.632172
t4 11.097424 10.935371 10.952677
linux 3.14.20 (i686) Inspiron 1501
tahrpup 6.0 (Puppy Linux)
Mobile AMD Sempron 3500+ 800 mhz
Memory:
Total: 14166616 kB
Free: 714000 kB
Available: 101500 kB
Howard — 19-Jun-2017/23:13:13-7:00
t1 18.689 18.720 18.844
t2 13.876 13.813 13.819
t3 18.454 18.532 18.610
t4 13.829 13.844 13.860
Windows 8 64bit
Ausus S200E
Celeron 847 1.1 Ghz
2 GB memory, 1.89 GB usable
hmnnn....
Nick — 20-Jun-2017/23:11:17-7:00
>> t: copy [] repeat i 10000000 [insert tail t i]
== []
>> delta-time [i: 1 until [t/:i: t/:i * 2 tail? t: next t]]
== 0:00:10.66
>> t: copy [] repeat i 10000000 [insert tail t i]
== []
>> delta-time [repeat x length? t [t/(x): t/(x) * 2]]
== 0:00:08.004
>> t: copy [] insert/dup t 1 10000000
== []
>> delta-time [i: 1 until [t/:i: t/:i * 2 tail? t: next t]]
== 0:00:10.386
>> t: copy [] insert/dup t 1 10000000
== []
>> delta-time [repeat x length? t [t/(x): t/(x) * 2]]
== 0:00:08.03
Andrew — 22-Jun-2017/19:15:21-7:00
My friend had an assignment in college for a program called MatLab. He mentioned that MatLab can multiply arrays together, like [2 3 4 5 6] * [3 4 5 6 7] to make one which is [6 12 20 30 42].
What would be an easy way to do this?
R E B O L []
lol1: [2 3 4 5 6]
lol2: [3 4 5 6 7]
lol3: []
foreach lol lol1 [append lol3 (lol * first lol2) remove lol2]
Nick — 23-Jun-2017/1:23:57-7:00
repeat i length? lol1 [insert tail lol3 lol1/:i * lol2/:i]
Nick — 23-Jun-2017/10:36:41-7:00
If you'll perform this operation often, create a function and put it in your rebol.r file:
multiply-blocks: func [bl1 bl2] [
bl3: copy []
repeat i length? bl1 [insert tail bl3 bl1/:i * bl2/:i]
bl3
]
multiply-blocks [2 3 4 5 6] [3 4 5 6 7]
lol1: [2 3 4 5 6]
lol2: [3 4 5 6 7]
multiply-blocks lol1 lol2
You can choose how to handle blocks of different length, how to handle a arbitrary number of blocks, etc.:
multiply-all: func [bl] [
result: copy []
lens: copy []
foreach b bl [append lens length? b]
len: first minimum-of lens
repeat i len [
total: 1
foreach b bl [total: total * b/:i]
append result total
]
result
]
multiply-all [ [1 2 3 4 5 6] [2 3 4 5] [3 4 5 6 7] ]
Nick — 23-Jun-2017/10:59:03-7:00
Here's the function above using 'map-each to find the shortest input block:
multiply-all: func [bl] [
result: copy []
repeat i first minimum-of map-each b bl [length? b] [
total: 1
foreach b bl [total: total * b/:i]
append result total
]
]
multiply-all [[1 2 3 4 5 6][2 3 4 5][3 4 5 6 7]]
Nick — 23-Jun-2017/11:04:50-7:00
(try that function with any number of blocks, each containing any arbitrary number of values)
Andrew — 23-Jun-2017/16:48:45-7:00
Could you explain what lol1/:i means, or give me a link to an explanation ?
Sunanda — 23-Jun-2017/17:00:57-7:00
> lol1/:i
It's an equivalent to pick lol1 i.
In addition, you can use the notation for assigning values too. Example with different word names:
blk: copy [a b c d e f]
ind: 4
blk/:ind ;; equivalent to pick blk ind
== d
blk/:ind: 88 ;; equivalent to poke blk ind 88
blk
== [a b c 88 e f]
Andrew — 23-Jun-2017/17:13:41-7:00
Thank you so much !
Andrew — 23-Jun-2017/17:32:30-7:00
Why do you do blk: copy [a b c d e f] instead of blk: [a b c d e f]?
Nick — 24-Jun-2017/6:36:11-7:00
'Copy ensures that any previous values in the block are erased.
Reply