aboutsummaryrefslogtreecommitdiff
path: root/externals/gridflow/base/grid.h
diff options
context:
space:
mode:
Diffstat (limited to 'externals/gridflow/base/grid.h')
-rw-r--r--externals/gridflow/base/grid.h1146
1 files changed, 0 insertions, 1146 deletions
diff --git a/externals/gridflow/base/grid.h b/externals/gridflow/base/grid.h
deleted file mode 100644
index 9e971b99..00000000
--- a/externals/gridflow/base/grid.h
+++ /dev/null
@@ -1,1146 +0,0 @@
-/*
- $Id: grid.h,v 1.2 2006-03-15 04:37:08 matju Exp $
-
- GridFlow
- Copyright (c) 2001,2002,2003,2004,2005 by Mathieu Bouchard
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
-
- See file ../COPYING for further informations on licensing terms.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#ifndef __GF_GRID_H
-#define __GF_GRID_H
-
-// current version number as string literal
-#define GF_VERSION "0.8.1"
-#define GF_COMPILE_TIME __DATE__ ", " __TIME__
-
-#include <new>
-#include <vector>
-#include <stdlib.h>
-#include <string.h>
-#include <signal.h>
-#include <stdio.h>
-#include <math.h>
-
-#ifdef __APPLE__
-static inline void *memalign (size_t a, size_t n) {return malloc(n);}
-#else
-#include <malloc.h>
-#endif
-
-extern "C" {
-#include <ruby.h>
-#include <rubyio.h>
-#include <version.h>
-};
-
-#ifndef RUBY_H
-#error "Can't do anything without ruby.h"
-#endif
-
-#include "../config.h"
-
-#ifdef __WIN32__
-#define INT winINT
-#define random rand
-#undef send
-#undef close
-#define sigjmp_buf jmp_buf
-#define siglongjmp longjmp
-#endif
-
-#define BUG(s,args...) {fprintf(stderr,s "\nat: %s\n",args,__PRETTY_FUNCTION__); ::raise(11);}
-#define L gfpost("%s:%d in %s",__FILE__,__LINE__,__PRETTY_FUNCTION__);
-
-#ifdef IS_BRIDGE
-#define RAISE(args...) rb_raise(rb_eArgError,args)
-#else
-#define RAISE(args...) rb_raise0(__FILE__,__LINE__,__PRETTY_FUNCTION__,rb_eArgError,args)
-#endif
-
-// avoid ruby warning
-#ifndef rb_enable_super
-#define rb_enable_super(a,b) \
- if (RUBY_RELEASE_CODE < 20030716) rb_enable_super(a,b)
-#endif
-
-typedef VALUE Ruby;
-
-/* undocumented function from Ruby that is one thing we need to fix a very elusive bug
-that manifests itself when embedding ruby inside a plugin of another app. This exists
-for all versions of Ruby up to now, and I don't know when it gets fixed. */
-extern "C" void Init_stack(VALUE *addr);
-
-extern "C" {
-void rb_raise0(
-const char *file, int line, const char *func, VALUE exc, const char *fmt, ...)
-__attribute__ ((noreturn));
-};
-#define SI(_sym_) (rb_intern(#_sym_))
-#define SYM(_sym_) (ID2SYM(SI(_sym_)))
-#define DGS(_class_) \
- _class_ *self; \
- Data_Get_Struct(rself,_class_,self); \
- self->check_magic();
-
-// returns the size of a statically defined array
-// warning: does not work with STACK_ARRAY()
-#define COUNT(_array_) ((int)(sizeof(_array_) / sizeof((_array_)[0])))
-
-static inline long rb_str_len(Ruby s) {return RSTRING(s)->len;}
-static inline char *rb_str_ptr(Ruby s) {return RSTRING(s)->ptr;}
-static inline long rb_ary_len(Ruby s) {return RARRAY(s)->len;}
-static inline Ruby *rb_ary_ptr(Ruby s) {return RARRAY(s)->ptr;}
-static inline const char *rb_sym_name(Ruby sym) {return rb_id2name(SYM2ID(sym));}
-#define rb_str_pt(s,t) Pt<t>((t*)rb_str_ptr(s),rb_str_len(s))
-#define IEVAL(_self_,s) rb_funcall(_self_,SI(instance_eval),1,rb_str_new2(s))
-#define EVAL(s) rb_eval_string(s)
-#define rassert(_p_) if (!(_p_)) RAISE(#_p_);
-// because of older versions of Ruby (1.6.?)
-#define rb_obj_class(o) rb_funcall((o),SI(class),0)
-
-#define WATCH(n,ar) { \
- char foo[16*1024], *p=foo; p += sprintf(p,"%s: ",#ar); \
- for (int q=0; q<n; q++) p += sprintf(p,"%lld ",(long long)ar[q]); \
- gfpost("%s",foo);}
-
-// we're gonna override assert, so load it first, to avoid conflicts
-#include <assert.h>
-
-#undef assert
-#define assert(_expr_) \
- if (!(_expr_)) { \
- fprintf(stderr, "%s:%d: assertion failed: %s is false\n", \
- __FILE__, __LINE__, #_expr_); \
- ::abort(); }
-
-// disabling assertion checking?
-#ifndef HAVE_DEBUG
-#undef assert
-#define assert(_foo_)
-#endif
-
-#ifdef HAVE_TSC_PROFILING
-#define HAVE_PROFILING
-#endif
-
-#ifdef HAVE_PROFILING
-#define PROF(_self_) for (GFStackMarker gf_marker(_self_);gf_marker.once();)
-#else
-#define PROF(_self_)
-#endif // HAVE_PROFILING
-
-static inline Ruby PTR2FIX (const void *ptr) {
- long p = (long)ptr;
- if ((p&3)!=0) BUG("unaligned pointer: %p\n",ptr);
- return LONG2NUM(p>>2);
-}
-#define FIX2PTR(type,ruby) ((type *)(TO(long,ruby)<<2))
-
-//****************************************************************
-
-/* int32 was long before, now int, because of amd64 */
-typedef char int8; typedef unsigned char uint8;
-typedef short int16; typedef unsigned short uint16;
-typedef int int32; typedef unsigned int uint32;
-typedef long long int64;typedef unsigned long long uint64;
-typedef float float32;
-typedef double float64;
-
-// three-way comparison (T is assumed Comparable)
-template <class T> static inline T cmp(T a, T b) { return a<b ? -1 : a>b; }
-
-// a remainder function such that div2(a,b)*b+mod(a,b) = a and for which
-// mod(a,b) is in [0;b) or (b;0]. in contrast to C-language builtin a%b,
-// this one has uniform behaviour around zero.
-static inline int mod(int a, int b) {
-int c=a%b; c+=b&-(c&&(a<0)^(b<0)); return c;}
-
-// counterpart of mod(a,b), just like a/b and a%b are counterparts
-static inline int div2(int a, int b) {
-int c=a<0; return (a/b)-(c&&!!(a%b));}
-
-static inline int32 gf_abs( int32 a) { return a>0?a:-a; }
-static inline int64 gf_abs( int64 a) { return a>0?a:-a; }
-static inline float32 gf_abs(float32 a) { return fabs(a); }
-static inline float64 gf_abs(float64 a) { return fabs(a); }
-
-// integer powers in log(b) time. T is assumed Integer
-template <class T> static inline T ipow(T a, T b) {
- for(T r=1;;) {if (b&1) r*=a; b>>=1; if (!b) return r; a*=a;}
-}
-
-// kludge
-static inline float32 ipow(float32 a, float32 b) { return pow(a,b); }
-static inline float64 ipow(float64 a, float64 b) { return pow(a,b); }
-
-#undef min
-#undef max
-// minimum/maximum functions; T is assumed to be Comparable
-template <class T> static inline T min(T a, T b) { return a<b?a:b; }
-template <class T> static inline T max(T a, T b) { return a>b?a:b; }
-//template <class T> inline T min(T a, T b) { T c = (a-b)>>31; return (a&c)|(b&~c); }
-
-// greatest common divisor, by euclid's algorithm
-// this runs in log(a+b) number operations
-template <class T> static T gcd (T a, T b) {
- while (b) {T c=mod(a,b); a=b; b=c;}
- return a;
-}
-
-// greatest common divisor, the binary algorithm. haven't tried yet.
-template <class T> static T gcd2 (T a, T b) {
- int s=0;
- while ((a|b)&1==0) { a>>=1; b>>=1; s++; }
- while (a) {
- if (a&1==0) a>>=1;
- else if (b&1==0) b>>=1;
- else {T t=abs(a-b); if (a<b) b=t; else a=t;}
- }
- return b<<s;
-}
-
-// least common multiple; this runs in log(a+b) like gcd.
-template <class T> static inline T lcm (T a, T b) {return a*b/gcd(a,b);}
-
-// returns the position (0..31) of highest bit set in a word, or 0 if none.
-#define Z(N) if ((x>>N)&(((typeof(x))1<<N)-1)) { x>>=N; i+=N; }
-static int highest_bit(uint8 x) {int i=0; Z(4)Z(2)Z(1)return i;}
-static int highest_bit(uint16 x) {int i=0; Z(8)Z(4)Z(2)Z(1)return i;}
-static int highest_bit(uint32 x) {int i=0; Z(16)Z(8)Z(4)Z(2)Z(1)return i;}
-static int highest_bit(uint64 x) {int i=0;Z(32)Z(16)Z(8)Z(4)Z(2)Z(1)return i;}
-#undef Z
-// returns the position (0..31) of lowest bit set in a word, or 0 if none.
-template <class T> static int lowest_bit(T n) { return highest_bit((~n+1)&n); }
-
-static double drand() { return 1.0*rand()/(RAND_MAX+1.0); }
-
-// is little-endian
-static inline bool is_le() {int x=1; return ((char *)&x)[0];}
-
-#if defined(HAVE_PENTIUM)
-static inline uint64 rdtsc() {
- uint64 x; __asm__ volatile (".byte 0x0f, 0x31":"=A"(x)); return x;
-}
-#elif defined(HAVE_PPC)
-static inline uint64 rdtsc() {
-#include <mach/mach.h>
-#include <mach/mach_time.h>
-/* see AbsoluteToNanoseconds(), Microseconds()
-http://www.simdtech.org/apps/group_public/email/altivec/msg01956.html
-and mach_absolute_time() and mach_timebase_info(&info),
-then ns=(time*info.numer)/info.denom;
-and the timebase_info is constant
-(double)mach_absolute_time*gTimeBaseToNS*/
-return 0;
-}
-#else
-static inline uint64 rdtsc() {return 0;}
-#endif
-
-#ifdef HAVE_LITE
-#define EACH_INT_TYPE(MACRO) MACRO(uint8) MACRO(int16) MACRO(int32)
-#define EACH_FLOAT_TYPE(MACRO)
-#else
-#define EACH_INT_TYPE(MACRO) MACRO(uint8) MACRO(int16) MACRO(int32) MACRO(int64)
-#define EACH_FLOAT_TYPE(MACRO) MACRO(float32) MACRO(float64)
-#endif
-#define EACH_NUMBER_TYPE(MACRO) EACH_INT_TYPE(MACRO) EACH_FLOAT_TYPE(MACRO) MACRO(ruby)
-
-// note: loop unrolling macros assume N!=0
-// btw this may cause alignment problems when 8 does not divide N
-#define UNROLL_8(MACRO,N,PTR,ARGS...) \
- int n__=(-N)&7; PTR-=n__; N+=n__; \
- switch (n__) { start: \
- case 0:MACRO(0); case 1:MACRO(1); case 2:MACRO(2); case 3:MACRO(3); \
- case 4:MACRO(4); case 5:MACRO(5); case 6:MACRO(6); case 7:MACRO(7); \
- PTR+=8; N-=8; ARGS; if (N) goto start; }
-#define UNROLL_4(MACRO,N,PTR,ARGS...) \
- int n__=(-N)&3; PTR-=n__; N+=n__; \
- switch (n__) { start: \
- case 0:MACRO(0); case 1:MACRO(1); case 2:MACRO(2); case 3:MACRO(3); \
- PTR+=4; N-=4; ARGS; if (N) goto start; }
-
-//****************************************************************
-// my own little Ruby <-> C++ layer
-
-//struct Arg { Ruby a; };
-//struct ArgList { int n; Pt<Arg> v; };
-static inline bool INTEGER_P(Ruby x) {return FIXNUM_P(x)||TYPE(x)==T_BIGNUM;}
-static inline bool FLOAT_P(Ruby x) {return TYPE(x)==T_FLOAT;}
-#define INT(x) TO(int32,x)
-#define TO(t,x) convert(x,(t*)0)
-
-// not using NUM2INT because Ruby can convert Symbol to int
-// (by compatibility with Ruby 1.4)
-static inline int32 convert(Ruby x, int32 *foo) {
- if (INTEGER_P(x)) return NUM2INT(x);
- if (FLOAT_P(x)) return NUM2INT(rb_funcall(x,SI(round),0));
- RAISE("expected Integer or Float (got %s)",
- rb_str_ptr(rb_funcall(x,SI(inspect),0)));
-}
-static int16 convert(Ruby x, int16 *foo) {
- int v = INT(x);
- if (v<-0x8000 || v>=0x8000) RAISE("value %d is out of range",v);
- return v;}
-static uint16 convert(Ruby x, uint16 *foo) {
- int v = INT(x);
- if (v<0 || v>=0x10000) RAISE("value %d is out of range",v);
- return v;}
-static bool convert(Ruby x, bool *foo) {
- if (x==Qtrue) return true;
- if (x==Qfalse) return false;
- switch (TYPE(x)) {
- case T_FIXNUM: case T_BIGNUM: case T_FLOAT: return !!INT(x);
- default: RAISE("can't convert to bool");
- }
-}
-
-#ifdef HAVE_GCC64
-static uint64 convert(Ruby val, uint64 *foo) { return NUM2ULONG(val); }
-static int64 convert(Ruby val, int64 *foo) { return NUM2ULONG(val); }
-static Ruby gf_ull2num(uint64 val) { return ULONG2NUM(val); }
-static Ruby gf_ll2num(uint64 val) { return LONG2NUM(val); }
-#else
-static uint64 convert(Ruby val, uint64 *foo) {
- if (FIXNUM_P(val)) return (uint64)FIX2LONG(val);
- if (TYPE(val)!=T_BIGNUM) RAISE("type error");
- uint64 v = (uint64)NUM2UINT(rb_funcall(val,SI(>>),1,INT2FIX(32))) << 32;
- return v + NUM2UINT(rb_funcall(val,SI(&),1,UINT2NUM(0xffffffff)));}
-static int64 convert(Ruby val, int64 *foo) {
- if (FIXNUM_P(val)) return (int64)FIX2LONG(val);
- if (TYPE(val)!=T_BIGNUM) RAISE("type error");
- int64 v = (int64)NUM2INT(rb_funcall(val,SI(>>),1,INT2FIX(32))) << 32;
- return v + NUM2UINT(rb_funcall(val,SI(&),1,UINT2NUM(0xffffffff)));}
-static Ruby gf_ull2num(uint64 val) {
- Ruby x = rb_funcall(UINT2NUM((uint32)(val>>32)),SI(<<),1,INT2FIX(32));
- return rb_funcall(x,SI(+),1,UINT2NUM((uint32)val));}
-static Ruby gf_ll2num(int64 val) {
- Ruby x = rb_funcall( INT2NUM(( int32)(val>>32)),SI(<<),1,INT2FIX(32));
- return rb_funcall(x,SI(+),1,UINT2NUM((uint32)val));}
-#endif
-
-static long convert(Ruby x, long *foo) {
- return sizeof(long)==sizeof(int32) ?
- convert(x,(int32 *)0) :
- convert(x,(int64 *)0);
-}
-
-static float64 convert(Ruby x, float64 *foo) {
- if (INTEGER_P(x)) return INT(x);
- if (TYPE(x)!=T_FLOAT) RAISE("not a Float");
- return ((RFloat*)x)->value;}
-static float32 convert(Ruby x, float32 *foo) {
- return (float32) convert(x,(float64 *)0);}
-typedef Ruby Symbol, Array, String, Integer;
-static Ruby convert(Ruby x, Ruby *bogus) { return x; }
-typedef Ruby (*RMethod)(...); /* !@#$ fishy */
-
-#define BUILTIN_SYMBOLS(MACRO) \
- MACRO(_grid,"grid") MACRO(_bang,"bang") MACRO(_float,"float") \
- MACRO(_list,"list") MACRO(_sharp,"#") \
- MACRO(iv_outlets,"@outlets") \
- MACRO(iv_ninlets,"@ninlets") \
- MACRO(iv_noutlets,"@noutlets")
-extern struct BuiltinSymbols {
-#define FOO(_sym_,_str_) Ruby _sym_;
-BUILTIN_SYMBOLS(FOO)
-#undef FOO
-} bsym;
-
-typedef struct R {
- VALUE r;
- R() {r=Qnil;}
- R(int x) {r=INT2NUM(x);}
- R(unsigned x) {r=UINT2NUM(x);}
- R(long x) {r=LONG2NUM(x);}
- R(unsigned long x) {r=ULONG2NUM(x);}
- R(double x) {r=rb_float_new(x);}
- R( int64 x) {r= gf_ll2num(x);}
- R(uint64 x) {r=gf_ull2num(x);}
- operator bool() {return !!INT2NUM(r);}
- operator uint8 () {return INT2NUM(r);}
- operator int16 () {return INT2NUM(r);}
- operator int32 () {return INT2NUM(r);}
- operator int64 () {return convert(r,(int64*)0);}
- operator float32 () {return convert(r,(float32*)0);}
- operator float64 () {return convert(r,(float64*)0);}
-#define FOO(As,Op) \
- R &operator As (int x) {r=rb_funcall(r, SI(Op),1,INT2NUM(x)); return *this;}
- FOO(+=,+) FOO(-=,-) FOO(*=,*) FOO(/=,/) FOO(%=,%)
- FOO(&=,&) FOO(|=,|) FOO(^=,^) FOO(<<=,<<) FOO(>>=,>>)
-#undef FOO
-// bool operator == (int x) {return rb_funcall(r,SI(==),1,INT2NUM(x));}
-#define FOO(Op) \
- R operator Op (R x) {return rb_funcall(r,SI(Op),1,x.r);} \
- R operator Op (int x) {return rb_funcall(r,SI(Op),1,INT2NUM(x));}
- FOO(+) FOO(-) FOO(*) FOO(/) FOO(%)
- FOO(&) FOO(|) FOO(^) FOO(<<) FOO(>>)
- FOO(<) FOO(>) FOO(<=) FOO(>=) FOO(==) FOO(!=)
-#undef FOO
- static R value(VALUE r) {R x; x.r=r; return x;}
-} ruby;
-
-static R operator -(int a, R b) {return rb_funcall(a,SI(Op),1,INT2NUM(b.r));}
-
-static inline R ipow(R a, R b) {return R::value(rb_funcall(a.r,SI(**),1,b.r));}
-static inline R gf_abs(R a) { return R::value(rb_funcall(a.r,SI(abs),0)); }
-static inline R cmp(R a, R b) { return R::value(rb_funcall(a.r,SI(<=>),1,b.r));}
-
-//****************************************************************
-// hook into pointer manipulation. will help find memory corruption bugs.
-
-template <class T> class Pt {
-typedef ptrdiff_t /* and not int nor long */ Z;
-public:
- T *p;
-#ifdef HAVE_DEBUG
- T *start;
- Z n;
- Pt() : p(0), start(0), n(0) {}
- Pt(T *q, Z _n) : p(q), start(q), n(_n) {}
- Pt(T *q, Z _n, T *_start) : p(q), start(_start), n(_n) {}
-#else
- Pt() : p(0) {}
- Pt(T *q, Z _n, T *_start=0) : p(q) {}
-#endif
- T &operator *() { return *p; }
- Pt operator+=(Z i) { p+=i; return *this; }
- Pt operator-=(Z i) { p-=i; return *this; }
- Pt operator++( ) { p++; return *this; }
- Pt operator--( ) { p--; return *this; }
- Pt operator++(int) { Pt f(*this); ++*this; return f; }
- Pt operator--(int) { Pt f(*this); --*this; return f; }
- T &operator[](Z i) {
-#ifdef HAVE_DEBUG_HARDER
- if (!(p+i>=start && p+i<start+n))
- BUG("BUFFER OVERFLOW: 0x%08lx[%ld]=0x%08lx is not in 0x%08lx..0x%08lx",
- (long)p, (long)i, (long)(p+i),(long)start,(long)(start+n));
-#endif
- return p[i];
- }
-
- void will_use(int k) {
-#ifdef HAVE_DEBUG_HARDER
- if (k==0) return;
- T *q = p+k;
- if (!(p>=start && p<start+n && q>=start && q<=start+n))
- BUG("BUFFER OVERFLOW: 0x%08lx...0x%08lx is not all inside 0x%08lx...0x%08lx",
- (long)p,(long)q,start,(long)(start+n));
-#endif
- }
-
- Z operator-(Pt x) { return p-x.p; }
- operator bool () { return (bool )p; }
- operator void *() { return (void *)p; }
- operator int8 *() { return (int8 *)p; }
-
-/* how do i make typecast operators that are not also default conversions??? */
-/* this should be found so i can clean up the following: */
-#define FOO(S) operator S *() { return (S *)p; }
-EACH_NUMBER_TYPE(FOO)
-#undef FOO
-#ifdef HAVE_DEBUG
-#define FOO(S) operator Pt<S>() { return Pt<S>((S *)p,n*sizeof(T)/1,(S *)start); }
-EACH_NUMBER_TYPE(FOO)
-#undef FOO
-#else
-#define FOO(S) operator Pt<S>() { return Pt<S>((S *)p,0); }
-EACH_NUMBER_TYPE(FOO)
-#undef FOO
-#endif
-/* end 0.8 (TESTING) */
-
-#ifdef HAVE_DEBUG
- template <class U> Pt operator+(U x) { return Pt(p+x,n,start); }
- template <class U> Pt operator-(U x) { return Pt(p-x,n,start); }
-#else
- template <class U> Pt operator+(U x) { return Pt(p+x,0); }
- template <class U> Pt operator-(U x) { return Pt(p-x,0); }
-#endif
-};
-
-//template <class T> class P : Pt<T> {};
-//a reference counting pointer class
-template <class T> class P {
-public:
-#define INCR if (p) p->refcount++;
-#define DECR if (p) {p->refcount--; if (!p->refcount) delete p;}
- T *p;
- P() : p(0) {}
- P(T *_p) { p = _p; INCR; }
- P(const P<T> &_p) { p = _p.p; INCR; }
- P<T> &operator =(T * _p) { DECR; p=_p; INCR; return *this; }
- P<T> &operator =(P<T> _p) { DECR; p=_p.p; INCR; return *this; }
- bool operator ==(P<T> _p) { return p == _p.p; }
- bool operator !=(P<T> _p) { return p != _p.p; }
- ~P() { DECR; }
- bool operator !(){ return !p; }
- operator bool() { return !!p; }
- T &operator *() { return *p; }
- T *operator ->() { return p; }
-//#undef INCR
-//#undef DECR
-};
-
-#ifndef IS_BRIDGE
-extern "C" void *gfmalloc(size_t n);
-extern "C" void gffree(void *p);
-// note that C++ (GCC 3.4) now refuses the :: prefix so i removed it in the 4 following lines:
-inline void *operator new (size_t n) { return gfmalloc(n); }
-inline void *operator new[] (size_t n) { return gfmalloc(n); }
-inline void operator delete (void *p) { gffree(p); }
-inline void operator delete[] (void *p) { gffree(p); }
-#endif
-
-#define STACK_ARRAY(T,V,N) T V##_foo[N]; Pt<T> V(V##_foo,N);
-#define ARRAY_NEW(T,N) (Pt<T>((T *)new T[N],N))
-
-void gfmemcopy(uint8 *out, const uint8 *in, int n);
-template <class T> inline void COPY(Pt<T> dest, Pt<T> src, int n) {
- src.will_use(n); dest.will_use(n);
- gfmemcopy((uint8*)dest,(const uint8*)src,n*sizeof(T));
-}
-template <class T> inline void CLEAR(Pt<T> dest, int n) {
- dest.will_use(n);
- memset(dest,0,n*sizeof(T));
-}
-template <class T> static void memswap (Pt<T> a, Pt<T> b, int n) {
- STACK_ARRAY(T,c,n); COPY(c,a,n); COPY(a,b,n); COPY(b,c,n);
-}
-
-//****************************************************************
-// CObject is the base class for C++ classes that get exported to Ruby.
-// BTW: It's quite convenient to have virtual-methods in the base class
-// because otherwise the vtable* isn't at the beginning of the object
-// and that's pretty confusing to a lot of people, especially when simple
-// casting causes a pointer to change its value.
-struct CObject {
-#define OBJECT_MAGIC 1618033989
- int32 magic;
- int32 refcount;
- Ruby rself; // point to Ruby peer
- CObject() : magic(OBJECT_MAGIC), refcount(0), rself(0) {}
- void check_magic () {
- if (magic != OBJECT_MAGIC) {
- fprintf(stderr,"Object memory corruption! (ask the debugger)\n");
- for (int i=-2; i<=2; i++)
- fprintf(stderr,"this[%d]=0x%08x\n",i,((int*)this)[i]);
- raise(11);
- }
- }
- virtual ~CObject() { magic = 0xDEADBEEF; }
- virtual void mark() {} // not used for now
-};
-void CObject_free (void *);
-
-// you shouldn't use MethodDecl directly (used by source_filter.rb)
-struct MethodDecl { const char *selector; RMethod method; };
-void define_many_methods(Ruby rself, int n, MethodDecl *methods);
-extern Ruby mGridFlow, cFObject, cGridObject, cFormat;
-
-//****************************************************************
-// a Dim is a list of dimensions that describe the shape of a grid
-\class Dim < CObject
-struct Dim : CObject {
- static const int MAX_DIM=16; // maximum number of dimensions in a grid
- int n;
- Pt<int32> v; // safe pointer
- int32 v2[MAX_DIM]; // real stuff
- void check(); // test invariants
- Dim(int n, Pt<int32> v) { this->v = Pt<int32>(v2,MAX_DIM); this->n = n; COPY(this->v,v,n); check();}
- Dim(int n, int32 *v) { this->v = Pt<int32>(v2,MAX_DIM); this->n = n; COPY(this->v,Pt<int32>(v,n),n); check();}
- Dim() {v=Pt<int32>(v2,MAX_DIM); n=0; check();}
- Dim(int a) {v=Pt<int32>(v2,MAX_DIM); n=1;v[0]=a; check();}
- Dim(int a,int b) {v=Pt<int32>(v2,MAX_DIM); n=2;v[0]=a;v[1]=b; check();}
- Dim(int a,int b,int c){v=Pt<int32>(v2,MAX_DIM); n=3;v[0]=a;v[1]=b;v[2]=c;check();}
- int count() {return n;}
- int get(int i) { return v[i]; }
- int32 prod(int start=0, int end=-1) {
- if (end<0) end+=n;
- int32 tot=1;
- for (int i=start; i<=end; i++) tot *= v[i];
- return tot;
- }
- char *to_s();
- bool equal(P<Dim> o) {
- if (n!=o->n) return false;
- for (int i=0; i<n; i++) if (v[i]!=o->v[i]) return false;
- return true;
- }
-};
-\end class Dim
-
-//****************************************************************
-//BitPacking objects encapsulate optimised loops of conversion
-struct BitPacking;
-// those are the types of the optimised loops of conversion
-// inputs are const
-struct Packer {
-#define FOO(S) void (*as_##S)(BitPacking *self, int n, Pt<S> in, Pt<uint8> out);
-EACH_INT_TYPE(FOO)
-#undef FOO
-};
-struct Unpacker {
-#define FOO(S) void (*as_##S)(BitPacking *self, int n, Pt<uint8> in, Pt<S> out);
-EACH_INT_TYPE(FOO)
-#undef FOO
-};
-
-\class BitPacking < CObject
-struct BitPacking : CObject {
- Packer *packer;
- Unpacker *unpacker;
- unsigned int endian; // 0=big, 1=little, 2=same, 3=different
- int bytes;
- int size;
- uint32 mask[4];
- BitPacking(){::abort();} // don't call, but don't remove. sorry.
- BitPacking(int endian, int bytes, int size, uint32 *mask,
- Packer *packer=0, Unpacker *unpacker=0);
- bool is_le();
- bool eq(BitPacking *o);
- \decl void initialize(Ruby foo1, Ruby foo2, Ruby foo3);
- \decl String pack2(String ins, String outs=Qnil);
- \decl String unpack2(String ins, String outs=Qnil);
- \decl String to_s();
-// main entrances to Packers/Unpackers
- template <class T> void pack( int n, Pt<T> in, Pt<uint8> out);
- template <class T> void unpack(int n, Pt<uint8> in, Pt<T> out);
-};
-\end class
-
-int high_bit(uint32 n);
-int low_bit(uint32 n);
-void swap32 (int n, Pt<uint32> data);
-void swap16 (int n, Pt<uint16> data);
-
-#define NT_UNSIGNED (1<<0)
-#define NT_FLOAT (1<<1)
-#define NT_UNIMPL (1<<2)
-#define NUMBER_TYPE_LIMITS(T,a,b,c) \
- inline T nt_smallest(T *bogus) {return a;} \
- inline T nt_greatest(T *bogus) {return b;} \
- inline T nt_all_ones(T *bogus) {return c;}
-
-NUMBER_TYPE_LIMITS( uint8,0,255,255)
-NUMBER_TYPE_LIMITS( int16,-0x8000,0x7fff,-1)
-NUMBER_TYPE_LIMITS( int32,-0x80000000,0x7fffffff,-1)
-NUMBER_TYPE_LIMITS( int64,-0x8000000000000000LL,0x7fffffffffffffffLL,-1)
-NUMBER_TYPE_LIMITS(float32,-HUGE_VAL,+HUGE_VAL,(RAISE("all_ones"),0))
-NUMBER_TYPE_LIMITS(float64,-HUGE_VAL,+HUGE_VAL,(RAISE("all_ones"),0))
-NUMBER_TYPE_LIMITS( ruby,ruby(-HUGE_VAL),ruby(+HUGE_VAL),(RAISE("all_ones"),0))
-
-#ifdef HAVE_LITE
-#define NT_NOTLITE NT_UNIMPL
-#define NONLITE(x...)
-#else
-#define NT_NOTLITE 0
-#define NONLITE(x...) x
-#endif
-#define NUMBER_TYPES(MACRO) \
- MACRO( uint8, 8,NT_UNSIGNED, "u8,b") MACRO( int8, 8,NT_UNIMPL, "i8") \
- MACRO( uint16,16,NT_UNSIGNED|NT_UNIMPL, "u16") MACRO(int16,16,0, "i16,s") \
- MACRO( uint32,32,NT_UNSIGNED|NT_UNIMPL, "u32") MACRO(int32,32,0, "i32,i") \
- MACRO( uint64,64,NT_UNSIGNED|NT_UNIMPL, "u64") MACRO(int64,64,NT_NOTLITE, "i64,l") \
- MACRO(float32,32,NT_NOTLITE|NT_FLOAT, "f32,f") \
- MACRO(float64,64,NT_NOTLITE|NT_FLOAT, "f64,d") \
- MACRO( ruby,sizeof(long),NT_NOTLITE,"r")
-
-enum NumberTypeE {
-#define FOO(_sym_,args...) _sym_##_e,
-NUMBER_TYPES(FOO)
-#undef FOO
- number_type_table_end
-};
-
-#define FOO(_type_) \
-inline NumberTypeE NumberTypeE_type_of(_type_ &x) { \
- return _type_##_e; }
-EACH_NUMBER_TYPE(FOO)
-#undef FOO
-
-\class NumberType < CObject
-struct NumberType : CObject {
- Ruby /*Symbol*/ sym;
- const char *name;
- int size;
- int flags;
- const char *aliases;
- NumberTypeE index;
- NumberType(const char *name_, int size_, int flags_, const char *aliases_) :
- name(name_), size(size_), flags(flags_), aliases(aliases_) {}
- \decl Symbol sym_m();
- \decl int size_m();
- \decl int flags_m();
- \decl int index_m();
-};
-\end class
-
-NumberTypeE NumberTypeE_find (Ruby sym);
-
-#define TYPESWITCH(T,C,E) switch (T) { \
- case uint8_e: C(uint8) break; case int16_e: C(int16) break; \
- case int32_e: C(int32) break; NONLITE(case int64_e: C(int64) break; \
- case float32_e: C(float32) break; case float64_e: C(float64) break; \
- case ruby_e: C(ruby) break;) \
- default: E; RAISE("type '%s' not available here",number_type_table[T].sym);}
-#define TYPESWITCH_JUSTINT(T,C,E) switch (T) { \
- case uint8_e: C(uint8) break; case int16_e: C(int16) break; \
- case int32_e: C(int32) break; NONLITE(case int64_e: C(int64) break;) \
- default: E; RAISE("type '%s' not available here",number_type_table[T].sym);}
-
-// Numop objects encapsulate optimised loops of simple operations
-
-enum LeftRight { at_left, at_right };
-
-template <class T>
-struct NumopOn : CObject {
- // Function Vectorisations
- typedef void (*Map )( int n, T *as, T b ); Map op_map;
- typedef void (*Zip )( int n, T *as, T *bs); Zip op_zip;
- typedef void (*Fold)(int an, int n, T *as, T *bs); Fold op_fold;
- typedef void (*Scan)(int an, int n, T *as, T *bs); Scan op_scan;
- // Algebraic Properties (those involving simply numeric types)
- typedef bool (*AlgebraicCheck)(T x, LeftRight side);
- // neutral: right: forall y {f(x,y)=x}; left: forall x {f(x,y)=y};
- // absorbent: right: exists a forall y {f(x,y)=a}; ...
- T (*neutral)(LeftRight); // default neutral: e.g. 0 for addition, 1 for multiplication
- AlgebraicCheck is_neutral, is_absorbent;
- NumopOn(Map m, Zip z, Fold f, Scan s, T (*neu)(LeftRight), AlgebraicCheck n, AlgebraicCheck a) :
- op_map(m), op_zip(z), op_fold(f), op_scan(s), neutral(neu), is_neutral(n), is_absorbent(a) {}
- NumopOn() {}
- NumopOn(const NumopOn &z) {
- op_map = z.op_map; op_zip = z.op_zip;
- op_fold = z.op_fold; op_scan = z.op_scan;
- is_neutral = z.is_neutral; neutral = z.neutral;
- is_absorbent = z.is_absorbent; }
-};
-
-// semigroup property: associativity: f(a,f(b,c))=f(f(a,b),c)
-#define OP_ASSOC (1<<0)
-// abelian property: commutativity: f(a,b)=f(b,a)
-#define OP_COMM (1<<1)
-
-\class Numop < CObject
-struct Numop : CObject {
- Ruby /*Symbol*/ sym;
- const char *name;
- int flags;
-//private:
-#define FOO(T) \
- NumopOn<T> on_##T; \
- NumopOn<T> *on(T &foo) { \
- if (!on_##T.op_map) \
- RAISE("operator %s does not support type "#T,rb_sym_name(sym)); \
- return &on_##T;}
-EACH_NUMBER_TYPE(FOO)
-#undef FOO
-//public:
- template <class T> inline void map(int n, Pt<T> as, T b) {
- as.will_use(n);
- on(*as)->op_map(n,(T *)as,b);}
- template <class T> inline void zip(int n, Pt<T> as, Pt<T> bs) {
- as.will_use(n);
- bs.will_use(n);
- on(*as)->op_zip(n,(T *)as,(T *)bs);}
- template <class T> inline void fold(int an, int n, Pt<T> as, Pt<T> bs) {
- as.will_use(an);
- bs.will_use(an*n);
- typename NumopOn<T>::Fold f = on(*as)->op_fold;
- if (!f) RAISE("operator %s does not support fold",rb_sym_name(sym));
- f(an,n,(T *)as,(T *)bs);}
- template <class T> inline void scan(int an, int n, Pt<T> as, Pt<T> bs) {
- as.will_use(an);
- bs.will_use(an*n);
- typename NumopOn<T>::Scan f = on(*as)->op_scan;
- if (!f) RAISE("operator %s does not support scan",rb_sym_name(sym));
- f(an,n,(T *)as,(T *)bs);}
-
- \decl void map_m (NumberTypeE nt, int n, String as, String b);
- \decl void zip_m (NumberTypeE nt, int n, String as, String bs);
- \decl void fold_m (NumberTypeE nt, int an, int n, String as, String bs);
- \decl void scan_m (NumberTypeE nt, int an, int n, String as, String bs);
-
- Numop(Ruby /*Symbol*/ sym_, const char *name_,
-#define FOO(T) NumopOn<T> op_##T,
-EACH_NUMBER_TYPE(FOO)
-#undef FOO
- int flags_) : sym(sym_), name(name_), flags(flags_) {
-#define FOO(T) on_##T = op_##T;
-EACH_NUMBER_TYPE(FOO)
-#undef FOO
- }
-};
-\end class
-
-extern NumberType number_type_table[];
-extern Ruby number_type_dict; // GridFlow.@number_type_dict={}
-extern Ruby op_dict; // GridFlow.@op_dict={}
-
-static inline NumberTypeE convert(Ruby x, NumberTypeE *bogus) {
- return NumberTypeE_find(x);
-}
-
-#ifndef IS_BRIDGE
-static Numop *convert(Ruby x, Numop **bogus) {
- Ruby s = rb_hash_aref(rb_ivar_get(mGridFlow,SI(@op_dict)),x);
- if (s==Qnil) RAISE("expected two-input-operator");
- return FIX2PTR(Numop,s);
-}
-#endif
-
-// ****************************************************************
-\class Grid < CObject
-struct Grid : CObject {
- P<Dim> dim;
- NumberTypeE nt;
- void *data;
- Grid(P<Dim> dim, NumberTypeE nt, bool clear=false) : dim(0), nt(int32_e), data(0) {
- if (!dim) RAISE("hell");
- init(dim,nt);
- if (clear) {int size = bytes(); CLEAR(Pt<char>((char *)data,size),size);}
- }
- Grid(Ruby x) : dim(0), nt(int32_e), data(0) { init_from_ruby(x); }
- Grid(int n, Ruby *a, NumberTypeE nt=int32_e) : dim(0), nt(int32_e), data(0) {
- init_from_ruby_list(n,a,nt);
- }
- int32 bytes() { return dim->prod()*number_type_table[nt].size/8; }
- P<Dim> to_dim () { return new Dim(dim->prod(),(Pt<int32>)*this); }
-#define FOO(type) \
- operator type *() { return (type *)data; } \
- operator Pt<type>() { return Pt<type>((type *)data,dim->prod()); }
-EACH_NUMBER_TYPE(FOO)
-#undef FOO
- Grid *dup () {
- Grid *foo=new Grid(dim,nt);
- memcpy(foo->data,data,bytes());
- return foo;
- }
- ~Grid() {if (data) free(data);}
-private:
- void init(P<Dim> dim, NumberTypeE nt) {
- this->dim = dim;
- this->nt = nt;
- data = 0;
- if (dim) data = memalign(16,bytes()+16);
- //fprintf(stderr,"rdata=%p data=%p align=%d\n",rdata,data,align);
- }
- void init_from_ruby(Ruby x);
- void init_from_ruby_list(int n, Ruby *a, NumberTypeE nt=int32_e);
-};
-\end class Grid
-
-static inline Grid *convert (Ruby r, Grid **bogus) {
- return r ? new Grid(r) : 0;
-}
-
-// DimConstraint interface:
-// return if d is acceptable
-// else RAISE with proper descriptive message
-typedef void (*DimConstraint)(P<Dim> d);
-
-struct PtrGrid : public P<Grid> {
- DimConstraint dc;
- void constrain(DimConstraint dc_) { dc=dc_; }
- P<Grid> next;
- PtrGrid() : P<Grid>(), dc(0), next(0) {}
- PtrGrid(const PtrGrid &_p) : P<Grid>(), dc(0), next(0) {dc=_p.dc; p=_p.p; INCR;}
- PtrGrid &operator =( Grid *_p) {if(dc&&p)dc(_p->dim); DECR; p=_p; INCR; return *this;}
- PtrGrid &operator =(P<Grid> _p) {if(dc&&p)dc(_p->dim); DECR; p=_p.p; INCR; return *this;}
- PtrGrid &operator =(PtrGrid _p) {if(dc&&p)dc(_p->dim); DECR; p=_p.p; INCR; return *this;}
-};
-
-#ifndef IS_BRIDGE
-static inline P<Dim> convert(Ruby x, P<Dim> *foo) {
- Grid *d = convert(x,(Grid **)0);
- if (!d) RAISE("urgh");
- if (d->dim->n!=1) RAISE("dimension list must have only one dimension itself");
- return new Dim(d->dim->v[0],(int32 *)(d->data));
-}
-
-static inline PtrGrid convert(Ruby x, PtrGrid *foo) {
- PtrGrid pg;
- pg = convert(x,(Grid **)0);
- return pg;
-}
-#endif
-
-//****************************************************************
-// GridInlet represents a grid-aware inlet
-
-// four-part macro for defining the behaviour of a gridinlet in a class
-// C:Class I:Inlet
-#define GRID_INLET(C,I) \
- template <class T> void C::grinw_##I (GridInlet *in, int n, Pt<T> data) { \
- ((C*)(in->parent))->grin_##I(in,n,data); } \
- template <class T> void C::grin_##I (GridInlet *in, int n, Pt<T> data) { \
- if (n==-1)
-#define GRID_ALLOC else if (n==-3)
-#define GRID_FLOW else if (n>=0)
-#define GRID_FINISH else if (n==-2)
-#define GRID_END }
-
-/* macro for defining a gridinlet's behaviour as just storage (no backstore) */
-// V is a PtrGrid instance-var
-#define GRID_INPUT(C,I,V) \
-GRID_INLET(C,I) { V=new Grid(in->dim,NumberTypeE_type_of(*data)); } \
-GRID_FLOW { COPY((Pt<T>)*(V)+in->dex, data, n); } GRID_FINISH
-
-// macro for defining a gridinlet's behaviour as just storage (with backstore)
-// V is a PtrGrid instance-var
-#define GRID_INPUT2(C,I,V) \
- GRID_INLET(C,I) { \
- if (is_busy_except(in)) { \
- V.next = new Grid(in->dim,NumberTypeE_type_of(*data)); \
- } else V= new Grid(in->dim,NumberTypeE_type_of(*data)); \
- } GRID_FLOW { \
- COPY(((Pt<T>)*(V.next?V.next.p:&*V.p))+in->dex, data, n); \
- } GRID_FINISH
-
-typedef struct GridInlet GridInlet;
-typedef struct GridHandler {
-#define FOO(T) \
- void (*flow_##T)(GridInlet *in, int n, Pt<T> data); \
- void flow(GridInlet *in, int n, Pt<T> data) const { \
- assert(flow_##T); flow_##T(in,n,data); }
-EACH_NUMBER_TYPE(FOO)
-#undef FOO
-} GridHandler;
-
-typedef struct GridObject GridObject;
-\class GridInlet < CObject
-struct GridInlet : CObject {
- GridObject *parent;
- const GridHandler *gh;
- GridObject *sender;
- P<Dim> dim;
- NumberTypeE nt;
- int dex;
- PtrGrid buf;// factor-chunk buffer
- int bufi; // buffer index: how much of buf is filled
- int mode; // 0=ignore; 4=ro; 6=rw
-
- int allocfactor,allocmin,allocmax,allocn;
- Pt<uint8> alloc;
-
-// methods
- GridInlet(GridObject *parent_, const GridHandler *gh_) :
- parent(parent_), gh(gh_), sender(0),
- dim(0), nt(int32_e), dex(0), bufi(0), mode(4) {}
- ~GridInlet() {}
- void set_factor(int factor);
- void set_mode(int mode_) { mode=mode_; }
- int32 factor() {return buf?buf->dim->prod():1;}
- Ruby begin(int argc, Ruby *argv);
-
- // n=-1 is begin, and n=-2 is _finish_. the name "end" is now used
- // as an end-marker for inlet definitions... sorry for the confusion
- // GF-0.8: n=-3 is alloc.
- template <class T> void flow(int mode, int n, Pt<T> data);
- void end(); // this one ought to be called finish().
- void from_ruby_list(int argc, Ruby *argv, NumberTypeE nt=int32_e) {
- Grid t(argc,argv,nt); from_grid(&t);
- }
- void from_ruby(int argc, Ruby *argv) {
- Grid t(argv[0]); from_grid(&t);
- }
- void from_grid(Grid *g);
- bool supports_type(NumberTypeE nt);
-private:
- template <class T> void from_grid2(Grid *g, T foo);
-};
-\end class GridInlet
-
-//****************************************************************
-// for use by source_filter.rb ONLY (for \grin and \classinfo)
-
-// C is for class, I for inlet number
-// GRIN1 : int32 only
-// GRIN4 : all types
-// GRIN2 : integers only; no floats (no R either actually)
-// GRINF : floats only; no integers
-#ifndef HAVE_LITE
-#define GRIN(TB,TS,TI,TL,TF,TD,TR) {TB,TS,TI,TL,TF,TD,TR}
-#else
-#define GRIN(TB,TS,TI,TL,TF,TD,TR) {TB,TS,TI}
-#endif // HAVE_LITE
-
-#define GRIN1(C,I) GRIN(0,0,C::grinw_##I,0,0,0,0)
-#define GRIN4(C,I) GRIN(C::grinw_##I,C::grinw_##I,C::grinw_##I,C::grinw_##I,C::grinw_##I,C::grinw_##I,C::grinw_##I)
-#define GRIN2(C,I) GRIN(C::grinw_##I,C::grinw_##I,C::grinw_##I,C::grinw_##I,0,0,0)
-#define GRINF(C,I) GRIN(0,0,0,0,C::grinw_##I,C::grinw_##I,0)
-
-struct FClass { // 0.7.8: removed all GridObject-specific stuff.
- void *(*allocator)(); // returns a new C++ object
- void (*startup)(Ruby rself); // initializer for the Ruby class
- const char *name; // C++/Ruby name (not PD name)
- int methodsn; MethodDecl *methods; // C++ -> Ruby methods
-};
-
-//****************************************************************
-// GridOutlet represents a grid-aware outlet
-\class GridOutlet < CObject
-struct GridOutlet : CObject {
-// number of (minimum,maximum) BYTES to send at once
-// starting with version 0.8, this is amount of BYTES, not amount of NUMBERS.
- static const int MIN_PACKET_SIZE = 1<<8;
- static const int MAX_PACKET_SIZE = 1<<12;
-// those are set only once
- GridObject *parent; // not a P<> because of circular refs
- P<Dim> dim; // dimensions of the grid being sent
- NumberTypeE nt;
- PtrGrid buf; // temporary buffer
- bool frozen; // is the "begin" phase finished?
- std::vector<GridInlet *> inlets; // which inlets are we connected to
-// those are updated during transmission
- int dex; // how many numbers were already sent in this connection
- int bufi; // number of bytes used in the buffer
-// methods
- GridOutlet(GridObject *parent_, int woutlet, P<Dim> dim_, NumberTypeE nt_=int32_e) :
- parent(parent_), dim(dim_), nt(nt_), frozen(false), dex(0), bufi(0) {
- int ntsz = number_type_table[nt].size;
- buf=new Grid(new Dim(MAX_PACKET_SIZE/*/ntsz*/), nt);
- begin(woutlet,dim,nt);
- }
- ~GridOutlet() {}
- void callback(GridInlet *in);
-
- // send/send_direct: data belongs to caller, may be stack-allocated,
- // receiver doesn't modify the data; in send(), there is buffering;
- // in send_direct(), there is not. When switching from buffered to
- // unbuffered mode, flush() must be called
- template <class T> void send(int n, Pt<T> data);
- void flush(); // goes with send();
-
- // give: data must be dynamically allocated as a whole: the data
- // will be deleted eventually, and should not be used by the caller
- // beyond the call to give().
- template <class T> void give(int n, Pt<T> data);
-
- // third way to send (upcoming, in GF-0.8.??) is called "ask".
- template <class T> void ask(int &n, Pt<T> &data, int factor, int min, int max);
-
-private:
- void begin(int woutlet, P<Dim> dim, NumberTypeE nt=int32_e);
- template <class T> void send_direct(int n, Pt<T> data);
- void end() {
- flush();
- for (uint32 i=0; i<inlets.size(); i++) inlets[i]->end();
- dim=0;
- }
-};
-\end class GridOutlet
-
-//****************************************************************
-
-typedef struct BFObject BFObject; // Pd t_object or something
-
-// represents objects that have inlets/outlets
-\class FObject < CObject
-struct FObject : CObject {
- BFObject *bself; // point to PD peer
- uint64 total_time;
- FObject() : bself(0), total_time(0) {}
- const char *args() {
- Ruby s=rb_funcall(rself,SI(args),0);
- if (s==Qnil) return 0;
- return rb_str_ptr(s);
- }
- \decl Ruby total_time_get();
- \decl Ruby total_time_set(Ruby x);
- \decl void send_in (...);
- \decl void send_out (...);
- \decl void delete_m ();
-};
-\end class FObject
-
-\class GridObject < FObject
-struct GridObject : FObject {
- std::vector<P<GridInlet> > in;
- P<GridOutlet> out;
- // Make sure you distinguish #close/#delete, and C++'s delete. The first
- // two are quite equivalent and should never make an object "crashable".
- // C++'s delete is called by Ruby's garbage collector or by PureData's delete.
- GridObject() {}
- ~GridObject() {check_magic();}
- bool is_busy_except(P<GridInlet> gin) {
- for (uint32 i=0; i<in.size(); i++)
- if (in[i] && in[i]!=gin && in[i]->dim) return true;
- return false;
- }
- \decl Ruby method_missing(...);
- \decl Array inlet_dim(int inln);
- \decl Symbol inlet_nt(int inln);
- \decl void inlet_set_factor(int inln, int factor);
- \decl void send_out_grid_begin(int outlet, Array dim, NumberTypeE nt=int32_e);
- \decl void send_out_grid_flow (int outlet, String buf, NumberTypeE nt=int32_e);
-};
-\end class GridObject
-
-uint64 gf_timeofday();
-extern "C" void Init_gridflow ();
-void gfpost(const char *fmt, ...);
-extern Numop *op_add,*op_sub,*op_mul,*op_div,*op_mod,*op_shl,*op_and,*op_put;
-
-#define INFO(OBJ) rb_str_ptr(rb_funcall(OBJ->rself,SI(info),0))
-//#define INFO(OBJ) "(bleh)"
-#define NOTEMPTY(_a_) if (!(_a_)) RAISE("in [%s], '%s' is empty",INFO(this), #_a_);
-#define SAME_TYPE(_a_,_b_) \
- if ((_a_)->nt != (_b_)->nt) RAISE("%s: same type please (%s has %s; %s has %s)", \
- INFO(this), \
- #_a_, number_type_table[(_a_)->nt].name, \
- #_b_, number_type_table[(_b_)->nt].name);
-static void SAME_DIM(int n, P<Dim> a, int ai, P<Dim> b, int bi) {
- if (ai+n > a->n) RAISE("left hand: not enough dimensions");
- if (bi+n > b->n) RAISE("right hand: not enough dimensions");
- for (int i=0; i<n; i++) {
- if (a->v[ai+i] != b->v[bi+i]) {
- RAISE("mismatch: left dim #%d is %d, right dim #%d is %d",
- ai+i, a->v[ai+i],
- bi+i, b->v[bi+i]);}}}
-
-// a stack for the profiler, etc.
-#define GF_STACK_MAX 256
-//#define NO_INLINE(decl) decl __attribute__((noinline))
-#define NO_INLINE(decl) decl
-struct GFStack {
- struct GFStackFrame {
- FObject *o;
- void *bp; // a pointer into system stack
- uint64 time;
- }; // sizeof() == 16 (in 32-bit mode)
- GFStackFrame s[GF_STACK_MAX];
- int n;
- GFStack() { n = 0; }
- NO_INLINE(void push (FObject *o));
- NO_INLINE(void pop ());
-};
-extern GFStack gf_stack;
-struct GFStackMarker {
- int n;
- bool flag;
- GFStackMarker(FObject *o) { n = gf_stack.n; gf_stack.push(o); flag=true; }
- ~GFStackMarker() { while (gf_stack.n != n) gf_stack.pop(); }
- bool once () {
- if (flag) { flag=false; return true; } else return false;
- }
-};
-
-typedef GridObject Format;
-
-#endif // __GF_GRID_H