You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

cIGraph_attribute_handler.c 18 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775
  1. #include "igraph.h"
  2. #include "ruby.h"
  3. #include "cIGraph.h"
  4. /* call-seq:
  5. * graph[u,v] -> Object
  6. *
  7. * Returns the object associated with the edge connecting vertices u and v.
  8. * Aliased to graph.get_edge_attr(u,v)
  9. */
  10. VALUE cIGraph_get_edge_attr(VALUE self, VALUE from, VALUE to){
  11. int idx;
  12. igraph_t *graph;
  13. VALUE e_ary;
  14. Data_Get_Struct(self, igraph_t, graph);
  15. e_ary = ((VALUE*)graph->attr)[1];
  16. idx = NUM2INT(cIGraph_get_eid(self, from, to, 1));
  17. return rb_ary_entry(e_ary,idx);
  18. }
  19. /* call-seq:
  20. * graph[u,v] = w
  21. *
  22. * Sets the object associated with the edge connecting vertices u and v.
  23. * Aliased to graph.set_edge_attr(u,v)
  24. */
  25. VALUE cIGraph_set_edge_attr(VALUE self, VALUE from, VALUE to, VALUE attr){
  26. int idx;
  27. igraph_t *graph;
  28. VALUE e_ary;
  29. Data_Get_Struct(self, igraph_t, graph);
  30. e_ary = ((VALUE*)graph->attr)[1];
  31. idx = NUM2INT(cIGraph_get_eid(self, from, to, 1));
  32. rb_ary_store(e_ary,idx,attr);
  33. return Qtrue;
  34. }
  35. /* call-seq:
  36. * graph.attributes -> Hash
  37. *
  38. * Returns the graph attributes. This is usually only used when reading in
  39. * graphs from GraphML format. Feel free to use instance variables on the
  40. * graph object if you like (they won't get copied though!).
  41. */
  42. VALUE cIGraph_graph_attributes(VALUE self){
  43. igraph_t *graph;
  44. VALUE hsh;
  45. Data_Get_Struct(self, igraph_t, graph);
  46. hsh = ((VALUE*)graph->attr)[2];
  47. return hsh;
  48. }
  49. igraph_attribute_table_t cIGraph_attribute_table = {
  50. cIGraph_attribute_init,
  51. cIGraph_attribute_destroy,
  52. cIGraph_attribute_copy,
  53. cIGraph_attribute_add_vertices,
  54. cIGraph_attribute_delete_vertices,
  55. cIGraph_attribute_add_edges,
  56. cIGraph_attribute_delete_edges,
  57. cIGraph_attribute_permute_edges,
  58. cIGraph_attribute_get_info,
  59. cIGraph_attribute_has_attr,
  60. cIGraph_attribute_get_type,
  61. cIGraph_get_numeric_graph_attr,
  62. cIGraph_get_string_graph_attr,
  63. cIGraph_get_numeric_vertex_attr,
  64. cIGraph_get_string_vertex_attr,
  65. cIGraph_get_numeric_edge_attr,
  66. cIGraph_get_string_edge_attr,
  67. };
  68. int cIGraph_attribute_init(igraph_t *graph, igraph_vector_ptr_t *attr) {
  69. VALUE* attrs;
  70. int i;
  71. VALUE key;
  72. VALUE value;
  73. attrs = (VALUE*)calloc(3, sizeof(VALUE));
  74. if(!attrs)
  75. IGRAPH_ERROR("Error allocating Arrays\n", IGRAPH_ENOMEM);
  76. //[0] is vertex array, [1] is edge array, [2] is graph attr
  77. attrs[0] = rb_ary_new();
  78. attrs[1] = rb_ary_new();
  79. attrs[2] = rb_hash_new();
  80. if(attr){
  81. for(i=0;i<igraph_vector_ptr_size(attr);i++){
  82. igraph_i_attribute_record_t *attr_rec;
  83. char *s;
  84. attr_rec = VECTOR(*attr)[i];
  85. key = rb_str_new2(attr_rec->name);
  86. switch (attr_rec->type) {
  87. case IGRAPH_ATTRIBUTE_NUMERIC:
  88. value=rb_float_new((double)VECTOR(*(igraph_vector_t*)attr_rec->value)[0]);
  89. break;
  90. case IGRAPH_ATTRIBUTE_STRING:
  91. igraph_strvector_get((igraph_strvector_t*)attr_rec->value, 0, &s);
  92. value=rb_str_new2(s);
  93. break;
  94. default:
  95. IGRAPH_WARNING("unsupported attribute type (not string and not numeric)");
  96. value=0;
  97. break;
  98. }
  99. if (value){
  100. rb_hash_aset((VALUE)attrs[2],key,value);
  101. }
  102. }
  103. }
  104. graph->attr = attrs;
  105. return IGRAPH_SUCCESS;
  106. }
  107. /* Destruction */
  108. void cIGraph_attribute_destroy(igraph_t *graph) {
  109. VALUE *attrs = (VALUE*)graph->attr;
  110. free(attrs);
  111. return;
  112. }
  113. /* Copying */
  114. int replace_i(VALUE key, VALUE val, VALUE hash){
  115. if (key != Qundef) {
  116. rb_hash_aset(hash, key, val);
  117. }
  118. //return ST_CONTINUE;
  119. return 0;
  120. }
  121. int cIGraph_attribute_copy(igraph_t *to, const igraph_t *from) {
  122. #ifdef DEBUG
  123. printf("Entering cIGraph_attribute_copy\n");
  124. #endif
  125. VALUE* attrs;
  126. VALUE vertex_array = ((VALUE*)from->attr)[0];
  127. VALUE edge_array = ((VALUE*)from->attr)[1];
  128. VALUE graph_attr = ((VALUE*)from->attr)[2];
  129. attrs = ALLOC_N(VALUE, 3);
  130. attrs[0] = rb_ary_dup(vertex_array);
  131. attrs[1] = rb_ary_dup(edge_array);
  132. attrs[2] = rb_hash_new();
  133. rb_hash_foreach(graph_attr, replace_i, attrs[2]);
  134. to->attr = attrs;
  135. #ifdef DEBUG
  136. printf("Leaving cIGraph_attribute_copy\n");
  137. #endif
  138. return IGRAPH_SUCCESS;
  139. }
  140. /* Adding vertices */
  141. int cIGraph_attribute_add_vertices(igraph_t *graph, long int nv, igraph_vector_ptr_t *attr) {
  142. #ifdef DEBUG
  143. printf("Entering cIGraph_attribute_add_vertices\n");
  144. #endif
  145. int i,j;
  146. VALUE vertex_array = ((VALUE*)graph->attr)[0];
  147. VALUE values;
  148. if(attr){
  149. if(igraph_vector_ptr_size(attr) > 0 && ((igraph_i_attribute_record_t*)VECTOR(*attr)[0])->type == IGRAPH_ATTRIBUTE_PY_OBJECT){
  150. values = (VALUE)((igraph_i_attribute_record_t*)VECTOR(*attr)[0])->value;
  151. Check_Type(values, T_ARRAY);
  152. for(i=0;i<RARRAY_LEN(values);i++){
  153. rb_ary_push(vertex_array, RARRAY_PTR(values)[i]);
  154. }
  155. //Otherwise read each attriute into hashes and use those
  156. } else {
  157. for(i=0;i<nv;i++){
  158. VALUE record;
  159. igraph_i_attribute_record_t *attr_rec;
  160. char *s;
  161. record = rb_hash_new();
  162. //For when no attributes are given
  163. if(igraph_vector_ptr_size(attr) == 0){
  164. record = INT2NUM(i+1);
  165. }
  166. for (j=0; j<igraph_vector_ptr_size(attr); j++) {
  167. VALUE key;
  168. VALUE value;
  169. //Add key value pair
  170. attr_rec = VECTOR(*attr)[j];
  171. key = rb_str_new2(attr_rec->name);
  172. switch (attr_rec->type) {
  173. case IGRAPH_ATTRIBUTE_NUMERIC:
  174. value=rb_float_new((double)VECTOR(*(igraph_vector_t*)attr_rec->value)[i]);
  175. break;
  176. case IGRAPH_ATTRIBUTE_STRING:
  177. igraph_strvector_get((igraph_strvector_t*)attr_rec->value, i, &s);
  178. value=rb_str_new2(s);
  179. break;
  180. default:
  181. IGRAPH_WARNING("unsupported attribute type (not string and not numeric)");
  182. value=Qnil;
  183. break;
  184. }
  185. rb_hash_aset(record,key,value);
  186. }
  187. rb_ary_push(vertex_array,record);
  188. }
  189. }
  190. } else {
  191. //Default: Add numbered vertices.
  192. for(i=0;i<nv;i++){
  193. rb_ary_push(vertex_array,INT2NUM(i));
  194. }
  195. }
  196. #ifdef DEBUG
  197. printf("Leaving cIGraph_attribute_add_vertices\n");
  198. #endif
  199. return IGRAPH_SUCCESS;
  200. }
  201. /* Deleting vertices */
  202. void cIGraph_attribute_delete_vertices(igraph_t *graph,
  203. const igraph_vector_t *eidx,
  204. const igraph_vector_t *vidx) {
  205. #ifdef DEBUG
  206. printf("Entering cIGraph_attribute_delete_vertices\n");
  207. #endif
  208. int i;
  209. VALUE vertex_array = ((VALUE*)graph->attr)[0];
  210. VALUE edge_array = ((VALUE*)graph->attr)[1];
  211. VALUE n_v_ary = rb_ary_new();
  212. VALUE n_e_ary = rb_ary_new();
  213. for(i=0;i<igraph_vector_size(vidx);i++){
  214. if(VECTOR(*vidx)[i] != 0)
  215. rb_ary_store(n_v_ary,VECTOR(*vidx)[i]-1,rb_ary_entry(vertex_array,i));
  216. }
  217. for(i=0;i<igraph_vector_size(eidx);i++){
  218. if(VECTOR(*eidx)[i] != 0)
  219. rb_ary_store(n_e_ary,VECTOR(*eidx)[i]-1,rb_ary_entry(edge_array,i));
  220. }
  221. ((VALUE*)graph->attr)[0] = n_v_ary;
  222. ((VALUE*)graph->attr)[1] = n_e_ary;
  223. #ifdef DEBUG
  224. printf("Leaving cIGraph_attribute_delete_vertices\n");
  225. #endif
  226. return;
  227. }
  228. /* Adding edges */
  229. int cIGraph_attribute_add_edges(igraph_t *graph,
  230. const igraph_vector_t *edges,
  231. igraph_vector_ptr_t *attr) {
  232. #ifdef DEBUG
  233. printf("Entering cIGraph_attribute_add_edges\n");
  234. #endif
  235. int i,j;
  236. VALUE edge_array = ((VALUE*)graph->attr)[1];
  237. VALUE values;
  238. if(attr){
  239. //If the only record is of type PY_OBJ then use the values as attributes
  240. if(((igraph_i_attribute_record_t*)VECTOR(*attr)[0])->type == IGRAPH_ATTRIBUTE_PY_OBJECT){
  241. values = (VALUE)((igraph_i_attribute_record_t*)VECTOR(*attr)[0])->value;
  242. Check_Type(values, T_ARRAY);
  243. for(i=0;i<RARRAY_LEN(values);i++){
  244. rb_ary_push(edge_array, RARRAY_PTR(values)[i]);
  245. }
  246. //Otherwise read each attriute into hashes and use those
  247. } else {
  248. for(i=0;i<igraph_vector_size(edges)/2;i++){
  249. VALUE record;
  250. igraph_i_attribute_record_t *attr_rec;
  251. char *s;
  252. record = rb_hash_new();
  253. for (j=0; j<igraph_vector_ptr_size(attr); j++) {
  254. VALUE key;
  255. VALUE value;
  256. //Add key value pair
  257. attr_rec = VECTOR(*attr)[j];
  258. key = rb_str_new2(attr_rec->name);
  259. switch (attr_rec->type) {
  260. case IGRAPH_ATTRIBUTE_NUMERIC:
  261. value=rb_float_new((double)VECTOR(*(igraph_vector_t*)attr_rec->value)[i]);
  262. break;
  263. case IGRAPH_ATTRIBUTE_STRING:
  264. igraph_strvector_get((igraph_strvector_t*)attr_rec->value, i, &s);
  265. value=rb_str_new2(s);
  266. break;
  267. default:
  268. IGRAPH_WARNING("unsupported attribute type (not string and not numeric)");
  269. value=Qnil;
  270. break;
  271. }
  272. rb_hash_aset(record,key,value);
  273. }
  274. rb_ary_push(edge_array,record);
  275. }
  276. }
  277. }
  278. #ifdef DEBUG
  279. printf("Leaving cIGraph_attribute_add_edges\n");
  280. #endif
  281. return IGRAPH_SUCCESS;
  282. }
  283. /* Deleting edges */
  284. void cIGraph_attribute_delete_edges(igraph_t *graph, const igraph_vector_t *idx) {
  285. #ifdef DEBUG
  286. printf("Entering cIGraph_attribute_delete_edges\n");
  287. #endif
  288. int i;
  289. VALUE edge_array = ((VALUE*)graph->attr)[1];
  290. VALUE n_e_ary = rb_ary_new();
  291. for(i=0;i<igraph_vector_size(idx);i++){
  292. if(VECTOR(*idx)[i] != 0)
  293. rb_ary_store(n_e_ary,VECTOR(*idx)[i]-1,rb_ary_entry(edge_array,i));
  294. }
  295. ((VALUE*)graph->attr)[1] = n_e_ary;
  296. #ifdef DEBUG
  297. printf("Leaving cIGraph_attribute_delete_edges\n");
  298. #endif
  299. return;
  300. }
  301. /* Permuting edges */
  302. int cIGraph_attribute_permute_edges(igraph_t *graph,
  303. const igraph_vector_t *idx) {
  304. #ifdef DEBUG
  305. printf("Entering cIGraph_attribute_permute_edges\n");
  306. #endif
  307. int i;
  308. VALUE edge_array = ((VALUE*)graph->attr)[1];
  309. VALUE n_e_ary = rb_ary_new();
  310. for(i=0;i<igraph_vector_size(idx);i++){
  311. rb_ary_push(n_e_ary,rb_ary_entry(edge_array,VECTOR(*idx)[i]));
  312. }
  313. ((VALUE*)graph->attr)[1] = n_e_ary;
  314. #ifdef DEBUG
  315. printf("Leaving cIGraph_attribute_permute_edges\n");
  316. #endif
  317. return 0;
  318. }
  319. VALUE keys_to_strvec(VALUE data, VALUE arr){
  320. VALUE key = rb_ary_entry(data, 0);
  321. VALUE val = rb_ary_entry(data, 1);
  322. VALUE rb_names = rb_ary_entry(arr, 0);
  323. VALUE rb_types = rb_ary_entry(arr, 1);
  324. VALUE str = StringValue(key);
  325. rb_ary_push(rb_names,str);
  326. if(TYPE(val) == T_STRING){
  327. rb_ary_push(rb_types,INT2FIX(IGRAPH_ATTRIBUTE_STRING));
  328. } else if (TYPE(val) == T_FLOAT || TYPE(val) == T_FIXNUM){
  329. rb_ary_push(rb_types,INT2FIX(IGRAPH_ATTRIBUTE_NUMERIC));
  330. } else {
  331. rb_ary_push(rb_types,INT2FIX(IGRAPH_ATTRIBUTE_PY_OBJECT));
  332. }
  333. return data;
  334. }
  335. /* Getting attribute names and types */
  336. int cIGraph_attribute_get_info(const igraph_t *graph,
  337. igraph_strvector_t *gnames,
  338. igraph_vector_t *gtypes,
  339. igraph_strvector_t *vnames,
  340. igraph_vector_t *vtypes,
  341. igraph_strvector_t *enames,
  342. igraph_vector_t *etypes) {
  343. #ifdef DEBUG
  344. printf("Entering cIGraph_attribute_get_info\n");
  345. #endif
  346. igraph_strvector_t *names[3] = { vnames, enames, gnames };
  347. igraph_vector_t *types[3] = { vtypes, etypes, gtypes };
  348. long int i,j;
  349. for (i=0; i<3; i++) {
  350. igraph_strvector_t *n = names[i];
  351. igraph_vector_t *t = types[i];
  352. VALUE rb_names = rb_ary_new();
  353. VALUE rb_types = rb_ary_new();
  354. VALUE obj_hash;
  355. //Graph attributes are different
  356. if (i != 2){
  357. VALUE store = ((VALUE*)graph->attr)[i];
  358. VALUE obj = RARRAY_PTR(store)[0];
  359. obj_hash = Qnil;
  360. if(rb_funcall(obj, rb_intern("respond_to?"), 1, rb_str_new2("to_hash")) == Qtrue){
  361. obj_hash = rb_funcall(obj, rb_intern("to_hash"), 0);
  362. }
  363. } else {
  364. obj_hash = ((VALUE*)graph->attr)[2];
  365. }
  366. if(!NIL_P(obj_hash)){
  367. //Take the keys of the hash, convert to strings and put in vector n
  368. rb_iterate(rb_each, obj_hash, keys_to_strvec, rb_ary_new3(2,rb_names,rb_types));
  369. }
  370. //Push names onto n and types onto t
  371. for(j=0;j<RARRAY_LEN(rb_names);j++){
  372. igraph_strvector_add(n, RSTRING_PTR(RARRAY_PTR(rb_names)[j]));
  373. igraph_vector_push_back(t, NUM2INT(RARRAY_PTR(rb_types)[j]));
  374. }
  375. }
  376. #ifdef DEBUG
  377. printf("Leaving cIGraph_attribute_get_info\n");
  378. #endif
  379. return 0;
  380. }
  381. /* Checks whether the graph has a graph/vertex/edge attribute with the given name */
  382. igraph_bool_t cIGraph_attribute_has_attr(const igraph_t *graph,
  383. igraph_attribute_elemtype_t type,
  384. const char* name) {
  385. #ifdef DEBUG
  386. printf("Entering cIGraph_attribute_has_attr\n");
  387. #endif
  388. long int attrnum;
  389. igraph_bool_t res = 0;
  390. VALUE obj;
  391. switch (type) {
  392. case IGRAPH_ATTRIBUTE_GRAPH: attrnum = 2; break;
  393. case IGRAPH_ATTRIBUTE_VERTEX: attrnum = 0; break;
  394. case IGRAPH_ATTRIBUTE_EDGE: attrnum = 1; break;
  395. default: return 0; break;
  396. }
  397. obj = ((VALUE*)graph->attr)[attrnum];
  398. if (attrnum != 2)
  399. obj = RARRAY_PTR(obj)[0];
  400. if(TYPE(obj) == T_HASH && rb_funcall(obj,rb_intern("include?"), 1, rb_str_new2(name))){
  401. res = 1;
  402. }
  403. #ifdef DEBUG
  404. printf("Leaving cIGraph_attribute_has_attr\n");
  405. #endif
  406. return res;
  407. }
  408. /* Returns the type of a given attribute */
  409. int cIGraph_attribute_get_type(const igraph_t *graph,
  410. igraph_attribute_type_t *type,
  411. igraph_attribute_elemtype_t elemtype,
  412. const char *name) {
  413. #ifdef DEBUG
  414. printf("Entering cIGraph_attribute_get_type\n");
  415. #endif
  416. long int attrnum;
  417. VALUE obj;
  418. VALUE val;
  419. switch (elemtype) {
  420. case IGRAPH_ATTRIBUTE_GRAPH: attrnum = 2; break;
  421. case IGRAPH_ATTRIBUTE_VERTEX: attrnum = 0; break;
  422. case IGRAPH_ATTRIBUTE_EDGE: attrnum = 1; break;
  423. default: return 0; break;
  424. }
  425. obj = ((VALUE*)graph->attr)[attrnum];
  426. if (attrnum != 2)
  427. obj = RARRAY_PTR(obj)[0];
  428. rb_funcall(obj,rb_intern("include?"), 1, rb_str_new2(name));
  429. if(rb_funcall(obj,rb_intern("include?"), 1, rb_str_new2(name))){
  430. val = rb_hash_aref(obj,rb_str_new2(name));
  431. if (TYPE(val) == T_STRING){
  432. *type = IGRAPH_ATTRIBUTE_STRING;
  433. } else if (TYPE(val) == T_FIXNUM || TYPE(val) == T_FLOAT){
  434. *type = IGRAPH_ATTRIBUTE_NUMERIC;
  435. } else {
  436. *type = IGRAPH_ATTRIBUTE_PY_OBJECT;
  437. }
  438. } else {
  439. *type = IGRAPH_ATTRIBUTE_PY_OBJECT;
  440. }
  441. #ifdef DEBUG
  442. printf("Leaving cIGraph_attribute_get_type\n");
  443. #endif
  444. return 0;
  445. }
  446. /* Getting numeric graph attributes */
  447. int cIGraph_get_numeric_graph_attr(const igraph_t *graph,
  448. const char *name, igraph_vector_t *value) {
  449. #ifdef DEBUG
  450. printf("Entering cIGraph_get_numeric_graph_attr\n");
  451. #endif
  452. VALUE val;
  453. val = rb_hash_aref(((VALUE*)graph->attr)[2],rb_str_new2(name));
  454. VECTOR(*value)[0] = NUM2DBL(val);
  455. #ifdef DEBUG
  456. printf("Leaving cIGraph_get_numeric_graph_attr\n");
  457. #endif
  458. return 0;
  459. }
  460. /* Getting string graph attributes */
  461. int cIGraph_get_string_graph_attr(const igraph_t *graph,
  462. const char *name, igraph_strvector_t *value) {
  463. #ifdef DEBUG
  464. printf("Entering cIGraph_get_string_graph_attr\n");
  465. #endif
  466. VALUE val;
  467. val = rb_hash_aref(((VALUE*)graph->attr)[2],rb_str_new2(name));
  468. igraph_strvector_set(value,0,RSTRING_PTR(val));
  469. #ifdef DEBUG
  470. printf("Leaving cIGraph_get_string_graph_attr\n");
  471. #endif
  472. return 0;
  473. }
  474. /* Getting numeric vertex attributes */
  475. int cIGraph_get_numeric_vertex_attr(const igraph_t *graph,
  476. const char *name,
  477. igraph_vs_t vs,
  478. igraph_vector_t *value) {
  479. #ifdef DEBUG
  480. printf("Entering cIGraph_get_numeric_vertex_attr\n");
  481. #endif
  482. VALUE array = ((VALUE*)graph->attr)[0];
  483. VALUE val, vertex;
  484. igraph_vit_t it;
  485. int i = 0;
  486. IGRAPH_CHECK(igraph_vit_create(graph, vs, &it));
  487. IGRAPH_FINALLY(igraph_vit_destroy, &it);
  488. IGRAPH_CHECK(igraph_vector_resize(value, IGRAPH_VIT_SIZE(it)));
  489. while(!IGRAPH_VIT_END(it)){
  490. vertex = RARRAY_PTR(array)[(int)IGRAPH_VIT_GET(it)];
  491. val = rb_hash_aref(vertex,rb_str_new2(name));
  492. if(val == Qnil)
  493. val = rb_float_new(NAN);
  494. VECTOR(*value)[i] = NUM2DBL(val);
  495. IGRAPH_VIT_NEXT(it);
  496. i++;
  497. }
  498. igraph_vit_destroy(&it);
  499. IGRAPH_FINALLY_CLEAN(1);
  500. #ifdef DEBUG
  501. printf("Leaving cIGraph_get_numeric_vertex_attr\n");
  502. #endif
  503. return 0;
  504. }
  505. /* Getting string vertex attributes */
  506. int cIGraph_get_string_vertex_attr(const igraph_t *graph,
  507. const char *name,
  508. igraph_vs_t vs,
  509. igraph_strvector_t *value) {
  510. #ifdef DEBUG
  511. printf("Entering cIGraph_get_string_vertex_attr\n");
  512. #endif
  513. VALUE array = ((VALUE*)graph->attr)[0];
  514. VALUE val, vertex;
  515. igraph_vit_t it;
  516. int i=0;
  517. IGRAPH_CHECK(igraph_vit_create(graph, vs, &it));
  518. IGRAPH_FINALLY(igraph_vit_destroy, &it);
  519. IGRAPH_CHECK(igraph_strvector_resize(value, IGRAPH_VIT_SIZE(it)));
  520. while(!IGRAPH_VIT_END(it)){
  521. vertex = RARRAY_PTR(array)[(int)IGRAPH_VIT_GET(it)];
  522. val = rb_hash_aref(vertex,rb_str_new2(name));
  523. if(val == Qnil)
  524. val = rb_str_new2("");
  525. igraph_strvector_set(value,i,RSTRING_PTR(val));
  526. IGRAPH_VIT_NEXT(it);
  527. i++;
  528. }
  529. igraph_vit_destroy(&it);
  530. IGRAPH_FINALLY_CLEAN(1);
  531. #ifdef DEBUG
  532. printf("Leaving cIGraph_get_string_vertex_attr\n");
  533. #endif
  534. return 0;
  535. }
  536. /* Getting numeric edge attributes */
  537. int cIGraph_get_numeric_edge_attr(const igraph_t *graph,
  538. const char *name,
  539. igraph_es_t es,
  540. igraph_vector_t *value) {
  541. #ifdef DEBUG
  542. printf("Entering cIGraph_get_numeric_edge_attr\n");
  543. #endif
  544. VALUE array = ((VALUE*)graph->attr)[1];
  545. VALUE val, vertex;
  546. igraph_eit_t it;
  547. int i = 0;
  548. IGRAPH_CHECK(igraph_eit_create(graph, es, &it));
  549. IGRAPH_FINALLY(igraph_eit_destroy, &it);
  550. IGRAPH_CHECK(igraph_vector_resize(value, IGRAPH_EIT_SIZE(it)));
  551. while(!IGRAPH_EIT_END(it)){
  552. vertex = RARRAY_PTR(array)[(int)IGRAPH_EIT_GET(it)];
  553. val = rb_hash_aref(vertex,rb_str_new2(name));
  554. if(val == Qnil)
  555. val = rb_float_new(NAN);
  556. VECTOR(*value)[i] = NUM2DBL(val);
  557. IGRAPH_EIT_NEXT(it);
  558. i++;
  559. }
  560. igraph_eit_destroy(&it);
  561. IGRAPH_FINALLY_CLEAN(1);
  562. #ifdef DEBUG
  563. printf("Leaving cIGraph_get_numeric_edge_attr\n");
  564. #endif
  565. return 0;
  566. }
  567. /* Getting string edge attributes */
  568. int cIGraph_get_string_edge_attr(const igraph_t *graph,
  569. const char *name,
  570. igraph_es_t es,
  571. igraph_strvector_t *value) {
  572. #ifdef DEBUG
  573. printf("Entering cIGraph_get_string_edge_attr\n");
  574. #endif
  575. VALUE array = ((VALUE*)graph->attr)[1];
  576. VALUE val, edge;
  577. igraph_eit_t it;
  578. int i=0;
  579. IGRAPH_CHECK(igraph_eit_create(graph, es, &it));
  580. IGRAPH_FINALLY(igraph_eit_destroy, &it);
  581. IGRAPH_CHECK(igraph_strvector_resize(value, IGRAPH_EIT_SIZE(it)));
  582. while(!IGRAPH_EIT_END(it)){
  583. edge = RARRAY_PTR(array)[(int)IGRAPH_EIT_GET(it)];
  584. val = rb_hash_aref(edge,rb_str_new2(name));
  585. if(val == Qnil)
  586. val = rb_str_new2("");
  587. //Fix for floats when required by ncol write
  588. val = rb_funcall(val,rb_intern("to_s"),0);
  589. igraph_strvector_set(value,i,RSTRING_PTR(val));
  590. IGRAPH_EIT_NEXT(it);
  591. i++;
  592. }
  593. igraph_eit_destroy(&it);
  594. IGRAPH_FINALLY_CLEAN(1);
  595. #ifdef DEBUG
  596. printf("Leaving cIGraph_get_string_edge_attr\n");
  597. #endif
  598. return 0;
  599. }

Ruby binding for the igraph library.