diff options
author | N.N. <matju@users.sourceforge.net> | 2008-04-28 18:10:15 +0000 |
---|---|---|
committer | N.N. <matju@users.sourceforge.net> | 2008-04-28 18:10:15 +0000 |
commit | 91c0003b158e5f0ed9d0677fb136ae8bb6f86ec5 (patch) | |
tree | d413a48086819f6a2620cd27d030861d122d4f3f /externals/gridflow/base | |
parent | 98dfdfa2fc1c92ba69e33fd77ed3392034297c1f (diff) |
this is an old gridflow, and there's already a svn repository at http://gridflow.ca/svn/trunk
svn path=/trunk/; revision=9739
Diffstat (limited to 'externals/gridflow/base')
-rw-r--r-- | externals/gridflow/base/bitpacking.c | 313 | ||||
-rw-r--r-- | externals/gridflow/base/flow_objects.c | 1195 | ||||
-rw-r--r-- | externals/gridflow/base/flow_objects.rb | 1457 | ||||
-rw-r--r-- | externals/gridflow/base/flow_objects_for_image.c | 619 | ||||
-rw-r--r-- | externals/gridflow/base/flow_objects_for_matrix.c | 77 | ||||
-rw-r--r-- | externals/gridflow/base/grid.c | 616 | ||||
-rw-r--r-- | externals/gridflow/base/grid.h | 1146 | ||||
-rw-r--r-- | externals/gridflow/base/main.c | 648 | ||||
-rw-r--r-- | externals/gridflow/base/main.rb | 384 | ||||
-rw-r--r-- | externals/gridflow/base/number.c | 374 | ||||
-rw-r--r-- | externals/gridflow/base/source_filter.rb | 276 | ||||
-rw-r--r-- | externals/gridflow/base/test.rb | 1074 |
12 files changed, 0 insertions, 8179 deletions
diff --git a/externals/gridflow/base/bitpacking.c b/externals/gridflow/base/bitpacking.c deleted file mode 100644 index cb09a812..00000000 --- a/externals/gridflow/base/bitpacking.c +++ /dev/null @@ -1,313 +0,0 @@ -/* - $Id: bitpacking.c,v 1.2 2006-03-15 04:37:06 matju Exp $ - - GridFlow - Copyright (c) 2001,2002,2003,2004 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. -*/ - -#include "grid.h.fcs" -#include <math.h> -#include <stdlib.h> -#include <stdio.h> - -//#define CONVERT0(z) (((in[z] << hb[z]) >> 7) & mask[z]) -#define CONVERT0(z) ((in[z] >> chop[z]) << slide[z]) - -#define CONVERT1 t = \ - CONVERT0(0) | CONVERT0(1) | CONVERT0(2) - -#define CONVERT2 \ - for (t=0,i=0; i<self->size; i++) t |= CONVERT0(i); - -#define CONVERT3 \ - for (t=0,i=0; i<self->size; i++) \ - t |= (((unsigned)in[i]>>(7-hb[i]))|(in[i]<<(hb[i]-7))) & mask[i]; - -#define WRITE_LE \ - for (int bytes = self->bytes; bytes; bytes--, t>>=8) *out++ = t; - -#define WRITE_BE { int bytes; \ - bytes = self->bytes; \ - while (bytes--) { out[bytes] = t; t>>=8; }\ - out += self->bytes; } - -/* this macro would be faster if the _increment_ - was done only once every loop. or maybe gcc does it, i dunno */ -#define NTIMES(_x_) \ - for (; n>=4; n-=4) { _x_ _x_ _x_ _x_ } \ - for (; n; n--) { _x_ } - -/* this could be faster (use asm) */ -void swap32 (int n, Pt<uint32> data) { - NTIMES({ - uint32 x = *data; - x = (x<<16) | (x>>16); - x = ((x&0xff00ff)<<8) | ((x>>8)&0xff00ff); - *data++ = x; - }) -} - -/* this could be faster (use asm or do it in int32 chunks) */ -void swap16 (int n, Pt<uint16> data) { - NTIMES({ uint16 x = *data; *data++ = (x<<8) | (x>>8); }) -} - -/* **************************************************************** */ - -template <class T> -static void default_pack(BitPacking *self, int n, Pt<T> in, Pt<uint8> out) { - uint32 t; - int i; - int sameorder = self->endian==2 || self->endian==::is_le(); - int size = self->size; - uint32 mask[4]; memcpy(mask,self->mask,size*sizeof(uint32)); - uint32 hb[4]; for (i=0; i<size; i++) hb[i] = highest_bit(mask[i]); - uint32 span[4]; for (i=0; i<size; i++) span[i] = hb[i] - lowest_bit(mask[i]); - uint32 chop[4]; for (i=0; i<size; i++) chop[i] = 7-span[i]; - uint32 slide[4]; for (i=0; i<size; i++) slide[i] = hb[i]-span[i]; - - if (sameorder && size==3) { - switch(self->bytes) { - case 2: NTIMES(CONVERT1; *((int16 *)out)=t; out+=2; in+=3;) return; - case 4: NTIMES(CONVERT1; *((int32 *)out)=t; out+=4; in+=3;) return; - } - } - if (self->is_le()) { - switch (size) { - case 3: for (; n--; in+=3) {CONVERT1; WRITE_LE;} break; - case 4: for (; n--; in+=4) {CONVERT1; WRITE_LE;} break; - default:for (; n--; in+=size) {CONVERT2; WRITE_LE;}} - } else { - switch (size) { - case 3: for (; n--; in+=3) {CONVERT1; WRITE_BE;} break; - case 4: for (; n--; in+=4) {CONVERT1; WRITE_BE;} break; - default:for (; n--; in+=size) {CONVERT2; WRITE_BE;}} - } -} - -#define LOOP_UNPACK(_reader_) \ - for (; n; n--) { \ - int bytes=0; uint32 temp=0; _reader_; \ - for (int i=0; i<self->size; i++, out++) { \ - uint32 t=temp&self->mask[i]; \ - *out = (t<<(7-hb[i]))|(t>>(hb[i]-7)); \ - } \ - } -// *out++ = ((temp & self->mask[i]) << 7) >> hb[i]; - -template <class T> -static void default_unpack(BitPacking *self, int n, Pt<uint8> in, Pt<T> out) { - int hb[4]; - for (int i=0; i<self->size; i++) hb[i] = highest_bit(self->mask[i]); - if (is_le()) { // smallest byte first - LOOP_UNPACK( - for(; self->bytes>bytes; bytes++, in++) temp |= *in<<(8*bytes); - ) - } else { // biggest byte first - LOOP_UNPACK( - bytes=self->bytes; for (; bytes; bytes--, in++) temp=(temp<<8)|*in; - ) - } -} - -/* **************************************************************** */ - -template <class T> -static void pack2_565(BitPacking *self, int n, Pt<T> in, Pt<uint8> out) { - const int hb[3] = {15,10,4}; - const uint32 mask[3] = {0x0000f800,0x000007e0,0x0000001f}; - uint32 span[3] = {4,5,4}; - uint32 chop[3] = {3,2,3}; - uint32 slide[3] = {11,5,0}; - uint32 t; - NTIMES(CONVERT1; *((short *)out)=t; out+=2; in+=3;) -} - -template <class T> -static void pack3_888(BitPacking *self, int n, Pt<T> in, Pt<uint8> out) { - Pt<int32> o32 = (Pt<int32>)out; - while (n>=4) { - o32[0] = (in[5]<<24) | (in[ 0]<<16) | (in[ 1]<<8) | in[2]; - o32[1] = (in[7]<<24) | (in[ 8]<<16) | (in[ 3]<<8) | in[4]; - o32[2] = (in[9]<<24) | (in[10]<<16) | (in[11]<<8) | in[6]; - o32+=3; in+=12; - n-=4; - } - out = (Pt<uint8>)o32; - NTIMES( out[2]=in[0]; out[1]=in[1]; out[0]=in[2]; out+=3; in+=3; ) -} - -/* -template <> -static void pack3_888(BitPacking *self, int n, Pt<uint8> in, Pt<uint8> out) { - Pt<uint32> o32 = Pt<uint32>((uint32 *)out.p,n*3/4); - Pt<uint32> i32 = Pt<uint32>((uint32 *)in.p,n*3/4); - while (n>=4) { -#define Z(w,i) ((word##w>>(i*8))&255) - uint32 word0 = i32[0]; - uint32 word1 = i32[1]; - uint32 word2 = i32[2]; - o32[0] = (Z(1,1)<<24) | (Z(0,0)<<16) | (Z(0,1)<<8) | Z(0,2); - o32[1] = (Z(1,3)<<24) | (Z(2,0)<<16) | (Z(0,3)<<8) | Z(1,0); - o32[2] = (Z(2,1)<<24) | (Z(2,2)<<16) | (Z(2,3)<<8) | Z(1,2); - o32+=3; i32+=3; - n-=4; - } -#undef Z - out = (Pt<uint8>)o32; - in = (Pt<uint8>)i32; - NTIMES( out[2]=in[0]; out[1]=in[1]; out[0]=in[2]; out+=3; in+=3; ) -} -*/ - -template <class T> -static void pack3_888b(BitPacking *self, int n, Pt<T> in, Pt<uint8> out) { - Pt<int32> o32 = (Pt<int32>)out; - while (n>=4) { - o32[0] = (in[0]<<16) | (in[1]<<8) | in[2]; - o32[1] = (in[3]<<16) | (in[4]<<8) | in[5]; - o32[2] = (in[6]<<16) | (in[7]<<8) | in[8]; - o32[3] = (in[9]<<16) | (in[10]<<8) | in[11]; - o32+=4; in+=12; - n-=4; - } - NTIMES( o32[0] = (in[0]<<16) | (in[1]<<8) | in[2]; o32++; in+=3; ) -} - -// (R,G,B,?) -> B:8,G:8,R:8,0:8 -// fishy -template <class T> -static void pack3_bgrn8888(BitPacking *self, int n, Pt<T> in, Pt<uint8> out) { -/* NTIMES( out[2]=in[0]; out[1]=in[1]; out[0]=in[2]; out+=4; in+=4; ) */ - Pt<int32> i32 = (Pt<int32>)in; - Pt<int32> o32 = (Pt<int32>)out; - while (n>=4) { - o32[0] = ((i32[0]&0xff)<<16) | (i32[0]&0xff00) | ((i32[0]>>16)&0xff); - o32[1] = ((i32[1]&0xff)<<16) | (i32[1]&0xff00) | ((i32[1]>>16)&0xff); - o32[2] = ((i32[2]&0xff)<<16) | (i32[2]&0xff00) | ((i32[2]>>16)&0xff); - o32[3] = ((i32[3]&0xff)<<16) | (i32[3]&0xff00) | ((i32[3]>>16)&0xff); - o32+=4; i32+=4; n-=4; - } - NTIMES( o32[0] = ((i32[0]&0xff)<<16) | (i32[0]&0xff00) | ((i32[0]>>16)&0xff); o32++; i32++; ) -} - -static uint32 bp_masks[][4] = { - {0x0000f800,0x000007e0,0x0000001f,0}, - {0x00ff0000,0x0000ff00,0x000000ff,0}, -}; - -static Packer bp_packers[] = { - {default_pack, default_pack, default_pack}, - {pack2_565, pack2_565, pack2_565}, - {pack3_888, pack3_888, pack3_888}, - {pack3_888b, default_pack, default_pack}, - {pack3_bgrn8888, default_pack, default_pack}, -}; - -static Unpacker bp_unpackers[] = { - {default_unpack, default_unpack, default_unpack}, -}; - -static BitPacking builtin_bitpackers[] = { - BitPacking(2, 2, 3, bp_masks[0], &bp_packers[1], &bp_unpackers[0]), - BitPacking(1, 3, 3, bp_masks[1], &bp_packers[2], &bp_unpackers[0]), - BitPacking(1, 4, 3, bp_masks[1], &bp_packers[3], &bp_unpackers[0]), - BitPacking(1, 4, 4, bp_masks[1], &bp_packers[4], &bp_unpackers[0]), -}; - -/* **************************************************************** */ - -bool BitPacking::eq(BitPacking *o) { - if (!(bytes == o->bytes)) return false; - if (!(size == o->size)) return false; - for (int i=0; i<size; i++) { - if (!(mask[i] == o->mask[i])) return false; - } - if (endian==o->endian) return true; - /* same==little on a little-endian; same==big on a big-endian */ - return (endian ^ o->endian ^ ::is_le()) == 2; -} - -BitPacking::BitPacking(int endian, int bytes, int size, uint32 *mask, -Packer *packer, Unpacker *unpacker) { - this->endian = endian; - this->bytes = bytes; - this->size = size; - for (int i=0; i<size; i++) this->mask[i] = mask[i]; - if (packer) { - this->packer = packer; - this->unpacker = unpacker; - return; - } - int packeri=-1; - this->packer = &bp_packers[0]; - this->unpacker = &bp_unpackers[0]; - - for (int i=0; i<(int)(sizeof(builtin_bitpackers)/sizeof(BitPacking)); i++) { - BitPacking *bp = &builtin_bitpackers[i]; - if (this->eq(bp)) { - this->packer = bp->packer; - this->unpacker = bp->unpacker; - packeri=i; - goto end; - } - } -end:; -/* - ::gfpost("Bitpacking: endian=%d bytes=%d size=%d packeri=%d", - endian, bytes, size, packeri); - ::gfpost(" packer=0x%08x unpacker=0x%08x",this->packer,this->unpacker); - ::gfpost(" mask=[0x%08x,0x%08x,0x%08x,0x%08x]",mask[0],mask[1],mask[2],mask[3]); -*/ -} - -bool BitPacking::is_le() { - return endian==1 || (endian ^ ::is_le())==3; -} - -template <class T> -void BitPacking::pack(int n, Pt<T> in, Pt<uint8> out) { - switch (NumberTypeE_type_of(*in)) { - case uint8_e: packer->as_uint8(this,n,(Pt<uint8>)in,out); break; - case int16_e: packer->as_int16(this,n,(Pt<int16>)in,out); break; - case int32_e: packer->as_int32(this,n,(Pt<int32>)in,out); break; - default: RAISE("argh"); - } -} - -template <class T> -void BitPacking::unpack(int n, Pt<uint8> in, Pt<T> out) { - switch (NumberTypeE_type_of(*out)) { - case uint8_e: unpacker->as_uint8(this,n,in,(Pt<uint8>)out); break; - case int16_e: unpacker->as_int16(this,n,in,(Pt<int16>)out); break; - case int32_e: unpacker->as_int32(this,n,in,(Pt<int32>)out); break; - default: RAISE("argh"); - } -} - -// i'm sorry... see the end of grid.c for an explanation... -//static -void make_hocus_pocus () { -// exit(1); -#define FOO(S) \ - ((BitPacking*)0)->pack(0,Pt<S>(),Pt<uint8>()); \ - ((BitPacking*)0)->unpack(0,Pt<uint8>(),Pt<S>()); -EACH_NUMBER_TYPE(FOO) -#undef FOO -} diff --git a/externals/gridflow/base/flow_objects.c b/externals/gridflow/base/flow_objects.c deleted file mode 100644 index f971553d..00000000 --- a/externals/gridflow/base/flow_objects.c +++ /dev/null @@ -1,1195 +0,0 @@ -/* - $Id: flow_objects.c,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. -*/ - -#include <sys/time.h> -#include <stdlib.h> -#include <math.h> -#include "grid.h.fcs" - -// BAD HACK: GCC complains: unimplemented (--debug|--debug-harder mode only) -#ifdef HAVE_DEBUG -#define SCOPY(a,b,n) COPY(a,b,n) -#else -#define SCOPY(a,b,n) SCopy<n>::f(a,b) -#endif - -template <int n> class SCopy { -public: template <class T> static inline void __attribute__((always_inline)) f(Pt<T> a, Pt<T> b) { - *a=*b; SCopy<n-1>::f(a+1,b+1);}}; -template <> class SCopy<0> { -public: template <class T> static inline void __attribute__((always_inline)) f(Pt<T> a, Pt<T> b) {}}; - -/*template <> class SCopy<4> { -public: template <class T> - static inline void __attribute__((always_inline)) f(Pt<T> a, Pt<T> b) { - *a=*b; SCopy<3>::f(a+1,b+1);} - // wouldn't gcc 2.95 complain here? - static inline void __attribute__((always_inline)) f(Pt<uint8> a, Pt<uint8> b) - { *(int32 *)a=*(int32 *)b; } -};*/ - -Numop *op_add, *op_sub, *op_mul, *op_div, *op_mod, *op_shl, *op_and, *op_put; - -static void expect_dim_dim_list (P<Dim> d) { - if (d->n!=1) RAISE("dimension list should be Dim[n], not %s",d->to_s());} -//static void expect_min_one_dim (P<Dim> d) { -// if (d->n<1) RAISE("minimum 1 dimension");} -static void expect_max_one_dim (P<Dim> d) { - if (d->n>1) { RAISE("expecting Dim[] or Dim[n], got %s",d->to_s()); }} -//static void expect_exactly_one_dim (P<Dim> d) { -// if (d->n!=1) { RAISE("expecting Dim[n], got %s",d->to_s()); }} - -//**************************************************************** -\class GridCast < GridObject -struct GridCast : GridObject { - \attr NumberTypeE nt; - \decl void initialize (NumberTypeE nt); - \grin 0 -}; - -GRID_INLET(GridCast,0) { - out = new GridOutlet(this,0,in->dim,nt); -} GRID_FLOW { - out->send(n,data); -} GRID_END - -\def void initialize (NumberTypeE nt) { - rb_call_super(argc,argv); - this->nt = nt; -} - -\classinfo { IEVAL(rself,"install '#cast',1,1"); } -\end class GridCast - -//**************************************************************** -//{ ?,Dim[B] -> Dim[*Cs] } -// out0 nt to be specified explicitly -\class GridImport < GridObject -struct GridImport : GridObject { - \attr NumberTypeE cast; - \attr P<Dim> dim; // size of grids to send - PtrGrid dim_grid; - GridImport() { dim_grid.constrain(expect_dim_dim_list); } - ~GridImport() {} - \decl void initialize(Ruby x, NumberTypeE cast=int32_e); - \decl void _0_cast(NumberTypeE cast); - \decl void _0_reset(); - \decl void _0_symbol(Symbol x); - \decl void _0_list(...); - \decl void _1_per_message(); - \grin 0 - \grin 1 int32 - template <class T> void process (int n, Pt<T> data) { - while (n) { - if (!out || !out->dim) out = new GridOutlet(this,0,dim?dim:in[0]->dim,cast); - int32 n2 = min((int32)n,out->dim->prod()-out->dex); - out->send(n2,data); - n-=n2; data+=n2; - } - } -}; - -GRID_INLET(GridImport,0) {} GRID_FLOW { process(n,data); } GRID_END -GRID_INPUT(GridImport,1,dim_grid) { dim = dim_grid->to_dim(); } GRID_END - -\def void _0_symbol(Symbol x) { - const char *name = rb_sym_name(argv[0]); - int n = strlen(name); - if (!dim) out=new GridOutlet(this,0,new Dim(n)); - process(n,Pt<uint8>((uint8 *)name,n)); -} - -\def void _0_cast(NumberTypeE cast) { this->cast = cast; } - -\def void _0_list(...) { - if (in.size()<1 || !in[0]) _0_grid(0,0); //HACK: enable grid inlet... - in[0]->from_ruby_list(argc,argv,cast); -} - -\def void _1_per_message() { dim=0; dim_grid=0; } - -\def void initialize(Ruby x, NumberTypeE cast) { - rb_call_super(argc,argv); - this->cast = cast; - if (argv[0]!=SYM(per_message)) { - dim_grid=new Grid(argv[0]); - dim = dim_grid->to_dim(); - } -} - -\def void _0_reset() { - STACK_ARRAY(int32,foo,1); *foo=0; - while (out->dim) out->send(1,foo); -} - -\classinfo { IEVAL(rself,"install '#import',2,1"); } -\end class GridImport - -//**************************************************************** -/*{ Dim[*As] -> ? }*/ -/* in0: integer nt */ -\class GridExport < GridObject -struct GridExport : GridObject { - \grin 0 -}; - -template <class T> -static Ruby INTORFLOAT2NUM(T value) {return INT2NUM(value);} -static Ruby INTORFLOAT2NUM(int64 value) {return gf_ll2num(value);} -static Ruby INTORFLOAT2NUM(float32 value) {return rb_float_new(value);} -static Ruby INTORFLOAT2NUM(float64 value) {return rb_float_new(value);} -static Ruby INTORFLOAT2NUM(ruby value) {return value.r;} - -GRID_INLET(GridExport,0) { -} GRID_FLOW { - for (int i=0; i<n; i++) { - Ruby a[] = { INT2NUM(0), INTORFLOAT2NUM(data[i]) }; - send_out(COUNT(a),a); - } -} GRID_END -\classinfo { IEVAL(rself,"install '#export',1,1"); } -\end class GridExport - -/* **************************************************************** */ -/*{ Dim[*As] -> ? }*/ -/* in0: integer nt */ -\class GridExportList < GridObject -struct GridExportList : GridObject { - Ruby /*Array*/ list; - int n; - \grin 0 -}; - -GRID_INLET(GridExportList,0) { - int n = in->dim->prod(); - if (n>250000) RAISE("list too big (%d elements)", n); - list = rb_ary_new2(n+2); - this->n = n; - rb_ivar_set(rself,SI(@list),list); // keep - rb_ary_store(list,0,INT2NUM(0)); - rb_ary_store(list,1,bsym._list); -} GRID_FLOW { - for (int i=0; i<n; i++, data++) - rb_ary_store(list,in->dex+i+2,INTORFLOAT2NUM(*data)); -} GRID_FINISH { - send_out(rb_ary_len(list),rb_ary_ptr(list)); - list = 0; - rb_ivar_set(rself,SI(@list),Qnil); // unkeep -} GRID_END - -\classinfo { IEVAL(rself,"install '#export_list',1,1"); } -\end class GridExportList - -/* **************************************************************** */ -// GridStore ("@store") is the class for storing a grid and restituting -// it on demand. The right inlet receives the grid. The left inlet receives -// either a bang (which forwards the whole image) or a grid describing what -// to send. -//{ Dim[*As,B],Dim[*Cs,*Ds] -> Dim[*As,*Ds] } -// in0: integer nt -// in1: whatever nt -// out0: same nt as in1 -\class GridStore < GridObject -struct GridStore : GridObject { - PtrGrid r; // can't be \attr - PtrGrid put_at; // can't be //\attr - \attr Numop *op; - int32 wdex [Dim::MAX_DIM]; // temporary buffer, copy of put_at - int32 fromb[Dim::MAX_DIM]; - int32 to2 [Dim::MAX_DIM]; - int lsd; // lsd = Last Same Dimension (for put_at) - int d; // goes with wdex - \decl void initialize (Grid *r=0); - \decl void _0_bang (); - \decl void _0_op (Numop *op); - \decl void _1_reassign (); - \decl void _1_put_at (Grid *index); - \grin 0 int - \grin 1 - GridStore() { put_at.constrain(expect_max_one_dim); } - template <class T> void compute_indices(Pt<T> v, int nc, int nd); -}; - -// takes the backstore of a grid and puts it back into place. a backstore -// is a grid that is filled while the grid it would replace has not -// finished being used. -static void snap_backstore (PtrGrid &r) { - if (r.next) {r=r.next.p; r.next=0;} -} - -template <class T> void GridStore::compute_indices(Pt<T> v, int nc, int nd) { - for (int i=0; i<nc; i++) { - uint32 wrap = r->dim->v[i]; - bool fast = lowest_bit(wrap)==highest_bit(wrap); // is power of two? - if (i) { - if (fast) op_shl->map(nd,v,(T)highest_bit(wrap)); - else op_mul->map(nd,v,(T)wrap); - } - if (fast) op_and->map(nd,v+nd*i,(T)(wrap-1)); - else op_mod->map(nd,v+nd*i,(T)(wrap)); - if (i) op_add->zip(nd,v,v+nd*i); - } -} - -// !@#$ i should ensure that n is not exceedingly large -// !@#$ worse: the size of the foo buffer may still be too large -GRID_INLET(GridStore,0) { - // snap_backstore must be done before *anything* else - snap_backstore(r); - int na = in->dim->n; - int nb = r->dim->n; - int nc = in->dim->get(na-1); - STACK_ARRAY(int32,v,Dim::MAX_DIM); - if (na<1) RAISE("must have at least 1 dimension.",na,1,1+nb); - int lastindexable = r->dim->prod()/r->dim->prod(nc) - 1; - int ngreatest = nt_greatest((T *)0); - if (lastindexable > ngreatest) { - RAISE("lastindexable=%d > ngreatest=%d (ask matju)",lastindexable,ngreatest); - } - if (nc > nb) - RAISE("wrong number of elements in last dimension: " - "got %d, expecting <= %d", nc, nb); - int nd = nb - nc + na - 1; - COPY(v,in->dim->v,na-1); - COPY(v+na-1,r->dim->v+nc,nb-nc); - out=new GridOutlet(this,0,new Dim(nd,v),r->nt); - if (nc>0) in->set_factor(nc); -} GRID_FLOW { - int na = in->dim->n; - int nc = in->dim->get(na-1); - int size = r->dim->prod(nc); - assert((n % nc) == 0); - int nd = n/nc; - STACK_ARRAY(T,w,n); - Pt<T> v=w; - if (sizeof(T)==1 && nc==1 && r->dim->v[0]<=256) { - // bug? shouldn't modulo be done here? - v=data; - } else { - COPY(v,data,n); - for (int k=0,i=0; i<nc; i++) for (int j=0; j<n; j+=nc) v[k++] = data[i+j]; - compute_indices(v,nc,nd); - } -#define FOO(type) { \ - Pt<type> p = (Pt<type>)*r; \ - if (size<=16) { \ - Pt<type> foo = ARRAY_NEW(type,nd*size); \ - int i=0; \ - switch (size) { \ - case 1: for (; i<nd&-4; i+=4, foo+=4) { \ - foo[0] = p[v[i+0]]; \ - foo[1] = p[v[i+1]]; \ - foo[2] = p[v[i+2]]; \ - foo[3] = p[v[i+3]]; \ - } break; \ - case 2: for (; i<nd; i++, foo+=2) SCOPY(foo,p+2*v[i],2); break; \ - case 3: for (; i<nd; i++, foo+=3) SCOPY(foo,p+3*v[i],3); break; \ - case 4: for (; i<nd; i++, foo+=4) SCOPY(foo,p+4*v[i],4); break; \ - default:; }; \ - for (; i<nd; i++, foo+=size) COPY(foo,p+size*v[i],size); \ - out->give(size*nd,foo-size*nd); \ - } else { \ - for (int i=0; i<nd; i++) out->send(size,p+size*v[i]); \ - } \ -} - TYPESWITCH(r->nt,FOO,) -#undef FOO -} GRID_FINISH { - if (in->dim->prod()==0) { - int n = in->dim->prod(0,-2); - int size = r->dim->prod(); -#define FOO(T) while (n--) out->send(size,(Pt<T>)*r); - TYPESWITCH(r->nt,FOO,) -#undef FOO - } -} GRID_END - -GRID_INLET(GridStore,1) { - NumberTypeE nt = NumberTypeE_type_of(*data); - if (!put_at) { // reassign - if (in[0].dim) - r.next = new Grid(in->dim,nt); - else - r = new Grid(in->dim,nt); - return; - } - // put_at ( ... ) - //!@#$ should check types. if (r->nt!=in->nt) RAISE("shoo"); - int nn=r->dim->n, na=put_at->dim->v[0], nb=in->dim->n; - STACK_ARRAY(int32,sizeb,nn); - for (int i=0; i<nn; i++) { fromb[i]=0; sizeb[i]=1; } - COPY(Pt<int32>(wdex,nn) ,(Pt<int32>)*put_at ,put_at->dim->prod()); - COPY(Pt<int32>(fromb,nn)+nn-na,(Pt<int32>)*put_at ,na); - COPY(Pt<int32>(sizeb,nn)+nn-nb,(Pt<int32>)in->dim->v,nb); - for (int i=0; i<nn; i++) to2[i] = fromb[i]+sizeb[i]; - d=0; - // find out when we can skip computing indices - //!@#$ should actually also stop before blowing up packet size - lsd=nn; - while (lsd>=nn-in->dim->n) { - lsd--; - int cs = in->dim->prod(lsd-nn+in->dim->n); - if (cs>GridOutlet::MAX_PACKET_SIZE || fromb[lsd]!=0 || sizeb[lsd]!=r->dim->v[lsd]) break; - } - lsd++; - int cs = in->dim->prod(lsd-nn+in->dim->n); - in->set_factor(cs); -} GRID_FLOW { - if (!put_at) { // reassign - COPY(((Pt<T>)*(r.next ? r.next.p : &*r.p))+in->dex, data, n); - return; - } - // put_at ( ... ) - int nn=r->dim->n; - int cs = in->factor(); // chunksize - STACK_ARRAY(int32,v,lsd); - Pt<int32> x = Pt<int32>(wdex,nn); - while (n) { - // here d is the dim# to reset; d=n for none - for(;d<lsd;d++) x[d]=fromb[d]; - COPY(v,x,lsd); - compute_indices(v,lsd,1); - op->zip(cs,(Pt<T>)*r+v[0]*cs,data); - data+=cs; - n-=cs; - // find next set of indices; here d is the dim# to increment - for(;;) { - d--; - if (d<0) goto end; - x[d]++; - if (x[d]<to2[d]) break; - } - end:; // why here ??? or why at all? - d++; - } - //end:; // why not here ??? -} GRID_END -\def void _0_op(Numop *op) { this->op=op; } -\def void _0_bang () { rb_funcall(rself,SI(_0_list),3,INT2NUM(0),SYM(#),INT2NUM(0)); } -\def void _1_reassign () { put_at=0; } -\def void _1_put_at (Grid *index) { put_at=index; } -\def void initialize (Grid *r) { - rb_call_super(argc,argv); - this->r = r?r:new Grid(new Dim(),int32_e,true); - op = op_put; -} -\classinfo { IEVAL(rself,"install '#store',2,1"); } -\end class GridStore - -//**************************************************************** -//{ Dim[*As]<T> -> Dim[*As]<T> } or -//{ Dim[*As]<T>,Dim[*Bs]<T> -> Dim[*As]<T> } -\class GridOp < GridObject -struct GridOp : GridObject { - \attr Numop *op; - PtrGrid r; - \decl void initialize(Numop *op, Grid *r=0); - \grin 0 - \grin 1 - \decl void _0_op(Numop *op); -}; - -GRID_INLET(GridOp,0) { - snap_backstore(r); - SAME_TYPE(in,r); - out=new GridOutlet(this,0,in->dim,in->nt); - in->set_mode(6); -} GRID_ALLOC { - //out->ask(in->allocn,(Pt<T> &)in->alloc,in->allocfactor,in->allocmin,in->allocmax); -} GRID_FLOW { - Pt<T> rdata = (Pt<T>)*r; - int loop = r->dim->prod(); - if (sizeof(T)==8) { - fprintf(stderr,"1: data=%p rdata=%p\n",data.p,rdata.p); - WATCH(n,data); - } - if (loop>1) { - if (in->dex+n <= loop) { - op->zip(n,data,rdata+in->dex); - } else { - // !@#$ should prebuild and reuse this array when "loop" is small - STACK_ARRAY(T,data2,n); - int ii = mod(in->dex,loop); - int m = min(loop-ii,n); - COPY(data2,rdata+ii,m); - int nn = m+((n-m)/loop)*loop; - for (int i=m; i<nn; i+=loop) COPY(data2+i,rdata,loop); - if (n>nn) COPY(data2+nn,rdata,n-nn); - if (sizeof(T)==8) { - fprintf(stderr,"2: data=%p data2=%p\n",data.p,data2.p); - WATCH(n,data); WATCH(n,data2); - } - op->zip(n,data,data2); - if (sizeof(T)==8) {WATCH(n,data); WATCH(n,data2);} - } - } else { - op->map(n,data,*rdata); - } - out->give(n,data); -} GRID_END - -GRID_INPUT2(GridOp,1,r) {} GRID_END -\def void _0_op(Numop *op) { this->op=op; } - -\def void initialize(Numop *op, Grid *r=0) { - rb_call_super(argc,argv); - this->op=op; - this->r = r?r:new Grid(new Dim(),int32_e,true); -} - -\classinfo { IEVAL(rself,"install '#',2,1"); } -\end class GridOp - -//**************************************************************** -\class GridFold < GridObject -struct GridFold : GridObject { - \attr Numop *op; - \attr PtrGrid seed; - \decl void initialize (Numop *op); - \decl void _0_op (Numop *op); - \decl void _0_seed (Grid *seed); - \grin 0 -}; - -GRID_INLET(GridFold,0) { - //{ Dim[*As,B,*Cs]<T>,Dim[*Cs]<T> -> Dim[*As,*Cs]<T> } - if (seed) SAME_TYPE(in,seed); - int an = in->dim->n; - int bn = seed?seed->dim->n:0; - if (an<=bn) RAISE("minimum 1 more dimension than the seed (%d vs %d)",an,bn); - STACK_ARRAY(int32,v,an-1); - int yi = an-bn-1; - COPY(v,in->dim->v,yi); - COPY(v+yi,in->dim->v+an-bn,bn); - if (seed) SAME_DIM(an-(yi+1),in->dim,(yi+1),seed->dim,0); - out=new GridOutlet(this,0,new Dim(an-1,v),in->nt); - int k = seed ? seed->dim->prod() : 1; - in->set_factor(in->dim->get(yi)*k); -} GRID_FLOW { - int an = in->dim->n; - int bn = seed?seed->dim->n:0; - int yn = in->dim->v[an-bn-1]; - int zn = in->dim->prod(an-bn); - STACK_ARRAY(T,buf,n/yn); - int nn=n; - int yzn=yn*zn; - for (int i=0; n; i+=zn, data+=yzn, n-=yzn) { - if (seed) COPY(buf+i,((Pt<T>)*seed),zn); - else CLEAR(buf+i,zn); - op->fold(zn,yn,buf+i,data); - } - out->send(nn/yn,buf); -} GRID_END - -\def void _0_op (Numop *op ) { this->op =op; } -\def void _0_seed (Grid *seed) { this->seed=seed; } -\def void initialize (Numop *op) { rb_call_super(argc,argv); this->op=op; } -\classinfo { IEVAL(rself,"install '#fold',1,1"); } -\end class GridFold - -\class GridScan < GridObject -struct GridScan : GridObject { - \attr Numop *op; - \attr PtrGrid seed; - \decl void initialize (Numop *op); - \decl void _0_op (Numop *op); - \decl void _0_seed (Grid *seed); - \grin 0 -}; - -GRID_INLET(GridScan,0) { - //{ Dim[*As,B,*Cs]<T>,Dim[*Cs]<T> -> Dim[*As,B,*Cs]<T> } - if (seed) SAME_TYPE(in,seed); - int an = in->dim->n; - int bn = seed?seed->dim->n:0; - if (an<=bn) RAISE("minimum 1 more dimension than the right hand"); - if (seed) SAME_DIM(bn,in->dim,an-bn,seed->dim,0); - out=new GridOutlet(this,0,in->dim,in->nt); - in->set_factor(in->dim->prod(an-bn-1)); -} GRID_FLOW { - int an = in->dim->n; - int bn = seed?seed->dim->n:0; - int yn = in->dim->v[an-bn-1]; - int zn = in->dim->prod(an-bn); - int factor = in->factor(); - STACK_ARRAY(T,buf,n); - COPY(buf,data,n); - if (seed) { - for (int i=0; i<n; i+=factor) op->scan(zn,yn,(Pt<T>)*seed,buf+i); - } else { - STACK_ARRAY(T,seed,zn); - CLEAR(seed,zn); - for (int i=0; i<n; i+=factor) op->scan(zn,yn,seed,buf+i); - } - out->send(n,buf); -} GRID_END - -\def void _0_op (Numop *op ) { this->op =op; } -\def void _0_seed (Grid *seed) { this->seed=seed; } -\def void initialize (Numop *op) { rb_call_super(argc,argv); this->op = op; } -\classinfo { IEVAL(rself,"install '#scan',1,1"); } -\end class GridScan - -//**************************************************************** -//{ Dim[*As,C]<T>,Dim[C,*Bs]<T> -> Dim[*As,*Bs]<T> } -\class GridInner < GridObject -struct GridInner : GridObject { - \attr Numop *op_para; - \attr Numop *op_fold; - \attr PtrGrid seed; - PtrGrid r; - PtrGrid r2; - GridInner() {} - \decl void initialize (Grid *r=0); - \decl void _0_op (Numop *op); - \decl void _0_fold (Numop *op); - \decl void _0_seed (Grid *seed); - \grin 0 - \grin 1 -}; - -template <class T> void inner_child_a (Pt<T> buf, Pt<T> data, int rrows, int rcols, int chunk) { - Pt<T> bt = buf, dt = data; - for (int j=0; j<chunk; j++, bt+=rcols, dt+=rrows) op_put->map(rcols,bt,*dt); -} -template <class T, int rcols> void inner_child_b (Pt<T> buf, Pt<T> data, int rrows, int chunk) { - Pt<T> bt = buf, dt = data; - for (int j=0; j<chunk; j++, bt+=rcols, dt+=rrows) { - for (int k=0; k<rcols; k++) bt[k] = *dt; - } -} -GRID_INLET(GridInner,0) { - SAME_TYPE(in,r); - SAME_TYPE(in,seed); - P<Dim> a = in->dim; - P<Dim> b = r->dim; - if (a->n<1) RAISE("a: minimum 1 dimension"); - if (b->n<1) RAISE("b: minimum 1 dimension"); - if (seed->dim->n != 0) RAISE("seed must be a scalar"); - int a_last = a->get(a->n-1); - int n = a->n+b->n-2; - SAME_DIM(1,a,a->n-1,b,0); - STACK_ARRAY(int32,v,n); - COPY(v,a->v,a->n-1); - COPY(v+a->n-1,b->v+1,b->n-1); - out=new GridOutlet(this,0,new Dim(n,v),in->nt); - in->set_factor(a_last); - - int rrows = in->factor(); - int rsize = r->dim->prod(); - int rcols = rsize/rrows; - Pt<T> rdata = (Pt<T>)*r; - int chunk = GridOutlet::MAX_PACKET_SIZE/rsize; - r2=new Grid(new Dim(chunk*rsize),r->nt); - Pt<T> buf3 = (Pt<T>)*r2; - for (int i=0; i<rrows; i++) - for (int j=0; j<chunk; j++) - COPY(buf3+(j+i*chunk)*rcols,rdata+i*rcols,rcols); -} GRID_FLOW { - int rrows = in->factor(); - int rsize = r->dim->prod(); - int rcols = rsize/rrows; - int chunk = GridOutlet::MAX_PACKET_SIZE/rsize; - STACK_ARRAY(T,buf ,chunk*rcols); - STACK_ARRAY(T,buf2,chunk*rcols); - int off = chunk; - while (n) { - if (chunk*rrows>n) chunk=n/rrows; - op_put->map(chunk*rcols,buf2,*(T *)*seed); - for (int i=0; i<rrows; i++) { - switch (rcols) { - case 1: inner_child_b<T,1>(buf,data+i,rrows,chunk); break; - case 2: inner_child_b<T,2>(buf,data+i,rrows,chunk); break; - case 3: inner_child_b<T,3>(buf,data+i,rrows,chunk); break; - case 4: inner_child_b<T,4>(buf,data+i,rrows,chunk); break; - default: inner_child_a(buf,data+i,rrows,rcols,chunk); - } - op_para->zip(chunk*rcols,buf,(Pt<T>)*r2+i*off*rcols); - op_fold->zip(chunk*rcols,buf2,buf); - } - out->send(chunk*rcols,buf2); - n-=chunk*rrows; - data+=chunk*rrows; - } -} GRID_FINISH { - r2=0; -} GRID_END - -GRID_INPUT(GridInner,1,r) {} GRID_END - -\def void initialize (Grid *r) { - rb_call_super(argc,argv); - this->op_para = op_mul; - this->op_fold = op_add; - this->seed = new Grid(new Dim(),int32_e,true); - this->r = r ? r : new Grid(new Dim(),int32_e,true); -} - -\def void _0_op (Numop *op ) { this->op_para=op; } -\def void _0_fold (Numop *op ) { this->op_fold=op; } -\def void _0_seed (Grid *seed) { this->seed=seed; } -\classinfo { IEVAL(rself,"install '#inner',2,1"); } -\end class GridInner - -/* **************************************************************** */ -/*{ Dim[*As]<T>,Dim[*Bs]<T> -> Dim[*As,*Bs]<T> }*/ -\class GridOuter < GridObject -struct GridOuter : GridObject { - \attr Numop *op; - PtrGrid r; - \decl void initialize (Numop *op, Grid *r=0); - \grin 0 - \grin 1 -}; - -GRID_INLET(GridOuter,0) { - SAME_TYPE(in,r); - P<Dim> a = in->dim; - P<Dim> b = r->dim; - int n = a->n+b->n; - STACK_ARRAY(int32,v,n); - COPY(v,a->v,a->n); - COPY(v+a->n,b->v,b->n); - out=new GridOutlet(this,0,new Dim(n,v),in->nt); -} GRID_FLOW { - int b_prod = r->dim->prod(); - if (b_prod > 4) { - STACK_ARRAY(T,buf,b_prod); - while (n) { - for (int j=0; j<b_prod; j++) buf[j] = *data; - op->zip(b_prod,buf,(Pt<T>)*r); - out->send(b_prod,buf); - data++; n--; - } - return; - } - n*=b_prod; - Pt<T> buf = ARRAY_NEW(T,n); - STACK_ARRAY(T,buf2,b_prod*64); - for (int i=0; i<64; i++) COPY(buf2+i*b_prod,(Pt<T>)*r,b_prod); - switch (b_prod) { - #define Z buf[k++]=data[i] - case 1: for (int i=0,k=0; k<n; i++) {Z;} break; - case 2: for (int i=0,k=0; k<n; i++) {Z;Z;} break; - case 3: for (int i=0,k=0; k<n; i++) {Z;Z;Z;} break; - case 4: for (int i=0,k=0; k<n; i++) {Z;Z;Z;Z;} break; - default:for (int i=0,k=0; k<n; i++) for (int j=0; j<b_prod; j++, k++) Z; - } - #undef Z - int ch=64*b_prod; - int nn=(n/ch)*ch; - for (int j=0; j<nn; j+=ch) op->zip(ch,buf+j,buf2); - op->zip(n-nn,buf+nn,buf2); - out->give(n,buf); -} GRID_END - -GRID_INPUT(GridOuter,1,r) {} GRID_END - -\def void initialize (Numop *op, Grid *r) { - rb_call_super(argc,argv); - this->op = op; - this->r = r ? r : new Grid(new Dim(),int32_e,true); -} - -\classinfo { IEVAL(rself,"install '#outer',2,1"); } -\end class GridOuter - -//**************************************************************** -//{ Dim[]<T>,Dim[]<T>,Dim[]<T> -> Dim[A]<T> } or -//{ Dim[B]<T>,Dim[B]<T>,Dim[B]<T> -> Dim[*As,B]<T> } -\class GridFor < GridObject -struct GridFor : GridObject { - \attr PtrGrid from; - \attr PtrGrid to; - \attr PtrGrid step; - GridFor () { - from.constrain(expect_max_one_dim); - to .constrain(expect_max_one_dim); - step.constrain(expect_max_one_dim); - } - \decl void initialize (Grid *from, Grid *to, Grid *step); - \decl void _0_set (Grid *r=0); - \decl void _0_bang (); - \grin 0 int - \grin 1 int - \grin 2 int - template <class T> void trigger (T bogus); -}; - -\def void initialize (Grid *from, Grid *to, Grid *step) { - rb_call_super(argc,argv); - this->from=from; - this->to =to; - this->step=step; -} - -template <class T> -void GridFor::trigger (T bogus) { - int n = from->dim->prod(); - int32 nn[n+1]; - STACK_ARRAY(T,x,64*n); - Pt<T> fromb = (Pt<T>)*from; - Pt<T> tob = (Pt<T>)*to ; - Pt<T> stepb = (Pt<T>)*step; - STACK_ARRAY(T,to2,n); - - for (int i=step->dim->prod()-1; i>=0; i--) - if (!stepb[i]) RAISE("step must not contain zeroes"); - for (int i=0; i<n; i++) { - nn[i] = (tob[i] - fromb[i] + stepb[i] - cmp(stepb[i],(T)0)) / stepb[i]; - if (nn[i]<0) nn[i]=0; - to2[i] = fromb[i]+stepb[i]*nn[i]; - } - P<Dim> d; - if (from->dim->n==0) { d = new Dim(*nn); } - else { nn[n]=n; d = new Dim(n+1,nn); } - int total = d->prod(); - out=new GridOutlet(this,0,d,from->nt); - if (total==0) return; - int k=0; - for(int d=0;;d++) { - // here d is the dim# to reset; d=n for none - for(;d<n;d++) x[k+d]=fromb[d]; - k+=n; - if (k==64*n) {out->send(k,x); k=0; COPY(x,x+63*n,n);} - else { COPY(x+k,x+k-n,n);} - d--; - // here d is the dim# to increment - for(;;d--) { - if (d<0) goto end; - x[k+d]+=stepb[d]; - if (x[k+d]!=to2[d]) break; - } - } - end: if (k) out->send(k,x); -} - -\def void _0_bang () { - SAME_TYPE(from,to); - SAME_TYPE(from,step); - if (!from->dim->equal(to->dim) || !to->dim->equal(step->dim)) - RAISE("dimension mismatch"); -#define FOO(T) trigger((T)0); - TYPESWITCH_JUSTINT(from->nt,FOO,); -#undef FOO -} - -\def void _0_set (Grid *r) { from=new Grid(argv[0]); } -GRID_INPUT(GridFor,2,step) {} GRID_END -GRID_INPUT(GridFor,1,to) {} GRID_END -GRID_INPUT(GridFor,0,from) {_0_bang(0,0);} GRID_END -\classinfo { IEVAL(rself,"install '#for',3,1"); } -\end class GridFor - -//**************************************************************** -\class GridFinished < GridObject -struct GridFinished : GridObject { - \grin 0 -}; -GRID_INLET(GridFinished,0) { - in->set_mode(0); -} GRID_FINISH { - Ruby a[] = { INT2NUM(0), bsym._bang }; - send_out(COUNT(a),a); -} GRID_END -\classinfo { IEVAL(rself,"install '#finished',1,1"); } -\end class GridFinished - -\class GridDim < GridObject -struct GridDim : GridObject { - \grin 0 -}; -GRID_INLET(GridDim,0) { - GridOutlet out(this,0,new Dim(in->dim->n)); - out.send(in->dim->n,Pt<int32>(in->dim->v,in->dim->n)); - in->set_mode(0); -} GRID_END -\classinfo { IEVAL(rself,"install '#dim',1,1"); } -\end class GridDim - -\class GridType < GridObject -struct GridType : GridObject { - \grin 0 -}; -GRID_INLET(GridType,0) { - Ruby a[] = { INT2NUM(0), SYM(symbol), number_type_table[in->nt].sym }; - send_out(COUNT(a),a); - in->set_mode(0); -} GRID_END -\classinfo { IEVAL(rself,"install '#type',1,1"); } -\end class GridType - -//**************************************************************** -//{ Dim[*As]<T>,Dim[B] -> Dim[*Cs]<T> } -\class GridRedim < GridObject -struct GridRedim : GridObject { - \attr P<Dim> dim; - PtrGrid dim_grid; - PtrGrid temp; // temp->dim is not of the same shape as dim - GridRedim() { dim_grid.constrain(expect_dim_dim_list); } - ~GridRedim() {} - \decl void initialize (Grid *d); - \grin 0 - \grin 1 int32 -}; - -GRID_INLET(GridRedim,0) { - int a = in->dim->prod(), b = dim->prod(); - if (a<b) temp=new Grid(new Dim(a),in->nt); - out=new GridOutlet(this,0,dim,in->nt); -} GRID_FLOW { - int i = in->dex; - if (!temp) { - int b = dim->prod(); - int n2 = min(n,b-i); - if (n2>0) out->send(n2,data); - // discard other values if any - } else { - int a = in->dim->prod(); - int n2 = min(n,a-i); - COPY((Pt<T>)*temp+i,data,n2); - if (n2>0) out->send(n2,data); - } -} GRID_FINISH { - if (!!temp) { - int a = in->dim->prod(), b = dim->prod(); - if (a) { - for (int i=a; i<b; i+=a) out->send(min(a,b-i),(Pt<T>)*temp); - } else { - STACK_ARRAY(T,foo,1); - foo[0]=0; - for (int i=0; i<b; i++) out->send(1,foo); - } - } - temp=0; -} GRID_END - -GRID_INPUT(GridRedim,1,dim_grid) { dim = dim_grid->to_dim(); } GRID_END - -\def void initialize (Grid *d) { - rb_call_super(argc,argv); - dim_grid=d; - dim = dim_grid->to_dim(); -} - -\classinfo { IEVAL(rself,"install '#redim',2,1"); } -\end class GridRedim - -//**************************************************************** -\class GridJoin < GridObject -struct GridJoin : GridObject { - \attr int which_dim; - PtrGrid r; - \grin 0 - \grin 1 - \decl void initialize (int which_dim=-1, Grid *r=0); -}; - -GRID_INLET(GridJoin,0) { - NOTEMPTY(r); - SAME_TYPE(in,r); - P<Dim> d = in->dim; - if (d->n != r->dim->n) RAISE("wrong number of dimensions"); - int w = which_dim; - if (w<0) w+=d->n; - if (w<0 || w>=d->n) - RAISE("can't join on dim number %d on %d-dimensional grids", - which_dim,d->n); - STACK_ARRAY(int32,v,d->n); - for (int i=0; i<d->n; i++) { - v[i] = d->get(i); - if (i==w) { - v[i]+=r->dim->v[i]; - } else { - if (v[i]!=r->dim->v[i]) RAISE("dimensions mismatch: dim #%i, left is %d, right is %d",i,v[i],r->dim->v[i]); - } - } - out=new GridOutlet(this,0,new Dim(d->n,v),in->nt); - if (d->prod(w)) in->set_factor(d->prod(w)); -} GRID_FLOW { - int w = which_dim; - if (w<0) w+=in->dim->n; - int a = in->factor(); - int b = r->dim->prod(w); - Pt<T> data2 = (Pt<T>)*r + in->dex*b/a; - if (a==3 && b==1) { - int m = n+n*b/a; - STACK_ARRAY(T,data3,m); - Pt<T> data4 = data3; - while (n) { - SCOPY(data4,data,3); SCOPY(data4+3,data2,1); - n-=3; data+=3; data2+=1; data4+=4; - } - out->send(m,data3); - } else if (a+b<=16) { - int m = n+n*b/a; - STACK_ARRAY(T,data3,m); - int i=0; - while (n) { - COPY(data3+i,data,a); data+=a; i+=a; n-=a; - COPY(data3+i,data2,b); data2+=b; i+=b; - } - out->send(m,data3); - } else { - while (n) { - out->send(a,data); - out->send(b,data2); - data+=a; data2+=b; n-=a; - } - } -} GRID_FINISH { - if (in->dim->prod()==0) out->send(r->dim->prod(),(Pt<T>)*r); -} GRID_END - -GRID_INPUT(GridJoin,1,r) {} GRID_END - -\def void initialize (int which_dim, Grid *r) { - rb_call_super(argc,argv); - this->which_dim = which_dim; - if (r) this->r=r; -} - -\classinfo { IEVAL(rself,"install '@join',2,1"); } -\end class GridJoin - -//**************************************************************** -\class GridGrade < GridObject -struct GridGrade : GridObject { - \grin 0 -}; - -template <class T> struct GradeFunction { - static int comparator (const void *a, const void *b) { - return **(T**)a - **(T**)b;}}; -#define FOO(S) \ -template <> struct GradeFunction<S> { \ - static int comparator (const void *a, const void *b) { \ - S x = **(S**)a - **(S**)b; \ - return x<0 ? -1 : x>0;}}; -FOO(int64) -FOO(float32) -FOO(float64) -#undef FOO - -GRID_INLET(GridGrade,0) { - out=new GridOutlet(this,0,in->dim,in->nt); - in->set_factor(in->dim->get(in->dim->n-1)); -} GRID_FLOW { - int m = in->factor(); - STACK_ARRAY(T*,foo,m); - STACK_ARRAY(T,bar,m); - for (; n; n-=m,data+=m) { - for (int i=0; i<m; i++) foo[i] = &data[i]; - qsort(foo,m,sizeof(T),GradeFunction<T>::comparator); - for (int i=0; i<m; i++) bar[i] = foo[i]-(T *)data; - out->send(m,bar); - } -} GRID_END - -\classinfo { IEVAL(rself,"install '#grade',1,1"); } -\end class GridGrade - -//**************************************************************** -//\class GridMedian < GridObject -//**************************************************************** - -\class GridTranspose < GridObject -struct GridTranspose : GridObject { - \attr int dim1; - \attr int dim2; - int d1,d2,na,nb,nc,nd; // temporaries - \decl void initialize (int dim1=0, int dim2=1); - \decl void _1_float (int dim1); - \decl void _2_float (int dim2); - \grin 0 -}; - -\def void _1_float (int dim1) { this->dim1=dim1; } -\def void _2_float (int dim2) { this->dim2=dim2; } - -GRID_INLET(GridTranspose,0) { - STACK_ARRAY(int32,v,in->dim->n); - COPY(v,in->dim->v,in->dim->n); - d1=dim1; d2=dim2; - if (d1<0) d1+=in->dim->n; - if (d2<0) d2+=in->dim->n; - if (d1>=in->dim->n || d2>=in->dim->n || d1<0 || d2<0) - RAISE("would swap dimensions %d and %d but this grid has only %d dimensions", - dim1,dim2,in->dim->n); - memswap(v+d1,v+d2,1); - if (d1==d2) { - out=new GridOutlet(this,0,new Dim(in->dim->n,v), in->nt); - } else { - nd = in->dim->prod(1+max(d1,d2)); - nc = in->dim->v[max(d1,d2)]; - nb = in->dim->prod(1+min(d1,d2))/nc/nd; - na = in->dim->v[min(d1,d2)]; - out=new GridOutlet(this,0,new Dim(in->dim->n,v), in->nt); - in->set_factor(na*nb*nc*nd); - } - // Turns a Grid[*,na,*nb,nc,*nd] into a Grid[*,nc,*nb,na,*nd]. -} GRID_FLOW { - STACK_ARRAY(T,res,na*nb*nc*nd); - if (dim1==dim2) { out->send(n,data); return; } - int prod = na*nb*nc*nd; - for (; n; n-=prod, data+=prod) { - for (int a=0; a<na; a++) - for (int b=0; b<nb; b++) - for (int c=0; c<nc; c++) - COPY(res +((c*nb+b)*na+a)*nd, - data+((a*nb+b)*nc+c)*nd,nd); - out->send(na*nb*nc*nd,res); - } -} GRID_END - -\def void initialize (int dim1=0, int dim2=1) { - rb_call_super(argc,argv); - this->dim1 = dim1; - this->dim2 = dim2; -} - -\classinfo { IEVAL(rself,"install '#transpose',3,1"); } -\end class GridTranspose - -//**************************************************************** -\class GridReverse < GridObject -struct GridReverse : GridObject { - \attr int dim1; // dimension to act upon - int d; // temporaries - \decl void initialize (int dim1=0); - \decl void _1_float (int dim1); - \grin 0 -}; - -\def void _1_float (int dim1) { this->dim1=dim1; } - -GRID_INLET(GridReverse,0) { - d=dim1; - if (d<0) d+=in->dim->n; - if (d>=in->dim->n || d<0) - RAISE("would reverse dimension %d but this grid has only %d dimensions", - dim1,in->dim->n); - out=new GridOutlet(this,0,new Dim(in->dim->n,in->dim->v), in->nt); - in->set_factor(in->dim->prod(d)); -} GRID_FLOW { - int f1=in->factor(), f2=in->dim->prod(d+1); - while (n) { - int hf1=f1/2; - Pt<T> data2 = data+f1-f2; - for (int i=0; i<hf1; i+=f2) memswap(data+i,data2-i,f2); - out->send(f1,data); - data+=f1; n-=f1; - } -} GRID_END - -\def void initialize (int dim1=0) { - rb_call_super(argc,argv); - this->dim1 = dim1; -} - -\classinfo { IEVAL(rself,"install '#reverse',2,1"); } -\end class GridReverse - -//**************************************************************** -\class GridCentroid < GridObject -struct GridCentroid : GridObject { - \decl void initialize (); - \grin 0 int - int sumx,sumy,sum,y; // temporaries -}; - -GRID_INLET(GridCentroid,0) { - if (in->dim->n != 3) RAISE("expecting 3 dims"); - if (in->dim->v[2] != 1) RAISE("expecting 1 channel"); - in->set_factor(in->dim->prod(1)); - out=new GridOutlet(this,0,new Dim(2), in->nt); - sumx=0; sumy=0; sum=0; y=0; -} GRID_FLOW { - int sx = in->dim->v[1]; - while (n) { - for (int x=0; x<sx; x++) { - sumx+=x*data[x]; - sumy+=y*data[x]; - sum += data[x]; - } - n-=sx; - data+=sx; - y++; - } -} GRID_FINISH { - STACK_ARRAY(int32,blah,2); - blah[0] = sum ? sumy/sum : 0; - blah[1] = sum ? sumx/sum : 0; - out->send(2,blah); - rb_funcall(rself,SI(send_out),2,INT2NUM(1),INT2NUM(blah[0])); - rb_funcall(rself,SI(send_out),2,INT2NUM(2),INT2NUM(blah[1])); -} GRID_END - -\def void initialize () { - rb_call_super(argc,argv); -} - -\classinfo { IEVAL(rself,"install '#centroid',1,3"); } -\end class GridCentroid - -//**************************************************************** -\class GridPerspective < GridObject -struct GridPerspective : GridObject { - \attr int32 z; - \grin 0 - \decl void initialize (int32 z=256); -}; - -GRID_INLET(GridPerspective,0) { - int n = in->dim->n; - STACK_ARRAY(int32,v,n); - COPY(v,in->dim->v,n); - v[n-1]--; - in->set_factor(in->dim->get(in->dim->n-1)); - out=new GridOutlet(this,0,new Dim(n,v),in->nt); -} GRID_FLOW { - int m = in->factor(); - for (; n; n-=m,data+=m) { - op_mul->map(m-1,data,(T)z); - op_div->map(m-1,data,data[m-1]); - out->send(m-1,data); - } -} GRID_END - -\def void initialize (int32 z) {rb_call_super(argc,argv); this->z=z; } -\classinfo { IEVAL(rself,"install '#perspective',1,1"); } -\end class GridPerspective - -static Numop *OP(Ruby x) { return FIX2PTR(Numop,rb_hash_aref(op_dict,x)); } - -void startup_flow_objects () { - op_add = OP(SYM(+)); - op_sub = OP(SYM(-)); - op_mul = OP(SYM(*)); - op_shl = OP(SYM(<<)); - op_mod = OP(SYM(%)); - op_and = OP(SYM(&)); - op_div = OP(SYM(/)); - op_put = OP(SYM(put)); - \startall -} diff --git a/externals/gridflow/base/flow_objects.rb b/externals/gridflow/base/flow_objects.rb deleted file mode 100644 index 8782ae21..00000000 --- a/externals/gridflow/base/flow_objects.rb +++ /dev/null @@ -1,1457 +0,0 @@ -=begin - $Id: flow_objects.rb,v 1.2 2006-03-15 04:37:28 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. -=end - -module GridFlow - -#-------- fClasses for: control + misc - -# a dummy class that gives access to any stuff global to GridFlow. -FObject.subclass("gridflow",1,1) { - def _0_profiler_reset - GridFlow.fobjects.each {|o,*| o.total_time = 0 } - GridFlow.profiler_reset2 if GridFlow.respond_to? :profiler_reset2 - end - def _0_profiler_dump - ol = [] - total=0 - post "-"*32 - post "microseconds percent pointer constructor" - GridFlow.fobjects.each {|o,*| ol.push o } - - # HACK: BitPacking is not a real fobject - # !@#$ is this still necessary? - ol.delete_if {|o| not o.respond_to? :total_time } - - ol.sort! {|a,b| a.total_time <=> b.total_time } - ol.each {|o| total += o.total_time } - total=1 if total<1 - total_us = 0 - ol.each {|o| - ppm = o.total_time * 1000000 / total - us = (o.total_time*1E6/GridFlow.cpu_hertz).to_i - total_us += us - post "%12d %2d.%04d %08x %s", us, - ppm/10000, ppm%10000, o.object_id, o.args - } - post "-"*32 - post "sum of accounted microseconds: #{total_us}" - if GridFlow.respond_to? :memcpy_calls then - post "memcpy calls: #{GridFlow.memcpy_calls} "+ - "; bytes: #{GridFlow.memcpy_bytes}"+ - "; time: #{GridFlow.memcpy_time}" - end - if GridFlow.respond_to? :malloc_calls then - post "malloc calls: #{GridFlow.malloc_calls} "+ - "; bytes: #{GridFlow.malloc_bytes}"+ - "; time: #{GridFlow.malloc_time}" - end - post "-"*32 - end - def _0_formats - post "-"*32 - GridFlow.fclasses.each {|k,v| - next if not /#io:/ =~ k - modes = case v.flags - when 2; "#out" - when 4; "#in" - when 6; "#in/#out" - end - post "%s %s: %s", modes, k, v.description - if v.respond_to? :info then - post "-> %s", v.info - end - } - post "-"*32 - end - # security issue if patches shouldn't be allowed to do anything they want - def _0_eval(*l) - s = l.map{|x|x.to_i.chr}.join"" - post "ruby: %s", s - post "returns: %s", eval(s).inspect - end - add_creator "@global" - GridFlow.bind "gridflow", "gridflow" rescue Exception -} -FObject.subclass("fps",1,1) { - def initialize(*options) - super - @history = [] # list of delays between incoming messages - @last = 0.0 # when was last time - @duration = 0.0 # how much delay since last summary - @period = 1 # minimum delay between summaries - @detailed = false - @mode = :real - options.each {|o| - case o - when :detailed; @detailed=true - when :real,:user,:system,:cpu; @mode=o - end - } - def @history.moment(n=1) - sum = 0 - each {|x| sum += x**n } - sum/length - end - end - def method_missing(*a) end # ignore non-bangs - def _0_period x; @period=x end - def publish - @history.sort! - n=@history.length - fps = @history.length/@duration - if not @detailed then send_out 0, fps; return end - send_out 0, fps, - 1000*@history.min, - 500*(@history[n/2]+@history[(n-1)/2]), - 1000*@history.max, - 1000/fps, - 1000*(@history.moment(2) - @history.moment(1)**2)**0.5 - end - def _0_bang - t = case @mode - when :real; Time.new.to_f - when :user; Process.times.utime - when :system; Process.times.stime - when :cpu; GridFlow.rdtsc/GridFlow.cpu_hertz - end - @history.push t-@last - @duration += t-@last - @last = t - return if @duration<@period - fps = @history.length/@duration - publish if fps>0.001 - @history.clear - @duration = 0 - end -} - -# to see what the messages look like when they get on the Ruby side. -FObject.subclass("rubyprint",1,0) { - def initialize(*a) - super - @time = !!(a.length and a[0]==:time) - end - - def method_missing(s,*a) - s=s.to_s - pre = if @time then sprintf "%10.6f ", Time.new.to_f else "" end - case s - when /^_0_/; post "%s","#{pre}#{s[3..-1]}: #{a.inspect}" - else super - end - end -} -FObject.subclass("printargs",0,0) { - def initialize(*a) super; post a.inspect end -} -GridObject.subclass("#print",1,0) { - install_rgrid 0, true - attr_accessor :name - def initialize(name=nil) - super # don't forget super!!! - if name then @name = name.to_s+": " else @name="" end - @base=10; @format="d"; @trunc=70; @maxrows=50 - end - def end_hook; end # other hijackability - def format - case @nt - when :float32; '%6.6f' - when :float64; '%14.14f' - else "%#{@columns}#{@format}" end - end - def _0_base(x) - @format = (case x - when 2; "b" - when 8; "o" - when 10; "d" - when 16; "x" - else raise "base #{x} not supported" end) - @base = x - end - def _0_trunc(x) - x=x.to_f - (0..240)===x or raise "out of range (not in 0..240 range)" - @trunc = x - end - def _0_maxrows(x) @maxrows = x.to_i end - def make_columns udata - min = udata.min - max = udata.max - @columns = "" # huh? - @columns = [ - sprintf(format,min).length, - sprintf(format,max).length].max - end - def unpack data - ps = GridFlow.packstring_for_nt @nt - data.unpack ps - end - def _0_rgrid_begin - @dim = inlet_dim 0 - @nt = inlet_nt 0 - @data = "" - end - def _0_rgrid_flow(data) @data << data end - def _0_rgrid_end - head = "#{name}Dim[#{@dim.join','}]" - head << "(#{@nt})" if @nt!=:int32 - head << ": " - if @dim.length > 3 then - post head+" (not printed)" - elsif @dim.length < 2 then - udata = unpack @data - make_columns udata - post trunc(head + dump(udata)) - elsif @dim.length == 2 then - post head - udata = unpack @data - make_columns udata - sz = udata.length/@dim[0] - rown = 1 - for row in 0...@dim[0] do - post trunc(dump(udata[sz*row,sz])) - rown += 1 - (post "..."; break) if rown>@maxrows - end - elsif @dim.length == 3 then - post head - make_columns unpack(@data) - sz = @data.length/@dim[0] - sz2 = sz/@dim[1] - rown = 1 - for row in 0...@dim[0] - column=0; str="" - for col in 0...@dim[1] - str << "(" << dump(unpack(@data[sz*row+sz2*col,sz2])) << ")" - break if str.length>@trunc - end - post trunc(str) - rown += 1 - (post "..."; break) if rown>@maxrows - end - end - @data,@dim,@nt = nil - end_hook - end - def dump(udata,sep=" ") - f = format - udata.map{|x| sprintf f,x }.join sep - end - def trunc s - if s.length>@trunc then s[0...@trunc]+" [...]" else s end - end -} -GridPack = -GridObject.subclass("#pack",1,1) { - install_rgrid 0 - class<<self;attr_reader :ninlets;end - def initialize(n=2,cast=:int32) - n||=self.class.ninlets - n>=16 and raise "too many inlets" - super - @data=[0]*n - @cast=cast - @ps =GridFlow.packstring_for_nt cast - end - def initialize2 - return if self.class.ninlets>1 - add_inlets @data.length-1 - end - def _0_cast(cast) - @ps = GridFlow.packstring_for_nt cast - @cast = cast - end - def self.define_inlet i - module_eval " - def _#{i}_int x; @data[#{i}]=x; _0_bang; end - def _#{i}_float x; @data[#{i}]=x; _0_bang; end - " - end - (0...15).each {|x| define_inlet x } - def _0_bang - send_out_grid_begin 0, [@data.length], @cast - send_out_grid_flow 0, @data.pack(@ps), @cast - end - self -} - -# the install_rgrids in the following are hacks so that -# outlets can work. (install_rgrid is supposed to be for receiving) -# maybe GF-0.8 doesn't need that. -GridPack.subclass("@two", 2,1) { install_rgrid 0; def initialize() super 2 end } -GridPack.subclass("@three",3,1) { install_rgrid 0; def initialize() super 2 end } -GridPack.subclass("@four", 4,1) { install_rgrid 0; def initialize() super 2 end } -GridPack.subclass("@eight",8,1) { install_rgrid 0; def initialize() super 2 end } -GridObject.subclass("#unpack",1,0) { - install_rgrid 0, true - def initialize(n=2) - @n=n - n>=10 and raise "too many outlets" - super - end - def initialize2; add_outlets @n end - def _0_rgrid_begin - inlet_dim(0)==[@n] or raise "expecting Dim[#{@n}], got Dim#{@dim}" - inlet_set_factor 0,@n - end - def _0_rgrid_flow data - @ps = GridFlow.packstring_for_nt inlet_nt(0) - duh = data.unpack(@ps) - i=duh.size-1 - until i<0 do send_out i,duh[i]; i-=1 end - end - def _0_rgrid_end; end -} - -GridObject.subclass("#export_symbol",1,1) { - install_rgrid 0 - def _0_rgrid_begin; @data="" end - def _0_rgrid_flow data; @data << data; end - def _0_rgrid_end - send_out 0, :symbol, @data.unpack("I*").pack("c*").intern - end -} -GridObject.subclass("unix_time",1,3) { - install_rgrid 0 - def _0_bang - t = Time.new - tt = t.to_s - send_out_grid_begin 0, [tt.length], :uint8 - send_out_grid_flow 0, tt, :uint8 - send_out 1, t.to_i/86400, t.to_i%86400, - ((t.to_f-t.to_f.floor)*1000000).to_i - send_out 2, t.year, t.month, t.day, t.hour, t.min, t.day - end -} -### test with "shell xlogo &" -> [exec] -FObject.subclass("exec",1,0) { - def _0_shell(*a) system(a.map!{|x| x.to_s }.join(" ")) end -} -FObject.subclass("renamefile",1,0) { - def initialize; end - def _0_list(a,b) File.rename(a.to_s,b.to_s) end -} -FObject.subclass("ls",1,1) { - def _0_symbol(s) send_out 0, :list, *Dir.new(s.to_s).map {|x| x.intern } end - def _0_glob (s) send_out 0, :list, *Dir[ s.to_s].map {|x| x.intern } end -} - -#-------- fClasses for: math - -FPatcher.subclass("gfmessagebox",1,1) { - def initialize(*a) @a=a end - def _0_float(x) send_out 0, *@a.map {|y| if y=="$1".intern then x else y end } end - def _0_symbol(x) send_out 0, *@a.map {|y| if y=="$1".intern then x else y end } end -} - -FPatcher.subclass("@!",1,1) { - @fobjects = ["# +","#type","gfmessagebox list $1 #"] - @wires = [-1,0,1,0, 1,0,2,0, 2,0,0,1, -1,0,0,0, 0,0,-1,0] - def initialize(sym) - super - @fobjects[0].send_in 0, case sym - when :rand; "op rand"; when :sqrt; "op sqrt" - when :abs; "op abs-"; when :sq; "op sq-" - else raise "bork BORK bork" end - end -} -FPatcher.subclass("@fold",2,1) { - @fobjects = ["#fold +","gfmessagebox seed $1"] - @wires = [-1,0,0,0, -1,1,1,0, 1,0,0,1, 0,0,-1,0] - def initialize(op,seed=0) super; o=@fobjects[0] - o.send_in 0, :op, op; o.send_in 0, :seed, seed end -} -FPatcher.subclass("@scan",2,1) { - @fobjects = ["#scan +","gfmessagebox seed $1"] - @wires = [-1,0,0,0, -1,1,1,0, 1,0,0,1, 0,0,-1,0] - def initialize(op,seed=0) super; o=@fobjects[0] - o.send_in 0, :op, op; o.send_in 0, :seed, seed end -} -FPatcher.subclass("@inner",3,1) { - @fobjects = ["#inner","gfmessagebox seed $1"] - @wires = [-1,0,0,0, -1,1,1,0, 1,0,0,0, 0,0,-1,0, -1,2,0,1] - def initialize(op=:*,fold=:+,seed=0,r=0) super; o=@fobjects[0] - o.send_in 0, :op, op; o.send_in 0, :fold, fold - o.send_in 0, :seed, seed; o.send_in 1, r end -} -FPatcher.subclass("@convolve",2,1) { - @fobjects = ["#convolve"] - @wires = [-1,0,0,0, -1,2,0,1, 0,0,-1,0] - def initialize(op=:*,fold=:+,seed=0,r=0) super; o=@fobjects[0] - o.send_in 0, :op, op; o.send_in 0, :fold, fold - o.send_in 0, :seed, seed; o.send_in 1, r end -} - -#-------- fClasses for: video - -FPatcher.subclass("@scale_to",2,1) { - @fobjects = [ - "@for {0 0} {42 42} {1 1}","@ *","@ /", - "@store","#dim","@redim {2}","#finished", - ] - @wires = [] - for i in 1..3 do @wires.concat [i-1,0,i,0] end - @wires.concat [3,0,-1,0, 4,0,5,0, 5,0,1,1, 6,0,0,0, - -1,0,4,0, -1,0,3,1, -1,0,6,0, -1,1,0,1, -1,1,2,1] - def initialize(size) - (size.length==2 and Numeric===size[0] and Numeric===size[1]) or - raise "expecting {height width}" - super - send_in 1, size - end -} - -#<vektor> told me to: -# RGBtoYUV : @fobjects = ["#inner (3 3 # 66 -38 112 128 -74 -94 25 112 -18)", -# "@ >> 8","@ + {16 128 128}"] -# YUVtoRGB : @fobjects = ["@ - (16 128 128)", -# "#inner (3 3 # 298 298 298 0 -100 516 409 -208 0)","@ >> 8"] - -FPatcher.subclass("#rotate",2,1) { - @fobjects = ["#inner","# >> 8"] - @wires = [-1,0,0,0, 0,0,1,0, 1,0,-1,0] - def update_rotator - n = @axis[2] - rotator = (0...n).map {|i| (0...n).map {|j| if i==j then 256 else 0 end }} - th = @angle * Math::PI / 18000 - scale = 1<<8 - (0...2).each {|i| (0...2).each {|j| - a = @axis[i].to_i - b = @axis[j].to_i - #GridFlow.post "(#{a},#{b}) #{rotator[a].inspect}" - rotator[a][b] = (scale*Math.cos(th+(j-i)*Math::PI/2)).to_i - }} - @fobjects[0].send_in 1,n,n,"#".intern,*rotator.flatten - end - def _0_axis(from,to,total) - total>=0 or raise "total-axis number incorrect" - from>=0 and from<total or raise "from-axis number incorrect" - to >=0 and to <total or raise "to-axis number incorrect" - @axis = [from.to_i,to.to_i,total.to_i] - update_rotator - end - def initialize(rot=0,axis=[0,1,2]) - super - @angle=0 - _0_axis(*axis) - send_in 1, rot - end - def _1_int(angle) @angle = angle; update_rotator end - alias _1_float _1_int -} - -FObject.subclass("foreach",1,1) { - def initialize() super end - def _0_list(*a) - a.each {|e| - if Symbol===e then - send_out 0,:symbol,e - else - send_out 0,e - end - } - end -} -FObject.subclass("listflatten",1,1) { - def initialize() super end - def _0_list(*a) send_out 0,:list,*a.flatten end -} -FObject.subclass("rubysprintf",2,1) { - def initialize(*format) _1_list(format) end - def _0_list(*a) send_out 0, :symbol, (sprintf @format, *a).intern end - alias _0_float _0_list - alias _0_symbol _0_list - def _1_list(*format) @format = format.join(" ") end - alias _1_symbol _1_list -} - -#-------- fClasses for: jMax compatibility - -class JMaxUDPSend < FObject - def initialize(host,port) - super - @socket = UDPSocket.new - @host,@port = host.to_s,port.to_i - end - def encode(x) - case x - when Integer; "\x03" + [x].pack("N") - when Float; "\x04" + [x].pack("g") - when Symbol, String; "\x01" + x.to_s + "\x02" - end - end - def method_missing(sel,*args) - sel=sel.to_s.sub(/^_\d_/, "") - @socket.send encode(sel) + - args.map{|arg| encode(arg) }.join("") + "\x0b", - 0, @host, @port - end - def delete; @socket.close end - install "jmax_udpsend", 1, 0 -end - -class JMaxUDPReceive < FObject - def initialize(port) - super - @socket = UDPSocket.new - @port = port.to_i - @socket.bind nil, @port - @clock = Clock.new self - @clock.delay 0 - end - def decode s - n = s.length - i=0 - m = [] - case s[i] - when 3; i+=5; m << s[i-4,4].unpack("N")[0] - when 4; i+=5; m << s[i-4,4].unpack("g")[0] - when 1; i2=s.index("\x02",i); m << s[i+1..i2-1].intern; i=i2+1 - when 11; break - else raise "unknown code in udp packet" - end while i<n - m - end - def call - ready_to_read = IO.select [@socket],[],[],0 - return if not ready_to_read - data,sender = @socket.recvfrom 1024 - return if not data - send_out 1, sender.map {|x| x=x.intern if String===x; x } - send_out 0, *(decode data) - @clock.delay 50 - end - def delete; @clock.unset; @socket.close end - install "jmax_udpreceive", 0, 2 -end - -class JMax4UDPSend < FObject - def initialize(host,port) - super - @socket = UDPSocket.new - @host,@port = host.to_s,port.to_i - @symbols = {} - end - def encode(x) - case x - when Integer; "\x01" + [x].pack("N") - when Float; "\x02" + [x].pack("G") - when Symbol, String - x = x.to_s - y = x.intern - if not @symbols[y] - @symbols[y]=true - "\x04" + [y].pack("N") + x + "\0" - else - "\x03" + [y].pack("N") - end - end - end - def method_missing(sel,*args) - sel=sel.to_s.sub(/^_\d_/, "") - sel=(case sel; when "int","float"; ""; else encode(sel) end) - args=args.map{|arg| encode(arg) }.join("") - @socket.send(sel+args+"\x0f", 0, @host, @port) - end - def delete; @socket.close end - install "jmax4_udpsend", 1, 0 -end - -class JMax4UDPReceive < FObject - def initialize(port) - super - @socket = UDPSocket.new - @port = port.to_i - @socket.bind nil, @port - @clock = Clock.new self - @clock.delay 0 - @symbols = {} - end - def decode s - n = s.length - i=0 - m = [] - case s[i] - when 1; i+=5; m << s[i-4,4].unpack("N")[0] - when 2; i+=9; m << s[i-8,8].unpack("G")[0] - when 3 - i+=5; sid = s[i-4,4].unpack("N")[0] - m << @symbols[sid] - when 4 - i+=5; sid = s[i-4,4].unpack("N")[0] - i2=s.index("\x00",i) - @symbols[sid] = s[i..i2-1].intern - m << @symbols[sid] - i=i2+1 - when 15; break - else post "unknown code %d in udp packet %s", s[i], s.inspect; return m - end while i<n - m - end - def call - ready_to_read = IO.select [@socket],[],[],0 - return if not ready_to_read - data,sender = @socket.recvfrom 1024 - return if not data - send_out 1, sender.map {|x| x=x.intern if String===x; x } - send_out 0, *(decode data) - @clock.delay 50 - end - def delete; @clock.unset; @socket.close end - install "jmax4_udpreceive", 0, 2 -end - -class PDNetSocket < FObject - def initialize(host,port,protocol=:udp,*options) - super - _1_connect(host,port,protocol) - @options = {} - options.each {|k| - k=k.intern if String===k - @options[k]=true - } - end - def _1_connect(host,port,protocol=:udp) - host = host.to_s - port = port.to_i - @host,@port,@protocol = host.to_s,port.to_i,protocol - case protocol - when :udp - @socket = UDPSocket.new - if host=="-" then - @socket.bind nil, port - end - when :tcp - if host=="-" then - @server = TCPServer.new("localhost",port) - else - @socket = TCPSocket.new(host,port) - end - - end - @clock = Clock.new self - @clock.delay 0 - @data = "" - end - def encode(x) - x=x.to_i if @options[:nofloat] and Float===x - x.to_s - end - def method_missing(sel,*args) - sel=sel.to_s - sel.sub!(/^_\d_/, "") or return super - sel=(case sel; when "int","float"; ""; else encode(sel) end) - msg = [sel,*args.map{|arg| encode(arg) }].join(" ") - if @options[:nosemicolon] then msg << "\n" else msg << ";\n" end - post "encoding as: %s", msg.inspect if @options[:debug] - case @protocol - when :udp; @socket.send msg, 0, @host, @port - when :tcp; @socket.send msg, 0 - end - end - def delete; @clock.unset; @socket.close end - def decode s - post "decoding from: %s", s.inspect if @options[:debug] - s.chomp!("\n") - s.chomp!("\r") - s.chomp!(";") - a=s.split(/[\s\0]+/) - a.shift if a[0]=="" - a.map {|x| - case x - when /-?\d+$/; x.to_i - when /-?\d/; x.to_f - else x.intern - end - } - end - def call - ready_to_accept = IO.select [@server],[],[],0 if @server - if ready_to_accept - @socket.close if @socket - @socket = @server.accept - end - ready_to_read = IO.select [@socket],[],[],0 if @socket - return if not ready_to_read - case @protocol - when :udp - data,sender = @socket.recvfrom 1024 - send_out 1, sender.map {|x| x=x.intern if String===x; x } - send_out 0, *(decode data) - when :tcp - @data << @socket.sysread(1024) - sender = @socket.peeraddr - loop do - n = /\n/ =~ @data - break if not n - send_out 1, sender.map {|x| x=x.intern if String===x; x } - send_out 0, *(decode @data.slice!(0..n)) - end - end - @clock.delay 50 - end - install "pd_netsocket", 2, 2 -end - -PDNetSocket.subclass("pd_netsend",1,0) {} -PDNetSocket.subclass("pd_netreceive",0,2) { - def initialize(port) super("-",port) end -} - -# bogus class for representing objects that have no recognized class. -FObject.subclass("broken",0,0) { - def args; a=@args.dup; a[7,0] = " "+classname; a end -} - -FObject.subclass("fork",1,2) { - def method_missing(sel,*args) - sel.to_s =~ /^_(\d)_(.*)$/ or super - send_out 1,$2.intern,*args - send_out 0,$2.intern,*args - end -} -FObject.subclass("shunt",2,0) { - def initialize(n=2,i=0) super; @n=n; @i=i end - def initialize2; add_outlets @n end - def method_missing(sel,*args) - sel.to_s =~ /^_(\d)_(.*)$/ or super - send_out @i,$2.intern,*args - end - def _1_int i; @i=i.to_i % @n end - alias :_1_float :_1_int - # hack: this is an alias. - class Demux < self; install "demux", 2, 0; end -} - -#-------- fClasses for: jmax2pd - - FObject.subclass("button",1,1) { - def method_missing(*) send_out 0 end - } - FObject.subclass("toggle",1,1) { - def _0_bang; @state ^= true; trigger end - def _0_int x; @state = x!=0; trigger end - def trigger; send_out 0, (if @state then 1 else 0 end) end - } - FObject.subclass("jpatcher",0,0) { - def initialize(*a) super; @subobjects={} end - attr_accessor :subobjects - } - FObject.subclass("jcomment",0,0) {} - FObject.subclass("loadbang",0,1) { def trigger; send_out 0 end } - FObject.subclass("messbox",1,1) { - def _0_bang; send_out 0, *@argv end - def clear; @argv=[]; end - def append(*argv) @argv<<argv; end - } - -#-------- fClasses for: list manipulation (jMax-compatible) - - FObject.subclass("listmake",2,1) { - def initialize(*a) @a=a end - def _0_list(*a) @a=a; _0_bang end - def _1_list(*a) @a=a end - def _0_bang; send_out 0, :list, *@a end - } - FObject.subclass("listlength",1,1) { - def initialize() super end - def _0_list(*a) send_out 0, a.length end - } - FObject.subclass("listelement",2,1) { - def initialize(i=0) super; @i=i.to_i end - def _1_int(i) @i=i.to_i end; alias _1_float _1_int - def _0_list(*a) - e=a[@i] - if Symbol===e then - send_out 0, :symbol, e - else - send_out 0, e - end - end - } - FObject.subclass("listsublist",3,1) { - def initialize(i=0,n=1) super; @i,@n=i.to_i,n.to_i end - def _1_int(i) @i=i.to_i end; alias _1_float _1_int - def _2_int(n) @n=n.to_i end; alias _2_float _2_int - def _0_list(*a) send_out 0, :list, *a[@i,@n] end - } - FObject.subclass("listprepend",2,1) { - def initialize(*b) super; @b=b end - def _0_list(*a) a[0,0]=@b; send_out 0, :list, *a end - def _1_list(*b) @b=b end - } - FObject.subclass("listappend",2,1) { - def initialize(*b) super; @b=b end - def _0_list(*a) a[a.length,0]=@b; send_out 0, :list, *a end - def _1_list(*b) @b=b end - } - FObject.subclass("listreverse",1,1) { - def initialize() super end - def _0_list(*a) send_out 0,:list,*a.reverse end - } - FObject.subclass("messageprepend",2,1) { - def initialize(*b) super; @b=b end - def _0_(*a) a[0,0]=@b; send_out 0, *a end - def _1_list(*b) @b=b end - def method_missing(sym,*a) - (m = /(_\d_)(.*)/.match sym.to_s) or return super - _0_ m[2].intern, *a - end - } - FObject.subclass("messageappend",2,1) { - def initialize(*b) super; @b=b end - def _0_(*a) a[a.length,0]=@b; send_out 0, *a end - def _1_list(*b) @b=b end - def method_missing(sym,*a) - (m = /(_\d_)(.*)/.match sym.to_s) or return super - _0_ m[2].intern, *a - end - } - -# this was the original demo for the Ruby/jMax/PureData bridges -# FObjects are Ruby Objects that are exported to the PureData system. -# _0_bang means bang message on inlet 0 -# FObject#send_out sends a message through an outlet -FObject.subclass("for",3,1) { - attr_accessor :start, :stop, :step - def cast(key,val) - val = Integer(val) if Float===val - raise ArgumentError, "#{key} isn't a number" unless Integer===val - end - def initialize(start,stop,step) - super - cast("start",start) - cast("stop",stop) - cast("step",step) - @start,@stop,@step = start,stop,step - end - def _0_bang - x = start - if step > 0 - (send_out 0, x; x += step) while x < stop - elsif step < 0 - (send_out 0, x; x += step) while x > stop - end - end - def _0_float(x) self.start=x; _0_bang end - alias _1_float stop= - alias _2_float stop= -} -FObject.subclass("oneshot",2,1) { - def initialize(state=true) @state=state!=0 end - def method_missing(sel,*a) - m = /^_0_(.*)$/.match(sel.to_s) or return super - send_out 0, m[1].intern, *a if @state - @state=false - end - def _1_int(state) @state=state!=0 end - alias _1_float _1_int - def _1_bang; @state=true end -} -FObject.subclass("inv+",2,1) { - def initialize(b=0) @b=b end; def _1_float(b) @b=b end - def _0_float(a) send_out 0, :float, @b-a end -} -FObject.subclass("inv*",2,1) { - def initialize(b=0) @b=b end; def _1_float(b) @b=b end - def _0_float(a) send_out 0, :float, @b/a end -} -FObject.subclass("range",1,1) { - def initialize(*a) @a=a end - def initialize2 - add_inlets @a.length - add_outlets @a.length - end - def _0_float(x) i=0; i+=1 until @a[i]==nil or x<@a[i]; send_out i,x end - def method_missing(sel,*a) - m = /^(_\d+_)(.*)/.match(sel.to_s) or return super - m[2]=="float" or return super - @a[m[1].to_i-1] = a[0] - post "setting a[#{m[1].to_i-1}] = #{a[0]}" - end -} -FObject.subclass("listfind",2,1) { - def initialize(*a) _1_list(*a) end - def _1_list(*a) @a = a end - def _0_float(x) - i=0 - while i<@a.length - (send_out 0,i; return) if @a[i]==x - i+=1 - end - send_out 0,-1 - end - doc:_1_list,"list to search into" - doc:_0_float,"float to find in that list" - doc_out:_0_float,"position of the incoming float in the stored list" -} - -#-------- fClasses for: GUI - -module Gooey # to be included in any FObject class - def initialize(*) - super - @selected=false - @bg = "#ffffff" # white background - @bgb = "#000000" # black border - @bgs = "#0000ff" # blue border when selected - @fg = "#000000" # black foreground - @rsym = "#{self.class}#{self.object_id}".intern # unique id for use in Tcl - @can = nil # the canvas number - @canvas = nil # the canvas string - @y,@x = 0,0 # position on canvas - @sy,@sx = 16,16 # size on canvas - @font = "Courier -12" - @vis = nil - end - attr_reader :canvas - attr_reader :selected - def canvas=(can) - @can = can if Integer===can - @canvas = case can - when String; can - when Integer; ".x%x.c"%(4*can) - else raise "huh?" - end - end - def initialize2(*) GridFlow.bind self, @rsym.to_s end - def pd_displace(can,x,y) self.canvas||=can; @x+=x; @y+=y; pd_show(can) end - def pd_activate(can,*) self.canvas||=can end - def quote(text) # for tcl (isn't completely right ?) - text=text.gsub(/[\{\}]/) {|x| "\\"+x } - "{#{text}}" - end - def pd_vis(can,vis) - self.canvas||=can; @vis=vis!=0; update end - def update; pd_show @can if @vis end - def pd_getrect(can) - self.canvas||=can - @x,@y = get_position(can) - # the extra one-pixel on each side was for #peephole only - # not sure what to do with this - [@x-1,@y-1,@x+@sx+1,@y+@sy+1] - end - def pd_click(can,x,y,shift,alt,dbl,doit) return 0 end - def outline; if selected then @bgs else "#000000" end end - def pd_select(can,sel) - self.canvas||=can - @selected=sel!=0 - GridFlow.gui %{ #{canvas} itemconfigure #{@rsym} -outline #{outline} \n } - end - def pd_delete(can) end - def pd_show(can) - self.canvas||=can - @x,@y = get_position can if can - end - def highlight(color,ratio) # doesn't use self - c = /^#(..)(..)(..)/.match(color)[1..3].map {|x| x.hex } - c.map! {|x| [255,(x*ratio).to_i].min } - "#%02x%02x%02x" % c - end -end - -class Display < FObject; include Gooey - attr_accessor :text - def initialize() - super - @sel = nil; @args = [] # contents of last received message - @text = "..." - @sy,@sx = 16,80 # default size of the widget - @bg,@bgs,@fg = "#6774A0","#00ff80","#ffff80" - end - def _0_set_size(sy,sx) @sy,@sx=sy,sx end - def atom_to_s a - case a - when Float; sprintf("%.5f",a).gsub(/\.?0+$/, "") - else a.to_s - end - end - def method_missing(sel,*args) - m = /^(_\d+_)(.*)/.match(sel.to_s) or return super - @sel,@args = m[2].intern,args - @text = case @sel - when nil; "..." - when :float; atom_to_s @args[0] - else @sel.to_s + ": " + @args.map{|a| atom_to_s a }.join(' ') - end - update - end - def pd_show(can) - super - return if not canvas or not @vis # can't show for now... - GridFlow.gui %{ - set canvas #{canvas} - $canvas delete #{@rsym}TEXT - set y #{@y+2} - foreach line [split #{quote @text} \\n] { - $canvas create text #{@x+2} $y -fill #{@fg} -font #{quote @font}\ - -text $line -anchor nw -tag #{@rsym}TEXT - set y [expr $y+14] - } - foreach {x1 y1 x2 y2} [$canvas bbox #{@rsym}TEXT] {} - set sx [expr $x2-$x1+1] - set sy [expr $y2-$y1+3] - $canvas delete #{@rsym} - $canvas create rectangle #{@x} #{@y} \ - [expr #{@x}+$sx] [expr #{@y}+$sy] -fill #{@bg} \ - -tags #{@rsym} -outline #{outline} - $canvas lower #{@rsym} #{@rsym}TEXT - pd \"#{@rsym} set_size $sy $sx;\n\"; - } - end - def pd_delete(can) - if @vis - GridFlow.gui %{ #{canvas} delete #{@rsym} #{@rsym}TEXT \n} - end - super - end - def delete; super end - def _0_grid(*foo) # big hack! - # hijacking a [#print] - gp = FObject["#print"] - @text = "" - overlord = self - gp.instance_eval { @overlord = overlord } - def gp.post(fmt,*args) @overlord.text << sprintf(fmt,*args) << "\n" end - def gp.end_hook - @overlord.instance_eval{@text.chomp!} - @overlord.update - end - #gp.send_in 0, :trunc, 70 - gp.send_in 0, :maxrows, 20 - gp.send_in 0, :grid, *foo - end - - install "display", 1, 1 - gui_enable if GridFlow.bridge_name =~ /puredata/ -end - -class GridEdit < GridObject; include Gooey - def initialize(grid) - super - @store = GridStore.new - @store.connect 0,self,2 - @fin = GridFinished.new - @fin.connect 0,self,3 - @bg,@bgs,@fg = "#609068","#0080ff","#ff80ff" - @bghi = highlight(@bg,1.25) # "#80C891" # highlighted @bg - #@bghihi = highlight(@bghi,1.5) # very highlighted @bg - @cellsy,@cellsx = 16,48 - @i,@j = nil,nil # highlighted cell dex - send_in 0, grid - end - def _0_cell_size(sy,sx) @cellsy,@cellsx=sy,sx; update end - def _0_float(*a) @store.send_in 1,:float,*a; @store.send_in 0; update end - def _0_list (*a) @store.send_in 1, :list,*a; @store.send_in 0; update end - def _0_grid (*a) @store.send_in 1, :grid,*a; @fin.send_in 0, :grid,*a end - def _3_bang; @store.send_in 0; update end - def edit_start(i,j) - edit_end if @i - @i,@j=i,j - GridFlow.gui %{ - set canvas #{canvas} - $canvas itemconfigure #{@rsym}CELL_#{@i}_#{@j} -fill #{@bghi} - } - end - def edit_end - GridFlow.gui %{ - set canvas #{canvas} - $canvas itemconfigure #{@rsym}CELL_#{@i}_#{@j} -fill #{@bg} - } - unfocus @can - end - def _2_rgrid_begin - @data = [] - @dim = inlet_dim 2 - @nt = inlet_nt 2 - post "_2_rgrid_begin: dim=#{@dim.inspect} nt=#{@nt.inspect}" - send_out_grid_begin 0, @dim, @nt - end - def _2_rgrid_flow data - ps = GridFlow.packstring_for_nt @nt - @data[@data.length,0] = data.unpack(ps) - post "_2_rgrid_flow: data=#{@data.inspect}" - send_out_grid_flow 0, data - end - def _2_rgrid_end - post "_2_rgrid_end" - end - def pd_click(can,x,y,shift,alt,dbl,doit) - post "pd_click: %s", [can,x,y,shift,alt,dbl,doit].inspect - return 0 if not doit!=0 - i = (y-@y-1)/@cellsy - j = (x-@x-1)/@cellsx - post "%d,%d", i,j - ny = @dim[0] || 1 - nx = @dim[1] || 1 - if (0...ny)===i and (0...nx)===j then - focus @can,x,y - edit_start i,j - end - return 0 - end - def pd_key(key) - post "pd_key: %s", [key].inspect - if key==0 then unfocus @can; return end - end - def pd_motion(dx,dy) - post "pd_motion: %s", [dx,dy].inspect - ny = @dim[0] || 1 - nx = @dim[1] || 1 - k = @i*nx+@j - post "@data[#{k}]=#{@data[k]} before" - @data[k]-=dy - @store.send_in 1, :put_at, [@i,@j] - @store.send_in 1, @data[k] - @store.send_in 0 - post "@data[#{k}]=#{@data[k]} after" - update - end - def pd_show(can) - super - return if not can - ny = @dim[0] || 1 - nx = @dim[1] || 1 - @sy = 2+@cellsy*ny - @sx = 2+@cellsx*nx - g = %{ - set canvas #{canvas} - $canvas delete #{@rsym} #{@rsym}CELL - $canvas create rectangle #{@x} #{@y} #{@x+@sx} #{@y+@sy} \ - -fill #{@bg} -tags #{@rsym} -outline #{outline} - } - ny.times {|i| - nx.times {|j| - y1 = @y+1+i*@cellsy; y2 = y1+@cellsy - x1 = @x+1+j*@cellsx; x2 = x1+@cellsx - v = @data[i*nx+j] - g << %{ - $canvas create rectangle #{x1} #{y1} #{x2} #{y2} -fill #{@bg} \ - -tags {#{@rsym}CELL #{@rsym}CELL_#{i}_#{j}} -outline #{outline} - $canvas create text #{x2-4} #{y1+2} -text "#{v}" -anchor ne -fill #ffffff \ - -tags {#{@rsym}CELL_#{i}_#{j}_T} - } - } - } - GridFlow.gui g - end - install "#edit", 2, 1 - install_rgrid 2, true - gui_enable if GridFlow.bridge_name =~ /puredata/ -end - -class Peephole < FPatcher; include Gooey - @fobjects = ["#dim","#export_list","#downscale_by 1 smoothly","#out","#scale_by 1", - proc{Demux.new(2)}] - @wires = [-1,0,0,0, 0,0,1,0, -1,0,5,0, 2,0,3,0, 4,0,3,0, 5,0,2,0, 5,1,4,0, 3,0,-1,0] - def initialize(sy=32,sx=32,*args) - super - @fobjects[1].connect 0,self,2 - post "Peephole#initialize: #{sx} #{sy} #{args.inspect}" - @scale = 1 - @down = false - @sy,@sx = sy,sx # size of the widget - @fy,@fx = 0,0 # size of last frame after downscale - @bg,@bgs = "#A07467","#00ff80" - end - def pd_show(can) - super - return if not can - if not @open - GridFlow.gui %{ - pd \"#{@rsym} open [eval list [winfo id #{@canvas}]] 1;\n\"; - } - @open=true - end - # round-trip to ensure this is done after the open - GridFlow.gui %{ - pd \"#{@rsym} set_geometry #{@y} #{@x} #{@sy} #{@sx};\n\"; - } - GridFlow.gui %{ - set canvas #{canvas} - $canvas delete #{@rsym} - $canvas create rectangle #{@x} #{@y} #{@x+@sx} #{@y+@sy} \ - -fill #{@bg} -tags #{@rsym} -outline #{outline} - } - set_geometry_for_real_now - end - def set_geometry_for_real_now - @fy,@fx=@sy,@sx if @fy<1 or @fx<1 - @down = (@fx>@sx or @fy>@sx) - if @down then - @scale = [(@fy+@sy-1)/@sy,(@fx+@sx-1)/@sx].max - @scale=1 if @scale<1 # what??? - @fobjects[2].send_in 1, @scale - sy2 = @fy/@scale - sx2 = @fx/@scale - else - @scale = [@sy/@fy,@sx/@fx].min - @fobjects[4].send_in 1, @scale - sy2 = @fy*@scale - sx2 = @fx*@scale - end - begin - @fobjects[5].send_in 1, (if @down then 0 else 1 end) - x2=@y+(@sy-sy2)/2 - y2=@x+(@sx-sx2)/2 - @fobjects[3].send_in 0, :set_geometry, - x2, y2, sy2, sx2 - rescue StandardError => e - post "peeperr: %s", e.inspect - end - post "set_geometry_for_real_now (%d,%d) (%d,%d) (%d,%d) (%d,%d) (%d,%d)", - @x+1,@y+1,@sx,@sy,@fx,@fy,sx2,sy2,x2,y2 - end - def _0_open(wid,use_subwindow) - post "%s", [wid,use_subwindow].inspect - @use_subwindow = use_subwindow==0 ? false : true - if @use_subwindow then - @fobjects[3].send_in 0, :open,:x11,:here,:embed_by_id,wid - end - end - def _0_set_geometry(y,x,sy,sx) - @sy,@sx = sy,sx - @y,@x = y,x - set_geometry_for_real_now - end - def _0_fall_thru(flag) # never worked ? - post "fall_thru: #{flag}" - @fobjects[3].send_in 0, :fall_thru, flag - end - # note: the numbering here is a FPatcher gimmick... -1,0 goes to _1_. - def _1_position(y,x,b) - s=@scale - if @down then y*=s;x*=s else y*=s;x*=s end - send_out 0,:position,y,x,b - end - def _2_list(sy,sx,chans) - @fy,@fx = sy,sx - set_geometry_for_real_now - end - def _0_paint() - post "paint()" - @fobjects[3].send_in 0, "draw" - end - def delete - post "deleting peephole" - GridFlow.gui %{ #{canvas} delete #{@rsym} \n} - @fobjects[3].send_in 0, :close - super - end - def method_missing(s,*a) - #post "%s: %s", s.to_s, a.inspect - super rescue NameError - end - - install "#peephole", 1, 1 - gui_enable if GridFlow.bridge_name =~ /puredata/ - #GridFlow.addtomenu "#peephole" # was this IMPD-specific ? -end - -#-------- fClasses for: Hardware - -# requires Ruby 1.8.0 because of bug in Ruby 1.6.x -FObject.subclass("joystick_port",0,1) { - def initialize(port) - raise "sorry, requires Ruby 1.8" if RUBY_VERSION<"1.8" - @f = File.open(port.to_s,"r+") - @status = nil - @clock = Clock.new self - @clock.delay 0 - @f.nonblock=true - end - def delete; @clock.unset; @f.close end - def call - loop{ - begin - event = @f.read(8) - rescue Errno::EAGAIN - @clock.delay 0 - return - end - return if not event - return if event.length<8 - send_out 0, *event.unpack("IsCC") - } - end -} - -# plotter control (HPGL) -FObject.subclass("plotter_control",1,1) { - def puts(x) - x<<"\n" - x.each_byte {|b| send_out 0, b } - send_out 0 - end - def _0_pu; puts "PU;" end - def _0_pd; puts "PD;" end - def _0_pa x,y; puts "PA#{x},#{y};" end - def _0_sp c; puts "SP#{c};"; end - def _0_ip(*v) puts "IP#{v.join','};" end - def _0_other(command,*v) puts "#{command.to_s.upcase}#{v.join','};" end - def _0_print(*text) puts "LB#{text.join(' ')}\003;" end - def _0_print_from_ascii(*codes) - _0_print codes.map{|code| code.chr }.join("") - end -} - -# ASCII, useful for controlling pics -FObject.subclass("ascii",1,1) { - def puts(x) - x.each_byte {|b| send_out 0, b } - end - def _0_float x; puts "#{x.to_i}" end -} - -# System, similar to shell -FObject.subclass("system",1,1) { - def _0_system(*a) - system(a.join(" ")) - end -} - -(begin require "linux/ParallelPort"; true; rescue LoadError; false end) and -FObject.subclass("parallel_port",1,3) { - def initialize(port,manually=0) - @f = File.open(port.to_s,"r+") - @f.extend Linux::ParallelPort - @status = nil - @flags = nil - @manually = manually!=0 - @clock = (if @manually then nil else Clock.new self end) - @clock.delay 0 if @clock - end - def delete; @clock.unset unless @manually; @f.close end - def _0_int(x) @f.write x.to_i.chr; @f.flush end - alias _0_float _0_int - def call - flags = @f.port_flags - send_out 2, flags if @flags != flags - @flags = flags - status = @f.port_status - send_out 1, status if @status != status - @status = status - @clock.delay 20 if @clock - end - def _0_bang - @status = @flags = nil - call - end - # outlet 0 reserved (future use) -} - -(begin require "linux/SoundMixer"; true; rescue LoadError; false end) and -#FObject.subclass("SoundMixer",1,1) { -class GFSoundMixer < FObject; install "SoundMixer",1,1 - # BUG? i may have the channels (left,right) backwards - def initialize(filename) - super - @file = File.open filename.to_s, 0 - @file.extend Linux::SoundMixer - $sm = self - end - @@vars = Linux::SoundMixer.instance_methods.grep(/=/) - @@vars_h = {} - @@vars.each {|attr| - attr.chop! - eval %{ def _0_#{attr}(x) @file.#{attr} = x[0]*256+x[1] end } - @@vars_h[attr]=true - } - def _0_get(sel=nil) - if sel then - sels=sel.to_s - sel=sels.intern - raise if not @@vars_h.include? sel.to_s - begin - x = @file.send sel - send_out 0, sel, "(".intern, (x>>8)&255, x&255, ")".intern - rescue - send_out 0, sel, "(".intern, -1, -1, ")".intern - end - else - @@vars.each {|var| _0_get var } - end - end -end#} - -# experimental -FObject.subclass("rubyarray",2,1) { - def initialize() @a=[]; @i=0; end - def _0_float i; @i=i; send_out 0, *@a[@i]; end - def _1_list(*l) @a[@i]=l; end - def _0_save(filename,format=nil) - f=File.open(filename.to_s,"w") - if format then - @a.each {|x| f.puts(format.to_s%x) } - else - @a.each {|x| f.puts(x.join(",")) } - end - f.close - end - def _0_load(filename) - f=File.open(filename.to_s,"r") - @a.clear - f.each {|x| @a.push x.split(",").map {|y| Float(y) rescue y.intern }} - f.close - end -} - -FObject.subclass("regsub",3,1) { - def initialize(from,to) _1_symbol(from); _2_symbol(to) end - def _0_symbol(s) send_out 0, :symbol, s.to_s.gsub(@from, @to).intern end - def _1_symbol(from) @from = Regexp.new(from.to_s.gsub(/`/,"\\")) end - def _2_symbol(to) @to = to.to_s.gsub(/`/,"\\") end - doc:_0_symbol,"a string to transform" - doc:_1_symbol,"a regexp pattern to be found inside of the string" - doc:_2_symbol,"a replacement for the found pattern" - doc_out:_0_symbol,"the transformed string" -} - -FObject.subclass("memstat",1,1) { - def _0_bang - f = File.open("/proc/#{$$}/stat") - send_out 0, Float(f.gets.split(" ")[22]) / 1024.0 - f.close - end - doc:_0_bang,"lookup process stats for the currently running pd+ruby "+ - "and figure out how much RAM it uses." - doc_out:_0_float,"virtual size of RAM in kilobytes (includes swapped out and shared memory)" -} - -FObject.subclass("sendgui",1,0) { - def _0_list(*x) - GridFlow.gui x.join(" ").gsub(/`/,";")+"\n" - end - install "sys_vgui", 1, 0 - doc:_0_list,"a Tcl/Tk command to send to the pd client." -} - -end # module GridFlow - -begin - require "gridflow/rblti" - GridFlow.post "Ruby-LTI support loaded." -rescue Exception => e - #GridFlow.post "%s", e.inspect - #GridFlow.post "(rblti not found)" -end diff --git a/externals/gridflow/base/flow_objects_for_image.c b/externals/gridflow/base/flow_objects_for_image.c deleted file mode 100644 index f6d6398d..00000000 --- a/externals/gridflow/base/flow_objects_for_image.c +++ /dev/null @@ -1,619 +0,0 @@ -/* - $Id: flow_objects_for_image.c,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. -*/ - -#include <math.h> -#include "grid.h.fcs" - -static void expect_picture (P<Dim> d) { - if (d->n!=3) RAISE("(height,width,chans) dimensions please");} -static void expect_rgb_picture (P<Dim> d) { - expect_picture(d); - if (d->get(2)!=3) RAISE("(red,green,blue) channels please");} -static void expect_rgba_picture (P<Dim> d) { - expect_picture(d); - if (d->get(2)!=4) RAISE("(red,green,blue,alpha) channels please");} -static void expect_max_one_dim (P<Dim> d) { - if (d->n>1) { RAISE("expecting Dim[] or Dim[n], got %s",d->to_s()); }} - -//**************************************************************** -//{ Dim[A,B,*Cs]<T>,Dim[D,E]<T> -> Dim[A,B,*Cs]<T> } - -static void expect_convolution_matrix (P<Dim> d) { - if (d->n != 2) RAISE("only exactly two dimensions allowed for now (got %d)", - d->n); -} - -// entry in a compiled convolution kernel -struct PlanEntry { int y,x; bool neutral; }; - -\class GridConvolve < GridObject -struct GridConvolve : GridObject { - \attr Numop *op_para; - \attr Numop *op_fold; - \attr PtrGrid seed; - \attr PtrGrid b; - PtrGrid a; - int plann; - PlanEntry *plan; //Pt? - int margx,margy; // margins - GridConvolve () : plan(0) { b.constrain(expect_convolution_matrix); plan=0; } - \decl void initialize (Grid *r=0); - \decl void _0_op (Numop *op); - \decl void _0_fold (Numop *op); - \decl void _0_seed (Grid *seed); - \grin 0 - \grin 1 - template <class T> void copy_row (Pt<T> buf, int sx, int y, int x); - template <class T> void make_plan (T bogus); - ~GridConvolve () {if (plan) delete[] plan;} -}; - -template <class T> void GridConvolve::copy_row (Pt<T> buf, int sx, int y, int x) { - int day = a->dim->get(0), dax = a->dim->get(1), dac = a->dim->prod(2); - y=mod(y,day); x=mod(x,dax); - Pt<T> ap = (Pt<T>)*a + y*dax*dac; - while (sx) { - int sx1 = min(sx,dax-x); - COPY(buf,ap+x*dac,sx1*dac); - x=0; - buf += sx1*dac; - sx -= sx1; - } -} - -static Numop *OP(Ruby x) {return FIX2PTR(Numop,rb_hash_aref(op_dict,x));} - -template <class T> void GridConvolve::make_plan (T bogus) { - P<Dim> da = a->dim, db = b->dim; - int dby = db->get(0); - int dbx = db->get(1); - if (plan) delete[] plan; - plan = new PlanEntry[dbx*dby]; - int i=0; - for (int y=0; y<dby; y++) { - for (int x=0; x<dbx; x++) { - T rh = ((Pt<T>)*b)[y*dbx+x]; - bool neutral = op_para->on(rh)->is_neutral(rh,at_right); - bool absorbent = op_para->on(rh)->is_absorbent(rh,at_right); - STACK_ARRAY(T,foo,1); - if (absorbent) { - foo[0] = 0; - op_para->map(1,foo,rh); - absorbent = op_fold->on(rh)->is_neutral(foo[0],at_right); - } - if (absorbent) continue; - plan[i].y = y; - plan[i].x = x; - plan[i].neutral = neutral; - i++; - } - } - plann = i; -} - -GRID_INLET(GridConvolve,0) { - SAME_TYPE(in,b); - SAME_TYPE(in,seed); - P<Dim> da = in->dim, db = b->dim; - if (!db) RAISE("right inlet has no grid"); - if (!seed) RAISE("seed missing"); - if (db->n != 2) RAISE("right grid must have two dimensions"); - if (da->n < 2) RAISE("left grid has less than two dimensions"); - if (seed->dim->n != 0) RAISE("seed must be scalar"); - if (da->get(0) < db->get(0)) RAISE("grid too small (y): %d < %d", da->get(0), db->get(0)); - if (da->get(1) < db->get(1)) RAISE("grid too small (x): %d < %d", da->get(1), db->get(1)); - margy = (db->get(0)-1)/2; - margx = (db->get(1)-1)/2; - a=new Grid(in->dim,in->nt); - out=new GridOutlet(this,0,da,in->nt); -} GRID_FLOW { - COPY((Pt<T>)*a+in->dex, data, n); -} GRID_FINISH { - Numop *op_put = OP(SYM(put)); - make_plan((T)0); - int dbx = b->dim->get(1); - int day = a->dim->get(0); - int n = a->dim->prod(1); - int sx = a->dim->get(1)+dbx-1; - int n2 = sx*a->dim->prod(2); - STACK_ARRAY(T,buf,n); - STACK_ARRAY(T,buf2,n2); - T orh=0; - for (int iy=0; iy<day; iy++) { - op_put->map(n,buf,*(T *)*seed); - for (int i=0; i<plann; i++) { - int jy = plan[i].y; - int jx = plan[i].x; - T rh = ((Pt<T>)*b)[jy*dbx+jx]; - if (i==0 || plan[i].y!=plan[i-1].y || orh!=rh) { - copy_row(buf2,sx,iy+jy-margy,-margx); - if (!plan[i].neutral) op_para->map(n2,buf2,rh); - } - op_fold->zip(n,buf,buf2+jx*a->dim->prod(2)); - orh=rh; - } - out->send(n,buf); - } - a=0; -} GRID_END - -GRID_INPUT(GridConvolve,1,b) {} GRID_END - -\def void _0_op (Numop *op ) { this->op_para=op; } -\def void _0_fold (Numop *op ) { this->op_fold=op; } -\def void _0_seed (Grid *seed) { this->seed=seed; } - -\def void initialize (Grid *r) { - rb_call_super(argc,argv); - this->op_para = op_mul; - this->op_fold = op_add; - this->seed = new Grid(new Dim(),int32_e,true); - this->b= r ? r : new Grid(new Dim(1,1),int32_e,true); -} - -\classinfo { IEVAL(rself,"install '#convolve',2,1"); } -\end class GridConvolve - -/* ---------------------------------------------------------------- */ -/* "#scale_by" does quick scaling of pictures by integer factors */ -/*{ Dim[A,B,3]<T> -> Dim[C,D,3]<T> }*/ -\class GridScaleBy < GridObject -struct GridScaleBy : GridObject { - \attr PtrGrid scale; // integer scale factor - int scaley; - int scalex; - \decl void initialize (Grid *factor=0); - \grin 0 - \grin 1 - void prepare_scale_factor () { - scaley = ((Pt<int32>)*scale)[0]; - scalex = ((Pt<int32>)*scale)[scale->dim->prod()==1 ? 0 : 1]; - if (scaley<1) scaley=2; - if (scalex<1) scalex=2; - } -}; - -GRID_INLET(GridScaleBy,0) { - P<Dim> a = in->dim; - expect_picture(a); - out=new GridOutlet(this,0,new Dim(a->get(0)*scaley,a->get(1)*scalex,a->get(2)),in->nt); - in->set_factor(a->get(1)*a->get(2)); -} GRID_FLOW { - int rowsize = in->dim->prod(1); - STACK_ARRAY(T,buf,rowsize*scalex); - int chans = in->dim->get(2); - #define Z(z) buf[p+z]=data[i+z] - for (; n>0; data+=rowsize, n-=rowsize) { - int p=0; - #define LOOP(z) \ - for (int i=0; i<rowsize; i+=z) \ - for (int k=0; k<scalex; k++, p+=z) - switch (chans) { - case 3: LOOP(3) {Z(0);Z(1);Z(2);} break; - case 4: LOOP(4) {Z(0);Z(1);Z(2);Z(3);} break; - default: LOOP(chans) {for (int c=0; c<chans; c++) Z(c);} - } - #undef LOOP - for (int j=0; j<scaley; j++) out->send(rowsize*scalex,buf); - } - #undef Z -} GRID_END - -static void expect_scale_factor (P<Dim> dim) { - if (dim->prod()!=1 && dim->prod()!=2) - RAISE("expecting only one or two numbers"); -} - -GRID_INPUT(GridScaleBy,1,scale) { prepare_scale_factor(); } GRID_END - -\def void initialize (Grid *factor) { - scale.constrain(expect_scale_factor); - rb_call_super(argc,argv); - scale=new Grid(INT2NUM(2)); - if (factor) scale=factor; - prepare_scale_factor(); -} - -\classinfo { IEVAL(rself,"install '#scale_by',2,1"); } -\end class GridScaleBy - -// ---------------------------------------------------------------- -//{ Dim[A,B,3]<T> -> Dim[C,D,3]<T> } -\class GridDownscaleBy < GridObject -struct GridDownscaleBy : GridObject { - \attr PtrGrid scale; - \attr bool smoothly; - int scaley; - int scalex; - PtrGrid temp; - \decl void initialize (Grid *factor=0, Symbol option=Qnil); - \grin 0 - \grin 1 - void prepare_scale_factor () { - scaley = ((Pt<int32>)*scale)[0]; - scalex = ((Pt<int32>)*scale)[scale->dim->prod()==1 ? 0 : 1]; - if (scaley<1) scaley=2; - if (scalex<1) scalex=2; - } -}; - -GRID_INLET(GridDownscaleBy,0) { - - P<Dim> a = in->dim; - if (a->n!=3) RAISE("(height,width,chans) please"); - out=new GridOutlet(this,0,new Dim(a->get(0)/scaley,a->get(1)/scalex,a->get(2)),in->nt); - in->set_factor(a->get(1)*a->get(2)); - // i don't remember why two rows instead of just one. - temp=new Grid(new Dim(2,in->dim->get(1)/scalex,in->dim->get(2)),in->nt); -} GRID_FLOW { - int rowsize = in->dim->prod(1); - int rowsize2 = temp->dim->prod(1); - Pt<T> buf = (Pt<T>)*temp; //!@#$ maybe should be something else than T ? - int xinc = in->dim->get(2)*scalex; - int y = in->dex / rowsize; - int chans=in->dim->get(2); - #define Z(z) buf[p+z]+=data[i+z] - if (smoothly) { - while (n>0) { - if (y%scaley==0) CLEAR(buf,rowsize2); - #define LOOP(z) \ - for (int i=0,p=0; p<rowsize2; p+=z) \ - for (int j=0; j<scalex; j++,i+=z) - switch (chans) { - case 1: LOOP(1) {Z(0);} break; - case 2: LOOP(2) {Z(0);Z(1);} break; - case 3: LOOP(3) {Z(0);Z(1);Z(2);} break; - case 4: LOOP(4) {Z(0);Z(1);Z(2);Z(3);} break; - default:LOOP(chans) {for (int k=0; k<chans; k++) Z(k);} break; - } - #undef LOOP - y++; - if (y%scaley==0 && out->dim) { - op_div->map(rowsize2,buf,(T)(scalex*scaley)); - out->send(rowsize2,buf); - CLEAR(buf,rowsize2); - } - data+=rowsize; - n-=rowsize; - } - #undef Z - } else { - #define Z(z) buf[p+z]=data[i+z] - for (; n>0 && out->dim; data+=rowsize, n-=rowsize,y++) { - if (y%scaley!=0) continue; - #define LOOP(z) for (int i=0,p=0; p<rowsize2; i+=xinc, p+=z) - switch(in->dim->get(2)) { - case 1: LOOP(1) {Z(0);} break; - case 2: LOOP(2) {Z(0);Z(1);} break; - case 3: LOOP(3) {Z(0);Z(1);Z(2);} break; - case 4: LOOP(4) {Z(0);Z(1);Z(2);Z(3);} break; - default:LOOP(chans) {for (int k=0; k<chans; k++) Z(k);}break; - } - #undef LOOP - out->send(rowsize2,buf); - } - } - #undef Z -} GRID_END - -GRID_INPUT(GridDownscaleBy,1,scale) { prepare_scale_factor(); } GRID_END - -\def void initialize (Grid *factor, Symbol option) { - scale.constrain(expect_scale_factor); - rb_call_super(argc,argv); - scale=new Grid(INT2NUM(2)); - if (factor) scale=factor; - prepare_scale_factor(); - smoothly = option==SYM(smoothly); -} - -\classinfo { IEVAL(rself,"install '#downscale_by',2,1"); } -\end class GridDownscaleBy - -//**************************************************************** -\class GridLayer < GridObject -struct GridLayer : GridObject { - PtrGrid r; - GridLayer() { r.constrain(expect_rgb_picture); } - \grin 0 int - \grin 1 int -}; - -GRID_INLET(GridLayer,0) { - NOTEMPTY(r); - SAME_TYPE(in,r); - P<Dim> a = in->dim; - expect_rgba_picture(a); - if (a->get(1)!=r->dim->get(1)) RAISE("same width please"); - if (a->get(0)!=r->dim->get(0)) RAISE("same height please"); - in->set_factor(a->prod(2)); - out=new GridOutlet(this,0,r->dim); -} GRID_FLOW { - Pt<T> rr = ((Pt<T>)*r) + in->dex*3/4; - STACK_ARRAY(T,foo,n*3/4); -#define COMPUTE_ALPHA(c,a) \ - foo[j+c] = (data[i+c]*data[i+a] + rr[j+c]*(256-data[i+a])) >> 8 - for (int i=0,j=0; i<n; i+=4,j+=3) { - COMPUTE_ALPHA(0,3); - COMPUTE_ALPHA(1,3); - COMPUTE_ALPHA(2,3); - } -#undef COMPUTE_ALPHA - out->send(n*3/4,foo); -} GRID_END - -GRID_INPUT(GridLayer,1,r) {} GRID_END - -\classinfo { IEVAL(rself,"install '#layer',2,1"); } -\end class GridLayer - -// **************************************************************** -// pad1,pad2 only are there for 32-byte alignment -struct Line { int32 y1,x1,y2,x2,x,m,pad1,pad2; }; - -static void expect_polygon (P<Dim> d) { - if (d->n!=2 || d->get(1)!=2) RAISE("expecting Dim[n,2] polygon"); -} - -\class DrawPolygon < GridObject -struct DrawPolygon : GridObject { - \attr Numop *op; - \attr PtrGrid color; - \attr PtrGrid polygon; - PtrGrid color2; - PtrGrid lines; - int lines_start; - int lines_stop; - DrawPolygon() { - color.constrain(expect_max_one_dim); - polygon.constrain(expect_polygon); - } - \decl void initialize (Numop *op, Grid *color=0, Grid *polygon=0); - \grin 0 - \grin 1 - \grin 2 int32 - void init_lines(); - -}; - -void DrawPolygon::init_lines () { - int nl = polygon->dim->get(0); - lines=new Grid(new Dim(nl,8), int32_e); - Pt<Line> ld = Pt<Line>((Line *)(int32 *)*lines,nl); - Pt<int32> pd = *polygon; - for (int i=0,j=0; i<nl; i++) { - ld[i].y1 = pd[j+0]; - ld[i].x1 = pd[j+1]; - j=(j+2)%(2*nl); - ld[i].y2 = pd[j+0]; - ld[i].x2 = pd[j+1]; - if (ld[i].y1>ld[i].y2) memswap(Pt<int32>(ld+i)+0,Pt<int32>(ld+i)+2,2); - } -} - -static int order_by_starting_scanline (const void *a, const void *b) { - return ((Line *)a)->y1 - ((Line *)b)->y1; -} - -static int order_by_column (const void *a, const void *b) { - return ((Line *)a)->x - ((Line *)b)->x; -} - -GRID_INLET(DrawPolygon,0) { - NOTEMPTY(color); - NOTEMPTY(polygon); - NOTEMPTY(lines); - SAME_TYPE(in,color); - if (in->dim->n!=3) RAISE("expecting 3 dimensions"); - if (in->dim->get(2)!=color->dim->get(0)) - RAISE("image does not have same number of channels as stored color"); - out=new GridOutlet(this,0,in->dim,in->nt); - lines_start = lines_stop = 0; - in->set_factor(in->dim->get(1)*in->dim->get(2)); - int nl = polygon->dim->get(0); - qsort((int32 *)*lines,nl,sizeof(Line),order_by_starting_scanline); - int cn = color->dim->prod(); - color2=new Grid(new Dim(cn*16), color->nt); - for (int i=0; i<16; i++) COPY((Pt<T>)*color2+cn*i,(Pt<T>)*color,cn); -} GRID_FLOW { - int nl = polygon->dim->get(0); - Pt<Line> ld = Pt<Line>((Line *)(int32 *)*lines,nl); - int f = in->factor(); - int y = in->dex/f; - int cn = color->dim->prod(); - Pt<T> cd = (Pt<T>)*color2; - - while (n) { - while (lines_stop != nl && ld[lines_stop].y1<=y) lines_stop++; - for (int i=lines_start; i<lines_stop; i++) { - if (ld[i].y2<=y) { - memswap(ld+i,ld+lines_start,1); - lines_start++; - } - } - if (lines_start == lines_stop) { - out->send(f,data); - } else { - int32 xl = in->dim->get(1); - Pt<T> data2 = ARRAY_NEW(T,f); - COPY(data2,data,f); - for (int i=lines_start; i<lines_stop; i++) { - Line &l = ld[i]; - l.x = l.x1 + (y-l.y1)*(l.x2-l.x1+1)/(l.y2-l.y1+1); - } - qsort(ld+lines_start,lines_stop-lines_start, - sizeof(Line),order_by_column); - for (int i=lines_start; i<lines_stop-1; i+=2) { - int xs = max(ld[i].x,(int32)0), xe = min(ld[i+1].x,xl); - if (xs>=xe) continue; /* !@#$ WHAT? */ - while (xe-xs>=16) { op->zip(16*cn,data2+cn*xs,cd); xs+=16; } - op->zip((xe-xs)*cn,data2+cn*xs,cd); - } - out->give(f,data2); - } - n-=f; - data+=f; - y++; - } -} GRID_END - - -GRID_INPUT(DrawPolygon,1,color) {} GRID_END -GRID_INPUT(DrawPolygon,2,polygon) {init_lines();} GRID_END - -\def void initialize (Numop *op, Grid *color, Grid *polygon) { - rb_call_super(argc,argv); - this->op = op; - if (color) this->color=color; - if (polygon) { this->polygon=polygon; init_lines(); } -} - -\classinfo { IEVAL(rself,"install '#draw_polygon',3,1"); } -\end class DrawPolygon - -//**************************************************************** -static void expect_position(P<Dim> d) { - if (d->n!=1) RAISE("position should have 1 dimension, not %d", d->n); - if (d->v[0]!=2) RAISE("position dim 0 should have 2 elements, not %d", d->v[0]); -} - -\class DrawImage < GridObject -struct DrawImage : GridObject { - \attr Numop *op; - \attr PtrGrid image; - \attr PtrGrid position; - \attr bool alpha; - \attr bool tile; - - DrawImage() : alpha(false), tile(false) { - position.constrain(expect_position); - image.constrain(expect_picture); - } - - \decl void initialize (Numop *op, Grid *image=0, Grid *position=0); - \decl void _0_alpha (bool v=true); - \decl void _0_tile (bool v=true); - \grin 0 - \grin 1 - \grin 2 int32 - // draw row # ry of right image in row buffer buf, starting at xs - // overflow on both sides has to be handled automatically by this method - template <class T> void draw_segment(Pt<T> obuf, Pt<T> ibuf, int ry, int x0); -}; - -#define COMPUTE_ALPHA(c,a) obuf[j+(c)] = ibuf[j+(c)] + (rbuf[a])*(obuf[j+(c)]-ibuf[j+(c)])/256; -#define COMPUTE_ALPHA4(b) \ - COMPUTE_ALPHA(b+0,b+3); \ - COMPUTE_ALPHA(b+1,b+3); \ - COMPUTE_ALPHA(b+2,b+3); \ - obuf[b+3] = rbuf[b+3] + (255-rbuf[b+3])*(ibuf[j+b+3])/256; - -template <class T> void DrawImage::draw_segment(Pt<T> obuf, Pt<T> ibuf, int ry, int x0) { - if (ry<0 || ry>=image->dim->get(0)) return; // outside of image - int sx = in[0]->dim->get(1), rsx = image->dim->get(1); - int sc = in[0]->dim->get(2), rsc = image->dim->get(2); - Pt<T> rbuf = (Pt<T>)*image + ry*rsx*rsc; - if (x0>sx || x0<=-rsx) return; // outside of buffer - int n=rsx; - if (x0+n>sx) n=sx-x0; - if (x0<0) { rbuf-=rsc*x0; n+=x0; x0=0; } - if (alpha && rsc==4 && sc==3) { // RGB by RGBA //!@#$ optimise - int j=sc*x0; - for (; n; n--, rbuf+=4, j+=3) { - op->zip(sc,obuf+j,rbuf); COMPUTE_ALPHA(0,3); COMPUTE_ALPHA(1,3); COMPUTE_ALPHA(2,3); - } - } else if (alpha && rsc==4 && sc==4) { // RGBA by RGBA - op->zip(n*rsc,obuf+x0*rsc,rbuf); - int j=sc*x0; - for (; n>=4; n-=4, rbuf+=16, j+=16) { - COMPUTE_ALPHA4(0);COMPUTE_ALPHA4(4); - COMPUTE_ALPHA4(8);COMPUTE_ALPHA4(12); - } - for (; n; n--, rbuf+=4, j+=4) { - COMPUTE_ALPHA4(0); - } - } else { // RGB by RGB, etc - op->zip(n*rsc,obuf+sc*x0,rbuf); - } -} - -GRID_INLET(DrawImage,0) { - NOTEMPTY(image); - NOTEMPTY(position); - SAME_TYPE(in,image); - if (in->dim->n!=3) RAISE("expecting 3 dimensions"); - int lchan = in->dim->get(2); - int rchan = image->dim->get(2); - if (alpha && rchan!=4) { - RAISE("alpha mode works only with 4 channels in right_hand"); - } - if (lchan != rchan-(alpha?1:0) && lchan != rchan) { - RAISE("right_hand has %d channels, alpha=%d, left_hand has %d, expecting %d or %d", - rchan, alpha?1:0, lchan, rchan-(alpha?1:0), rchan); - } - out=new GridOutlet(this,0,in->dim,in->nt); - in->set_factor(in->dim->get(1)*in->dim->get(2)); -} GRID_FLOW { - int f = in->factor(); - int y = in->dex/f; - if (position->nt != int32_e) RAISE("position has to be int32"); - int py = ((int32*)*position)[0], rsy = image->dim->v[0], sy=in->dim->get(0); - int px = ((int32*)*position)[1], rsx = image->dim->v[1], sx=in->dim->get(1); - for (; n; y++, n-=f, data+=f) { - int ty = div2(y-py,rsy); - if (tile || ty==0) { - Pt<T> data2 = ARRAY_NEW(T,f); - COPY(data2,data,f); - if (tile) { - for (int x=px-div2(px+rsx-1,rsx)*rsx; x<sx; x+=rsx) { - draw_segment(data2,data,mod(y-py,rsy),x); - } - } else { - draw_segment(data2,data,y-py,px); - } - out->give(f,data2); - } else { - out->send(f,data); - } - } -} GRID_END - -GRID_INPUT(DrawImage,1,image) {} GRID_END -GRID_INPUT(DrawImage,2,position) {} GRID_END -\def void _0_alpha (bool v=true) { alpha = v; gfpost("ALPHA=%d",v); } -\def void _0_tile (bool v=true) { tile = v; } - -\def void initialize (Numop *op, Grid *image, Grid *position) { - rb_call_super(argc,argv); - this->op = op; - if (image) this->image=image; - if (position) this->position=position; - else this->position=new Grid(new Dim(2),int32_e,true); -} - -\classinfo { IEVAL(rself,"install '#draw_image',3,1"); } -\end class DrawImage - -void startup_flow_objects_for_image () { - \startall -} diff --git a/externals/gridflow/base/flow_objects_for_matrix.c b/externals/gridflow/base/flow_objects_for_matrix.c deleted file mode 100644 index b88accba..00000000 --- a/externals/gridflow/base/flow_objects_for_matrix.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - $Id: flow_objects_for_matrix.c,v 1.2 2006-03-15 04:37:08 matju Exp $ - - GridFlow - Copyright (c) 2001,2002,2003 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. -*/ - -#include <math.h> -#include "grid.h.fcs" - -// produce an upper triangular matrix with ones on the diagonal -// will also affect any additional columns using the same row-operations - -void expect_complete_matrix (P<Dim> d) { - if (d->n!=2) RAISE("bletch"); - if (d->get(0)>d->get(1)) RAISE("argh"); -} - -\class GridMatrixSolve < GridObject -struct GridMatrixSolve : GridObject { - Numop *op_sub; - Numop *op_mul; - Numop *op_div; - PtrGrid matrix; - GridMatrixSolve() { - matrix.constrain(expect_complete_matrix); - } - \decl void initialize (); - \grin 0 float -}; - -GRID_INPUT(GridMatrixSolve,0,matrix) { - int n = matrix->dim->get(0); // # rows - int m = matrix->dim->get(1); // # columns - Pt<T> mat = (Pt<T>)*matrix; - for (int j=0; j<n; j++) { - op_div->map(m,mat+j*m,mat[j*m+j]); - for (int i=j+1; i<n; i++) { - STACK_ARRAY(T,row,m); - COPY(row,mat+j,m); - op_mul->map(m,row,mat[i*m+j]); - op_sub->zip(m,mat+i*m,row); - } - } - GridOutlet out(this,0,matrix->dim); - out.send(n*m,mat); -} GRID_END - -\def void initialize () { - rb_call_super(argc,argv); - this->op_sub = op_sub; - this->op_mul = op_mul; - this->op_div = op_div; -} - -\classinfo { IEVAL(rself,"install '#matrix_solve',1,1"); } -\end class - -void startup_flow_objects_for_matrix () { - \startall -} diff --git a/externals/gridflow/base/grid.c b/externals/gridflow/base/grid.c deleted file mode 100644 index c3ec5932..00000000 --- a/externals/gridflow/base/grid.c +++ /dev/null @@ -1,616 +0,0 @@ -/* - $Id: grid.c,v 1.2 2006-03-15 04:37:08 matju Exp $ - - GridFlow - Copyright (c) 2001,2002,2003,2004 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. -*/ - -#include <stdlib.h> -#include <fcntl.h> -#include <errno.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <sys/time.h> -#include "grid.h.fcs" -#include <ctype.h> - -/* copied from bridge/puredata.c (sorry: linkage issue) */ -struct Pointer : CObject { - void *p; - Pointer(void *_p) : p(_p) {} -}; - -#define Pointer_s_new Pointer_s_new_2 -#define Pointer_get Pointer_get_2 - -static Ruby Pointer_s_new (void *ptr) { - Pointer *self = new Pointer(ptr); - Ruby rself = Data_Wrap_Struct(EVAL("GridFlow::Pointer"), 0, CObject_free, self); - self->rself = rself; - return rself; -} -static void *Pointer_get (Ruby rself) { - DGS(Pointer); - return self->p; -} - -//#define TRACE fprintf(stderr,"%s %s [%s:%d]\n",INFO(parent),__PRETTY_FUNCTION__,__FILE__,__LINE__);assert(this); -#define TRACE assert(this); - -#define CHECK_TYPE(d) \ - if (NumberTypeE_type_of(d)!=this->nt) RAISE("%s(%s): " \ - "type mismatch during transmission (got %s expecting %s)", \ - INFO(parent), __PRETTY_FUNCTION__, \ - number_type_table[NumberTypeE_type_of(d)].name, \ - number_type_table[this->nt].name); - -#define CHECK_BUSY(s) \ - if (!dim) RAISE("%s: " #s " not busy",INFO(parent)); - -#define CHECK_ALIGN(d) \ - {int bytes = number_type_table[nt].size/8; \ - int align = ((long)(void*)d)%bytes; \ - if (align) {L;gfpost("%s(%s): Alignment Warning: %p is not %d-aligned: %d", \ - INFO(parent), __PRETTY_FUNCTION__, (void*)d,bytes,align);}} - -#define CHECK_ALIGN2(d,nt) \ - {int bytes = number_type_table[nt].size/8; \ - int align = ((long)(void*)d)%bytes; \ - if (align) {L;gfpost("Alignment Warning: %p is not %d-aligned: %d", \ - (void*)d,bytes,align);}} - -// **************** Grid ****************************************** - -#define FOO(S) static inline void NUM(Ruby x, S &y) {y=convert(x,(int32*)0);} -EACH_INT_TYPE(FOO) -#undef FOO - -#define FOO(S) \ -static inline void NUM(Ruby x, S &y) { \ - if (TYPE(x)==T_FLOAT) y = RFLOAT(x)->value; \ - else if (INTEGER_P(x)) y = convert(x,(S*)0); \ - else RAISE("expected Float (or at least Integer)");} -EACH_FLOAT_TYPE(FOO) -#undef FOO - -static inline void NUM(Ruby x, ruby &y) { y.r=x; } - -void Grid::init_from_ruby_list(int n, Ruby *a, NumberTypeE nt) { - Ruby delim = SYM(#); - for (int i=0; i<n; i++) { - if (a[i] == delim) { - STACK_ARRAY(int32,v,i); - if (i!=0 && TYPE(a[i-1])==T_SYMBOL) nt=NumberTypeE_find(a[--i]); - for (int j=0; j<i; j++) v[j] = convert(a[j],(int32*)0); - init(new Dim(i,v),nt); - CHECK_ALIGN2(this->data,nt); - if (a[i] != delim) i++; - i++; a+=i; n-=i; - goto fill; - } - } - if (n!=0 && TYPE(a[0])==T_SYMBOL) { - nt = NumberTypeE_find(a[0]); - a++, n--; - } - init(new Dim(n),nt); - CHECK_ALIGN2(this->data,nt); - fill: - int nn = dim->prod(); - n = min(n,nn); -#define FOO(type) { \ - Pt<type> p = (Pt<type>)*this; \ - if (n==0) CLEAR(p,nn); \ - else { \ - for (int i=0; i<n; i++) NUM(a[i],p[i]); \ - for (int i=n; i<nn; i+=n) COPY(p+i,p,min(n,nn-i)); }} - TYPESWITCH(nt,FOO,) -#undef FOO -} - -void Grid::init_from_ruby(Ruby x) { - if (TYPE(x)==T_ARRAY) { - init_from_ruby_list(rb_ary_len(x),rb_ary_ptr(x)); - } else if (INTEGER_P(x) || FLOAT_P(x)) { - init(new Dim(),int32_e); - CHECK_ALIGN2(this->data,nt); - ((Pt<int32>)*this)[0] = INT(x); - } else { - rb_funcall( - EVAL("proc{|x| raise \"can't convert to grid: #{x.inspect}\"}"), - SI(call),1,x); - } -} - -// **************** GridInlet ************************************* - -// must be set before the end of GRID_BEGIN phase, and so cannot be changed -// afterwards. This is to allow some optimisations. Anyway there is no good reason -// why this would be changed afterwards. -void GridInlet::set_factor(int factor) { - if(!dim) RAISE("huh?"); - if(factor<=0) RAISE("%s: factor=%d should be >= 1",INFO(parent),factor); - if (dim->prod() && dim->prod() % factor) - RAISE("%s: set_factor: expecting divisor",INFO(parent)); - if (factor > 1) { - buf=new Grid(new Dim(factor), nt); - bufi=0; - } else { - buf=0; - } -} - -static Ruby GridInlet_begin_1(GridInlet *self) { -#define FOO(T) self->gh->flow(self,-1,Pt<T>()); break; - TYPESWITCH(self->nt,FOO,) -#undef FOO - return Qnil; -} - -static Ruby GridInlet_begin_2(GridInlet *self) { - self->dim = 0; // hack - return (Ruby) 0; -} - -bool GridInlet::supports_type(NumberTypeE nt) { -#define FOO(T) return !! gh->flow_##T; - TYPESWITCH(nt,FOO,return false) -#undef FOO -} - -Ruby GridInlet::begin(int argc, Ruby *argv) {TRACE; - if (!argc) return PTR2FIX(this); - GridOutlet *back_out = (GridOutlet *) Pointer_get(argv[0]); - nt = (NumberTypeE) INT(argv[1]); - argc-=2, argv+=2; - PROF(parent) { - if (dim) RAISE("%s: grid inlet conflict; aborting %s in favour of %s", - INFO(parent), INFO(sender), INFO(back_out->parent)); - sender = back_out->parent; - if ((int)nt<0 || (int)nt>=(int)number_type_table_end) - RAISE("%s: inlet: unknown number type",INFO(parent)); - if (!supports_type(nt)) - RAISE("%s: number type %s not supported here", - INFO(parent), number_type_table[nt].name); - STACK_ARRAY(int32,v,argc); - for (int i=0; i<argc; i++) v[i] = NUM2INT(argv[i]); - P<Dim> dim = this->dim = new Dim(argc,v); - dex=0; - buf=0; - int r = rb_ensure( - (RMethod)GridInlet_begin_1,(Ruby)this, - (RMethod)GridInlet_begin_2,(Ruby)this); - if (!r) {abort(); goto hell;} - this->dim = dim; - back_out->callback(this); - hell:;} // PROF - return Qnil; -} - -template <class T> void GridInlet::flow(int mode, int n, Pt<T> data) {TRACE; - CHECK_BUSY(inlet); - CHECK_TYPE(*data); - CHECK_ALIGN(data); - PROF(parent) { - if (this->mode==0) {dex += n; return;} // ignore data - if (n==0) return; // no data - switch(mode) { - case 4:{ - int d = dex + bufi; - if (d+n > dim->prod()) { - gfpost("grid input overflow: %d of %d from [%s] to [%s]", - d+n, dim->prod(), INFO(sender), 0); - n = dim->prod() - d; - if (n<=0) return; - } - int bufn = factor(); - if (buf && bufi) { - Pt<T> bufd = (Pt<T>)*buf; - int k = min(n,bufn-bufi); - COPY(bufd+bufi,data,k); - bufi+=k; data+=k; n-=k; - if (bufi==bufn) { - int newdex = dex+bufn; - if (this->mode==6) { - Pt<T> data2 = ARRAY_NEW(T,bufn); - COPY(data2,bufd,bufn); - CHECK_ALIGN(data2); - gh->flow(this,bufn,data2); - } else { - CHECK_ALIGN(bufd); - gh->flow(this,bufn,bufd); - } - dex = newdex; - bufi = 0; - } - } - int m = (n/bufn)*bufn; - if (m) { - int newdex = dex + m; - if (this->mode==6) { - Pt<T> data2 = ARRAY_NEW(T,m); - COPY(data2,data,m); - CHECK_ALIGN(data2); - gh->flow(this,m,data2); - } else { - gh->flow(this,m,data); - } - dex = newdex; - } - data += m; - n -= m; - if (buf && n>0) COPY((Pt<T>)*buf+bufi,data,n), bufi+=n; - }break; - case 6:{ - assert(!buf); - int newdex = dex + n; - gh->flow(this,n,data); - if (this->mode==4) delete[] (T *)data; - dex = newdex; - }break; - case 0: break; // ignore data - default: RAISE("%s: unknown inlet mode",INFO(parent)); - }} // PROF -} - -void GridInlet::end() {TRACE; - assert(this); - if (!dim) RAISE("%s: inlet not busy",INFO(parent)); - if (dim->prod() != dex) { - gfpost("incomplete grid: %d of %d from [%s] to [%s]", - dex, dim->prod(), INFO(sender), INFO(parent)); - } - PROF(parent) { -#define FOO(T) gh->flow(this,-2,Pt<T>()); - TYPESWITCH(nt,FOO,) -#undef FOO - } // PROF - dim=0; - buf=0; - dex=0; -} - -template <class T> void GridInlet::from_grid2(Grid *g, T foo) {TRACE; - nt = g->nt; - dim = g->dim; - int n = g->dim->prod(); - gh->flow(this,-1,Pt<T>()); - if (n>0 && this->mode!=0) { - Pt<T> data = (Pt<T>)*g; - CHECK_ALIGN(data); - int size = g->dim->prod(); - if (this->mode==6) { - Pt<T> d = data; - data = ARRAY_NEW(T,size); // problem with int64,float64 here. - COPY(data,d,size); - CHECK_ALIGN(data); - gh->flow(this,n,data); - } else { - int ntsz = number_type_table[nt].size; - int m = GridOutlet::MAX_PACKET_SIZE/*/ntsz*//factor(); - if (!m) m++; - m *= factor(); - while (n) { - if (m>n) m=n; - CHECK_ALIGN(data); - gh->flow(this,m,data); - data+=m; n-=m; dex+=m; - } - } - } - gh->flow(this,-2,Pt<T>()); - //!@#$ add error handling. - // rescue; abort(); end ??? - dim = 0; - dex = 0; -} - -void GridInlet::from_grid(Grid *g) {TRACE; - if (!supports_type(g->nt)) - RAISE("%s: number type %s not supported here", - INFO(parent), number_type_table[g->nt].name); -#define FOO(T) from_grid2(g,(T)0); - TYPESWITCH(g->nt,FOO,) -#undef FOO -} - -/* **************** GridOutlet ************************************ */ - -void GridOutlet::begin(int woutlet, P<Dim> dim, NumberTypeE nt) {TRACE; - int n = dim->count(); - this->nt = nt; - this->dim = dim; - Ruby a[n+4]; - a[0] = INT2NUM(woutlet); - a[1] = bsym._grid; - a[2] = Pointer_s_new(this); - a[3] = INT2NUM(nt); - for(int i=0; i<n; i++) a[4+i] = INT2NUM(dim->get(i)); - parent->send_out(COUNT(a),a); - frozen=true; - if (!dim->prod()) {end(); return;} - int32 lcm_factor = 1; - for (uint32 i=0; i<inlets.size(); i++) lcm_factor = lcm(lcm_factor,inlets[i]->factor()); - if (nt != buf->nt) { - // biggest packet size divisible by lcm_factor - int32 v = (MAX_PACKET_SIZE/lcm_factor)*lcm_factor; - if (v==0) v=MAX_PACKET_SIZE; // factor too big. don't have a choice. - buf=new Grid(new Dim(v),nt); - } -} - -// send modifies dex; send_direct doesn't -template <class T> -void GridOutlet::send_direct(int n, Pt<T> data) {TRACE; - assert(data); assert(frozen); - CHECK_BUSY(outlet); CHECK_TYPE(*data); CHECK_ALIGN(data); - for (; n>0; ) { - int pn = min(n,MAX_PACKET_SIZE); - for (uint32 i=0; i<inlets.size(); i++) inlets[i]->flow(4,pn,data); - data+=pn, n-=pn; - } -} - -void GridOutlet::flush() {TRACE; - if (!bufi) return; -#define FOO(T) send_direct(bufi,(Pt<T>)*buf); - TYPESWITCH(buf->nt,FOO,) -#undef FOO - bufi = 0; -} - -template <class T, class S> -static void convert_number_type(int n, Pt<T> out, Pt<S> in) { - for (int i=0; i<n; i++) out[i]=(T)in[i]; -} - -//!@#$ buffering in outlet still is 8x faster...? -//!@#$ should use BitPacking for conversion...? -// send modifies dex; send_direct doesn't -template <class T> -void GridOutlet::send(int n, Pt<T> data) {TRACE; - assert(data); assert(frozen); - if (!n) return; - CHECK_BUSY(outlet); CHECK_ALIGN(data); - if (NumberTypeE_type_of(*data)!=nt) { - int bs = MAX_PACKET_SIZE; -#define FOO(T) { \ - STACK_ARRAY(T,data2,bs); \ - for (;n>=bs;n-=bs,data+=bs) { \ - convert_number_type(bs,data2,data); send(bs,data2);} \ - convert_number_type(n,data2,data); \ - send(n,data2); } - TYPESWITCH(nt,FOO,) -#undef FOO - } else { - dex += n; - assert(dex <= dim->prod()); - if (n > MIN_PACKET_SIZE || bufi + n > MAX_PACKET_SIZE) flush(); - if (n > MIN_PACKET_SIZE) { - send_direct(n,data); - } else { - COPY((Pt<T>)*buf+bufi,data,n); - bufi += n; - } - if (dex==dim->prod()) end(); - } -} - -template <class T> -void GridOutlet::give(int n, Pt<T> data) {TRACE; - assert(data); CHECK_BUSY(outlet); assert(frozen); - assert(dex+n <= dim->prod()); CHECK_ALIGN(data); - if (NumberTypeE_type_of(*data)!=nt) { - send(n,data); - delete[] (T *)data; - return; - } - if (inlets.size()==1 && inlets[0]->mode == 6) { - // this is the copyless buffer passing - flush(); - inlets[0]->flow(6,n,data); - dex += n; - } else { - flush(); - send_direct(n,data); - dex += n; - delete[] (T *)data; - } - if (dex==dim->prod()) end(); -} - -void GridOutlet::callback(GridInlet *in) {TRACE; - CHECK_BUSY(outlet); assert(!frozen); - int mode = in->mode; - assert(mode==6 || mode==4 || mode==0); - inlets.push_back(in); -} - -\class GridObject < FObject - -//!@#$ does not handle types properly -//!@#$ most possibly a big hack -template <class T> -void GridObject_r_flow(GridInlet *in, int n, Pt<T> data) { - GridObject *self = in->parent; - uint32 i; - for (i=0; i<self->in.size(); i++) if (in==self->in[i].p) break; - if (i==self->in.size()) RAISE("inlet not found?"); - if (n==-1) { - rb_funcall(self->rself,SI(send_in),2,INT2NUM(i),SYM(rgrid_begin)); - } else if (n>=0) { - Ruby buf = rb_str_new((char *)((uint8 *)data),n*sizeof(T)); - rb_funcall(self->rself,SI(send_in),3,INT2NUM(i),SYM(rgrid_flow),buf); - } else { - rb_funcall(self->rself,SI(send_in),2,INT2NUM(i),SYM(rgrid_end)); - } -} - -\def Symbol inlet_nt (int inln) { - if (inln<0 || inln>=(int)in.size()) RAISE("bad inlet number"); - P<GridInlet> inl = in[inln]; - if (!inl) RAISE("no such inlet #%d",inln); - if (!inl->dim) return Qnil; - return number_type_table[inl->nt].sym; -} - -\def Array inlet_dim (int inln) { - if (inln<0 || inln>=(int)in.size()) RAISE("bad inlet number"); - P<GridInlet> inl = in[inln]; - if (!inl) RAISE("no such inlet #%d",inln); - if (!inl->dim) return Qnil; - int n=inl->dim->count(); - Ruby a = rb_ary_new2(n); - for(int i=0; i<n; i++) rb_ary_push(a,INT2NUM(inl->dim->v[i])); - return a; -} - -\def void inlet_set_factor (int inln, int factor) { - if (inln<0 || inln>=(int)in.size()) RAISE("bad inlet number"); - P<GridInlet> inl = in[inln]; - if (!inl) RAISE("no such inlet #%d",inln); - if (!inl->dim) RAISE("inlet #%d not active",inln); - inl->set_factor(factor); -} - -\def void send_out_grid_begin (int outlet, Array buf, NumberTypeE nt=int32_e) { - if (outlet<0) RAISE("bad outlet number"); - int n = rb_ary_len(buf); - Ruby *p = rb_ary_ptr(buf); - STACK_ARRAY(int32,v,n); - for (int i=0; i<n; i++) v[i] = convert(p[i],(int32*)0); - out = new GridOutlet(this,outlet,new Dim(n,v),nt); // valgrind says leak? -} - -template <class T> -void send_out_grid_flow_2(P<GridOutlet> go, Ruby s, T bogus) { - int n = rb_str_len(s) / sizeof(T); - Pt<T> p = rb_str_pt(s,T); - go->send(n,p); -} - -\def void send_out_grid_flow (int outlet, String buf, NumberTypeE nt=int32_e) { - if (outlet<0) RAISE("bad outlet number"); -#define FOO(T) send_out_grid_flow_2(out,argv[1],(T)0); - TYPESWITCH(nt,FOO,) -#undef FOO -} - -// install_rgrid(Integer inlet, Boolean multi_type? = true) -static Ruby GridObject_s_install_rgrid(int argc, Ruby *argv, Ruby rself) { - if (argc<1 || argc>2) RAISE("er..."); - IEVAL(rself,"@handlers||=[]"); - Ruby handlers = rb_ivar_get(rself,SI(@handlers)); - GridHandler *gh = new GridHandler; - bool mt = argc>1 ? argv[1]==Qtrue : 0; /* multi_type? */ - if (mt) { -#define FOO(S) gh->flow_##S = GridObject_r_flow; -EACH_NUMBER_TYPE(FOO) -#undef FOO - } else { -#define FOO(S) gh->flow_##S = 0; -EACH_NUMBER_TYPE(FOO) -#undef FOO - } - gh->flow_int32 = GridObject_r_flow; - //IEVAL(rself,"self.class_eval { def _0_grid(*a) ___grid(0,*a) end }"); - rb_funcall(handlers,SI([]=),2,INT2NUM(INT(argv[0])),PTR2FIX(gh)); - return Qnil; -} - -static Ruby GridObject_s_instance_methods(int argc, Ruby *argv, Ruby rself) { - static const char *names[] = {"grid","list","float"}; - Ruby list = rb_class_instance_methods(argc,argv,rself); - Ruby handlers = rb_ivar_get(rself,SI(@handlers)); - if (handlers==Qnil) return list; - for (int i=0; i<rb_ary_len(handlers); i++) { - Ruby ghp = rb_ary_ptr(handlers)[i]; - if (ghp==Qnil) continue; - GridHandler *gh = FIX2PTR(GridHandler,ghp); - char buf[256]; - for (int j=0; j<COUNT(names); j++) { - sprintf(buf,"_%d_%s",i,names[j]); - rb_ary_push(list,rb_str_new2(buf)); - } - } - return list; -} - -// this does auto-conversion of list/float to grid -// this also (will) do grid inputs for ruby stuff. -\def Ruby method_missing (...) { - { - if (argc<1) RAISE("not enough arguments"); - if (!SYMBOL_P(argv[0])) RAISE("expected symbol"); - const char *name = rb_sym_name(argv[0]); - char *endp; - if (*name++!='_') goto hell; - int i = strtol(name,&endp,10); - if (name==endp) goto hell; - if (*endp++!='_') goto hell; - if (strcmp(endp,"grid")==0) { - Ruby handlers = rb_ivar_get(rb_obj_class(rself),SI(@handlers)); - if (TYPE(handlers)!=T_ARRAY) { - rb_p(handlers); - RAISE("gridhandler-list missing (maybe forgot install_rgrid ?)" - " while trying to receive on inlet %d",i); - } - if (i>=rb_ary_len(handlers)) RAISE("BORK"); - GridHandler *gh = FIX2PTR(GridHandler, rb_ary_ptr(handlers)[i]); - if (in.size()<=(uint32)i) in.resize(i+1); - if (!in[i]) in[i]=new GridInlet((GridObject *)this,gh); - return in[i]->begin(argc-1,argv+1); - } - // we call the grid method recursively to ask it its GridInlet* - // don't do this before checking the missing method is exactly that =) - char foo[42]; - sprintf(foo,"_%d_grid",i); - P<GridInlet> inl = FIX2PTR(GridInlet,rb_funcall(rself,rb_intern(foo),0)); - if (strcmp(endp,"list" )==0) return inl->from_ruby_list(argc-1,argv+1), Qnil; - if (strcmp(endp,"float")==0) return inl->from_ruby (argc-1,argv+1), Qnil; - } - hell: return rb_call_super(argc,argv); -} - -\classinfo { - IEVAL(rself,"install 'GridObject',0,0"); - // define in Ruby-metaclass - rb_define_singleton_method(rself,"instance_methods",(RMethod)GridObject_s_instance_methods,-1); - rb_define_singleton_method(rself,"install_rgrid",(RMethod)GridObject_s_install_rgrid,-1); - rb_enable_super(rb_singleton_class(rself),"instance_methods"); -} -\end class GridObject - -Ruby cGridObject; - -void startup_grid () { - \startall - cGridObject = rb_const_get(mGridFlow,SI(GridObject)); -} - -// never call this. this is a hack to make some things work. -// i'm trying to circumvent either a bug in the compiler or i don't have a clue. :-( -void make_gimmick () { - GridOutlet foo(0,0,0); -#define FOO(S) foo.give(0,Pt<S>()); -EACH_NUMBER_TYPE(FOO) -#undef FOO -} - 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 diff --git a/externals/gridflow/base/main.c b/externals/gridflow/base/main.c deleted file mode 100644 index d65c81d0..00000000 --- a/externals/gridflow/base/main.c +++ /dev/null @@ -1,648 +0,0 @@ -/* - $Id: main.c,v 1.2 2006-03-15 04:37:08 matju Exp $ - - GridFlow - Copyright (c) 2001,2002,2003,2004 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. -*/ - -#include <stdlib.h> -#include <sys/stat.h> -#include <sys/time.h> -#include <time.h> -#include <stdarg.h> -#include <string.h> -#include <signal.h> -#include <stdio.h> -#include <fcntl.h> -#include <unistd.h> -#include <stdarg.h> - -#include "grid.h.fcs" -#include "../config.h" -#include <assert.h> -#include <limits.h> - -BuiltinSymbols bsym; -GFStack gf_stack; -Ruby mGridFlow; -Ruby cFObject; - -extern "C"{ -void rb_raise0( -const char *file, int line, const char *func, VALUE exc, const char *fmt, ...) { - va_list args; - char buf[BUFSIZ]; - va_start(args,fmt); - vsnprintf(buf, BUFSIZ, fmt, args); - buf[BUFSIZ-1]=0; - va_end(args); - VALUE e = rb_exc_new2(exc, buf); - char buf2[BUFSIZ]; - snprintf(buf2, BUFSIZ, "%s:%d:in `%s'", file, line, func); - buf2[BUFSIZ-1]=0; - VALUE ary = rb_funcall(e,SI(caller),0); - if (gf_stack.n) { - rb_funcall(ary,SI(unshift),2,rb_str_new2(buf2), - rb_str_new2(INFO(gf_stack.s[gf_stack.n-1].o))); - } else { - rb_funcall(ary,SI(unshift),1,rb_str_new2(buf2)); - } - rb_funcall(e,SI(set_backtrace),1,ary); - rb_exc_raise(e); -}}; - -Ruby rb_ary_fetch(Ruby rself, int i) { - Ruby argv[] = { INT2NUM(i) }; - return rb_ary_aref(COUNT(argv),argv,rself); -} - -//---------------------------------------------------------------- -// CObject - -static void CObject_mark (void *z) {} -void CObject_free (void *foo) { - CObject *self = (CObject *)foo; - self->check_magic(); - if (!self->rself) { - fprintf(stderr,"attempt to free object that has no rself\n"); - abort(); - } - self->rself = 0; /* paranoia */ - delete self; -} - -//---------------------------------------------------------------- -// Dim - -void Dim::check() { - if (n>MAX_DIM) RAISE("too many dimensions"); - for (int i=0; i<n; i++) if (v[i]<0) RAISE("Dim: negative dimension"); -} - -// !@#$ big leak machine? -// returns a string like "Dim[240,320,3]" -char *Dim::to_s() { - // if you blow 256 chars it's your own fault - char buf[256]; - char *s = buf; - s += sprintf(s,"Dim["); - for(int i=0; i<n; i++) s += sprintf(s,"%s%d", ","+!i, v[i]); - s += sprintf(s,"]"); - return strdup(buf); -} - -//---------------------------------------------------------------- -\class FObject < CObject - -static void FObject_prepare_message(int &argc, Ruby *&argv, Ruby &sym, FObject *foo=0) { - if (argc<1) { - sym = bsym._bang; - } else if (argc>1 && !SYMBOL_P(*argv)) { - sym = bsym._list; - } else if (INTEGER_P(*argv)||FLOAT_P(*argv)) { - sym = bsym._float; - } else if (SYMBOL_P(*argv)) { - sym = *argv; - argc--, argv++; - } else if (argc==1 && TYPE(*argv)==T_ARRAY) { - sym = bsym._list; - argc = rb_ary_len(*argv); - argv = rb_ary_ptr(*argv); - } else { - RAISE("%s received bad message: argc=%d; argv[0]=%s",foo?INFO(foo):"", argc, - argc ? rb_str_ptr(rb_inspect(argv[0])) : ""); - } -} - -struct Helper { - int argc; - Ruby *argv; - FObject *self; - Ruby rself; - int n; // stack level -}; - -static Ruby GridFlow_handle_braces(Ruby rself, Ruby argv); - -// inlet #-1 is reserved for SystemInlet messages -// inlet #-2 is for inlet #0 messages that happen at start time -static void send_in_2 (Helper *h) { PROF(h->self) { - int argc = h->argc; - Ruby *argv = h->argv; - if (h->argc<1) RAISE("not enough args"); - int inlet = INT(argv[0]); - argc--, argv++; - Ruby foo; - if (argc==1 && TYPE(argv[0])==T_STRING /* && argv[0] =~ / / */) { - foo = rb_funcall(mGridFlow,SI(parse),1,argv[0]); - argc = rb_ary_len(foo); - argv = rb_ary_ptr(foo); - } - if (argc>1) { - foo = rb_ary_new4(argc,argv); - GridFlow_handle_braces(0,foo); - argc = rb_ary_len(foo); - argv = rb_ary_ptr(foo); - } - if (inlet==-2) { - Array init_messages = rb_ivar_get(h->rself,SI(@init_messages)); - rb_ary_push(init_messages, rb_ary_new4(argc,argv)); - inlet=0; - } - if (inlet<0 || inlet>9 /*|| inlet>real_inlet_max*/) - if (inlet!=-3 && inlet!=-1) RAISE("invalid inlet number: %d", inlet); - Ruby sym; - FObject_prepare_message(argc,argv,sym,h->self); -// if (rb_const_get(mGridFlow,SI(@verbose))==Qtrue) gfpost m.inspect - char buf[256]; - if (inlet==-1) sprintf(buf,"_sys_%s",rb_sym_name(sym)); - else sprintf(buf,"_%d_%s",inlet,rb_sym_name(sym)); - rb_funcall2(h->rself,rb_intern(buf),argc,argv); -} /* PROF */ } - -static void send_in_3 (Helper *h) { - while (gf_stack.n > h->n) gf_stack.pop(); -} - -\def void send_in (...) { - Helper h = {argc,argv,this,rself,gf_stack.n}; - rb_ensure( - (RMethod)send_in_2,(Ruby)&h, - (RMethod)send_in_3,(Ruby)&h); -} - -\def void send_out (...) { - int n=0; - if (argc<1) RAISE("not enough args"); - int outlet = INT(*argv); - if (outlet<0 || outlet>9 /*|| outlet>real_outlet_max*/) - RAISE("invalid outlet number: %d",outlet); - argc--, argv++; - Ruby sym; - FObject_prepare_message(argc,argv,sym,this); - Ruby noutlets2 = rb_ivar_get(rb_obj_class(rself),SYM2ID(SYM(@noutlets))); - if (TYPE(noutlets2)!=T_FIXNUM) { - IEVAL(rself,"STDERR.puts inspect"); - RAISE("don't know how many outlets this has"); - } - int noutlets = INT(noutlets2); - //if (outlet<0 || outlet>=noutlets) RAISE("outlet %d does not exist",outlet); - // was PROF(0) a hack because of exception-handling problems? - PROF(0) { - Ruby argv2[argc+2]; - for (int i=0; i<argc; i++) argv2[2+i] = argv[i]; - argv2[0] = INT2NUM(outlet); - argv2[1] = sym; - rb_funcall2(rself,SI(send_out2), argc+2, argv2); - - Ruby ary = rb_ivar_defined(rself,SYM2ID(bsym.iv_outlets)) ? - rb_ivar_get(rself,SYM2ID(bsym.iv_outlets)) : Qnil; - if (ary==Qnil) goto end; - if (TYPE(ary)!=T_ARRAY) RAISE("send_out: expected array"); - ary = rb_ary_fetch(ary,outlet); - if (ary==Qnil) goto end; - if (TYPE(ary)!=T_ARRAY) RAISE("send_out: expected array"); - n = rb_ary_len(ary); - - for (int i=0; i<n; i++) { - Ruby conn = rb_ary_fetch(ary,i); - Ruby rec = rb_ary_fetch(conn,0); - int inl = INT(rb_ary_fetch(conn,1)); - argv2[0] = INT2NUM(inl); - rb_funcall2(rec,SI(send_in),argc+2,argv2); - } - } /* PROF */ -end:; -} - -Ruby FObject_s_new(Ruby argc, Ruby *argv, Ruby qlass) { - Ruby allocator = rb_ivar_defined(qlass,SI(@allocator)) ? - rb_ivar_get(qlass,SI(@allocator)) : Qnil; - FObject *self; - if (allocator==Qnil) { - // this is a pure-ruby FObject/GridObject - // !@#$ GridObject is in FObject constructor (ugly) - self = new GridObject; - } else { - // this is a C++ FObject/GridObject - void*(*alloc)() = (void*(*)())FIX2PTR(void,allocator); - self = (FObject *)alloc(); - } - self->check_magic(); - Ruby keep = rb_ivar_get(mGridFlow, SI(@fobjects)); - self->bself = 0; - Ruby rself = Data_Wrap_Struct(qlass, CObject_mark, CObject_free, self); - self->rself = rself; - rb_hash_aset(keep,rself,Qtrue); // prevent sweeping - rb_funcall2(rself,SI(initialize),argc,argv); - return rself; -} - -Ruby FObject_s_install(Ruby rself, Ruby name, Ruby inlets2, Ruby outlets2) { - int inlets, outlets; - Ruby name2; - if (SYMBOL_P(name)) { - name2 = rb_funcall(name,SI(to_str),0); - } else if (TYPE(name) == T_STRING) { - name2 = rb_funcall(name,SI(dup),0); - } else { - RAISE("expect symbol or string"); - } - inlets = INT(inlets2); if ( inlets<0 || inlets>9) RAISE("..."); - outlets = INT(outlets2); if (outlets<0 || outlets>9) RAISE("..."); - rb_ivar_set(rself,SI(@ninlets),INT2NUM(inlets)); - rb_ivar_set(rself,SI(@noutlets),INT2NUM(outlets)); - rb_ivar_set(rself,SI(@foreign_name),name2); - rb_hash_aset(rb_ivar_get(mGridFlow,SI(@fclasses)), name2, rself); - rb_funcall(rself, SI(install2), 1, name2); - return Qnil; -} - -\def Ruby total_time_get () {return gf_ull2num(total_time);} - -\def Ruby total_time_set (Ruby x) { - if (argc<1) RAISE("muh"); - total_time = TO(uint64,x); - return argv[0]; -} - -\def void delete_m () { - Ruby keep = rb_ivar_get(mGridFlow, SI(@fobjects)); - rb_funcall(keep,SI(delete),1,rself); -} - -\classinfo -\end class FObject - -/* ---------------------------------------------------------------- */ -/* C++<->Ruby bridge for classes/functions in base/number.c */ - -static Ruby String_swap32_f (Ruby rself) { - int n = rb_str_len(rself)/4; - swap32(n,Pt<uint32>((uint32 *)rb_str_ptr(rself),n)); - return rself; -} - -static Ruby String_swap16_f (Ruby rself) { - int n = rb_str_len(rself)/2; - swap16(n,Pt<uint16>((uint16 *)rb_str_ptr(rself),n)); - return rself; -} - -NumberTypeE NumberTypeE_find (Ruby sym) { - if (TYPE(sym)!=T_SYMBOL) RAISE("expected symbol (not %s)", - rb_str_ptr(rb_inspect(rb_obj_class(sym)))); - Ruby nt_dict = rb_ivar_get(mGridFlow,SI(@number_type_dict)); - Ruby v = rb_hash_aref(nt_dict,sym); - if (v!=Qnil) return FIX2PTR(NumberType,v)->index; - RAISE("unknown number type \"%s\"", rb_sym_name(sym)); -} - -/* **************************************************************** */ -\class BitPacking < CObject - -\def void initialize(Ruby foo1, Ruby foo2, Ruby foo3) {} - -// !@#$ doesn't support number types -\def String pack2 (String ins, String outs=Qnil) { - int n = rb_str_len(ins) / sizeof(int32) / size; - Pt<int32> in = Pt<int32>((int32 *)rb_str_ptr(ins),rb_str_len(ins)); - int bytes2 = n*bytes; - Ruby out = outs!=Qnil ? rb_str_resize(outs,bytes2) : rb_str_new("",bytes2); - rb_str_modify(out); - pack(n,Pt<int32>(in,n),Pt<uint8>((uint8 *)rb_str_ptr(out),bytes2)); - return out; -} - -// !@#$ doesn't support number types -\def String unpack2 (String ins, String outs=Qnil) { - int n = rb_str_len(argv[0]) / bytes; - Pt<uint8> in = Pt<uint8>((uint8 *)rb_str_ptr(ins),rb_str_len(ins)); - int bytes2 = n*size*sizeof(int32); - Ruby out = outs!=Qnil ? rb_str_resize(outs,bytes2) : rb_str_new("",bytes2); - rb_str_modify(out); - unpack(n,Pt<uint8>((uint8 *)in,bytes2),Pt<int32>((int32 *)rb_str_ptr(out),n)); - return out; -} - -static Ruby BitPacking_s_new(Ruby argc, Ruby *argv, Ruby qlass) { - Ruby keep = rb_ivar_get(mGridFlow, rb_intern("@fobjects")); - if (argc!=3) RAISE("bad args"); - if (TYPE(argv[2])!=T_ARRAY) RAISE("bad mask"); - int endian = INT(argv[0]); - int bytes = INT(argv[1]); - Ruby *masks = rb_ary_ptr(argv[2]); - uint32 masks2[4]; - int size = rb_ary_len(argv[2]); - if (size<1) RAISE("not enough masks"); - if (size>4) RAISE("too many masks (%d)",size); - for (int i=0; i<size; i++) masks2[i] = NUM2UINT(masks[i]); - BitPacking *self = new BitPacking(endian,bytes,size,masks2); - Ruby rself = Data_Wrap_Struct(qlass, 0, CObject_free, self); - self->rself = rself; - rb_hash_aset(keep,rself,Qtrue); // prevent sweeping (leak) (!@#$ WHAT???) - rb_funcall2(rself,SI(initialize),argc,argv); - return rself; -} - -\classinfo -\end class BitPacking - -void gfpost(const char *fmt, ...) { - va_list args; - int length; - va_start(args,fmt); - const int n=256; - char post_s[n]; - length = vsnprintf(post_s,n,fmt,args); - if (length<0 || length>=n) sprintf(post_s+n-6,"[...]"); /* safety */ - va_end(args); - rb_funcall(mGridFlow,SI(gfpost2),2,rb_str_new2(fmt),rb_str_new2(post_s)); -} - -void define_many_methods(Ruby rself, int n, MethodDecl *methods) { - for (int i=0; i<n; i++) { - MethodDecl *md = &methods[i]; - char *buf = strdup(md->selector); - if (strlen(buf)>2 && strcmp(buf+strlen(buf)-2,"_m")==0) - buf[strlen(buf)-2]=0; - rb_define_method(rself,buf,(RMethod)md->method,-1); - rb_enable_super(rself,buf); - free(buf); - } -} - -static Ruby GridFlow_fclass_install(Ruby rself_, Ruby fc_, Ruby super) { - FClass *fc = FIX2PTR(FClass,fc_); - Ruby rself = super!=Qnil ? - rb_define_class_under(mGridFlow, fc->name, super) : - rb_funcall(mGridFlow,SI(const_get),1,rb_str_new2(fc->name)); - define_many_methods(rself,fc->methodsn,fc->methods); - rb_ivar_set(rself,SI(@allocator),PTR2FIX((void*)(fc->allocator))); //#!@$?? - if (fc->startup) fc->startup(rself); - return Qnil; -} - -//---------------------------------------------------------------- -// GridFlow.class -//\class GridFlow_s < patate - -typedef void (*Callback)(void*); -static Ruby GridFlow_exec (Ruby rself, Ruby data, Ruby func) { - void *data2 = FIX2PTR(void,data); - Callback func2 = (Callback) FIX2PTR(void,func); - func2(data2); - return Qnil; -} - -static Ruby GridFlow_get_id (Ruby rself, Ruby arg) { - fprintf(stderr,"%ld\n",arg); - return INT2NUM((int)arg); -} - -Ruby GridFlow_rdtsc (Ruby rself) { return gf_ull2num(rdtsc()); } - -/* This code handles nested lists because PureData (0.38) doesn't do it */ -static Ruby GridFlow_handle_braces(Ruby rself, Ruby argv) { - int stack[16]; - int stackn=0; - Ruby *av = rb_ary_ptr(argv); - int ac = rb_ary_len(argv); - int j=0; - for (int i=0; i<ac; ) { - int close=0; - if (SYMBOL_P(av[i])) { - const char *s = rb_sym_name(av[i]); - while (*s=='(' || *s=='{') { - if (stackn==16) RAISE("too many nested lists (>16)"); - stack[stackn++]=j; - s++; - } - const char *se = s+strlen(s); - while (se>s && (se[-1]==')' || se[-1]=='}')) { se--; close++; } - if (s!=se) { - Ruby u = rb_str_new(s,se-s); - av[j++] = rb_funcall(rself,SI(FloatOrSymbol),1,u); - } - } else { - av[j++]=av[i]; - } - i++; - while (close--) { - if (!stackn) RAISE("unbalanced '}' or ')'",av[i]); - Ruby a2 = rb_ary_new(); - int j2 = stack[--stackn]; - for (int k=j2; k<j; k++) rb_ary_push(a2,av[k]); - j=j2; - av[j++] = a2; - } - } - if (stackn) RAISE("unbalanced '{' or '(' (stackn=%d)",stackn); - RARRAY(argv)->len = j; - return rself; -} - -/* ---------------------------------------------------------------- */ - -static uint32 memcpy_calls = 0; -static uint64 memcpy_bytes = 0; -static uint64 memcpy_time = 0; -static uint32 malloc_calls = 0; /* only new not delete */ -static uint64 malloc_bytes = 0; /* only new not delete */ -static uint64 malloc_time = 0; /* in cpu ticks */ - -// don't touch. -static void gfmemcopy32(int32 *as, int32 *bs, int n) { - int32 ba = bs-as; -#define FOO(I) as[I] = (as+ba)[I]; - UNROLL_8(FOO,n,as) -#undef FOO - -} - -void gfmemcopy(uint8 *out, const uint8 *in, int n) { - uint64 t = rdtsc(); - memcpy_calls++; - memcpy_bytes+=n; - for (; n>16; in+=16, out+=16, n-=16) { - ((int32*)out)[0] = ((int32*)in)[0]; - ((int32*)out)[1] = ((int32*)in)[1]; - ((int32*)out)[2] = ((int32*)in)[2]; - ((int32*)out)[3] = ((int32*)in)[3]; - } - for (; n>4; in+=4, out+=4, n-=4) { *(int32*)out = *(int32*)in; } - for (; n; in++, out++, n--) { *out = *in; } - t=rdtsc()-t; - memcpy_time+=t; -} - -extern "C" { -void *gfmalloc(size_t n) { - uint64 t = rdtsc(); -// void *p = malloc(n); - void *p = memalign(16,n); - long align = (long)p & 7; - if (align) fprintf(stderr,"malloc alignment = %ld mod 8\n",align); - t=rdtsc()-t; - malloc_time+=t; - malloc_calls++; - malloc_bytes+=n; - return p; -} -void gffree(void *p) { - uint64 t = rdtsc(); - free(p); - t=rdtsc()-t; - malloc_time+=t; -}}; - -Ruby GridFlow_memcpy_calls (Ruby rself) { return LONG2NUM(memcpy_calls); } -Ruby GridFlow_memcpy_bytes (Ruby rself) { return gf_ull2num(memcpy_bytes); } -Ruby GridFlow_memcpy_time (Ruby rself) { return gf_ull2num(memcpy_time); } -Ruby GridFlow_malloc_calls (Ruby rself) { return LONG2NUM(malloc_calls); } -Ruby GridFlow_malloc_bytes (Ruby rself) { return gf_ull2num(malloc_bytes); } -Ruby GridFlow_malloc_time (Ruby rself) { return gf_ull2num(malloc_time); } - -Ruby GridFlow_profiler_reset2 (Ruby rself) { - memcpy_calls = memcpy_bytes = memcpy_time = 0; - malloc_calls = malloc_bytes = malloc_time = 0; - return Qnil; -} - -/* ---------------------------------------------------------------- */ - -void startup_number(); -void startup_grid(); -void startup_flow_objects(); -void startup_flow_objects_for_image(); -void startup_flow_objects_for_matrix(); - -Ruby cFormat; - -#define SDEF(_class_,_name_,_argc_) \ - rb_define_singleton_method(c##_class_,#_name_,(RMethod)_class_##_s_##_name_,_argc_) -#define SDEF2(_name1_,_name2_,_argc_) \ - rb_define_singleton_method(mGridFlow,_name1_,(RMethod)_name2_,_argc_) - -STARTUP_LIST(void) - -// Ruby's entrypoint. -void Init_gridflow () { -#define FOO(_sym_,_name_) bsym._sym_ = ID2SYM(rb_intern(_name_)); -BUILTIN_SYMBOLS(FOO) -#undef FOO - signal(11,SIG_DFL); // paranoia - mGridFlow = EVAL("module GridFlow; CObject = ::Object; " - "class<<self; attr_reader :bridge_name; end; " - "def post_string(s) STDERR.puts s end; " - "self end"); - SDEF2("exec",GridFlow_exec,2); - SDEF2("get_id",GridFlow_get_id,1); - SDEF2("rdtsc",GridFlow_rdtsc,0); - SDEF2("profiler_reset2",GridFlow_profiler_reset2,0); - SDEF2("memcpy_calls",GridFlow_memcpy_calls,0); - SDEF2("memcpy_bytes",GridFlow_memcpy_bytes,0); - SDEF2("memcpy_time", GridFlow_memcpy_time,0); - SDEF2("malloc_calls",GridFlow_malloc_calls,0); - SDEF2("malloc_bytes",GridFlow_malloc_bytes,0); - SDEF2("malloc_time", GridFlow_malloc_time,0); - SDEF2("handle_braces!",GridFlow_handle_braces,1); - SDEF2("fclass_install",GridFlow_fclass_install,2); - -//#define FOO(A) fprintf(stderr,"sizeof("#A")=%d\n",sizeof(A)); -//FOO(Dim) FOO(BitPacking) FOO(GridHandler) FOO(GridInlet) FOO(GridOutlet) FOO(GridObject) -//#undef FOO - - rb_ivar_set(mGridFlow, SI(@fobjects), rb_hash_new()); - rb_ivar_set(mGridFlow, SI(@fclasses), rb_hash_new()); - rb_ivar_set(mGridFlow, SI(@bsym), PTR2FIX(&bsym)); - rb_define_const(mGridFlow, "GF_VERSION", rb_str_new2(GF_VERSION)); - rb_define_const(mGridFlow, "GF_COMPILE_TIME", rb_str_new2(GF_COMPILE_TIME)); - rb_define_const(mGridFlow, "GCC_VERSION", rb_str_new2(GCC_VERSION)); - cFObject = rb_define_class_under(mGridFlow, "FObject", rb_cObject); - EVAL( -\ruby - module GridFlow - class FObject - def send_out2(*) end - def self.install2(*) end - def self.add_creator(name) - name=name.to_str.dup - GridFlow.fclasses[name]=self - GridFlow.add_creator_2 name end - end - end -\end ruby -); - define_many_methods(cFObject,COUNT(FObject_methods),FObject_methods); - SDEF(FObject, install, 3); - SDEF(FObject, new, -1); - ID gbi = SI(gf_bridge_init); - if (rb_respond_to(rb_cData,gbi)) rb_funcall(rb_cData,gbi,0); - Ruby cBitPacking = - rb_define_class_under(mGridFlow, "BitPacking", rb_cObject); - define_many_methods(cBitPacking, - ciBitPacking.methodsn, - ciBitPacking.methods); - SDEF(BitPacking,new,-1); - rb_define_method(rb_cString, "swap32!", (RMethod)String_swap32_f, 0); - rb_define_method(rb_cString, "swap16!", (RMethod)String_swap16_f, 0); - - startup_number(); - startup_grid(); - startup_flow_objects(); - startup_flow_objects_for_image(); - startup_flow_objects_for_matrix(); - if (!EVAL("begin require 'gridflow/base/main.rb'; true\n" - "rescue Exception => e; " - "STDERR.puts \"can't load: #{$!}\n" - "backtrace: #{$!.backtrace.join\"\n\"}\n" - "$: = #{$:.inspect}\"\n; false end")) return; - cFormat = EVAL("GridFlow::Format"); - STARTUP_LIST() - EVAL("h=GridFlow.fclasses; h['#io:window'] = h['#io:quartz']||h['#io:x11']||h['#io:sdl']"); - EVAL("GridFlow.load_user_config"); - signal(11,SIG_DFL); // paranoia -} - -void GFStack::push (FObject *o) { - void *bp = &o; // really. just finding our position on the stack. - if (n>=GF_STACK_MAX) - RAISE("stack overflow (maximum %d FObject activations at once)", GF_STACK_MAX); - uint64 t = rdtsc(); - if (n) s[n-1].time = t - s[n-1].time; - s[n].o = o; - s[n].bp = bp; - s[n].time = t; - n++; -} - -void GFStack::pop () { - uint64 t = rdtsc(); - if (!n) RAISE("stack underflow (WHAT?)"); - n--; - if (s[n].o) s[n].o->total_time += t - s[n].time; - if (n) s[n-1].time = t - s[n-1].time; -} - -uint64 gf_timeofday () { - timeval t; - gettimeofday(&t,0); - return t.tv_sec*1000000+t.tv_usec; -} diff --git a/externals/gridflow/base/main.rb b/externals/gridflow/base/main.rb deleted file mode 100644 index 5b33bfad..00000000 --- a/externals/gridflow/base/main.rb +++ /dev/null @@ -1,384 +0,0 @@ -=begin - $Id: main.rb,v 1.2 2006-03-15 04:37:28 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. -=end - -# ENV["RUBY_VERBOSE_GC"]="yes" - -# this file gets loaded by main.c upon startup -# module GridFlow is supposed to be created by main.c -# this includes GridFlow.post_string(s) - -# because Ruby1.6 has no #object_id and Ruby1.8 warns on #id -unless Object.instance_methods(true).include? "object_id" - class Object; alias object_id id end -end - -# in case of bug in Ruby ("Error: Success") -module Errno; class E000 < StandardError; end; end - -#$post_log = File.open "/tmp/gridflow.log", "w" -$post_log = nil - -class Array - def split(elem) - r=[] - j=0 - for i in 0...length - (r<<self[j,i-j]; j=i+1) if self[i]==elem - end - r<<self[j,length-j] - end -end - -module GridFlow #------------------ - -def self.post(s,*a) - post_string(sprintf("%s"+s,post_header,*a)) - ($post_log << sprintf(s,*a); $post_log.flush) if $post_log -end - -class<<self - attr_accessor :data_path - attr_accessor :post_header - attr_accessor :verbose - attr_reader :fobjects - attr_reader :fclasses - attr_reader :cpu_hertz - attr_reader :subprocesses - attr_reader :bridge_name - alias gfpost post -end - -@subprocesses={} -@verbose=false -@data_path=[] -if GridFlow.respond_to? :config then - @data_path << GridFlow.config["PUREDATA_PATH"]+"/extra/gridflow/images" -end - -def self.hunt_zombies - #STDERR.puts "GridFlow.hunt_zombies" - # the $$ value is bogus - begin - died = [] - subprocesses.each {|x,v| - Process.waitpid2(x,Process::WNOHANG) and died<<x - } - rescue Errno::ECHILD - end - #STDERR.puts died.inspect - died.each {|x| subprocesses.delete x } -end - -def self.packstring_for_nt(nt) - case nt - when :u, :u8, :uint8; "C*" - when :s, :i16, :int16; "s*" - when :i, :i32, :int32; "l*" - when :l, :i64, :int64; raise "int64? lol" - when :f, :f32, :float32; "f*" - when :d, :f64, :float64; "d*" - else raise "no decoder for #{nt.inspect}" - end -end - -self.post_header = "[gf] " - -def self.gfpost2(fmt,s); post("%s",s) end - -if GridFlow.bridge_name then - post "This is GridFlow #{GridFlow::GF_VERSION} within Ruby version #{RUBY_VERSION}" - post "base/main.c was compiled on #{GridFlow::GF_COMPILE_TIME}" - post "Please use at least 1.6.6 if you plan to use sockets" if RUBY_VERSION<"1.6.6" -end - -if not GridFlow.bridge_name then - require "gridflow/bridge/placebo" -end - -Brace1 = "{".intern -Brace2 = "}".intern -Paren1 = "(".intern -Paren2 = ")".intern - -def self.parse(m) - m = m.gsub(/(\{|\})/," \\1 ").split(/\s+/) - m.map! {|x| case x - when Integer, Symbol; x - when /^[+\-]?[0-9]+$/; x.to_i - when String; x.intern - end - } - m -end - -def self.stringify_list(argv) - argv.map {|x| stringify x }.join(" ") -end - -def self.stringify(arg) - case arg - when Integer, Float, Symbol; arg.to_s - when Array; "{#{stringify_list arg}}" - end -end - -::Object.module_eval do def FloatOrSymbol(x) Float(x) rescue x.intern end end - -# adding some functionality to that: -class FObject - @broken_ok = false - @do_loadbangs = true - class<<self - # global - attr_accessor :broken_ok - # per-class - attr_reader :ninlets - attr_reader :noutlets - attr_accessor :do_loadbangs - attr_accessor :comment - def foreign_name; @foreign_name if defined? @foreign_name end - def doc(selector=nil,text=nil) - return @doc if not selector - if not defined? @doc; @doc={}; end - return @doc[selector] if not text - @doc[selector] = text - end - def doc_out(selector=nil,text=nil) - return @doc_out if not selector - if not defined? @doc_out; @doc_out={}; end - return @doc_out[selector] if not text - @doc_out[selector] = text - end - end - def post(*a) GridFlow.post(*a) end - def self.subclass(*args,&b) - qlass = Class.new self - qlass.install(*args) - #qlass.module_eval{qlass.instance_eval(&b)} - qlass.instance_eval{qlass.module_eval(&b)} - #qlass.module_eval(&b) - end - alias :total_time :total_time_get - alias :total_time= :total_time_set - attr_writer :args # String - attr_accessor :argv # Array - attr_reader :outlets - attr_accessor :parent_patcher - attr_accessor :properties - attr_accessor :classname - def initialize2; end - def args - if defined? @args - @args - else - "[#{self.class} ...]" - end - end - alias info args - def connect outlet, object, inlet - @outlets ||= [] - @outlets[outlet] ||= [] - @outlets[outlet].push [object, inlet] - end - def self.name_lookup sym - qlasses = GridFlow.fclasses - qlass = qlasses[sym.to_s] - if not qlass - return qlasses['broken'] if @broken_ok - raise "object class '#{sym}' not found" - end - qlass - end - def self.[](*m) - o=nil - if m.length==1 and m[0] =~ / / - o="[#{m[0]}]" - m=GridFlow.parse(m[0]) - else - o=m.inspect - end - GridFlow.handle_braces!(m) - ms = m.split ','.intern - m = ms.shift - qlass = m.shift - qlassname = qlass.to_s - qlass = name_lookup qlass.to_s unless Class===qlass - r = qlass.new(*m) - r.classname = qlassname - GridFlow.post "%s",r.args if GridFlow.verbose - for x in ms do r.send_in(-2, *x) end if FObject.do_loadbangs - r - end - def inspect - if args then "#<#{self.class} #{args}>" else super end - end - def initialize(*argv) - s = GridFlow.stringify_list argv - @argv = argv - @args = "[" - @args << (self.class.foreign_name || self.to_s) - @args << " " if s.length>0 - @args << s << "]" - @parent_patcher = nil - @properties = {} - @init_messages = [] - end -end - -class FPatcher < FObject - class << self - attr_reader :fobjects - attr_reader :wires - end - def initialize(*) - super - fobjects = self.class.fobjects - wires = self.class.wires - @fobjects = fobjects.map {|x| if String===x then FObject[x] else x.call end } - @inlets = [] - @ninlets = self.class.ninlets or raise "oops" - i=0 - @fobjects << self - while i<wires.length do - a,b,c,d = wires[i,4] - if a==-1 then - a=self - @inlets[b]||=[] - @inlets[b] << [@fobjects[c],d] - else - if c==-1 then - @fobjects[a].connect b,self,d+@ninlets - else - @fobjects[a].connect b,@fobjects[c],d - end - end - i+=4 - end - end - def method_missing(sym,*args) - sym=sym.to_s - if sym =~ /^_(\d)_(.*)/ then - inl = Integer $1 - sym = $2.intern - if inl<@ninlets then - raise "#{inspect} has not @inlets[#{inl}]" if not @inlets[inl] - for x in @inlets[inl] do - x[0].send_in x[1],sym,*args end - else - send_out(inl-@ninlets,sym,*args) - end - else super end - end -end - -def GridFlow.estimate_cpu_clock - u0,t0=GridFlow.rdtsc,Time.new.to_f; sleep 0.01 - u1,t1=GridFlow.rdtsc,Time.new.to_f; (u1-u0)/(t1-t0) -end - -begin - @cpu_hertz = (0...3).map { - GridFlow.estimate_cpu_clock - }.sort[1] # median of three tries -rescue - GridFlow.post $! -end - -def GridFlow.find_file s - s=s.to_s - if s==File.basename(s) then - dir = GridFlow.data_path.find {|x| File.exist? "#{x}/#{s}" } - if dir then "#{dir}/#{s}" else s end - elsif GridFlow.respond_to? :find_file_2 - GridFlow.find_file_2 s - else - s - end -end - -def GridFlow.macerr(i) - begin - f=File.open("/System/Library/Frameworks/CoreServices.framework/"+ - "Versions/A/Frameworks/CarbonCore.framework/Versions/A/Headers/"+ - "MacErrors.h") - while f.gets - m = /^\s*(\w+)\s*=\s*(-\d+),\s*\/\*\s*(.*)\s*\*\/$/.match $_ - next if not m - if m[2].to_i == i then return "#{m[2]}: \"#{m[3]}\"" end - end - return "no error message available for this error number" - rescue FileError - return "Can't find Apple's precious copyrighted list of error messages on this system." - ensure - f.close if f - end -end - -end # module GridFlow - -class IO - def nonblock= flag - bit = Fcntl::O_NONBLOCK - state = fcntl(Fcntl::F_GETFL, 0) - fcntl(Fcntl::F_SETFL, (state & ~bit) | - (if flag; bit else 0 end)) - end -end - -def protect - yield -rescue Exception => e - STDERR.puts "#{e.class}: #{e}" - STDERR.puts e.backtrace -end - -def GridFlow.load_user_config - require "gridflow/bridge/puredata.rb" if GridFlow.bridge_name == "puredata" - user_config_file = ENV["HOME"] + "/.gridflow_startup" - begin - load user_config_file if File.exist? user_config_file - rescue Exception => e - GridFlow.post "#{e.class}: #{e}:\n" + e.backtrace.join("\n") - GridFlow.post "while loading ~/.gridflow_startup" - end -end - -require "gridflow/base/flow_objects.rb" -require "gridflow/format/main.rb" - -%w( - # #for #finished #type #dim #transpose #perspective #store #outer - #grade #redim #import #export #export_list #cast - #scale_by #downscale_by #draw_polygon #draw_image #layer - #print #pack #export_symbol #rotate - #in #out -).each {|k| - GridFlow::FObject.name_lookup(k).add_creator k.gsub(/#/,"@") -} - -END { - GridFlow.fobjects.each {|k,v| k.delete if k.respond_to? :delete } - GridFlow.fobjects.clear - GC.start -} - diff --git a/externals/gridflow/base/number.c b/externals/gridflow/base/number.c deleted file mode 100644 index b362e2cb..00000000 --- a/externals/gridflow/base/number.c +++ /dev/null @@ -1,374 +0,0 @@ -/* - $Id: number.c,v 1.2 2006-03-15 04:37:08 matju Exp $ - - GridFlow - Copyright (c) 2001,2002,2003,2004 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. -*/ - -#include "grid.h.fcs" -#include <math.h> -#include <stdlib.h> -#include <stdio.h> -#include <limits.h> - -#ifdef PASS1 -NumberType number_type_table[] = { -#define FOO(_sym_,_size_,_flags_,args...) NumberType( #_sym_, _size_, _flags_, args ), -NUMBER_TYPES(FOO) -#undef FOO -}; -const long number_type_table_n = COUNT(number_type_table); -#endif - -// those are bogus class-templates in the sense that you don't create -// objects from those, you just call static functions. The same kind -// of pattern is present in STL to overcome some limitations of C++. - -template <class T> class Op { -public: - // I call abort() on those because I can't say they're purevirtual. - static T f(T a, T b) {abort();} - static bool is_neutral(T x, LeftRight side) {assert(!"Op::is_neutral called?"); return false;} - static bool is_absorbent(T x, LeftRight side) {assert(!"Op::is_absorbent called?"); return false;} -}; - -template <class O> class OpLoops { -public: - template <class T> static void op_map (int n, T *as, T b) { - if (!n) return; -#define FOO(I) as[I]=O::f(as[I],b); - UNROLL_8(FOO,n,as) -#undef FOO - } - template <class T> static void op_zip (int n, T *as, T *bs) { - if (!n) return; - ptrdiff_t ba=bs-as; // really! -#define FOO(I) as[I]=O::f(as[I],as[ba+I]); - UNROLL_8(FOO,n,as) -#undef FOO - } - // disabled - template <class T> static void op_zip2 (int n, T *as, T *bs, T *cs) { - if (!n) return; - ptrdiff_t ba=bs-as, ca=cs-as; -#define FOO(I) as[ca+I]=O::f(as[I],as[ba+I]); - UNROLL_8(FOO,n,as) -#undef FOO - } -#define W(i) as[i]=O::f(as[i],bs[i]); -#define Z(i,j) as[i]=O::f(O::f(O::f(O::f(as[i],bs[i]),bs[i+j]),bs[i+j+j]),bs[i+j+j+j]); - template <class T> static void op_fold (int an, int n, T *as, T *bs) { - switch (an) { - case 1: for (; (n&3)!=0; bs++, n--) W(0); - for (; n; bs+=4, n-=4) { Z(0,1); } break; - case 2: for (; (n&3)!=0; bs+=2, n--) { W(0); W(1); } - for (; n; bs+=8, n-=4) { Z(0,2); Z(1,2); } break; - case 3: for (; (n&3)!=0; bs+=3, n--) { W(0); W(1); W(2); } - for (; n; bs+=12, n-=4) { Z(0,3); Z(1,3); Z(2,3); } break; - case 4: for (; (n&3)!=0; bs+=4, n--) { W(0); W(1); W(2); W(3); } - for (; n; bs+=16, n-=4) { Z(0,4); Z(1,4); Z(2,4); Z(3,4); } break; - default:for (; n--; ) { - int i=0; - for (; i<(an&-4); i+=4, bs+=4) { - as[i+0]=O::f(as[i+0],bs[0]); - as[i+1]=O::f(as[i+1],bs[1]); - as[i+2]=O::f(as[i+2],bs[2]); - as[i+3]=O::f(as[i+3],bs[3]); - } - for (; i<an; i++, bs++) as[i] = O::f(as[i],*bs); - } - } - } - template <class T> static void op_scan (int an, int n, T *as, T *bs) { - for (; n--; as=bs-an) { - for (int i=0; i<an; i++, as++, bs++) *bs=O::f(*as,*bs); - } - } -}; - -template <class T> -static void quick_mod_map (int n, T *as, T b) { - if (!b) return; -#define FOO(I) as[I]=mod(as[I],b); - UNROLL_8(FOO,n,as) -#undef FOO -} - -template <class T> static void quick_ign_map (int n, T *as, T b) {} -template <class T> static void quick_ign_zip (int n, T *as, T *bs) {} -template <class T> static void quick_put_map (int n, T *as, T b) { -#define FOO(I) as[I]=b; - UNROLL_8(FOO,n,as) -#undef FOO -} - -#ifdef PASS1 -void quick_put_map (int n, int16 *as, int16 b) { - if (n&1!=0 && (long)as&4!=0) { *as++=b; n--; } - quick_put_map (n>>1, (int32 *)as, (int32)(b<<16)+b); - if (n&1!=0) *as++=b; -} -void quick_put_map (int n, uint8 *as, uint8 b) { - while (n&3!=0 && (long)as&4!=0) { *as++=b; n--; } - int32 c=(b<<8)+b; c+=c<<16; - quick_put_map (n>>2, (int32 *)as, c); - while (n&3!=0) *as++=b; -} -#endif -template <class T> static void quick_put_zip (int n, T *as, T *bs) { - gfmemcopy((uint8 *)as, (uint8 *)bs, n*sizeof(T)); -} - -// classic two-input operator -#define DEF_OP(op,expr,neu,isneu,isorb) \ - template <class T> class Y##op : Op<T> { public: \ - inline static T f(T a, T b) { return expr; } \ - inline static T neutral (LeftRight side) {return neu;} \ - inline static bool is_neutral (T x, LeftRight side) {return isneu;} \ - inline static bool is_absorbent(T x, LeftRight side) {return isorb;}}; -#define DEF_OPFT(op,expr,neu,isneu,isorb,T) \ - template <> class Y##op<T> : Op<T> { public: \ - inline static T f(T a, T b) { return expr; } \ - inline static T neutral (LeftRight side) {return neu;} \ - inline static bool is_neutral (T x, LeftRight side) {return isneu;} \ - inline static bool is_absorbent(T x, LeftRight side) {return isorb;}}; -// this macro is for operators that have different code for the float version -#define DEF_OPF(op,expr,expr2,neu,isneu,isorb) \ - DEF_OP( op,expr, neu,isneu,isorb) \ - DEF_OPFT(op,expr2,neu,isneu,isorb,float32) \ - DEF_OPFT(op,expr2,neu,isneu,isorb,float64) - -#define DECL_OPON(base,op,T) NumopOn<T>( \ - &base<Y##op<T> >::op_map, &base<Y##op<T> >::op_zip, \ - &base<Y##op<T> >::op_fold, &base<Y##op<T> >::op_scan, \ - &Y##op<T>::neutral, &Y##op<T>::is_neutral, &Y##op<T>::is_absorbent) -#define DECL_OPON_NOFOLD(base,op,T) NumopOn<T>( \ - &base<Y##op<T> >::op_map, &base<Y##op<T> >::op_zip, 0,0, \ - &Y##op<T>::neutral, &Y##op<T>::is_neutral, &Y##op<T>::is_absorbent) -#define DECL_OP(op,sym,flags) Numop(0, sym, \ - DECL_OPON(OpLoops,op,uint8), DECL_OPON(OpLoops,op,int16), \ - DECL_OPON(OpLoops,op,int32) NONLITE(, DECL_OPON(OpLoops,op,int64), \ - DECL_OPON(OpLoops,op,float32), DECL_OPON(OpLoops,op,float64), \ - DECL_OPON(OpLoops,op,ruby)), flags) -#define DECL_OP_NOFLOAT(op,sym,flags) Numop(0, sym, \ - DECL_OPON(OpLoops,op,uint8), DECL_OPON(OpLoops,op,int16), \ - DECL_OPON(OpLoops,op,int32) NONLITE(, DECL_OPON(OpLoops,op,int64), \ - NumopOn<float32>(0,0,0,0,0,0,0), NumopOn<float64>(0,0,0,0,0,0,0), \ - DECL_OPON(OpLoops,op,ruby)), flags) -#define DECL_OP_NOFOLD(op,sym,flags) Numop(0, sym, \ - DECL_OPON_NOFOLD(OpLoops,op,uint8), DECL_OPON_NOFOLD(OpLoops,op,int16), \ - DECL_OPON_NOFOLD(OpLoops,op,int32) NONLITE(, DECL_OPON_NOFOLD(OpLoops,op,int64), \ - DECL_OPON_NOFOLD(OpLoops,op,float32), DECL_OPON_NOFOLD(OpLoops,op,float64), \ - DECL_OPON_NOFOLD(OpLoops,op,ruby)), flags) - -template <class T> static inline T gf_floor (T a) { - return (T) floor((double)a); } -template <class T> static inline T gf_trunc (T a) { - return (T) floor(abs((double)a)) * (a<0?-1:1); } - -// trying to avoid GCC warning about uint8 too small for ==256 -template <class T> static bool equal256 (T x) {return x==256;} -template <> static bool equal256 (uint8 x) {return false;} - -#ifdef PASS1 -DEF_OP(ignore, a, 0, side==at_right, side==at_left) -DEF_OP(put, b, 0, side==at_left, side==at_right) -DEF_OP(add, a+b, 0, x==0, false) -DEF_OP(sub, a-b, 0, side==at_right && x==0, false) -DEF_OP(bus, b-a, 0, side==at_left && x==0, false) -DEF_OP(mul, a*b, 1, x==1, x==0) -DEF_OP(mulshr8, (a*b)>>8, 256, equal256(x), x==0) -DEF_OP(div, b==0 ? (T)0 : a/b , 1, side==at_right && x==1, false) -DEF_OP(div2, b==0 ? 0 : div2(a,b), 1, side==at_right && x==1, false) -DEF_OP(vid, a==0 ? (T)0 : b/a , 1, side==at_left && x==1, false) -DEF_OP(vid2, a==0 ? 0 : div2(b,a), 1, side==at_left && x==1, false) -DEF_OPF(mod, b==0 ? 0 : mod(a,b), b==0 ? 0 : a-b*gf_floor(a/b), 0, false, side==at_left && x==0 || side==at_right && x==1) -DEF_OPF(dom, a==0 ? 0 : mod(b,a), a==0 ? 0 : b-a*gf_floor(b/a), 0, false, side==at_left && x==0 || side==at_right && x==1) -//DEF_OPF(rem, b==0 ? 0 : a%b, b==0 ? 0 : a-b*gf_trunc(a/b)) -//DEF_OPF(mer, a==0 ? 0 : b%a, a==0 ? 0 : b-a*gf_trunc(b/a)) -DEF_OP(rem, b==0?(T)0:a%b, 0, false, side==at_left&&x==0 || side==at_right&&x==1) -DEF_OP(mer, a==0?(T)0:b%a, 0, false, side==at_left&&x==0 || side==at_right&&x==1) -#endif -#ifdef PASS2 -DEF_OP(gcd, gcd(a,b), 0, x==0, x==1) -DEF_OP(gcd2, gcd2(a,b), 0, x==0, x==1) // should test those and pick one of the two -DEF_OP(lcm, a==0 || b==0 ? (T)0 : lcm(a,b), 1, x==1, x==0) -DEF_OPF(or , a|b, (float32)((int32)a | (int32)b), 0, x==0, x==nt_all_ones(&x)) -DEF_OPF(xor, a^b, (float32)((int32)a ^ (int32)b), 0, x==0, false) -DEF_OPF(and, a&b, (float32)((int32)a & (int32)b), -1 /*nt_all_ones((T*)0)*/, x==nt_all_ones(&x), x==0) -DEF_OPF(shl, a<<b, a*pow(2.0,+b), 0, side==at_right && x==0, false) -DEF_OPF(shr, a>>b, a*pow(2.0,-b), 0, side==at_right && x==0, false) -DEF_OP(sc_and, a ? b : a, 1, side==at_left && x!=0, side==at_left && x==0) -DEF_OP(sc_or, a ? a : b, 0, side==at_left && x==0, side==at_left && x!=0) -DEF_OP(min, min(a,b), nt_greatest((T*)0), x==nt_greatest(&x), x==nt_smallest(&x)) -DEF_OP(max, max(a,b), nt_smallest((T*)0), x==nt_smallest(&x), x==nt_greatest(&x)) -DEF_OP(cmp, cmp(a,b), 0, false, false) -DEF_OP(eq, a == b, 0, false, false) -DEF_OP(ne, a != b, 0, false, false) -DEF_OP(gt, a > b, 0, false, side==at_left&&x==nt_smallest(&x)||side==at_right&&x==nt_greatest(&x)) -DEF_OP(le, a <= b, 0, false, side==at_left&&x==nt_smallest(&x)||side==at_right&&x==nt_greatest(&x)) -DEF_OP(lt, a < b, 0, false, side==at_left&&x==nt_greatest(&x)||side==at_right&&x==nt_smallest(&x)) -DEF_OP(ge, a >= b, 0, false, side==at_left&&x==nt_greatest(&x)||side==at_right&&x==nt_smallest(&x)) -#endif -#ifdef PASS3 -DEF_OP(sin, (T)((float64)b * sin((float64)a * (M_PI / 18000))), 0, false, false) // "LN=9000+36000n RA=0 LA=..." -DEF_OP(cos, (T)((float64)b * cos((float64)a * (M_PI / 18000))), 0, false, false) // "LN=36000n RA=0 LA=..." -DEF_OP(atan, (T)(atan2(a,b) * (18000 / M_PI)), 0, false, false) // "LA=0" -DEF_OP(tanh, (T)((float64)b * tanh((float64)a * (M_PI / 18000))), 0, false, x==0) -DEF_OP(gamma, b<=0 ? (T)0 : (T)(0+floor(pow((float64)a/256.0,256.0/(float64)b)*256.0)), 0, false, false) // "RN=256" -DEF_OP(pow, ipow(a,b), 0, false, false) // "RN=1" -DEF_OP(log, (T)(a==0 ? (T)0 : (T)((float64)b * log((float64)gf_abs(a)))), 0, false, false) // "RA=0" -// 0.8 -DEF_OPF(clipadd, clipadd(a,b), a+b, 0, x==0, false) -DEF_OPF(clipsub, clipsub(a,b), a-b, 0, side==at_right && x==0, false) -DEF_OP(abssub, gf_abs(a-b), 0, false, false) -DEF_OP(sqsub, (a-b)*(a-b), 0, false, false) -DEF_OP(avg, (a+b)/2, 0, false, false) -DEF_OP(hypot, (T)(0+floor(sqrt(a*a+b*b))), 0, false, false) -DEF_OP(sqrt, (T)(0+floor(sqrt(a))), 0, false, false) -DEF_OP(rand, a==0 ? (T)0 : (T)(random()%(int32)a), 0, false, false) -//DEF_OP(erf,"erf*", 0) -#endif - -extern Numop op_table1[], op_table2[], op_table3[]; -extern const long op_table1_n, op_table2_n, op_table3_n; - -#ifdef PASS1 -Numop op_table1[] = { - DECL_OP(ignore, "ignore", OP_ASSOC), - DECL_OP(put, "put", OP_ASSOC), - DECL_OP(add, "+", OP_ASSOC|OP_COMM), // "LINV=sub" - DECL_OP(sub, "-", 0), - DECL_OP(bus, "inv+", 0), - DECL_OP(mul, "*", OP_ASSOC|OP_COMM), - DECL_OP_NOFLOAT(mulshr8, "*>>8", OP_ASSOC|OP_COMM), - DECL_OP(div, "/", 0), - DECL_OP_NOFLOAT(div2, "div", 0), - DECL_OP(vid, "inv*", 0), - DECL_OP_NOFLOAT(vid2, "swapdiv", 0), - DECL_OP_NOFLOAT(mod, "%", 0), - DECL_OP_NOFLOAT(dom, "swap%", 0), - DECL_OP_NOFLOAT(rem, "rem", 0), - DECL_OP_NOFLOAT(mer, "swaprem", 0), -}; -const long op_table1_n = COUNT(op_table1); -#endif -#ifdef PASS2 -Numop op_table2[] = { - DECL_OP_NOFLOAT(gcd, "gcd", OP_ASSOC|OP_COMM), - DECL_OP_NOFLOAT(gcd2, "gcd2", OP_ASSOC|OP_COMM), - DECL_OP_NOFLOAT(lcm, "lcm", OP_ASSOC|OP_COMM), - DECL_OP(or , "|", OP_ASSOC|OP_COMM), - DECL_OP(xor, "^", OP_ASSOC|OP_COMM), - DECL_OP(and, "&", OP_ASSOC|OP_COMM), - DECL_OP_NOFOLD(shl, "<<", 0), - DECL_OP_NOFOLD(shr, ">>", 0), - DECL_OP_NOFOLD(sc_and,"&&", 0), - DECL_OP_NOFOLD(sc_or, "||", 0), - DECL_OP(min, "min", OP_ASSOC|OP_COMM), - DECL_OP(max, "max", OP_ASSOC|OP_COMM), - DECL_OP_NOFOLD(eq, "==", OP_COMM), - DECL_OP_NOFOLD(ne, "!=", OP_COMM), - DECL_OP_NOFOLD(gt, ">", 0), - DECL_OP_NOFOLD(le, "<=", 0), - DECL_OP_NOFOLD(lt, "<", 0), - DECL_OP_NOFOLD(ge, ">=", 0), - DECL_OP_NOFOLD(cmp, "cmp", 0), -}; -const long op_table2_n = COUNT(op_table2); -#endif -#ifdef PASS3 -uint8 clipadd(uint8 a, uint8 b) { int32 c=a+b; return c<0?0:c>255?255:c; } -int16 clipadd(int16 a, int16 b) { int32 c=a+b; return c<-0x8000?-0x8000:c>0x7fff?0x7fff:c; } -int32 clipadd(int32 a, int32 b) { int64 c=a+b; return c<-0x80000000?-0x80000000:c>0x7fffffff?0x7fffffff:c; } -int64 clipadd(int64 a, int64 b) { int64 c=(a>>1)+(b>>1)+(a&b&1), p=nt_smallest((int64 *)0), q=nt_greatest((int64 *)0); - return c<p/2?p:c>q/2?q:a+b; } -uint8 clipsub(uint8 a, uint8 b) { int32 c=a-b; return c<0?0:c>255?255:c; } -int16 clipsub(int16 a, int16 b) { int32 c=a-b; return c<-0x8000?-0x8000:c>0x7fff?0x7fff:c; } -int32 clipsub(int32 a, int32 b) { int64 c=a-b; return c<-0x80000000?-0x80000000:c>0x7fffffff?0x7fffffff:c; } -int64 clipsub(int64 a, int64 b) { int64 c=(a>>1)-(b>>1); //??? - int64 p=nt_smallest((int64 *)0), q=nt_greatest((int64 *)0); - return c<p/2?p:c>q/2?q:a-b; } - -ruby clipadd(ruby a, ruby b) { return a+b; } -ruby clipsub(ruby a, ruby b) { return a-b; } - -Numop op_table3[] = { - DECL_OP_NOFOLD(sin, "sin*", 0), - DECL_OP_NOFOLD(cos, "cos*", 0), - DECL_OP_NOFOLD(atan, "atan", 0), - DECL_OP_NOFOLD(tanh, "tanh*", 0), - DECL_OP_NOFOLD(gamma, "gamma", 0), - DECL_OP_NOFOLD(pow, "**", 0), - DECL_OP_NOFOLD(log, "log*", 0), -// 0.8 - DECL_OP(clipadd,"clip+", OP_ASSOC|OP_COMM), - DECL_OP(clipsub,"clip-", 0), - DECL_OP_NOFOLD(abssub,"abs-", OP_COMM), - DECL_OP_NOFOLD(sqsub,"sq-", OP_COMM), - DECL_OP_NOFOLD(avg,"avg", OP_COMM), - DECL_OP_NOFOLD(hypot,"hypot", OP_COMM), - DECL_OP_NOFOLD(sqrt,"sqrt", 0), - DECL_OP_NOFOLD(rand,"rand", 0), - //DECL_OP_NOFOLD(erf,"erf*", 0), -}; -const long op_table3_n = COUNT(op_table3); -#endif - -// D=dictionary, A=table, A##_n=table count. -#define INIT_TABLE(D,A) { D=IEVAL(mGridFlow,"@"#D" ||= {}"); \ - for(int i=0; i<A##_n; i++) { \ - A[i].sym = ID2SYM(rb_intern(A[i].name)); \ - rb_hash_aset(D,A[i].sym,PTR2FIX((A+i)));}} - -#ifdef PASS1 -Ruby op_dict = Qnil; -Ruby number_type_dict = Qnil; -void startup_number () { - INIT_TABLE(op_dict,op_table1) - INIT_TABLE(op_dict,op_table2) - INIT_TABLE(op_dict,op_table3) - INIT_TABLE(number_type_dict,number_type_table) - - for (int i=0; i<COUNT(number_type_table); i++) { - number_type_table[i].index = (NumberTypeE) i; - char a[64]; - strcpy(a,number_type_table[i].aliases); - char *b = strchr(a,','); - if (b) { - *b=0; - rb_hash_aset(number_type_dict, ID2SYM(rb_intern(b+1)), - PTR2FIX(&number_type_table[i])); - } - rb_hash_aset(number_type_dict, ID2SYM(rb_intern(a)), - PTR2FIX(&number_type_table[i])); - } -// S:name; M:mode; F:replacement function; -#define OVERRIDE_INT(S,M,F) { \ - Numop *foo = FIX2PTR(Numop,rb_hash_aref(op_dict,SYM(S))); \ - foo->on_uint8.op_##M=F; \ - foo->on_int16.op_##M=F; \ - foo->on_int32.op_##M=F; } - OVERRIDE_INT(ignore,map,quick_ign_map); - OVERRIDE_INT(ignore,zip,quick_ign_zip); - //OVERRIDE_INT(put,map,quick_put_map); - //OVERRIDE_INT(put,zip,quick_put_zip); - //OVERRIDE_INT(%,map,quick_mod_map); // !@#$ does that make an improvement at all? -} -#endif diff --git a/externals/gridflow/base/source_filter.rb b/externals/gridflow/base/source_filter.rb deleted file mode 100644 index c55f4d95..00000000 --- a/externals/gridflow/base/source_filter.rb +++ /dev/null @@ -1,276 +0,0 @@ -#!/usr/bin/env ruby - -$keywords = %w(class decl def end grdecl) -$stack = [] -$classes = [] - -ClassDecl = Struct.new(:name,:supername,:methods,:grins,:attrs,:info) -MethodDecl = Struct.new(:rettype,:selector,:arglist,:minargs,:maxargs,:where,:static) -Arg = Struct.new(:type,:name,:default) - -class MethodDecl - def ==(o) - return false unless rettype==o.rettype && static==o.static && - maxargs==o.maxargs # && minargs==o.minargs - arglist.each_index{|i| arglist[i] == o.arglist[i] or return false } - return true - end -end - -class Arg - def ==(o) - type==o.type && name==o.name # && default==o.default - end -end - -In = File.open ARGV[0], "r" -Out = File.open ARGV[1], "w" - -def handle_class(line) - raise "already in class #{where}" if $stack[-1] and ClassDecl===$stack[-1] - #STDERR.puts "class: #{line}" - /^(\w+)(?:\s*<\s*(\w+))?$/.match line or raise "syntax error #{where}" - q=ClassDecl.new($1,$2,{},{},{},false) - $stack << q - $classes << q - Out.puts "" -end - -def parse_methoddecl(line,term) - /^(static\s)?\s*(\w+)\s+(\w+)\s*\(([^\)]*)\)\s*#{term}/.match line or - raise "syntax error #{where} #{line}" - static,rettype,selector,arglist = $1,$2,$3,$4 - arglist,minargs,maxargs = parse_arglist arglist - MethodDecl.new(rettype,selector,arglist,minargs,maxargs,where,static) -end - -def parse_arglist(arglist) - arglist = arglist.split(/,/) - maxargs = arglist.length - args = arglist.map {|arg| - if /^\s*\.\.\.\s*$/.match arg then maxargs=-1; next end - /^\s*([\w\s\*<>]+)\s*\b(\w+)\s*(?:\=(.*))?/.match arg or - raise "syntax error in \"#{arg}\" #{where}" - type,name,default=$1,$2,$3 - Arg.new(type.sub(/\s+$/,""),name,default) - }.compact - minargs = args.length - minargs-=1 while minargs>0 and args[minargs-1].default - [args,minargs,maxargs] -end - -def unparse_arglist(arglist,with_default=true) - arglist.map {|arg| - x="#{arg.type} #{arg.name} " - x<<'='<<arg.default if with_default and arg.default - x - }.join(", ") -end - -def where - "[#{ARGV[0]}:#{$linenumber}]" -end - -def handle_attr(line) - type = line.gsub(%r"//.*$","").gsub(%r"/\*.*\*/","").gsub(%r";?\s*$","") - name = type.slice!(/\w+$/) - raise "missing \\class #{where}" if - not $stack[-1] or not ClassDecl===$stack[-1] - $stack[-1].attrs[name]=Arg.new(type,name,nil) - Out.print line.gsub(/\/\/.*$/,"") # hack! - handle_decl "void _0_#{name}_m (#{type} #{name});" -# Out.puts "# #{$linenumber}" -end - -def handle_decl(line) - raise "missing \\class #{where}" if - not $stack[-1] or not ClassDecl===$stack[-1] - classname = $stack[-1].name - m = parse_methoddecl(line,";\s*$") - $stack[-1].methods[m.selector] = m - - Out.print "static " if m.static - Out.print "#{m.rettype} #{m.selector}(int argc, Ruby *argv" - Out.print "," if m.arglist.length>0 - Out.print "#{unparse_arglist m.arglist});" - Out.puts "static Ruby #{m.selector}_wrap"+ - "(int argc, Ruby *argv, Ruby rself);//FCS" -# Out.puts "# #{$linenumber}" -end - -def handle_def(line) - m = parse_methoddecl(line,"\\{?.*$") - term = line[/\{.*/] - qlass = $stack[-1] - raise "missing \\class #{where}" if not qlass or not ClassDecl===qlass - classname = qlass.name - if qlass.methods[m.selector] - n = m; m = qlass.methods[m.selector] - if m!=n then - STDERR.puts "warning: def does not match decl:" - STDERR.puts "#{m.where}: \\decl #{m.inspect}" - STDERR.puts "#{n.where}: \\def #{n.inspect}" - end - else - qlass.methods[m.selector] = m - end - - Out.print "Ruby #{classname}::#{m.selector}_wrap"+ - "(int argc, Ruby *argv, Ruby rself) {"+ - "static const char *methodspec = "+ - "\"#{qlass.name}::#{m.selector}(#{unparse_arglist m.arglist,false})\";"+ - "DGS(#{classname});" - - Out.print "if (argc<#{m.minargs}" - Out.print "||argc>#{m.maxargs}" if m.maxargs!=-1 - Out.print ") RAISE(\"got %d args instead of %d..%d in %s\""+ - ",argc,#{m.minargs},#{m.maxargs},methodspec);" - - error = proc {|x,y| - "RAISE(\"got %s instead of #{x} in %s\","+ - "rb_str_ptr(rb_inspect(rb_obj_class(#{y}))),methodspec)" - } - - m.arglist.each_with_index{|arg,i| - case arg.type - when "Symbol" - Out.print "if (argc>#{i} && TYPE(argv[#{i}])!=T_SYMBOL) "+ - error[arg.type,"argv[#{i}]"]+";" - when "Array" - Out.print "if (argc>#{i} && TYPE(argv[#{i}])!=T_ARRAY) "+ - error[arg.type,"argv[#{i}]"]+";" - when "String" - Out.print "if (argc>#{i} && TYPE(argv[#{i}])==T_SYMBOL) "+ - "argv[#{i}]=rb_funcall(argv[#{i}],SI(to_s),0);" - Out.print "if (argc>#{i} && TYPE(argv[#{i}])!=T_STRING) "+ - error[arg.type,"argv[#{i}]"]+";" - end - } - -# Out.print "return " if m.rettype!="void" - Out.print "VALUE foo = " if m.rettype!="void" ### - - Out.print " self->#{m.selector}(argc,argv" - m.arglist.each_with_index{|arg,i| - if arg.default then - Out.print ",argc<#{i+1}?#{arg.default}:convert(argv[#{i}],(#{arg.type}*)0)" - else - Out.print ",convert(argv[#{i}],(#{arg.type}*)0)" - end - } - Out.print ");" - Out.print "self->check_magic();" - Out.print "return Qnil;" if m.rettype=="void" - Out.print "return foo;" if m.rettype!="void" ### - Out.print "} #{m.rettype} #{classname}::#{m.selector}(int argc, Ruby *argv" - Out.print "," if m.arglist.length>0 - Out.puts "#{unparse_arglist m.arglist, false})#{term}//FCS" -end - -def handle_classinfo(line) - frame = $stack[-1] - cl = frame.name - line="{}" if /^\s*$/ =~ line - Out.puts "static void #{cl}_startup (Ruby rself);" - Out.puts "static void *#{cl}_allocator () {return new #{cl};}" - Out.puts "static MethodDecl #{cl}_methods[] = {" - Out.puts frame.methods.map {|foo,method| - c,s = frame.name,method.selector - "{ \"#{s}\",(RMethod)#{c}::#{s}_wrap }" - }.join(",") - Out.puts "}; static FClass ci#{cl} = { #{cl}_allocator, #{cl}_startup," - Out.puts "#{cl.inspect}, COUNT(#{cl}_methods), #{cl}_methods };" - Out.puts "void #{frame.name}_startup (Ruby rself) "+line -end - -def handle_grin(line) - fields = line.split(/\s+/) - i = fields[0].to_i - c = $stack[-1].name - Out.print "template <class T> void grin_#{i}(GridInlet *in, int n, Pt<T> data);" - Out.print "template <class T> static void grinw_#{i} (GridInlet *in, int n, Pt<T> data);" - Out.print "static GridHandler grid_#{i}_hand;" - handle_decl "Ruby _#{i}_grid(...);" - $stack[-1].grins[i] = fields.dup -end - -def handle_end(line) - frame = $stack.pop - fields = line.split(/\s+/) - n = fields.length - if ClassDecl===frame then - #handle_classinfo if not frame.info - cl = frame.name - if fields[0]!="class" or - (n>1 and fields[1]!=cl) - then raise "end not matching #{where}" end - $stack.push frame - frame.attrs.each {|name,attr| - type,name,default = attr.to_a - #STDERR.puts "type=#{type} name=#{name} default=#{default}" - handle_def "void _0_#{name}_m (#{type} #{name}) { this->#{name}=#{name}; }" - } - frame.grins.each {|i,v| - k = case v[1] - when nil; '4' - when 'int32'; '1' - when 'int'; '2' - when 'float'; 'F' - else raise 'BORK BORK BORK' end - Out.print "static GridHandler #{cl}_grid_#{i}_hand = GRIN#{k}(#{cl},#{i});" - handle_def "Ruby _#{i}_grid(...) {"+ - "if (in.size()<=#{i}) in.resize(#{i}+1);"+ - "if (!in[#{i}]) in[#{i}]=new GridInlet((GridObject *)this,&#{cl}_grid_#{i}_hand);"+ - "return in[#{i}]->begin(argc,argv);}" - - } - $stack.pop - Out.puts "# #{$linenumber}" - end - if :ruby==frame then - if fields[0]!="ruby" then raise "expected \\end ruby" end - end - Out.puts "" -end - -def handle_startall(line) - $classes.each {|q| - Out.print "rb_funcall(EVAL(\"GridFlow\"),SI(fclass_install),2,PTR2FIX(&ci#{q.name})," - if q.supername then - Out.print "EVAL(\"GridFlow::#{q.supername}\"));" - else - Out.print "Qnil);" - end - } - Out.puts "" -end - -def handle_ruby(line) - Out.puts "" - $stack.push :ruby -end - -$rubymode=false -$linenumber=1 -loop{ - x = In.gets - break if not x - if /^\s*\\(\w+)\s*(.*)$/.match x then - begin - send("handle_#{$1}",$2) - rescue StandardError => e - STDERR.puts e.inspect - STDERR.puts "at line #{$linenumber}" - STDERR.puts e.backtrace - File.unlink ARGV[1] - exit 1 - end - else - if $stack[-1]==:ruby then - x.gsub!(/([\\\"])/) { "\\"+$1 } - x="\"#{x.chomp}\\n\"\n" - end - Out.puts x - end - $linenumber+=1 -} diff --git a/externals/gridflow/base/test.rb b/externals/gridflow/base/test.rb deleted file mode 100644 index 86c17af3..00000000 --- a/externals/gridflow/base/test.rb +++ /dev/null @@ -1,1074 +0,0 @@ -# $Id: test.rb,v 1.2 2006-03-15 04:37:28 matju Exp $ - -$:.delete_if {|x| x=='.' } -require "gridflow" - -include GridFlow -GridFlow.verbose=true - -$imdir = "./images" -$animdir = "./images/movies" -srand Time.new.to_i -$port = 4200+rand(100) - -def pressakey; puts "press return to continue."; readline; end - -FO = FObject # shortcut - -class Expect < FO - def praise(*a) - #raise(*a) - puts a - end - def expect(*v) - @count=0 - @v=v - @expecting=true - yield - @expecting=false - praise "wrong number of messages (#{@count}), expecting #{@v.inspect}" if @count!=@v.length - end - def _0_list(*l) - return if not @expecting - praise "wrong number of messages (#{@count})" if @count==@v.length - praise "got #{l.inspect} expecting #{@v.inspect}" if @v[@count]!=l - @count+=1 - end - def method_missing(s,*a) - praise "stray message: #{s}: #{a.inspect}" - end - install "expect", 1, 0 -end - -def cast value, type - case type - when :b, :u8,:uint8; value & 0xff - when :s,:i16,:int16; (value & 0x7fff) - (value & 0x8000) - when :i,:i32,:int32; value - when :l,:i64,:int64; value - when :f,:f32,:float32; value.to_f - when :d,:f64,:float64; value.to_f - when :r,:ruby; value - else raise "hell" - end -end - -def test_bitpacking - #!@#$ WRITE ME -end - -def test_numops - #!@#$ WRITE ME -end - -#def tnt() for nt in [:b,:s,:i,:l,:f,:d,:r] do yield end end -def _(o,s,i,d) o.connect(s,i,d) end -def chain(*a) - (a.length-1).times {|i| a[i].connect 0,a[i+1],a } - a[-1] -end - -def test_math -for nt in [:b,:s,:i,:l,:f,:d,:r] do - hm = "#".intern - #GridFlow.verbose = false - - (e=FO["#export_list"]) - (x=Expect.new) - _ e,0,x,0 - - x.expect([1,2,3,11,12,13,21,22,23]) { - e.send_in 0, 3,3,nt,hm,1,2,3,11,12,13,21,22,23 } - - (a=FO["fork"]) - (b=FO["@ +"]) - _ a,0,b,0 - _ a,1,b,1 - _ b,0,e,0 - x.expect([4]) { a.send_in 0, 2 } - - x.expect([2,3,5,7]) { e.send_in 0,:list,nt,2,3,5,7 } - a = FO["#fold + , seed {#{nt} # 0}"] - _ a,0,e,0 - x.expect([cast(420000,nt)]) { a.send_in 0,"10000 #{nt} # 42" } - - a = FO["# + {#{nt} 0 10}"] - _ a,0,e,0 - x.expect([1,12,4,18,16,42,64]) { - a.send_in 0,:list,nt, 1,2,4,8,16,32,64 } - - a = FO["# + {#{nt} 2 3 5}"] - b = FO["#fold + , seed {#{nt} # 0}"] - _ a,0,b,0 - _ b,0,e,0 - x.expect([cast(45332,nt)]) { a.send_in 0, 1000,nt,hm,42 } - - a = FO["@ + {#{nt} # 42}"] - _ a,0,e,0 - x.expect((43..169).to_a) { - a.send_in 0,:list,nt, *(1..127).to_a } - - x.expect([3,5,9,15]) { - a.send_in 1,:list,4,nt,hm, 2,3,5,7 - a.send_in 0,:list,4,nt,hm, 1,2,4,8 } - x.expect([11,12,14,18]) { - a.send_in 1, "list #{nt} # 10" - a.send_in 0,:list,nt, 1,2,4,8 } - -if nt!=:b and nt!=:f and nt!=:d - a=FO["# / {#{nt} # 3}" ]; _ a,0,e,0; x.expect([-2,-1,-1,-1,0,0,0,0,0,1,1,1,2]) { a.send_in(0,:list,nt, *(-6..6).to_a) } - a=FO["# div {#{nt} # 3}"]; _ a,0,e,0; x.expect([-2,-2,-2,-1,-1,-1,0,0,0,1,1,1,2]) { a.send_in(0, :list, nt, *(-6..6).to_a) } -end - - (a = FO["# ignore {#{nt} # 42}"]).connect 0,e,0 - x.expect((42..52).to_a) { a.send_in(0, :list, nt, *(42..52).to_a) } - - (a = FO["# put {#{nt} # 42}"]).connect 0,e,0 - x.expect([42]*13) { a.send_in(0, :list, nt, *(-6..6).to_a) } - -if nt!=:b - (a = FO["# abs-"]).connect 0,e,0 - x.expect([2,3,5,7]) { - a.send_in 0,:list,nt, -2,3,-5,7 } -end - - (a = FO["#fold *, seed {#{nt} # 1}"]).connect 0,e,0 - x.expect([210]) { a.send_in 0,:list,nt, 2,3,5,7 } - x.expect([128]) { a.send_in 0,:list,nt, 1,1,2,1,2,2,2,1,1,2,1,2,2 } - - (a = FO["#fold +, seed {#{nt} 0 0}"]).connect 0,e,0 - x.expect([18,23]) { a.send_in 0, 3,2,nt,hm,2,3,5,7,11,13 } - - (a = FO["#scan +, seed {#{nt} 0 0}"]).connect 0,e,0 - x.expect([2,3,7,10,18,23]) { a.send_in 0, 3,2,nt,hm,2,3,5,7,11,13 } - - (a = FO["#scan *, seed {#{nt} # 1}"]).connect 0,e,0 - x.expect([2,6,30,210]) { a.send_in 0,:list,nt, 2,3,5,7 } - x.expect([1,1,2,2,4,8,16,16,16,32,32,64,128]) { - a.send_in 0,:list,nt, 1,1,2,1,2,2,2,1,1,2,1,2,2 } - - (a = FO["#scan +, seed {#{nt} 0 0 0}"]).connect 0,e,0 - x.expect([1,2,3,5,7,9,12,15,18]) { - a.send_in 0,:list,3,3,nt,hm,*(1..9).to_a } - - (a = FO["#scan +, seed {#{nt} # 0}"]).connect 0,e,0 - x.expect([1,3,6, 4,9,15, 7,15,24]) { - a.send_in 0,:list,3,3,nt,hm,*(1..9).to_a } - - (a = FO["#outer +"]).connect 0,e,0 - x.expect([9,10,12,17,18,20,33,34,36]) { - a.send_in 1,:list,nt, 1,2,4 - a.send_in 0,:list,nt, 8,16,32 } - - x.expect((0...100).to_a) { - a.send_in 1,(0...10).to_a - a.send_in 0,(0...10).map{|i| 10*i }} - -if nt!=:b and nt!=:f and nt!=:d - (a = FO["#outer",:%,[nt,3,-3]]).connect 0,e,0 - x.expect([0,0,1,-2,2,-1,0,0,1,-2,2,-1,0,0]) { - a.send_in 0,:list,nt, -30,-20,-10,0,+10,+20,+30 } - - (a = FO["#outer","swap%".intern,[nt,3,-3]]).connect 0,e,0 - x.expect([-27,-3,-17,-3,-7,-3,0,0,3,7,3,17,3,27]) { - a.send_in 0,:list,nt, -30,-20,-10,0,+10,+20,+30 } -end - - (a = FO["#import {3}"]).connect 0,e,0; x.expect([2,3,5]) { [2,3,5].each {|v| a.send_in 0,:list,nt,hm,v }} - (a = FO["#import {3}"]).connect 0,e,0; x.expect([2,3,5]) { [2,3,5].each {|v| a.send_in 0,:list,nt,v }} - (a = FO["#redim {5}"]).connect 0,e,0; x.expect([2,3,5,2,3]) { a.send_in 0,:list,2,3,5 } - (a = FO["#redim {5}"]).connect 0,e,0; x.expect([0,0,0,0,0]) { a.send_in 0,:list } - (a = FO["#redim {0}"]).connect 0,e,0; x.expect([]) { a.send_in 0,:list,42,37,69 } - - (a = FO["#inner {2 2 #{nt} # 2 3 5 7}, seed {#{nt} # 0}"]).connect 0,e,0 - (i0 = FO["@redim {2 2}"]).connect 0,a,0 - x.expect([12,17,48,68]) { i0.send_in 0,:list,nt, 1,2,4,8 } - - (a = FO["#outer * {3 2 #{nt} # 1 2 3}"]).connect 0,e,0 - b = FO["#dim"] - c = FO["#export_list"] - a.connect 0,b,0 - y = Expect.new - b.connect 0,c,0 - c.connect 0,y,0 - - y.expect([2,3,2]) { - x.expect([1,2,3,1,2,3,10,20,30,10,20,30]) { - a.send_in 0,:list,nt, 1, 10 }} - - #pr=GridPrint.new - (b = FO["#redim {5 5}"]).connect 0,e,0 - (a = FO["#convolve, seed {#{nt} # 0}"]).connect 0,b,0 - (i0 = FO["#redim {5 5 1}"]).connect 0,a,0 - (i1 = FO["#redim {3 1}"]).connect 0,a,1 - i1.send_in 1, 3,3 - x.expect([5,6,5,4,4,4,6,7,6,4,3,3,6,7,5,4,2,3,6,6,5,4,3,4,5]) { - a.send_in 1,:list,3,3,nt,hm, 1,1,1,1,1,1,1,1,1 - i0.send_in 0,:list,nt, 1,1,1,0,0,0 } - - (a = FO["#convolve, seed {#{nt} # 0}"]).connect 0,e,0 - x.expect([1,3,6,4,0]) { - a.send_in 1, 1,2,nt,hm, 1,1 - a.send_in 0, 1,5,nt,hm, 0,1,2,4,0 } - - (a = FO["#import {4}"]).connect 0,e,0 - x.expect([2,3,5,7]) { - [2,3,5,7].each {|v| a.send_in 0,v }} - x.expect([1,2,3],[4,5,6],[7,8,9]) { - a.send_in 1, :list, 3 - a.send_in 0, :list, *(1..9).to_a} - - for o in ["#store"] - (a = FO[o]).connect 0,e,0 - a.send_in 1, 5, 4, nt, hm, 1,2,3,4,5 - x.expect([1,2,3,4,4,5,1,2,2,3,4,5]) { - a.send_in 0, 3,1, hm, 0,2,4 } - x.expect([1,2,3,4,5]*24) { a.send_in 0, 2,3,0,hm } - x.expect([1,2,3,4,5]*4) { a.send_in 0, 0,hm } - x.expect([1,2,3,4,5]*4) { a.send_in 0 } - x.expect([1,2,3,4]) { a.send_in 0,[0] } - a.send_in 1,:put_at,[0,0] - a.send_in 1,2,2,nt,hm,6,7,8,9 - x.expect([6,7,3,4, 8,9,2,3, 4,5,1,2, 3,4,5,1, 2,3,4,5]) { a.send_in 0 } - x.expect([6,7,3,4]) { a.send_in 0,[0] } - x.expect([8,9,2,3]) { a.send_in 0,[1] } - a.send_in 1,:put_at,[1,1] - a.send_in 1,2,2,nt,hm,11,13,17,19 - x.expect([6,7,3,4, 8,11,13,3, 4,17,19,2, 3,4,5,1, 2,3,4,5]) { a.send_in 0 } - end - - b = FO["#dim"] - c = FO["#export_list"] - a.connect 0,b,0 - y = Expect.new - b.connect 0,c,0 - c.connect 0,y,0 - -if nt!=:b and nt!=:f and nt!=:d and nt!=:l - (a = FO["#for {#{nt} # 0} {#{nt} # 10} {#{nt} # 1}"]).connect 0,e,0 - a.connect 0,b,0 - y.expect([10]) { - x.expect((0...10).to_a) { - a.send_in 0 } } - - (a = FO["#for {#{nt} # 0} {#{nt} # -10} {#{nt} # 1}"]).connect 0,e,0 - a.connect 0,b,0 - y.expect([0]) { x.expect([]) { a.send_in 0 } } - - (a = FO["#for {#{nt} # 0} {#{nt} # -10} {#{nt} # -1}"]).connect 0,e,0 - a.connect 0,b,0 - y.expect([10]) { x.expect([0,-1,-2,-3,-4,-5,-6,-7,-8,-9]) { a.send_in 0 } } - - (a = FO["#for {#{nt} 0} {#{nt} 10} {#{nt} 1}"]).connect 0,e,0 - a.connect 0,b,0 - y.expect([10,1]) { - x.expect((0...10).to_a) { - a.send_in 0 } } - - (a = FO["#for {#{nt} 2 3} {#{nt} 5 7} {#{nt} 1 1}"]).connect 0,e,0 - a.connect 0,b,0 - y.expect([3,4,2]) { - x.expect([2,3,2,4,2,5,2,6,3,3,3,4,3,5,3,6,4,3,4,4,4,5,4,6]) { - a.send_in 0 } } -end - - (a = FO["@complex_sq"]).connect 0,e,0 - x.expect([8,0]) { a.send_in 0, 2, 2 } - x.expect([0,9]) { a.send_in 0, 0, 3 } - - (a = FO["#rotate 3000 {1 2 5}"]).connect 0,e,0 - a.send_in 0, "5 5 # 1000 0 0 0 0 0" - -#if nt==:f or nt==:d -# (a = FO["@matrix_solve"]).connect 0,e,0 -# x.expect([1,0,0,0,1,0,0,0,1]) { a.send_in 0, 3, 3, nt, hm, 1,0,0,0,1,0,0,0,1 } -#end - GridFlow.gfpost "ending test for #{nt}" -end # for nt - - (a = FO["#pack 2"]).connect 0,e,0 - x.expect([42,0]) { a.send_in 0,42 } - x.expect([42,28]) { a.send_in 1,28 } - x.expect([1313,28]) { a.send_in 0,1313 } - - (a = FO["#pack 3"]).connect 0,e,0 - x.expect([42,0,0]) { a.send_in 0,42 } - x.expect([42,28,0]) { a.send_in 1,28 } - x.expect([42,28,-1]) { a.send_in 2,-1 } - - (a = FO["#pack 4"]).connect 0,e,0 - x.expect([42,0,0,0]) { a.send_in 0,42 } - x.expect([42,0,0,-42]) { a.send_in 3,-42 } - - (a = FO["#pack 5"]).connect 0,e,0 - x.expect([3.5,0,0,0]) { a.send_in 0,3.5 } - x.expect([3.5,0,0,-3.5]) { a.send_in 3,-3.5 } - - e = FO["#export_list"] - e.connect 0,x,0 - - a = FO["#import per_message"] - a.connect 0,e,0 - x.expect([1,2,3]) { a.send_in 0,1,2,3 } - x.expect([102,111,111]) { a.send_in 0,:symbol,:foo } - x.expect([ 70, 79, 79]) { a.send_in 0,:symbol,:FOO } - - a = FO["@join 1"] - a.connect 0,e,0 - a.send_in 1,2,2,nt,hm,11,13,17,19 - x.expect([2,3,11,13,5,7,17,19]) { a.send_in 0,2,2,nt,hm,2,3,5,7 } - -if nt!=:d - a.send_in 1, 5,1,nt,hm,42 - y.expect([5,4]) { - x.expect([2,3,5,42,7,11,13,42,17,19,23,42,29,31,37,42,41,43,47,42]) { - a.send_in 0, 5,3,nt,hm,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47 }} -end - a = FO["@join 0"] - a.connect 0,e,0 - a.send_in 1,2,2,nt,hm,11,13,17,19 - x.expect([2,3,5,7,11,13,17,19]) { a.send_in 0,2,2,nt,hm,2,3,5,7 } - - a = FO["@join 0 {2 2 2 #{nt} # 1 2 3}"] - a.connect 0,e,0 - a.connect 0,b,0 - y.expect([2,2,2]) { x.expect([1,2,3,1,2,3,1,2]) { a.send_in 0,0,2,2,nt,hm }} - - a = FO["#ravel"] - b = FO["#dim"] - be = FO["#export_list"] - bx = Expect.new - a.connect 0,e,0 - a.connect 0,b,0 - b.connect 0,be,0 - be.connect 0,bx,0 - bx.expect([9]) { - x.expect([1,2,3,2,4,6,3,6,9]) { - o = FO["#outer *"] - o.connect 0,a,0 - o.send_in 1,1,2,3 - o.send_in 0,1,2,3 - } - } - - a = FO["#grade"] - a.connect 0,e,0 - x.expect([0,2,4,6,8,9,7,5,3,1]) { a.send_in 0, 0,9,1,8,2,7,3,6,4,5 } - x.expect([0,9,1,8,2,7,3,6,4,5]) { a.send_in 0, 0,2,4,6,8,9,7,5,3,1 } - x.expect([7,6,5,4,3,2,1,0]) { a.send_in 0, 7,6,5,4,3,2,1,0 } - - a = FO["#grade"] - b = FO["#fold +"] - a.connect 0,b,0 - b.connect 0,e,0 - x.expect([100*99/2]) { a.send_in 0, (0...100).map { (rand*0x10000).to_i }} - x.expect([100*99/2]) { a.send_in 0, (0...100).map { (rand*0x10).to_i }} - x.expect([100*99/2]) { a.send_in 0, (0...100).map { 0 }} - - a = FO["#perspective"] - a.connect 0,e,0 - c = [] - 8.times {|v| - 3.times {|i| - c << (v[i] * 1000 - 500) + (if i==2 then 2000 else 0 end) - } - } - x.expect([ - -85,-85,85,-85,-85,85,85,85, - -51,-51,51,-51,-51,51,51,51]) { - a.send_in 0, 8,3,hm,*c } - -# regressiontests for past bugs - a = FO["#inner"] # that's it. -end - -def test_rtmetro - rt = FO["rtmetro 1000"] - pr = FO["rubyprint"] - rt.connect 0,pr,0 - GridFlow.post "trying to start the rtmetro" - rt.send_in 0,1 - $mainloop.timers.after(10.0) { - GridFlow.post "trying to stop the rtmetro (after 10 sec delay)" - rt.send_in 0,0 - } - $mainloop.loop -end - -def test_print - i = FO["#redim {3}"] - pr = FO["#print"] -# pr = GridFlow::RubyPrint.new - i.connect 0,pr,0 - i.send_in 0, 85, 170, 255 - i.send_in 1, 3, 3 - i.send_in 0, 1, 0, 0, 0 - i.send_in 1, 2, 2, 2 - i.send_in 0, 2, 3, 5, 7, 11, 13, 17, 19 -end - -class Barf < GridObject - def _0_rgrid_begin - raise "barf" - end - install_rgrid 0 - install "barf", 1, 0 -end - -def test_nonsense -# (a = FO["@! abs"]).connect 0,e,0 -# x.expect_error { -# a.send_in 1, 42,42 } - - a = FO["#import {3}"] - b = Barf.new - a.connect 0,b,0 - begin - a.send_in 0, 1, 2, 3 - rescue StandardError - nil - else - raise "Expected StandardError" - end - p b.inlet_dim(0) -end - -def test_store - a = FO["#in file #{$imdir}/teapot.png"] - b = FO["#store"] - c = FO["#out x11"] - a.connect 0,b,1 - a.send_in 0,"cast uint8" - a.send_in 0 - b.connect 0,c,0 - d = FO["#for {0 0} {256 256} {1 1}"] - e = FO["# ^ 85"] - d.connect 0,e,0 - e.connect 0,b,0 - f = FO["fps detailed"] - c.connect 0,f,0 - pr = FO["rubyprint"] - f.connect 0,pr,0 - GridFlow.verbose = false - 256.times {|t| - e.send_in 1,t - d.send_in 0 - } -end - -# generates recursive checkerboard pattern (munchies) in bluish colours. -class Munchies < FPatcher - @FOs = ["fork","fork","#for 0 64 1","#for 0 64 1","#for 2 5 1", - "#outer ^","#outer *"] - @wires = [-1,0,0,0, 0,0,1,0, 1,1,4,0, 4,0,6,1, - 1,0,3,0, 3,0,5,1, 0,0,2,0, 2,0,5,0, 5,0,6,0, 6,0,-1,0 ] - def initialize() super end - install "munchies",1,1 -end - -def test_munchies - m=Munchies.new - gout = FO["#out window"] - m.connect 0,gout,0 - m.send_in 0 - $mainloop.loop -end - -def test_image command - gin = FO["#in"] - gout = FO["#out window"] - gin.connect 0,gout,0 -# 31.times { - 3.times { - gin.send_in 0,"open #{command}" - gout.send_in 0,"timelog 1" - gin.send_in 0 - } - FO["#global"].send_in 0, "profiler_dump" - $mainloop.loop -end - -def test_ppm2 - gin = FO["#in"] - store = FO["#store"] - pa = FO["#convolve << + 0"] - pb = FO["# / 9"] - ra = FO["#redim {3 3}"] - gout = FO["#out window"] - gin.connect 0,store,1 - store.connect 0,pa,0 - pa.connect 0,pb,0 - pb.connect 0,gout,0 - ra.connect 0,pa,1 - ra.send_in 0,"0 0" - gout.send_in 0,"timelog 1" - gin.send_in 0,"open file #{$imdir}/teapot.png" -# gin.send_in 0,"open file #{$imdir}/g001.jpg" - gin.send_in 0 -# 40.times { store.send_in 0 } - loop { store.send_in 0 } - v4j = FO["#global"] - v4j.send_in 0,"profiler_dump" -# $mainloop.loop -end - -def test_foo - foo = FO["#for {0 0} {64 64} {1 1}"] - che = FO["#checkers"] - sca = FO["#scale_by {5 3}"] - out = FO["#out window"] - foo.connect 0,che,0 - che.connect 0,sca,0 - sca.connect 0,out,0 - foo.send_in 0 - $mainloop.loop -end - -def test_anim(*msgs) - GridFlow.verbose = false - gin = FO["#in"] - gout1 = FO["#out window"] - #gout1 = FO["@out quicktime file test.mov"] - #gout1.send_in 0, :codec, :jpeg - fps = FO["fps detailed"] - rpr = FO["rubyprint"] - gout1.connect 0,fps,0 - #fps.connect 0,rpr,0 -=begin - gout1 = FO["#downscale_by {3 2}"] - gout2 = FO["#rgb_to_greyscale"] - gout3 = FO["#out aalib X11 -height 60 -width 132"] - gout1.connect 0,gout2,0 - gout2.connect 0,gout3,0 -=end - - rpr = FO["rubyprint"] -# gin.connect 1,rpr,0 - - gin.connect 0,gout1,0 -=begin - layer=FO["@layer"] - gin.connect 0,layer,0 - layer.connect 0,gout1,0 - check=FO["@checkers"] - phor=FO["@for {0 0} {256 256} {1 1}"] - phor.connect 0,check,0 - check.connect 0,layer,1 - phor.send_in 0 -=end - -# scale = FO["@scale_by 3"] -# gin.connect 0,scale,0 -# scale.connect 0,gout1,0 - -# pr = FO["rubyprint time"]; gout.connect 0,pr,0 - msgs.each {|m| gin.send_in 0,m } - gin.send_in 0, "cast uint8" -# gout.send_in 0,"timelog 1" - d=Time.new - frames=2000 - frames.times {|n| - #GridFlow.post "%d", n - gin.send_in 0 - #gin.send_in 0, rand(1000) - } -# loop { gin.send_in 0 } -# metro = FO["rtmetro 80"] -# metro.connect 0,gin,0 -# metro.send_in 0,1 -# $mainloop.loop - - d=Time.new-d - printf "%d frames in %.6f seconds (avg %.6f ms, %.6f fps)\n", - frames, d, 1000*d/frames, frames/d -# global.send_in 0,"dfgdfgdkfjgl" - gout1.send_in 0, :close - global = FO["@global"] - global.send_in 0,"profiler_dump" -end - -class TestTCP < FO - attr_accessor :idle - def initialize - @idle = true - end - def _0_bang - # GridFlow.gfpost "tick" - # avoid recursion - $mainloop.timers.after(0) { - ($in_client.send_in 0; @idle=false) if @idle - } - end - install "tcptest",1,1 -end - -def test_tcp - if fork - # client (is receiving) - GridFlow.post_header = "[client] " - $in_client = in1 = FO["@in"] - out = FO["@out x11"] - in1.connect 0,out,0 - out.send_in 0,"timelog 1" - out.send_in 0,"autodraw 2" - GridFlow.post "test: waiting 1 second" - sleep 1 - p "HI" - #in1.send_in 0,"open grid tcp localhost #{$port}" - in1.send_in 0,"open grid tcp 127.0.0.1 #{$port}" - p "HI" - - test_tcp = TestTCP.new - - out.connect 0,test_tcp,0 - test_tcp.connect 0,in1,0 - - GridFlow.post "entering mainloop..." - $mainloop.loop - else - # server (is sending) - GridFlow.post_header = "[server] " - $in1_server = in1 = FO["@in"] - $in2_server = in2 = FO["@in"] - $out = out = FO["@out"] - toggle = 0 - in1.connect 0,out,0 - in2.connect 0,out,0 - in1.send_in 0,"open #{$imdir}/r001.jpg" - in2.send_in 0,"open #{$imdir}/b001.jpg" - out.send_in 0,"open grid tcpserver #{$port}" - out.send_in 0,"type uint8" - test_tcp = GridFlow::FO.new - def test_tcp._0_bang - # GridFlow.post "tick" - @toggle ||= 0 - # avoid recursion - $mainloop.timers.after(0.01) { - if $out.format.stream - if @toggle==0; $in1_server else $in2_server end.send_in 0 - @toggle ^= 1 - end - _0_bang - } - end - out.connect 0,test_tcp,0 - test_tcp.send_in 0 - GridFlow.post "entering mainloop..." - $mainloop.loop - end -end - -def test_layer - - gin = FO["@in png file ShaunaKennedy/atmosphere-bleu.png"] -# gin1 = FO["@in file #{$imdir}/r001.jpg"] -# gin = FO["@join 2 {240 320 1 # 128}"] -# gin1.connect 0,gin,0 - -# gfor = FO["@for {0 0} {120 160} {1 1}"] -# gfor = FO["@for {0 0} {240 320} {1 1}"] - gfor = FO["@for {0 0} {480 640} {1 1}"] - gche = FO["@checkers"] - - gove = FO["@layer"] -# gove = FO["@fold + {0 0 0 0}"] -# gout = FO["@print"] -# gove = FO["@inner2 * + 0 {3 4 # 1 0 0 0 0}"] -# gout = FO["@out sdl"] - gout = FO["@out x11"] - - gin.connect 0,gove,0 - gfor.connect 0,gche,0 - gche.connect 0,gove,1 - gove.connect 0,gout,0 - - gfor.send_in 0 - - fps = FO["fps detailed"] - pr = FO["rubyprint"] - gout.connect 0,fps,0 - fps.connect 0,pr,0 - - loop{gin.send_in 0} -# gin.send_in 0 -# gin1.send_in 0 - $mainloop.loop -end - -Images = [ - "png file opensource.png", - "#{$imdir}/ruby0216.jpg", - "#{$imdir}/g001.jpg", -# "#{$imdir}/teapot.tga", - "grid gzfile #{$imdir}/foo.grid.gz", - "grid gzfile #{$imdir}/foo2.grid.gz", -# "videodev /dev/video0", -] - -def test_formats_speed - gin = FO["@in"] - gout = FO["@out x11"] - gin.connect 0,gout,0 - GridFlow.verbose=false - t1=[] - Images.each {|command| - gin.send_in 0,"open #{command}" - t0 = Time.new - 10.times {gin.send_in 0} - t1 << (Time.new - t0) - sleep 1 - } - p t1 -end - -def test_formats - gin = FO["@in"] - gout = FO["@out window"] - gs = FO["@ + {int16 # 0}"] - gin.connect 0,gs,0 - gs.connect 0,gout,0 -# GridFlow.verbose=false - t1=[] - Images.each {|command| - GridFlow.post "SENDING open %s", command - gin.send_in 0,"open #{command}" - gin.send_in 0,"cast int16" - # test for load, rewind, load - 5.times {|x| gs.send_in 1, [:int16, '#'.intern, x*128]; gin.send_in 0} - # test for filehandle leak - #1000.times { gin.send_in 0,"open #{command}" } - sleep 1 - } - p t1 -end - -def test_rewind - gin = FO["@in videodev /dev/video1 noinit"] - gin.send_in 0, "transfer read" - gout = FO["@out ppm file /tmp/foo.ppm"] -# gout = FO["@out x11"] - gin.connect 0,gout,0 - loop { - gin.send_in 0 - gout.send_in 0, "rewind" - } -end - -def test_formats_write - # read files, store and save them, reload, compare, expect identical - a = FO["@in"] - b = FO["@out"]; a.connect 0,b,0 - c = FO["@ -"]; a.connect 0,c,1 - d = FO["@in"]; d.connect 0,c,0 - e = FO["@fold +"]; c.connect 0,e,0 - f = FO["@fold +"]; e.connect 0,f,0 - g = FO["@fold +"]; f.connect 0,g,0 - h = FO["@ / 15000"]; g.connect 0,h,0 - i = FO["@export_list"]; h.connect 0,i,0 - x = Expect.new; i.connect 0,x,0 - [ - ["ppm file", "#{$imdir}/g001.jpg"], - ["targa file", "#{$imdir}/teapot.tga"], - ["targa file", "#{$imdir}/tux.tga"], - ["jpeg file", "#{$imdir}/ruby0216.jpg"], - ["grid gzfile", "#{$imdir}/foo.grid.gz", "endian little"], - ["grid gzfile", "#{$imdir}/foo.grid.gz", "endian big"], - ].each {|type,file,*rest| - a.send_in 0, "open #{type} #{file}" - b.send_in 0, "open #{type} /tmp/patate" - rest.each {|r| b.send_in 0,r } - a.send_in 0 - b.send_in 0, "close" - raise "written file does not exist" if not File.exist? "/tmp/patate" - d.send_in 0, "open #{type} /tmp/patate" - x.expect([0]) { d.send_in 0 } -# d.send_in 0 - } -end - -def test_mpeg_write - a = FO["@in ppm file /opt/mex/r.ppm.cat"] - b = FO["@out x11"] - a.connect 0,b,0 - loop{a.send_in 0} -end - -def test_headerless - gout = FO["@out"] - gout.send_in 0, "open grid file #{$imdir}/hello.txt" - gout.send_in 0, "headerless" - gout.send_in 0, "type uint8" - gout.send_in 0, "104 101 108 108 111 32 119 111 114 108 100 33 10" - gout.send_in 0, "close" - gin = FO["@in"] - pr = FO["@print"] - gin.connect 0,pr,0 - gin.send_in 0, "open grid file #{$imdir}/hello.txt" - gin.send_in 0, "headerless 13" - gin.send_in 0, "type uint8" - gin.send_in 0 -end - - -def test_sound -# o2 = FO["@ * 359"] # @ 439.775 Hz -# o1 = FO["@for 0 44100 1"] # 1 sec @ 1.225 Hz ? - o1 = FO["@for 0 4500 1"] - o2 = FO["@ * 1600"] # @ 439.775 Hz - o3 = FO["@ sin* 255"] - o4 = FO["@ gamma 400"] - o5 = FO["@ << 7"] - out = FO["@out"] - o1.connect 0,o2,0 - o2.connect 0,o3,0 - o3.connect 0,o4,0 - o4.connect 0,o5,0 - o5.connect 0,out,0 -# out.send_in 0,"open raw file /dev/dsp" - out.send_in 0,"open grid file /dev/dsp" - out.send_in 0,"type int16" - x=0 - loop { - o4.send_in 1, x - o1.send_in 0 - x+=10 - } -end - -include Math -def test_polygon - o1 = FO["@for 0 5 1"] - o2 = FO["@ * 14400"] - o3 = FO["@outer + {0 9000}"] - o4 = FO["@ +"] - o5 = FO["@ cos* 112"] - o6 = FO["@ + {120 160}"] - poly = FO["@draw_polygon + {3 uint8 # 255}"] -if false - out1 = FO["@cast int32"] - out2 = FO["@solarize"] -# out1 = FO["@downscale_by 2 smoothly"] - out3 = FO["@out x11"] - out1.connect 0,out2,0 - out2.connect 0,out3,0 -else - out1 = FO["@out x11"] - fps = FO["fps detailed cpu"] - out1.connect 0,fps,0 - pr = FO["rubyprint"] - fps.connect 0,pr,0 -end - store = FO["@store"]; store.send_in 1, "240 320 3 uint8 # 0" -# store2 = FO["@store"] - store.connect 0,poly,0 - poly.connect 0,store,1 -# store2.connect 0,store,1 - o1.connect 0,o2,0 - o2.connect 0,o3,0 - o3.connect 0,o4,0 - o4.connect 0,o5,0 - o5.connect 0,o6,0 - o6.connect 0,poly,2 -# cast = FO["@cast int32"] -# poly.connect 0,cast,0 -# cast.connect 0,out1,0 - poly.connect 0,out1,0 - x=0 - GridFlow.verbose=false - task=proc { - o4.send_in 1, 5000*x - o5.send_in 1, 200+200*sin(x) - poly.send_in 1,:list,:uint8, *(0..2).map{|i| 4+4*cos(0.2*x+i*PI*2/3) } - o1.send_in 0 - store.send_in 0 -# store2.send_in 0 - x+=1 - if x<1000 then $mainloop.timers.after(0.0) {task[]} - else GridGlobal.new.send_in 0,"profiler_dump"; exit end - } - task[] - $mainloop.loop -end - -class FRoute2 < FO - def initialize(selector) - @selector = selector.to_s - end - def method_missing(sym,*a) - sym=sym.to_s - if sym =~ /^_0_(.*)/ - send_out((if $1==@selector then 0 else 1 end), $1.intern, *a) - else super end - end - install "route2", 1, 2 -end - -def test_aalib -# gin = FO["@in ppm file #{$imdir}/r001.jpg"] - gin = FO["@in ppm file #{$animdir}/b.jpg.cat"] - grey = FO["@rgb_to_greyscale"] - cont = FO["@ << 1"] - clip = FO["@ min 255"] - gout = FO["@out aalib X11"] - sto = FO["@store"] - op = FO["aa_fill_with_text {localhost 4242}"] - filt = FO["route2 grid"] - gin.connect 0,grey,0 - grey.connect 0,cont,0 - cont.connect 0,clip,0 - clip.connect 0,gout,0 - gout.connect 0,filt,0 - filt.connect 0,sto,1 - sto.connect 0,op,0 - op.connect 0,gout,0 - gout.send_in 0, :autodraw, 0 - GridFlow.verbose = false - task=proc{ - gin.send_in 0 - gout.send_in 0, :dump - sto.send_in 0 - gout.send_in 0, :draw - $mainloop.timers.after(0.1,&task) - } - task[] - $mainloop.loop -end - -def test_store2 - o = [ - FO["@for {0 0} {240 320} {1 1}"], - FO["@ / 2"], - FO["@ + 0"], - FO["@ + 0"], - FO["@store"], - FO["@out x11"]] - (0..4).each {|x| o[x].connect 0,o[x+1],0 } - q = FO["@in ppm file images/r001.jpg"] - q.connect 0,o[4],1 - q.send_in 0 - o[0].send_in 0 - $mainloop.loop -end - -def test_remap - rem = FO["@remap_image"] - rot = FO["@rotate 4000"] - rem.connect 1,rot,0 - rot.connect 0,rem,1 - gin = FO["@in ppm file #{$imdir}/teapot.png"] - gout = FO["@out x11"] - gin.connect 0,rem,0 - rem.connect 0,gout,0 - gin.send_in 0 - $mainloop.loop -end - -def test_asm - GridFlow.verbose=false - a = FO["@in ppm file images/r001.jpg"] - aa = FO["@cast uint8"] - b = FO["@store"] - d = FO["@store"] - a.connect 0,aa,0 - aa.connect 0,b,1 - aa.connect 0,d,1 - a.send_in 0 - c = FO["@ + {uint8 # 0}"] - t0 = Time.new; 1000.times {b.send_in 0}; t1 = Time.new-t0 - t1 *= 1 - b.connect 0,c,0 - stuff=proc{ - 3.times{ - t0 = Time.new; 1000.times {b.send_in 0}; t2 = Time.new-t0 - t2 *= 1 - GridFlow.post " %f %f %f", t1, t2, t2-t1 - } - } - puts "map:" - stuff[] - d.connect 0,c,1 # for zip - d.send_in 0 - puts "zip:" - stuff[] -end - -def test_metro - o1 = RtMetro.new(1000,:geiger) - o2 = RubyPrint.new(:time) - o1.connect 0,o2,0 - o1.send_in 0,1 - $mainloop.loop -end - -def test_outer - o = FO["@outer + {0}"] - o.send_in 0, 25, 240, 320, 3, "#".intern, 42 - g = FO["@global"] - g.send_in 0, :profiler_dump -end - -def test_jmax_to_pd filename - require "gridflow/extra/jmax_format.rb" - require "gridflow/extra/puredata_format.rb" - jfr = JMaxFileReader.new(File.open(filename),FO) - FO.broken_ok = true - my_patcher = jfr.parse -# my_patcher.subobjects.each {|x,| x.trigger if LoadBang===x } -# $mainloop.loop -# $p=my_patcher; ARGV.clear; load "/home/matju/bin/iruby" - filename = File.basename filename - filename[File.extname(filename)]=".pd" - filename[0,0]="pd_examples/" - pfw = PureDataFileWriter.new(filename) - pfw.write_patcher my_patcher - pfw.close -end - -def test_error - x = FO["@store"] - x.send_in 0 -end - -if ARGV[0] then - name = ARGV.shift - send "test_#{name}", *ARGV -# ARGV.each {|a| send "test_#{a}" } - exit 0 -end - -#test_polygon -#test_math -#test_munchies -#test_image "grid file #{$imdir}/foo.grid" -#test_image "grid gzfile #{$imdir}/foo.grid.gz" -#test_print -#test_nonsense -#test_ppm2 -#test_anim "open file #{$imdir}/g001.jpg"#,"loop 0" -#test_anim "open ppm file #{$animdir}/b.ppm.cat" -#test_anim "open jpeg file #{$imdir}/rgb.jpeg.cat" -#test_anim "open quicktime file BLAH" -#test_anim "open quicktime file #{$imdir}/rgb_uncompressed.mov" -#test_anim "open quicktime file #{$imdir}/test_mjpega.mov" -#test_anim "open ppm gzfile motion_tracking.ppm.cat.gz" -#test_anim "open videodev /dev/video","channel 1","size 480 640" -#test_anim "open videodev /dev/video1 noinit","transfer read" -#test_anim "open videodev /dev/video","channel 1","size 120 160" -#test_anim "open mpeg file /home/matju/net/Animations/washington_zoom_in.mpeg" -#test_anim "open quicktime file /home/matju/Shauna/part_1.mov" -#test_anim "open quicktime file #{$imdir}/gt.mov" -#test_anim "open quicktime file /home/matju/pics/domopers_hi.mov" -#test_anim "open quicktime file /home/matju/net/c.mov" -#test_formats -#test_tcp -#test_sound -#test_metro -#$mainloop.loop - -=begin -a = FO["@print"] -a.send_in 0, "3 3 #{nt} # 1 0 0 0" -a.send_in 0, "3 3 3 #{nt} # 1 2 3 4" -a.send_in 0, "base 16" -a.send_in 0, "3 3 3 #{nt} # 255 0 0 0" -=end |