blitz_array.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  1. #include "blitz.h"
  2. #include <stdarg.h>
  3. static void bbArrayFree( BBObject *o );
  4. static BBDebugScope debugScope={
  5. BBDEBUGSCOPE_USERTYPE,
  6. "Array",
  7. {
  8. {
  9. BBDEBUGDECL_END
  10. }
  11. }
  12. };
  13. BBClass_Array bbArrayClass={
  14. &bbObjectClass, //extends
  15. bbArrayFree, //free
  16. &debugScope, //DebugScope
  17. 0, //instance_size
  18. 0, //ctor
  19. 0, //dtor
  20. bbObjectToString,
  21. bbObjectCompare,
  22. bbObjectSendMessage,
  23. 0, //interface
  24. 0, //extra
  25. 0, //obj_size
  26. 0, //instance_count
  27. offsetof(BBArray, type), //fields_offset
  28. bbArraySort,
  29. bbArrayDimensions
  30. };
  31. BBArray bbEmptyArray={
  32. (BBClass*)&bbArrayClass, //clas
  33. //BBGC_MANYREFS, //refs
  34. "", //type
  35. 0, //dims
  36. 0, //size
  37. 0, //data_size
  38. 0, //data_start
  39. 0 //scales[0]
  40. };
  41. //***** Note: Only used by ref counting GC.
  42. static void bbArrayFree( BBObject *o ){
  43. if (bbCountInstances) {
  44. bbAtomicAdd((int*)&bbArrayClass.instance_count, -1);
  45. }
  46. }
  47. static int arrayCellSize(const char * type, unsigned short data_size, int * flags) {
  48. int size = 4;
  49. switch( type[0] ){
  50. case 'b':size=1;break;
  51. case 's':size=2;break;
  52. case 'l':size=8;break;
  53. case 'y':size=8;break;
  54. case 'd':size=8;break;
  55. case '*':size=sizeof(void*);break;
  56. case ':':size=sizeof(void*);*flags=0;break;
  57. case '$':size=sizeof(void*);*flags=0;break;
  58. case '[':size=sizeof(void*);*flags=0;break;
  59. case '(':size=sizeof(void*);break;
  60. case 'z':size=sizeof(BBSIZET);break;
  61. case 'v':size=sizeof(BBLONGINT);break;
  62. case 'e':size=sizeof(BBULONGINT);break;
  63. #ifdef _WIN32
  64. case 'w':size=sizeof(WPARAM);break;
  65. case 'x':size=sizeof(LPARAM);break;
  66. #endif
  67. #ifdef __x86_64__
  68. case 'h':size=sizeof(BBFLOAT64);break;
  69. case 'j':size=sizeof(BBINT128);break;
  70. case 'k':size=sizeof(BBFLOAT128);break;
  71. case 'm':size=sizeof(BBDOUBLE128);break;
  72. #endif
  73. case '@':size=data_size;*flags=0;break; // structs
  74. case '/':size=data_size;break; // enums
  75. }
  76. return size;
  77. }
  78. BBArray *bbAllocateArray( const char *type,int dims,int *lens, unsigned short data_size ){
  79. int k,*len;
  80. unsigned int size=4;
  81. int length=1;
  82. int flags=BBGC_ATOMIC;
  83. BBArray *arr;
  84. len=lens;
  85. for( k=0;k<dims;++k ){
  86. int n=*len++;
  87. if( n<=0 ) return &bbEmptyArray;
  88. length*=n;
  89. }
  90. size = arrayCellSize(type, data_size, &flags);
  91. int base_size = size;
  92. size*=length;
  93. arr=(BBArray*)bbGCAllocObject( BBARRAYSIZE(size,dims),(BBClass*)&bbArrayClass,flags );
  94. arr->type=type;
  95. arr->dims=dims;
  96. arr->size=size;
  97. arr->data_size = base_size;
  98. arr->data_start = (offsetof(BBArray, scales) + dims * sizeof(int)+0x0f) & ~0x0f; // 16-byte aligned
  99. len=lens;
  100. for( k=0;k<dims;++k ) arr->scales[k]=*len++;
  101. for( k=dims-2;k>=0;--k ) arr->scales[k]*=arr->scales[k+1];
  102. return arr;
  103. }
  104. static void *arrayInitializer( BBArray *arr ){
  105. switch( arr->type[0] ){
  106. case ':':return &bbNullObject;
  107. case '$':return &bbEmptyString;
  108. case '[':return &bbEmptyArray;
  109. case '(':return &brl_blitz_NullFunctionError;
  110. }
  111. return 0;
  112. }
  113. static void initializeArray( BBArray *arr, BBArrayStructInit structInit ){
  114. void *init,**p;
  115. if( !arr->size ) return;
  116. init=arrayInitializer( arr );
  117. p=(void**)(BBARRAYDATA( arr,arr->dims ));
  118. if( init ){
  119. int k;
  120. for( k=arr->scales[0];k>0;--k ) *p++=init;
  121. }else{
  122. memset( p,0,arr->size );
  123. if (structInit) {
  124. int k;
  125. char * s = (char*)p;
  126. for( k=arr->scales[0];k>0;--k ) {
  127. structInit(s);
  128. s += arr->data_size;
  129. }
  130. }
  131. }
  132. }
  133. BBArray *bbArrayNew( const char *type,int dims,... ){
  134. int lens[256];
  135. va_list lengths;
  136. va_start(lengths, dims);
  137. int i;
  138. for (i = 0; i < dims; i++) {
  139. lens[i] = va_arg(lengths, int);
  140. }
  141. va_end(lengths);
  142. BBArray *arr=bbAllocateArray( type,dims, lens, 0 );
  143. initializeArray( arr, 0 );
  144. return arr;
  145. }
  146. BBArray *bbArrayNewStruct( const char *type, unsigned short data_size, BBArrayStructInit init, int dims, ... ){
  147. int lens[256];
  148. va_list lengths;
  149. va_start(lengths, dims);
  150. int i;
  151. for (i = 0; i < dims; i++) {
  152. lens[i] = va_arg(lengths, int);
  153. }
  154. va_end(lengths);
  155. BBArray *arr=bbAllocateArray( type,dims, lens, data_size );
  156. initializeArray( arr, init );
  157. return arr;
  158. }
  159. BBArray *bbArrayNewEx( const char *type,int dims,int *lens ){
  160. BBArray *arr=bbAllocateArray( type,dims,lens,0 );
  161. initializeArray( arr, 0 );
  162. return arr;
  163. }
  164. BBArray *bbArrayNew1D( const char *type,int length ){
  165. BBArray *arr=bbAllocateArray( type,1,&length, 0 );
  166. initializeArray( arr, 0 );
  167. return arr;
  168. }
  169. BBArray *bbArrayNew1DNoInit( const char *type,int length ){
  170. return bbAllocateArray( type,1,&length, 0 );
  171. }
  172. BBArray *bbArrayNew1DStruct( const char *type,int length, unsigned short data_size, BBArrayStructInit init ){
  173. BBArray *arr=bbAllocateArray( type,1,&length, data_size );
  174. initializeArray( arr, init );
  175. return arr;
  176. }
  177. BBArray *bbArraySlice( const char *type,BBArray *inarr,int beg,int end ){
  178. return bbArraySliceStruct(type, inarr, beg, end, 0, 0);
  179. }
  180. BBArray *bbArraySliceStruct( const char *type,BBArray *inarr,int beg,int end, unsigned short data_size, BBArrayStructInit structInit ){
  181. char *p;
  182. void *init;
  183. BBArray *arr;
  184. int n,k,el_size;
  185. int length=end-beg;
  186. if( length<=0 ) return &bbEmptyArray;
  187. arr=bbAllocateArray( type,1,&length,data_size );
  188. el_size=arr->size/length;
  189. init=arrayInitializer( arr );
  190. p=(char*)BBARRAYDATA( arr,1 );
  191. n=-beg;
  192. if( n>0 ){
  193. if( beg+n>end ) n=end-beg;
  194. if( init ){
  195. void **dst=(void**)p;
  196. for( k=0;k<n;++k ) *dst++=init;
  197. p=(char*)dst;
  198. }else{
  199. memset( p,0,n*el_size );
  200. if (structInit) {
  201. char * s = (char*)p;
  202. for( k=0;k<n;++k ) {
  203. structInit(s);
  204. s += arr->data_size;
  205. }
  206. }
  207. p+=n*el_size;
  208. }
  209. beg+=n;
  210. if( beg==end ) return arr;
  211. }
  212. n=inarr->scales[0]-beg;
  213. if( n>0 ){
  214. if( beg+n>end ) n=end-beg;
  215. memcpy( p,(char*)BBARRAYDATA(inarr,inarr->dims)+beg*el_size,n*el_size );
  216. p+=n*el_size;
  217. beg+=n;
  218. if( beg==end ) return arr;
  219. }
  220. n=end-beg;
  221. if( n>0 ){
  222. if( init ){
  223. void **dst=(void**)p;
  224. for( k=0;k<n;++k ) *dst++=init;
  225. }else{
  226. memset( p,0,n*el_size );
  227. if (structInit) {
  228. char * s = (char*)p;
  229. for( k=0;k<n;++k ) {
  230. structInit(s);
  231. s += arr->data_size;
  232. }
  233. }
  234. }
  235. }
  236. return arr;
  237. }
  238. void bbArrayCopy(BBArray * srcArr, int srcPos, BBArray * dstArr, int dstPos, int length) {
  239. if (srcPos < 0 || dstPos < 0 || length <= 0) {
  240. return;
  241. }
  242. if (strcmp(srcArr->type, dstArr->type)) {
  243. brl_blitz_RuntimeError(bbStringFromCString("Incompatible array element types for copy"));
  244. }
  245. if (srcPos + length > srcArr->scales[0]) {
  246. brl_blitz_ArrayBoundsError();
  247. }
  248. if (dstPos + length > dstArr->scales[0]) {
  249. brl_blitz_ArrayBoundsError();
  250. }
  251. int flags = 0;
  252. int size = arrayCellSize(srcArr->type, srcArr->data_size, &flags);
  253. char * src = (char*)BBARRAYDATA(srcArr, 1) + srcPos * size;
  254. char * dst = (char*)BBARRAYDATA(dstArr, 1) + dstPos * size;
  255. memmove(dst, src, length * size);
  256. }
  257. BBArray *bbArrayConcat( const char *type,BBArray *x,BBArray *y ){
  258. BBArray *arr;
  259. char *data;
  260. int length=x->scales[0]+y->scales[0];
  261. if( length<=0 ) return &bbEmptyArray;
  262. int data_size = x->data_size != 0 ? x->data_size : y->data_size;
  263. // both arrays are empty?
  264. if (data_size == 0) return &bbEmptyArray;
  265. if (x->data_size > 0 && y->data_size > 0 && x->data_size != y->data_size) {
  266. brl_blitz_RuntimeError(bbStringFromCString("Incompatible array element types for concatenation"));
  267. }
  268. arr=bbAllocateArray( type,1,&length, data_size );
  269. data=(char*)BBARRAYDATA( arr,1 );
  270. memcpy( data,BBARRAYDATA( x,1 ),x->size );
  271. memcpy( data+x->size,BBARRAYDATA( y,1 ),y->size );
  272. return arr;
  273. }
  274. BBArray *bbArrayFromData( const char *type,int length,void *data ){
  275. return bbArrayFromDataSize(type, length, data, 0);
  276. }
  277. BBArray *bbArrayFromDataSize( const char *type,int length,void *data, unsigned short data_size ){
  278. BBArray *arr;
  279. if( length<=0 ) return &bbEmptyArray;
  280. arr=bbAllocateArray( type,1,&length,data_size );
  281. memcpy( BBARRAYDATA( arr,1 ),data,arr->size );
  282. return arr;
  283. }
  284. BBArray *bbArrayFromDataStruct( const char *type,int length,void *data, unsigned short data_size ){
  285. BBArray *arr;
  286. if( length<=0 ) return &bbEmptyArray;
  287. arr=bbAllocateArray( type,1,&length, data_size );
  288. memcpy( BBARRAYDATA( arr,1 ),data,arr->size );
  289. return arr;
  290. }
  291. BBArray *bbArrayDimensions( BBArray *arr ){
  292. int *p,i,n;
  293. BBArray *dims;
  294. if( !arr->scales[0] ) return &bbEmptyArray;
  295. n=arr->dims;
  296. dims=bbArrayNew1D( "i",n );
  297. p=(int*)BBARRAYDATA( dims,1 );
  298. for( i=0;i<n-1;++i ){
  299. p[i]=arr->scales[i]/arr->scales[i+1];
  300. }
  301. p[i]=arr->scales[i];
  302. return dims;
  303. }
  304. void * bbArrayIndex( BBArray * arr, int offset, int index) {
  305. if (index < 0 || index >= arr->scales[0]) brl_blitz_ArrayBoundsError();
  306. return BBARRAYDATA(arr, offset);
  307. }
  308. BBArray *bbArrayCastFromObject( BBObject *o,const char *type ){
  309. BBArray *arr=(BBArray*)o;
  310. if( arr==&bbEmptyArray ) return arr;
  311. if( arr->clas!=(BBClass*)&bbArrayClass ) return &bbEmptyArray;
  312. if( arr->type[0]==':' && type[0]==':' ) return arr;
  313. if( strcmp( arr->type,type ) ) return &bbEmptyArray;
  314. return arr;
  315. }
  316. #define SWAP(X,Y) {t=*(X);*(X)=*(Y);*(Y)=t;}
  317. #define QSORTARRAY( TYPE,IDENT )\
  318. static void IDENT( TYPE *lo,TYPE *hi ){\
  319. TYPE t;\
  320. TYPE *i;\
  321. TYPE *x;\
  322. TYPE *y;\
  323. if( hi<=lo ) return;\
  324. if( lo+1==hi ){\
  325. if( LESSTHAN(hi,lo) ) SWAP(lo,hi);\
  326. return;\
  327. }\
  328. i=(hi-lo)/2+lo;\
  329. if( LESSTHAN(i,lo) ) SWAP(i,lo);\
  330. if( LESSTHAN(hi,i) ){\
  331. SWAP(i,hi);\
  332. if( LESSTHAN(i,lo) ) SWAP(i,lo);\
  333. }\
  334. x=lo+1;\
  335. y=hi-1;\
  336. do{\
  337. while( LESSTHAN(x,i) ) ++x;\
  338. while( LESSTHAN(i,y) ) --y;\
  339. if( x>y ) break;\
  340. if( x<y ){\
  341. SWAP(x,y);\
  342. if( i==x ) i=y;\
  343. else if( i==y ) i=x;\
  344. }\
  345. ++x;\
  346. --y;\
  347. }while( x<=y );\
  348. IDENT(lo,y);\
  349. IDENT(x,hi);\
  350. }
  351. #undef LESSTHAN
  352. #define LESSTHAN(X,Y) (*(X)<*(Y))
  353. QSORTARRAY( unsigned char,_qsort_b )
  354. QSORTARRAY( unsigned short,_qsort_s )
  355. QSORTARRAY( int,qsort_i )
  356. QSORTARRAY( unsigned int,qsort_u )
  357. QSORTARRAY( BBInt64,qsort_l )
  358. QSORTARRAY( BBUInt64,qsort_y )
  359. QSORTARRAY( float,qsort_f )
  360. QSORTARRAY( double,qsort_d )
  361. QSORTARRAY( BBSIZET,qsort_z )
  362. QSORTARRAY( BBLONGINT,qsort_v )
  363. QSORTARRAY( BBULONGINT,qsort_e )
  364. #ifdef _WIN32
  365. QSORTARRAY( WPARAM,qsort_w )
  366. QSORTARRAY( LPARAM,qsort_x )
  367. #endif
  368. #undef LESSTHAN
  369. #define LESSTHAN(X,Y) ((*X)->clas->Compare(*(X),*(Y))<0)
  370. QSORTARRAY( BBObject*,qsort_obj )
  371. #undef LESSTHAN
  372. #define LESSTHAN(X,Y) (*(X)>*(Y))
  373. QSORTARRAY( unsigned char,qsort_b_d )
  374. QSORTARRAY( unsigned short,qsort_s_d )
  375. QSORTARRAY( int,qsort_i_d )
  376. QSORTARRAY( unsigned int,qsort_u_d )
  377. QSORTARRAY( BBInt64,qsort_l_d )
  378. QSORTARRAY( BBUInt64,qsort_y_d )
  379. QSORTARRAY( float,qsort_f_d )
  380. QSORTARRAY( double,qsort_d_d )
  381. QSORTARRAY( BBSIZET,qsort_z_d )
  382. QSORTARRAY( BBLONGINT,qsort_v_d )
  383. QSORTARRAY( BBULONGINT,qsort_e_d )
  384. #ifdef _WIN32
  385. QSORTARRAY( WPARAM,qsort_w_d )
  386. QSORTARRAY( LPARAM,qsort_x_d )
  387. #endif
  388. #undef LESSTHAN
  389. #define LESSTHAN(X,Y) ((*X)->clas->Compare(*(X),*(Y))>0)
  390. QSORTARRAY( BBObject*,qsort_obj_d )
  391. void bbArraySort( BBArray *arr,int ascending ){
  392. int n;
  393. void *p;
  394. n=arr->scales[0]-1;
  395. if( n<=0 ) return;
  396. p=BBARRAYDATA(arr,arr->dims);
  397. if( ascending ){
  398. switch( arr->type[0] ){
  399. case 'b':_qsort_b( (unsigned char*)p,(unsigned char*)p+n );break;
  400. case 's':_qsort_s( (unsigned short*)p,(unsigned short*)p+n );break;
  401. case 'i':qsort_i( (int*)p,(int*)p+n );break;
  402. case 'u':qsort_u( (unsigned int*)p,(unsigned int*)p+n );break;
  403. case 'l':qsort_l( (BBInt64*)p,(BBInt64*)p+n );break;
  404. case 'y':qsort_y( (BBUInt64*)p,(BBUInt64*)p+n );break;
  405. case 'f':qsort_f( (float*)p,(float*)p+n );break;
  406. case 'd':qsort_d( (double*)p,(double*)p+n );break;
  407. case '$':case ':':qsort_obj( (BBObject**)p,(BBObject**)p+n );break;
  408. case 'z':qsort_z( (BBSIZET*)p,(BBSIZET*)p+n );break;
  409. case 'v':qsort_v( (BBLONGINT*)p,(BBLONGINT*)p+n );break;
  410. case 'e':qsort_e( (BBULONGINT*)p,(BBULONGINT*)p+n );break;
  411. #ifdef _WIN32
  412. case 'w':qsort_w( (WPARAM*)p,(WPARAM*)p+n );break;
  413. case 'x':qsort_x( (LPARAM*)p,(LPARAM*)p+n );break;
  414. #endif
  415. }
  416. }else{
  417. switch( arr->type[0] ){
  418. case 'b':qsort_b_d( (unsigned char*)p,(unsigned char*)p+n );break;
  419. case 's':qsort_s_d( (unsigned short*)p,(unsigned short*)p+n );break;
  420. case 'i':qsort_i_d( (int*)p,(int*)p+n );break;
  421. case 'u':qsort_u_d( (unsigned int*)p,(unsigned int*)p+n );break;
  422. case 'l':qsort_l_d( (BBInt64*)p,(BBInt64*)p+n );break;
  423. case 'y':qsort_y_d( (BBUInt64*)p,(BBUInt64*)p+n );break;
  424. case 'f':qsort_f_d( (float*)p,(float*)p+n );break;
  425. case 'd':qsort_d_d( (double*)p,(double*)p+n );break;
  426. case '$':case ':':qsort_obj_d( (BBObject**)p,(BBObject**)p+n );break;
  427. case 'z':qsort_z_d( (BBSIZET*)p,(BBSIZET*)p+n );break;
  428. case 'v':qsort_v_d( (BBLONGINT*)p,(BBLONGINT*)p+n );break;
  429. case 'e':qsort_e_d( (BBULONGINT*)p,(BBULONGINT*)p+n );break;
  430. #ifdef _WIN32
  431. case 'w':qsort_w_d( (WPARAM*)p,(WPARAM*)p+n );break;
  432. case 'x':qsort_x_d( (LPARAM*)p,(LPARAM*)p+n );break;
  433. #endif
  434. }
  435. }
  436. }
  437. int bbObjectIsEmptyArray(BBObject * o) {
  438. return (BBArray*)o == &bbEmptyArray;
  439. }