Algorithm-PageRank-XS

 view release on metacpan or  search on metacpan

XS.xs  view on Meta::CPAN

  p->dim_map = newHV();
  p->rev_map = newHV();
  p->num_elements = 0;
}

static size_t get_dim_map(pTHX_ pagerank p, SV * value) {
  STRLEN len;
  SV * retval;
  SV ** hvret;
  size_t result;
  char *val = SvPV(value, len);
  if (hv_exists(p->dim_map, val, len)) {
    hvret = hv_fetch(p->dim_map, val, len, 0);
    if (hvret != NULL) {
      if (SvIOKp(*hvret)) {
        return SvIV(*hvret);
      }
    }
  }
  /* Not in the map, continue adding it. */
  result = p->num_elements++;
  retval = sv_newmortal();

  SvREFCNT_inc(retval);
  sv_setiv(retval, result);
  hv_store(p->dim_map, val, len, retval, 0);

  SvREFCNT_inc(value);
  val = SvPV(retval, len);
  hv_store(p->rev_map, val, len, value, 0);

  return result;
}

MODULE = Algorithm::PageRank::XS	PACKAGE = Algorithm::PageRank::XS
PROTOTYPES: ENABLE

SV *
new(char *class, ...)
PREINIT:
  pagerank p;
  I32 i;
CODE:
  if (items % 2 == 0) croak("Odd number of elements in options");
  New(__LINE__, p, 1, struct pagerank);
  p->alpha = 0.85;
  p->max_tries = 200;
  p->convergence = 0.001;
  p->num_elements = 0;

  RETVAL = sv_newmortal();
  sv_setref_pv(RETVAL, class, (void *) p);

  for (i=1; i < items; i += 2)
    option(aTHX_ p, ST(i), ST(i + 1));

  p->dim_map = newHV();
  p->rev_map = newHV();
  p->main_table = table_init();
  SvREFCNT_inc(RETVAL);
OUTPUT:
  RETVAL


void
add_arc(pagerank p, ...)
  PREINIT:
    SV *from_, *to_;
    size_t from, to;
    I32 i;
    Array * tmp;
  CODE:
    if (items % 2 == 0) croak("Odd number of elements to describe arcs");

    for (i = 1; i < items; i += 2) {
      from_ = ST(i);
      to_ = ST(i + 1);
      from = get_dim_map(aTHX_ p, from_);
      to = get_dim_map(aTHX_ p, to_);

      if ((tmp = table_get(p->main_table, to)) == NULL)
        table_add(p->main_table, to, array_init(from));
      else
        array_push(tmp, from);
    }

void
from_file(pagerank p, SV * file)
  PREINIT:
    FILE * file_;
    STRLEN len, lenb;
    char * buffer, *t;
    I32 i;
    SV * tmp1;
    size_t from, to;
    Array * tmp;
    IO * io;
CODE:
    clear(aTHX_ p);
    New(__LINE__, buffer, 1024, char);

    if (SvROK(file) && SvTYPE(SvRV(file)) == SVt_PVGV &&
        (io = GvIO(SvRV(file)))) {
      /* We have a GLOB */
      file_ = fdopen(PerlIO_fileno(IoIFP(io)), "r");
      if (file_ == NULL)
        croak("Could not read from passed file reference");
    }
    else if (SvPOK(file)) {
      /* We have a file */
      t = SvPV(file, len);
      if (len == 0) {
        Perl_warner(aTHX_ packWARN(WARN_SYNTAX),
                    "file is empty, using stdin as default.");
        file_ = stdin;
      }
      else {
        file_ = fopen(t, "r");
        if (file_ == NULL)
          croak("Could not open file for reading.");
      }

XS.xs  view on Meta::CPAN

      to_ = *tmp2;

      from = get_dim_map(aTHX_ p, from_);
      to = get_dim_map(aTHX_ p, to_);

      if ((tmp = table_get(p->main_table, to)) == NULL)
        table_add(p->main_table, to, array_init(from));
      else
        array_push(tmp, from);
    }

void
iterate(SV * num)
  CODE:
  Perl_warner(aTHX_ packWARN(WARN_SYNTAX),
              "iterate() is not supported by Algorithm::PageRank::XS.");

SV *
result(pagerank p)
  PREINIT:
    HV * results;
    SV * curkey, * curval;
    int i;
    char * reskey;
    STRLEN len;
    Array * result;
    SV ** res;
  INIT:
    results = (AV *)sv_2mortal((SV *)newAV());
  CODE:
    if (p->num_elements < 2)
      croak("Only one element in pagerank table.");

    result = page_rank(p->main_table, p->num_elements, p->alpha, p->convergence,
                       p->max_tries);
    if (!result) {
      /* To prevent us from running twice. */
      clear(aTHX_ p);
      croak("pageRank calculation failed.");
    }

    results = newHV();
    curkey = sv_newmortal();
    for (i = 0; i < array_len(result); i++) {
      sv_setuv(curkey, i);
      reskey = SvPV(curkey, len);
      res = hv_fetch(p->rev_map, reskey, len, 0);
      if (res == NULL) {
        clear(aTHX_ p);
        croak("pageRank calculation failed -- couldn't find label");
      }

      reskey = SvPV(*res, len);

      curval = newSVnv(array_get(result, i));
      hv_store(results, reskey, len, curval, 0);
    }
    array_delete(result);
    RETVAL = newRV((SV *)results);
    clear(aTHX_ p);
  OUTPUT:
    RETVAL

void
DESTROY(pagerank p)
  PREINIT:
        SV *x;
  PPCODE:
        hv_undef(p->dim_map);
        hv_undef(p->rev_map);
        table_delete(p->main_table);
        Safefree(p);

BOOT:
  if (MAX_SIZE < 0) croak("signed size_t?");



( run in 0.491 second using v1.01-cache-2.11-cpan-13bb782fe5a )