Graph-Layout-Aesthetic
view release on metacpan or search on metacpan
#define PERL_NO_GET_CONTEXT /* we want efficiency */
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "ppport.h"
/* perl force */
#include "aesth.h"
typedef struct private {
SV *state_sv;
SV *force_sv;
SV *closure;
} *private;
declare_aesth(perl);
define_setup(perl) {
private private;
I32 count;
SV *s;
aglo_state tmp;
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
EXTEND(SP, 2);
PUSHs(sv_2mortal(newRV(force_sv)));
PUSHs(s = sv_2mortal(newRV(state_sv)));
PUTBACK;
tmp = C_CHECK(state_sv, "Graph::Layout::Aesthetic", "state_sv");
if (tmp != state) croak("state is not the struct referred by state_sv");
/* We don't check the class of force_sv. If the user wants to do evil
things, let him */
/* Temporarily increase refcounts on things we need later just in case
the "setup" method destroys their last reference */
sv_2mortal(SvREFCNT_inc(state_sv));
sv_2mortal(SvREFCNT_inc(force_sv));
count = call_method("setup", G_SCALAR);
if (count != 1) croak("Forced scalar context call succeeded in returning %d values. This is impossible", (int) count);
SPAGAIN;
Newc(__LINE__, private, sizeof(struct private) + (2*state->dimensions-1) * sizeof(aglo_real), char, struct private);
private->closure = SvREFCNT_inc(POPs);
private->state_sv = newRV(state_sv);
/* private->state_sv is effectively a self-reference */
sv_rvweaken(private->state_sv);
private->force_sv = newRV(force_sv);
PUTBACK;
FREETMPS;
LEAVE;
return private;
}
define_cleanup(perl) {
I32 count;
SV *f = PRIVATE->force_sv;
SV *s = PRIVATE->state_sv;
SV *c = PRIVATE->closure;
dSP;
Safefree(private);
ENTER;
SAVETMPS;
PUSHMARK(SP);
EXTEND(SP, 3);
PUSHs(sv_2mortal(f));
PUSHs(sv_2mortal(s));
PUSHs(sv_2mortal(c));
PUTBACK;
count = call_method("cleanup", G_VOID);
if (count) {
if (count < 0) croak("Forced void context call of 'cleanup' succeeded in returning %d values. This is impossible", (int) count);
SPAGAIN;
SP -= count;
PUTBACK;
}
FREETMPS;
LEAVE;
return;
}
define_aesth(perl) {
I32 count;
aglo_vertex j, v;
aglo_unsigned i, d;
AV *gav, *av;
SV *gradient_sv;
dSP;
ENTER;
SAVETMPS;
gav = newAV();
gradient_sv = sv_2mortal(newRV_noinc((SV *) gav));
d = state->dimensions;
v = state->graph->vertices;
av_extend(gav, v-1);
for (j=0; j<v; j++) {
av = newAV();
av_push(gav, newRV_noinc((SV *) av));
( run in 4.795 seconds using v1.01-cache-2.11-cpan-d8267643d1d )