ruby-mpi 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +4 -4
- data/LICENSE.txt +1 -1
- data/README.rdoc +6 -1
- data/Rakefile +2 -1
- data/VERSION +1 -1
- data/ext/mpi/extconf.rb +11 -3
- data/ext/mpi/mpi.c +139 -73
- data/lib/mpi/utils.rb +17 -0
- data/samples/hello.rb +7 -1
- data/samples/narray.rb +6 -0
- data/samples/narray_offset.rb +29 -0
- data/spec/ruby-mpi_spec.rb +2 -6
- data/test/test_utils.rb +21 -0
- metadata +83 -76
- data/Gemfile.lock +0 -30
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 20fe1ffeb2cd83c63f27589552a8578a5890de22
|
4
|
+
data.tar.gz: fa319f8be8c7ce5b9287a1c58f9fd848f1f364fe
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bff7b2110e2c36af4507a8664cce6251ed2f8e890a9d56afbc960ff83b8904ac76273885e0ed5a327fb13593bdfa119b0b9232c8b3157f3523ffea3f2c73885e
|
7
|
+
data.tar.gz: c42acd7ec6937987e394610ce94bf1e31ba648e0c544710767e7472ae86d3fcd2ff2d7507928052fa46d208b4450540ec1d65c3913f27ed3f57d3de0a85d6fca
|
data/Gemfile
CHANGED
@@ -6,9 +6,9 @@ source "http://rubygems.org"
|
|
6
6
|
# Add dependencies to develop your gem here.
|
7
7
|
# Include everything needed to run rake, tests, features, etc.
|
8
8
|
group :development do
|
9
|
-
gem "rspec", "
|
10
|
-
gem "bundler", "
|
11
|
-
gem "jeweler", "
|
12
|
-
gem "
|
9
|
+
gem "rspec", ">= 2.3.0"
|
10
|
+
gem "bundler", ">= 1.0.0"
|
11
|
+
gem "jeweler", ">= 1.5.2"
|
12
|
+
gem "simplecov", ">= 0"
|
13
13
|
gem "narray", ">= 0"
|
14
14
|
end
|
data/LICENSE.txt
CHANGED
data/README.rdoc
CHANGED
@@ -5,6 +5,11 @@ Ruby-MPI is a ruby binding of Message Passing Interface (MPI), which is an API s
|
|
5
5
|
== Install
|
6
6
|
|
7
7
|
# gem install ruby-mpi
|
8
|
+
|
9
|
+
== How to run
|
10
|
+
Use mpirun or mpiexec to run a script
|
11
|
+
e.g. (run with 4 processes)
|
12
|
+
# mpirun -np 4 ruby hello.rb
|
8
13
|
|
9
14
|
== Contributing to Ruby-MPI
|
10
15
|
|
@@ -18,6 +23,6 @@ Ruby-MPI is a ruby binding of Message Passing Interface (MPI), which is an API s
|
|
18
23
|
|
19
24
|
== Copyright
|
20
25
|
|
21
|
-
Copyright (c) 2011 Seiya Nishizawa. See LICENSE.txt for
|
26
|
+
Copyright (c) 2011-2012 Seiya Nishizawa. See LICENSE.txt for
|
22
27
|
further details.
|
23
28
|
|
data/Rakefile
CHANGED
@@ -40,7 +40,7 @@ end
|
|
40
40
|
|
41
41
|
task :default => :spec
|
42
42
|
|
43
|
-
require '
|
43
|
+
require 'rdoc/task'
|
44
44
|
Rake::RDocTask.new do |rdoc|
|
45
45
|
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
46
46
|
|
@@ -48,6 +48,7 @@ Rake::RDocTask.new do |rdoc|
|
|
48
48
|
rdoc.title = "ruby-mpi #{version}"
|
49
49
|
rdoc.rdoc_files.include('README*')
|
50
50
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
51
|
+
rdoc.rdoc_files.include('samples/*.rb')
|
51
52
|
end
|
52
53
|
|
53
54
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
data/ext/mpi/extconf.rb
CHANGED
@@ -4,12 +4,20 @@ CONFIG['CC'] = "mpicc"
|
|
4
4
|
gem_path = nil
|
5
5
|
begin
|
6
6
|
require "rubygems"
|
7
|
-
if
|
8
|
-
|
7
|
+
if Gem::Specification.respond_to?(:find_by_name)
|
8
|
+
if spec = Gem::Specification.find_by_name("narray")
|
9
|
+
gem_path = spec.full_gem_path
|
10
|
+
end
|
11
|
+
else
|
12
|
+
if (spec = Gem.source_index.find_name("narray")).any?
|
13
|
+
gem_path = spec.full_gem_path
|
14
|
+
end
|
9
15
|
end
|
10
16
|
rescue LoadError
|
11
17
|
dir_config("narray", Config::CONFIG["sitearchdir"])
|
12
18
|
end
|
13
|
-
find_header("narray.h", gem_path)
|
19
|
+
unless find_header("narray.h", gem_path)
|
20
|
+
find_header("narray.h", File.join(gem_path,"src"))
|
21
|
+
end
|
14
22
|
|
15
23
|
create_makefile("mpi")
|
data/ext/mpi/mpi.c
CHANGED
@@ -6,38 +6,45 @@
|
|
6
6
|
#include "mpi.h"
|
7
7
|
|
8
8
|
|
9
|
-
#define OBJ2C(rb_obj, len, buffer, typ) \
|
9
|
+
#define OBJ2C(rb_obj, len, buffer, typ, off) \
|
10
10
|
{\
|
11
11
|
if (TYPE(rb_obj) == T_STRING) {\
|
12
|
-
len = RSTRING_LEN(rb_obj);\
|
13
|
-
buffer = (void*)StringValuePtr(rb_obj);\
|
14
|
-
typ =
|
15
|
-
} else if (IsNArray(rb_obj)) {
|
12
|
+
if (len==0) len = RSTRING_LEN(rb_obj);\
|
13
|
+
buffer = (void*)(StringValuePtr(rb_obj) + off);\
|
14
|
+
typ = MPI_BYTE;\
|
15
|
+
} else if (IsNArray(rb_obj)) {\
|
16
16
|
struct NARRAY *a;\
|
17
17
|
GetNArray(rb_obj, a);\
|
18
18
|
buffer = (void*)(a->ptr);\
|
19
|
-
len = a->total;\
|
19
|
+
if (len==0) len = a->total;\
|
20
20
|
switch (a->type) {\
|
21
21
|
case NA_BYTE:\
|
22
22
|
typ = MPI_BYTE;\
|
23
|
+
buffer = (void*)((char*)buffer + off);\
|
23
24
|
break;\
|
24
25
|
case NA_SINT:\
|
25
26
|
typ = MPI_SHORT;\
|
27
|
+
buffer = (void*)((char*)buffer + off*4);\
|
26
28
|
break;\
|
27
29
|
case NA_LINT:\
|
28
30
|
typ = MPI_LONG;\
|
31
|
+
buffer = (void*)((char*)buffer + off*8);\
|
29
32
|
break;\
|
30
33
|
case NA_SFLOAT:\
|
31
34
|
typ = MPI_FLOAT;\
|
35
|
+
buffer = (void*)((char*)buffer + off*4);\
|
32
36
|
break;\
|
33
37
|
case NA_DFLOAT:\
|
34
38
|
typ = MPI_DOUBLE;\
|
39
|
+
buffer = (void*)((char*)buffer + off*8);\
|
35
40
|
break;\
|
36
41
|
case NA_SCOMPLEX:\
|
37
42
|
typ = MPI_2COMPLEX;\
|
43
|
+
buffer = (void*)((char*)buffer + off*8);\
|
38
44
|
break;\
|
39
45
|
case NA_DCOMPLEX:\
|
40
46
|
typ = MPI_2DOUBLE_COMPLEX;\
|
47
|
+
buffer = (void*)((char*)buffer + off*16);\
|
41
48
|
break;\
|
42
49
|
default:\
|
43
50
|
rb_raise(rb_eArgError, "narray type is invalid");\
|
@@ -54,48 +61,36 @@ static VALUE eBUFFER, eCOUNT, eTYPE, eTAG, eCOMM, eRANK, eREQUEST, eROOT, eGROUP
|
|
54
61
|
|
55
62
|
struct _Comm {
|
56
63
|
MPI_Comm Comm;
|
64
|
+
bool free;
|
57
65
|
};
|
58
66
|
struct _Request {
|
59
67
|
MPI_Request Request;
|
68
|
+
bool free;
|
60
69
|
};
|
61
70
|
struct _Op {
|
62
71
|
MPI_Op Op;
|
72
|
+
bool free;
|
63
73
|
};
|
64
74
|
struct _Errhandler {
|
65
75
|
MPI_Errhandler Errhandler;
|
76
|
+
bool free;
|
66
77
|
};
|
67
78
|
|
68
79
|
static bool _initialized = false;
|
69
80
|
static bool _finalized = false;
|
70
81
|
|
71
82
|
|
72
|
-
#define
|
73
|
-
static void \
|
74
|
-
name ## _free(void *ptr)\
|
75
|
-
{\
|
76
|
-
struct _ ## name *obj;\
|
77
|
-
obj = (struct _ ## name*) ptr;\
|
78
|
-
if (!_finalized)\
|
79
|
-
MPI_ ## name ## _free(&(obj->name)); \
|
80
|
-
free(obj);\
|
81
|
-
}
|
82
|
-
DEF_FREE(Comm)
|
83
|
-
DEF_FREE(Request)
|
84
|
-
DEF_FREE(Op)
|
85
|
-
DEF_FREE(Errhandler)
|
86
|
-
static void
|
87
|
-
Status_free(void *ptr)
|
88
|
-
{
|
89
|
-
free((MPI_Status*) ptr);
|
90
|
-
}
|
91
|
-
|
92
|
-
|
93
|
-
#define CAE_ERR(type) case MPI_ERR_ ## type: rb_raise(e ## type,""); break
|
83
|
+
#define CAE_ERR(type) case MPI_ERR_ ## type: rb_raise(e ## type,"%s",str); break
|
94
84
|
static void
|
95
85
|
check_error(int error)
|
96
86
|
{
|
97
|
-
|
98
|
-
|
87
|
+
if (error == MPI_SUCCESS) return;
|
88
|
+
int code, len;
|
89
|
+
char str[MPI_MAX_ERROR_STRING];
|
90
|
+
if (MPI_Error_class(error, &code)!=MPI_SUCCESS || MPI_Error_string(error, str, &len)!=MPI_SUCCESS)
|
91
|
+
rb_raise(rb_eRuntimeError, "unknown error occuerd in MPI call");
|
92
|
+
|
93
|
+
switch (code) {
|
99
94
|
CAE_ERR(BUFFER);
|
100
95
|
CAE_ERR(COUNT);
|
101
96
|
CAE_ERR(TYPE);
|
@@ -154,15 +149,48 @@ check_error(int error)
|
|
154
149
|
CAE_ERR(SYSRESOURCE);
|
155
150
|
#endif
|
156
151
|
default:
|
157
|
-
rb_raise(rb_eRuntimeError, "unknown error");
|
152
|
+
rb_raise(rb_eRuntimeError, "unknown error: %d", code);
|
158
153
|
}
|
159
154
|
}
|
160
155
|
|
156
|
+
#define DEF_FREE(name, capit) \
|
157
|
+
static void \
|
158
|
+
name ## _free(void *ptr)\
|
159
|
+
{\
|
160
|
+
struct _ ## name *obj;\
|
161
|
+
obj = (struct _ ## name*) ptr;\
|
162
|
+
if (!_finalized && obj->free && obj->name!=MPI_ ## capit ##_NULL)\
|
163
|
+
check_error(MPI_ ## name ## _free(&(obj->name))); \
|
164
|
+
free(obj);\
|
165
|
+
}
|
166
|
+
#define DEF_FREE2(name, capit) \
|
167
|
+
static void \
|
168
|
+
name ## _free2(void *ptr)\
|
169
|
+
{\
|
170
|
+
struct _ ## name *obj;\
|
171
|
+
obj = (struct _ ## name*) ptr;\
|
172
|
+
free(obj);\
|
173
|
+
}
|
174
|
+
DEF_FREE(Comm, COMM)
|
175
|
+
DEF_FREE(Request, REQUEST)
|
176
|
+
DEF_FREE(Op, OP)
|
177
|
+
DEF_FREE(Errhandler, ERRHANDLER)
|
178
|
+
DEF_FREE2(Comm, COMM)
|
179
|
+
DEF_FREE2(Op, OP)
|
180
|
+
DEF_FREE2(Errhandler, ERRHANDLER)
|
181
|
+
static void
|
182
|
+
Status_free(void *ptr)
|
183
|
+
{
|
184
|
+
free((MPI_Status*) ptr);
|
185
|
+
}
|
186
|
+
|
187
|
+
|
161
188
|
#define DEF_CONST(v, const, name) \
|
162
189
|
{\
|
163
190
|
v = ALLOC(struct _ ## v);\
|
164
191
|
v->v = const;\
|
165
|
-
|
192
|
+
v->free = false;\
|
193
|
+
rb_define_const(c ## v, #name, Data_Wrap_Struct(c ## v, NULL, v ## _free2, v)); \
|
166
194
|
}
|
167
195
|
|
168
196
|
static void
|
@@ -216,7 +244,7 @@ rb_m_init(int argc, VALUE *argv, VALUE self)
|
|
216
244
|
// define MPI::Comm::WORLD
|
217
245
|
struct _Comm *Comm;
|
218
246
|
DEF_CONST(Comm, MPI_COMM_WORLD, WORLD);
|
219
|
-
MPI_Errhandler_set(MPI_COMM_WORLD, MPI_ERRORS_RETURN);
|
247
|
+
check_error(MPI_Errhandler_set(MPI_COMM_WORLD, MPI_ERRORS_RETURN));
|
220
248
|
|
221
249
|
// define MPI::Op::???
|
222
250
|
struct _Op *Op;
|
@@ -249,6 +277,16 @@ rb_m_finalize(VALUE self)
|
|
249
277
|
return self;
|
250
278
|
}
|
251
279
|
|
280
|
+
static VALUE
|
281
|
+
rb_m_abort(VALUE self, VALUE rcomm, VALUE rerror)
|
282
|
+
{
|
283
|
+
struct _Comm *comm;
|
284
|
+
int ierror;
|
285
|
+
Data_Get_Struct(rcomm, struct _Comm, comm);
|
286
|
+
ierror = MPI_Abort(comm->Comm, NUM2INT(rerror));
|
287
|
+
return INT2NUM(ierror);
|
288
|
+
}
|
289
|
+
|
252
290
|
|
253
291
|
// MPI::Comm
|
254
292
|
static VALUE
|
@@ -262,6 +300,7 @@ rb_comm_initialize(VALUE self)
|
|
262
300
|
{
|
263
301
|
rb_raise(rb_eRuntimeError, "not developed yet");
|
264
302
|
// MPI_Comm_create()
|
303
|
+
// comm->free = true;
|
265
304
|
}
|
266
305
|
static VALUE
|
267
306
|
rb_comm_size(VALUE self)
|
@@ -285,11 +324,11 @@ static VALUE
|
|
285
324
|
rb_comm_send(VALUE self, VALUE rb_obj, VALUE rb_dest, VALUE rb_tag)
|
286
325
|
{
|
287
326
|
void* buffer;
|
288
|
-
int len, dest, tag;
|
327
|
+
int len=0, dest, tag;
|
289
328
|
MPI_Datatype type;
|
290
329
|
struct _Comm *comm;
|
291
330
|
|
292
|
-
OBJ2C(rb_obj, len, buffer, type);
|
331
|
+
OBJ2C(rb_obj, len, buffer, type, 0);
|
293
332
|
dest = NUM2INT(rb_dest);
|
294
333
|
tag = NUM2INT(rb_tag);
|
295
334
|
Data_Get_Struct(self, struct _Comm, comm);
|
@@ -301,31 +340,43 @@ static VALUE
|
|
301
340
|
rb_comm_isend(VALUE self, VALUE rb_obj, VALUE rb_dest, VALUE rb_tag)
|
302
341
|
{
|
303
342
|
void* buffer;
|
304
|
-
int len, dest, tag;
|
343
|
+
int len=0, dest, tag;
|
305
344
|
MPI_Datatype type;
|
306
345
|
struct _Comm *comm;
|
307
346
|
struct _Request *request;
|
308
347
|
VALUE rb_request;
|
309
348
|
|
310
|
-
OBJ2C(rb_obj, len, buffer, type);
|
349
|
+
OBJ2C(rb_obj, len, buffer, type, 0);
|
311
350
|
dest = NUM2INT(rb_dest);
|
312
351
|
tag = NUM2INT(rb_tag);
|
313
352
|
Data_Get_Struct(self, struct _Comm, comm);
|
314
353
|
rb_request = Data_Make_Struct(cRequest, struct _Request, NULL, Request_free, request);
|
354
|
+
request->free = true;
|
315
355
|
check_error(MPI_Isend(buffer, len, type, dest, tag, comm->Comm, &(request->Request)));
|
316
356
|
|
317
357
|
return rb_request;
|
318
358
|
}
|
319
359
|
static VALUE
|
320
|
-
rb_comm_recv(
|
360
|
+
rb_comm_recv(int argc, VALUE *argv, VALUE self)
|
321
361
|
{
|
362
|
+
VALUE rb_obj, rb_source, rb_tag;
|
363
|
+
VALUE rb_len, rb_offset; // option
|
322
364
|
void* buffer;
|
323
|
-
int
|
365
|
+
int source, tag, len = 0, offset = 0;
|
324
366
|
MPI_Datatype type;
|
325
367
|
MPI_Status *status;
|
326
368
|
struct _Comm *comm;
|
327
369
|
|
328
|
-
|
370
|
+
rb_scan_args(argc, argv, "32", &rb_obj, &rb_source, &rb_tag, &rb_len, &rb_offset);
|
371
|
+
|
372
|
+
if (rb_len != Qnil) {
|
373
|
+
len = NUM2INT(rb_len);
|
374
|
+
}
|
375
|
+
if (rb_offset != Qnil) {
|
376
|
+
offset = NUM2INT(rb_offset);
|
377
|
+
}
|
378
|
+
|
379
|
+
OBJ2C(rb_obj, len, buffer, type, offset);
|
329
380
|
source = NUM2INT(rb_source);
|
330
381
|
tag = NUM2INT(rb_tag);
|
331
382
|
|
@@ -336,20 +387,33 @@ rb_comm_recv(VALUE self, VALUE rb_obj, VALUE rb_source, VALUE rb_tag)
|
|
336
387
|
return Data_Wrap_Struct(cStatus, NULL, Status_free, status);
|
337
388
|
}
|
338
389
|
static VALUE
|
339
|
-
rb_comm_irecv(
|
390
|
+
rb_comm_irecv(int argc, VALUE *argv, VALUE self)
|
340
391
|
{
|
392
|
+
VALUE rb_obj, rb_source, rb_tag;
|
393
|
+
VALUE rb_len, rb_offset; // option
|
341
394
|
void* buffer;
|
342
|
-
int
|
395
|
+
int source, tag, len = 0, offset = 0;
|
343
396
|
MPI_Datatype type;
|
344
397
|
struct _Comm *comm;
|
345
398
|
struct _Request *request;
|
346
399
|
VALUE rb_request;
|
347
400
|
|
348
|
-
|
401
|
+
rb_scan_args(argc, argv, "32", &rb_obj, &rb_source, &rb_tag, &rb_len, &rb_offset);
|
402
|
+
|
403
|
+
if (rb_len != Qnil) {
|
404
|
+
len = NUM2INT(rb_len);
|
405
|
+
}
|
406
|
+
if (rb_offset != Qnil) {
|
407
|
+
offset = NUM2INT(rb_offset);
|
408
|
+
}
|
409
|
+
|
410
|
+
OBJ2C(rb_obj, len, buffer, type, offset);
|
349
411
|
source = NUM2INT(rb_source);
|
350
412
|
tag = NUM2INT(rb_tag);
|
413
|
+
|
351
414
|
Data_Get_Struct(self, struct _Comm, comm);
|
352
415
|
rb_request = Data_Make_Struct(cRequest, struct _Request, NULL, Request_free, request);
|
416
|
+
request->free = true;
|
353
417
|
check_error(MPI_Irecv(buffer, len, type, source, tag, comm->Comm, &(request->Request)));
|
354
418
|
|
355
419
|
return rb_request;
|
@@ -358,17 +422,17 @@ static VALUE
|
|
358
422
|
rb_comm_gather(VALUE self, VALUE rb_sendbuf, VALUE rb_recvbuf, VALUE rb_root)
|
359
423
|
{
|
360
424
|
void *sendbuf, *recvbuf = NULL;
|
361
|
-
int sendcount, recvcount = 0;
|
362
|
-
MPI_Datatype sendtype, recvtype =
|
425
|
+
int sendcount=0, recvcount = 0;
|
426
|
+
MPI_Datatype sendtype, recvtype = 0;
|
363
427
|
int root, rank, size;
|
364
428
|
struct _Comm *comm;
|
365
|
-
OBJ2C(rb_sendbuf, sendcount, sendbuf, sendtype);
|
429
|
+
OBJ2C(rb_sendbuf, sendcount, sendbuf, sendtype, 0);
|
366
430
|
root = NUM2INT(rb_root);
|
367
431
|
Data_Get_Struct(self, struct _Comm, comm);
|
368
432
|
check_error(MPI_Comm_rank(comm->Comm, &rank));
|
369
433
|
check_error(MPI_Comm_size(comm->Comm, &size));
|
370
434
|
if (rank == root) {
|
371
|
-
OBJ2C(rb_recvbuf, recvcount, recvbuf, recvtype);
|
435
|
+
OBJ2C(rb_recvbuf, recvcount, recvbuf, recvtype, 0);
|
372
436
|
if (recvcount < sendcount*size)
|
373
437
|
rb_raise(rb_eArgError, "recvbuf is too small");
|
374
438
|
recvcount = sendcount;
|
@@ -380,15 +444,15 @@ static VALUE
|
|
380
444
|
rb_comm_allgather(VALUE self, VALUE rb_sendbuf, VALUE rb_recvbuf)
|
381
445
|
{
|
382
446
|
void *sendbuf, *recvbuf;
|
383
|
-
int sendcount, recvcount;
|
447
|
+
int sendcount=0, recvcount=0;
|
384
448
|
MPI_Datatype sendtype, recvtype;
|
385
449
|
int rank, size;
|
386
450
|
struct _Comm *comm;
|
387
|
-
OBJ2C(rb_sendbuf, sendcount, sendbuf, sendtype);
|
451
|
+
OBJ2C(rb_sendbuf, sendcount, sendbuf, sendtype, 0);
|
388
452
|
Data_Get_Struct(self, struct _Comm, comm);
|
389
453
|
check_error(MPI_Comm_rank(comm->Comm, &rank));
|
390
454
|
check_error(MPI_Comm_size(comm->Comm, &size));
|
391
|
-
OBJ2C(rb_recvbuf, recvcount, recvbuf, recvtype);
|
455
|
+
OBJ2C(rb_recvbuf, recvcount, recvbuf, recvtype, 0);
|
392
456
|
if (recvcount < sendcount*size)
|
393
457
|
rb_raise(rb_eArgError, "recvbuf is too small");
|
394
458
|
recvcount = sendcount;
|
@@ -399,11 +463,11 @@ static VALUE
|
|
399
463
|
rb_comm_bcast(VALUE self, VALUE rb_buffer, VALUE rb_root)
|
400
464
|
{
|
401
465
|
void *buffer;
|
402
|
-
int count;
|
466
|
+
int count=0;
|
403
467
|
MPI_Datatype type;
|
404
468
|
int root;
|
405
469
|
struct _Comm *comm;
|
406
|
-
OBJ2C(rb_buffer, count, buffer, type);
|
470
|
+
OBJ2C(rb_buffer, count, buffer, type, 0);
|
407
471
|
root = NUM2INT(rb_root);
|
408
472
|
Data_Get_Struct(self, struct _Comm, comm);
|
409
473
|
check_error(MPI_Bcast(buffer, count, type, root, comm->Comm));
|
@@ -413,17 +477,17 @@ static VALUE
|
|
413
477
|
rb_comm_scatter(VALUE self, VALUE rb_sendbuf, VALUE rb_recvbuf, VALUE rb_root)
|
414
478
|
{
|
415
479
|
void *sendbuf = NULL, *recvbuf;
|
416
|
-
int sendcount = 0, recvcount;
|
417
|
-
MPI_Datatype sendtype =
|
480
|
+
int sendcount = 0, recvcount=0;
|
481
|
+
MPI_Datatype sendtype = 0, recvtype;
|
418
482
|
int root, rank, size;
|
419
483
|
struct _Comm *comm;
|
420
|
-
OBJ2C(rb_recvbuf, recvcount, recvbuf, recvtype);
|
484
|
+
OBJ2C(rb_recvbuf, recvcount, recvbuf, recvtype, 0);
|
421
485
|
root = NUM2INT(rb_root);
|
422
486
|
Data_Get_Struct(self, struct _Comm, comm);
|
423
487
|
check_error(MPI_Comm_rank(comm->Comm, &rank));
|
424
488
|
check_error(MPI_Comm_size(comm->Comm, &size));
|
425
489
|
if (rank == root) {
|
426
|
-
OBJ2C(rb_sendbuf, sendcount, sendbuf, sendtype);
|
490
|
+
OBJ2C(rb_sendbuf, sendcount, sendbuf, sendtype, 0);
|
427
491
|
if (sendcount > recvcount*size)
|
428
492
|
rb_raise(rb_eArgError, "recvbuf is too small");
|
429
493
|
sendcount = recvcount;
|
@@ -435,17 +499,17 @@ static VALUE
|
|
435
499
|
rb_comm_sendrecv(VALUE self, VALUE rb_sendbuf, VALUE rb_dest, VALUE rb_sendtag, VALUE rb_recvbuf, VALUE rb_source, VALUE rb_recvtag)
|
436
500
|
{
|
437
501
|
void *sendbuf, *recvbuf;
|
438
|
-
int sendcount, recvcount;
|
502
|
+
int sendcount=0, recvcount=0;
|
439
503
|
MPI_Datatype sendtype, recvtype;
|
440
504
|
int dest, source;
|
441
505
|
int sendtag, recvtag;
|
442
506
|
int size;
|
443
507
|
struct _Comm *comm;
|
444
508
|
MPI_Status *status;
|
445
|
-
OBJ2C(rb_sendbuf, sendcount, sendbuf, sendtype);
|
509
|
+
OBJ2C(rb_sendbuf, sendcount, sendbuf, sendtype, 0);
|
446
510
|
Data_Get_Struct(self, struct _Comm, comm);
|
447
511
|
check_error(MPI_Comm_size(comm->Comm, &size));
|
448
|
-
OBJ2C(rb_recvbuf, recvcount, recvbuf, recvtype);
|
512
|
+
OBJ2C(rb_recvbuf, recvcount, recvbuf, recvtype, 0);
|
449
513
|
dest = NUM2INT(rb_dest);
|
450
514
|
source = NUM2INT(rb_source);
|
451
515
|
sendtag = NUM2INT(rb_sendtag);
|
@@ -458,14 +522,14 @@ static VALUE
|
|
458
522
|
rb_comm_alltoall(VALUE self, VALUE rb_sendbuf, VALUE rb_recvbuf)
|
459
523
|
{
|
460
524
|
void *sendbuf, *recvbuf;
|
461
|
-
int sendcount, recvcount;
|
525
|
+
int sendcount=0, recvcount=0;
|
462
526
|
MPI_Datatype sendtype, recvtype;
|
463
527
|
int size;
|
464
528
|
struct _Comm *comm;
|
465
|
-
OBJ2C(rb_sendbuf, sendcount, sendbuf, sendtype);
|
529
|
+
OBJ2C(rb_sendbuf, sendcount, sendbuf, sendtype, 0);
|
466
530
|
Data_Get_Struct(self, struct _Comm, comm);
|
467
531
|
check_error(MPI_Comm_size(comm->Comm, &size));
|
468
|
-
OBJ2C(rb_recvbuf, recvcount, recvbuf, recvtype);
|
532
|
+
OBJ2C(rb_recvbuf, recvcount, recvbuf, recvtype, 0);
|
469
533
|
if (recvcount < sendcount)
|
470
534
|
rb_raise(rb_eArgError, "recvbuf is too small");
|
471
535
|
recvcount = recvcount/size;
|
@@ -477,18 +541,18 @@ static VALUE
|
|
477
541
|
rb_comm_reduce(VALUE self, VALUE rb_sendbuf, VALUE rb_recvbuf, VALUE rb_op, VALUE rb_root)
|
478
542
|
{
|
479
543
|
void *sendbuf, *recvbuf = NULL;
|
480
|
-
int sendcount, recvcount = 0;
|
481
|
-
MPI_Datatype sendtype, recvtype =
|
544
|
+
int sendcount=0, recvcount = 0;
|
545
|
+
MPI_Datatype sendtype, recvtype = 0;
|
482
546
|
int root, rank, size;
|
483
547
|
struct _Comm *comm;
|
484
548
|
struct _Op *op;
|
485
|
-
OBJ2C(rb_sendbuf, sendcount, sendbuf, sendtype);
|
549
|
+
OBJ2C(rb_sendbuf, sendcount, sendbuf, sendtype, 0);
|
486
550
|
root = NUM2INT(rb_root);
|
487
551
|
Data_Get_Struct(self, struct _Comm, comm);
|
488
552
|
check_error(MPI_Comm_rank(comm->Comm, &rank));
|
489
553
|
check_error(MPI_Comm_size(comm->Comm, &size));
|
490
554
|
if (rank == root) {
|
491
|
-
OBJ2C(rb_recvbuf, recvcount, recvbuf, recvtype);
|
555
|
+
OBJ2C(rb_recvbuf, recvcount, recvbuf, recvtype, 0);
|
492
556
|
if (recvcount != sendcount)
|
493
557
|
rb_raise(rb_eArgError, "sendbuf and recvbuf has the same length");
|
494
558
|
if (recvtype != sendtype)
|
@@ -502,16 +566,16 @@ static VALUE
|
|
502
566
|
rb_comm_allreduce(VALUE self, VALUE rb_sendbuf, VALUE rb_recvbuf, VALUE rb_op)
|
503
567
|
{
|
504
568
|
void *sendbuf, *recvbuf;
|
505
|
-
int sendcount, recvcount;
|
569
|
+
int sendcount=0, recvcount=0;
|
506
570
|
MPI_Datatype sendtype, recvtype;
|
507
571
|
int rank, size;
|
508
572
|
struct _Comm *comm;
|
509
573
|
struct _Op *op;
|
510
|
-
OBJ2C(rb_sendbuf, sendcount, sendbuf, sendtype);
|
574
|
+
OBJ2C(rb_sendbuf, sendcount, sendbuf, sendtype, 0);
|
511
575
|
Data_Get_Struct(self, struct _Comm, comm);
|
512
576
|
check_error(MPI_Comm_rank(comm->Comm, &rank));
|
513
577
|
check_error(MPI_Comm_size(comm->Comm, &size));
|
514
|
-
OBJ2C(rb_recvbuf, recvcount, recvbuf, recvtype);
|
578
|
+
OBJ2C(rb_recvbuf, recvcount, recvbuf, recvtype, 0);
|
515
579
|
if (recvcount != sendcount)
|
516
580
|
rb_raise(rb_eArgError, "sendbuf and recvbuf has the same length");
|
517
581
|
if (recvtype != sendtype)
|
@@ -529,7 +593,8 @@ rb_comm_get_Errhandler(VALUE self)
|
|
529
593
|
|
530
594
|
Data_Get_Struct(self, struct _Comm, comm);
|
531
595
|
rb_errhandler = Data_Make_Struct(cErrhandler, struct _Errhandler, NULL, Errhandler_free, errhandler);
|
532
|
-
|
596
|
+
errhandler->free = false;
|
597
|
+
check_error(MPI_Comm_get_errhandler(comm->Comm, &(errhandler->Errhandler)));
|
533
598
|
return rb_errhandler;
|
534
599
|
}
|
535
600
|
static VALUE
|
@@ -540,7 +605,7 @@ rb_comm_set_Errhandler(VALUE self, VALUE rb_errhandler)
|
|
540
605
|
|
541
606
|
Data_Get_Struct(self, struct _Comm, comm);
|
542
607
|
Data_Get_Struct(rb_errhandler, struct _Errhandler, errhandler);
|
543
|
-
MPI_Comm_set_errhandler(comm->Comm, errhandler->Errhandler);
|
608
|
+
check_error(MPI_Comm_set_errhandler(comm->Comm, errhandler->Errhandler));
|
544
609
|
return self;
|
545
610
|
}
|
546
611
|
static VALUE
|
@@ -607,6 +672,7 @@ void Init_mpi()
|
|
607
672
|
mMPI = rb_define_module("MPI");
|
608
673
|
rb_define_module_function(mMPI, "Init", rb_m_init, -1);
|
609
674
|
rb_define_module_function(mMPI, "Finalize", rb_m_finalize, -1);
|
675
|
+
rb_define_module_function(mMPI, "Abort", rb_m_abort, 2);
|
610
676
|
rb_define_const(mMPI, "VERSION", INT2NUM(MPI_VERSION));
|
611
677
|
rb_define_const(mMPI, "SUBVERSION", INT2NUM(MPI_SUBVERSION));
|
612
678
|
rb_define_const(mMPI, "SUCCESS", INT2NUM(MPI_SUCCESS));
|
@@ -620,8 +686,8 @@ void Init_mpi()
|
|
620
686
|
rb_define_method(cComm, "size", rb_comm_size, 0);
|
621
687
|
rb_define_method(cComm, "Send", rb_comm_send, 3);
|
622
688
|
rb_define_method(cComm, "Isend", rb_comm_isend, 3);
|
623
|
-
rb_define_method(cComm, "Recv", rb_comm_recv,
|
624
|
-
rb_define_method(cComm, "Irecv", rb_comm_irecv,
|
689
|
+
rb_define_method(cComm, "Recv", rb_comm_recv, -1);
|
690
|
+
rb_define_method(cComm, "Irecv", rb_comm_irecv, -1);
|
625
691
|
rb_define_method(cComm, "Gather", rb_comm_gather, 3);
|
626
692
|
rb_define_method(cComm, "Allgather", rb_comm_allgather, 2);
|
627
693
|
rb_define_method(cComm, "Bcast", rb_comm_bcast, 2);
|
data/lib/mpi/utils.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
module MPI
|
2
|
+
|
3
|
+
module_function
|
4
|
+
|
5
|
+
def task_divide(m, size)
|
6
|
+
dm = m.to_f/size
|
7
|
+
ary = Array.new(size)
|
8
|
+
ary[0] = dm.round
|
9
|
+
sum = ary[0]
|
10
|
+
(size-1).times do|i|
|
11
|
+
ary[i+1] = (dm*(i+2)).round - sum
|
12
|
+
sum += ary[i+1]
|
13
|
+
end
|
14
|
+
ary
|
15
|
+
end
|
16
|
+
|
17
|
+
end # module MPI
|
data/samples/hello.rb
CHANGED
@@ -4,13 +4,19 @@ MPI.Init
|
|
4
4
|
|
5
5
|
|
6
6
|
world = MPI::Comm::WORLD
|
7
|
+
|
8
|
+
if world.size == 1
|
9
|
+
print "Size is one, so do nothing\n"
|
10
|
+
exit
|
11
|
+
end
|
12
|
+
|
7
13
|
rank = world.rank
|
8
14
|
|
9
15
|
if rank == 0
|
10
16
|
(world.size-1).times do |i|
|
11
17
|
str ="\x00"*100
|
12
18
|
world.Recv(str, i+1, 0)
|
13
|
-
p str
|
19
|
+
p str.gsub(/\000/,"")
|
14
20
|
end
|
15
21
|
else
|
16
22
|
message = "Hello from #{rank}"
|
data/samples/narray.rb
CHANGED
@@ -0,0 +1,29 @@
|
|
1
|
+
require "mpi"
|
2
|
+
|
3
|
+
MPI.Init
|
4
|
+
|
5
|
+
|
6
|
+
world = MPI::Comm::WORLD
|
7
|
+
|
8
|
+
if world.size == 1
|
9
|
+
print "Size is one, so do nothing\n"
|
10
|
+
exit
|
11
|
+
end
|
12
|
+
|
13
|
+
rank = world.rank
|
14
|
+
size = world.size
|
15
|
+
|
16
|
+
length = 2
|
17
|
+
if rank == 0
|
18
|
+
a = NArray.float(length,size-1)
|
19
|
+
(size-1).times do |i|
|
20
|
+
world.Recv(a, i+1, 1, length, i*length)
|
21
|
+
end
|
22
|
+
p a
|
23
|
+
else
|
24
|
+
a = NArray.float(length).indgen + rank*10
|
25
|
+
world.Send(a, 0, 1)
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
MPI.Finalize
|
data/spec/ruby-mpi_spec.rb
CHANGED
@@ -34,14 +34,13 @@ describe "MPI" do
|
|
34
34
|
status = @world.Recv(str, i+1, tag)
|
35
35
|
status.source.should eql(i+1)
|
36
36
|
status.tag.should eql(tag)
|
37
|
-
status.error.should eq(MPI::SUCCESS)
|
38
37
|
str.should match(/\AHello from #{i+1}/)
|
39
38
|
end
|
40
39
|
end
|
41
40
|
end
|
42
41
|
|
43
42
|
it "should send and receive NArray" do
|
44
|
-
tag =
|
43
|
+
tag = 1
|
45
44
|
rank = @world.rank
|
46
45
|
[NArray[1,2,3], NArray[3.0,2.0,1.0]].each do |ary0|
|
47
46
|
ary0 = NArray[1,2,3]
|
@@ -52,7 +51,6 @@ describe "MPI" do
|
|
52
51
|
status = @world.Recv(ary1, i+1, tag)
|
53
52
|
status.source.should eql(i+1)
|
54
53
|
status.tag.should eql(tag)
|
55
|
-
status.error.should eq(MPI::SUCCESS)
|
56
54
|
ary1.should == ary0
|
57
55
|
end
|
58
56
|
end
|
@@ -60,14 +58,12 @@ describe "MPI" do
|
|
60
58
|
end
|
61
59
|
|
62
60
|
it "should send and receive without blocking" do
|
63
|
-
tag =
|
61
|
+
tag = 2
|
64
62
|
rank = @world.rank
|
65
63
|
message = "Hello from #{rank}"
|
66
64
|
if rank != 0
|
67
65
|
request = @world.Isend(message, 0, tag)
|
68
66
|
status = request.Wait
|
69
|
-
# status.source.should eql(rank)
|
70
|
-
status.tag.should eql(tag)
|
71
67
|
end
|
72
68
|
if rank == 0
|
73
69
|
(@world.size-1).times do |i|
|
data/test/test_utils.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require "test/unit"
|
2
|
+
|
3
|
+
$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
|
4
|
+
require "mpi/utils"
|
5
|
+
|
6
|
+
class TestMPIUtils < Test::Unit::TestCase
|
7
|
+
|
8
|
+
def setup
|
9
|
+
end
|
10
|
+
|
11
|
+
def teardown
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_task_divide
|
15
|
+
[[4,1], [6,3], [7,3], [15,4], [3, 7]].each do |m, size|
|
16
|
+
ary = MPI.task_divide(m, size)
|
17
|
+
assert ary.max-ary.min <= 1
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
metadata
CHANGED
@@ -1,86 +1,98 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-mpi
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
version: 0.2.0
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.0
|
6
5
|
platform: ruby
|
7
|
-
authors:
|
6
|
+
authors:
|
8
7
|
- Seiya Nishizawa
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
- !ruby/object:Gem::Dependency
|
11
|
+
date: 2014-05-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
16
14
|
name: rspec
|
17
|
-
requirement:
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
- !ruby/object:Gem::Version
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
22
19
|
version: 2.3.0
|
23
20
|
type: :development
|
24
21
|
prerelease: false
|
25
|
-
version_requirements:
|
26
|
-
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 2.3.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
27
28
|
name: bundler
|
28
|
-
requirement:
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
- !ruby/object:Gem::Version
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
33
|
version: 1.0.0
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
|
-
version_requirements:
|
37
|
-
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.0.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
38
42
|
name: jeweler
|
39
|
-
requirement:
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
- !ruby/object:Gem::Version
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
44
47
|
version: 1.5.2
|
45
48
|
type: :development
|
46
49
|
prerelease: false
|
47
|
-
version_requirements:
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.5.2
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: simplecov
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
56
62
|
type: :development
|
57
63
|
prerelease: false
|
58
|
-
version_requirements:
|
59
|
-
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
60
70
|
name: narray
|
61
|
-
requirement:
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
version: "0"
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
67
76
|
type: :development
|
68
77
|
prerelease: false
|
69
|
-
version_requirements:
|
70
|
-
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: A ruby binding of Message Passing Interface (MPI), which is an API specification
|
84
|
+
that allows processes to communicate with one another by sending and receiving messages.
|
71
85
|
email: seiya@gfd-dennou.org
|
72
86
|
executables: []
|
73
|
-
|
74
|
-
extensions:
|
87
|
+
extensions:
|
75
88
|
- ext/mpi/extconf.rb
|
76
|
-
extra_rdoc_files:
|
89
|
+
extra_rdoc_files:
|
77
90
|
- LICENSE.txt
|
78
91
|
- README.rdoc
|
79
|
-
files:
|
92
|
+
files:
|
80
93
|
- .document
|
81
94
|
- .rspec
|
82
95
|
- Gemfile
|
83
|
-
- Gemfile.lock
|
84
96
|
- LICENSE.txt
|
85
97
|
- README.rdoc
|
86
98
|
- Rakefile
|
@@ -88,41 +100,36 @@ files:
|
|
88
100
|
- ext/mpi/extconf.rb
|
89
101
|
- ext/mpi/mpi.c
|
90
102
|
- lib/mpi.rb
|
103
|
+
- lib/mpi/utils.rb
|
91
104
|
- ruby-mpi.gemspec
|
92
105
|
- samples/hello.rb
|
93
106
|
- samples/narray.rb
|
107
|
+
- samples/narray_offset.rb
|
94
108
|
- spec/ruby-mpi_spec.rb
|
95
109
|
- spec/spec_helper.rb
|
110
|
+
- test/test_utils.rb
|
96
111
|
homepage: http://github.com/seiya/ruby-mpi
|
97
|
-
licenses:
|
112
|
+
licenses:
|
98
113
|
- MIT
|
114
|
+
metadata: {}
|
99
115
|
post_install_message:
|
100
116
|
rdoc_options: []
|
101
|
-
|
102
|
-
require_paths:
|
117
|
+
require_paths:
|
103
118
|
- lib
|
104
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
none: false
|
115
|
-
requirements:
|
116
|
-
- - ">="
|
117
|
-
- !ruby/object:Gem::Version
|
118
|
-
version: "0"
|
119
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - '>='
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '0'
|
124
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
125
|
+
requirements:
|
126
|
+
- - '>='
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '0'
|
119
129
|
requirements: []
|
120
|
-
|
121
130
|
rubyforge_project:
|
122
|
-
rubygems_version: 1.
|
131
|
+
rubygems_version: 2.1.11
|
123
132
|
signing_key:
|
124
|
-
specification_version:
|
133
|
+
specification_version: 4
|
125
134
|
summary: A ruby binding of MPI
|
126
|
-
test_files:
|
127
|
-
- spec/ruby-mpi_spec.rb
|
128
|
-
- spec/spec_helper.rb
|
135
|
+
test_files: []
|
data/Gemfile.lock
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
GEM
|
2
|
-
remote: http://rubygems.org/
|
3
|
-
specs:
|
4
|
-
diff-lcs (1.1.2)
|
5
|
-
git (1.2.5)
|
6
|
-
jeweler (1.5.2)
|
7
|
-
bundler (~> 1.0.0)
|
8
|
-
git (>= 1.2.5)
|
9
|
-
rake
|
10
|
-
narray (0.5.9.9)
|
11
|
-
rake (0.8.7)
|
12
|
-
rcov (0.9.9)
|
13
|
-
rspec (2.3.0)
|
14
|
-
rspec-core (~> 2.3.0)
|
15
|
-
rspec-expectations (~> 2.3.0)
|
16
|
-
rspec-mocks (~> 2.3.0)
|
17
|
-
rspec-core (2.3.1)
|
18
|
-
rspec-expectations (2.3.0)
|
19
|
-
diff-lcs (~> 1.1.2)
|
20
|
-
rspec-mocks (2.3.0)
|
21
|
-
|
22
|
-
PLATFORMS
|
23
|
-
ruby
|
24
|
-
|
25
|
-
DEPENDENCIES
|
26
|
-
bundler (~> 1.0.0)
|
27
|
-
jeweler (~> 1.5.2)
|
28
|
-
narray
|
29
|
-
rcov
|
30
|
-
rspec (~> 2.3.0)
|