PageRenderTime 103ms CodeModel.GetById 32ms RepoModel.GetById 1ms app.codeStats 1ms

/src/opers.c

https://bitbucket.org/dimpase/libgap
C | 6369 lines | 4510 code | 875 blank | 984 comment | 841 complexity | dc13b5f83f338baa78a683c9af96f25f MD5 | raw file
Possible License(s): GPL-3.0

Large files files are truncated, but you can click here to view the full file

  1. /****************************************************************************
  2. **
  3. *W opers.c GAP source Frank Celler
  4. *W & Martin Schönert
  5. **
  6. **
  7. *Y Copyright (C) 1996, Lehrstuhl D für Mathematik, RWTH Aachen, Germany
  8. *Y (C) 1998 School Math and Comp. Sci., University of St Andrews, Scotland
  9. *Y Copyright (C) 2002 The GAP Group
  10. **
  11. ** This file contains the functions of the filters, operations, attributes,
  12. ** and properties package.
  13. */
  14. #include <assert.h>
  15. #include "system.h" /* Ints, UInts */
  16. #include "gasman.h" /* garbage collector */
  17. #include "objects.h" /* objects */
  18. #include "scanner.h" /* scanner */
  19. #include "gvars.h" /* global variables */
  20. #include "gap.h" /* error handling, initialisation */
  21. #include "calls.h" /* generic call mechanism */
  22. #include "opers.h" /* generic operations */
  23. #include "ariths.h" /* basic arithmetic */
  24. #include "lists.h" /* generic lists */
  25. #include "bool.h" /* booleans */
  26. #include "plist.h" /* plain lists */
  27. #include "blister.h" /* boolean lists */
  28. #include "string.h" /* strings */
  29. #include "range.h" /* ranges */
  30. #include "records.h" /* generic records */
  31. #include "precord.h" /* plain records */
  32. #include "saveload.h" /* saving and loading */
  33. #include "listfunc.h"
  34. #include "integer.h"
  35. /****************************************************************************
  36. **
  37. *V TRY_NEXT_METHOD . . . . . . . . . . . . . . . . . `TRY_NEXT_MESSAGE' flag
  38. */
  39. Obj TRY_NEXT_METHOD;
  40. #define CACHE_SIZE 5
  41. /****************************************************************************
  42. **
  43. *F * * * * * * * * * * * * internal flags functions * * * * * * * * * * * * *
  44. */
  45. /****************************************************************************
  46. **
  47. *F PrintFlags( <flags> ) . . . . . . . . . . . . . . . . print a flags list
  48. */
  49. void PrintFlags (
  50. Obj flags )
  51. {
  52. Pr( "<flag list>", 0L, 0L );
  53. }
  54. /****************************************************************************
  55. **
  56. *F TypeFlags( <flags> ) . . . . . . . . . . . . . . . type of a flags list
  57. */
  58. Obj TYPE_FLAGS;
  59. Obj TypeFlags (
  60. Obj flags )
  61. {
  62. return TYPE_FLAGS;
  63. }
  64. /****************************************************************************
  65. **
  66. *F SaveFlags( <flags> ) . . . . . . . . . . . . . . . . . save a flags list
  67. **
  68. */
  69. void SaveFlags (
  70. Obj flags )
  71. {
  72. UInt i, len, *ptr;
  73. SaveSubObj(TRUES_FLAGS(flags));
  74. SaveSubObj(HASH_FLAGS(flags));
  75. SaveSubObj(ADDR_OBJ(flags)[2]); /* length, as an object */
  76. SaveSubObj(AND_CACHE_FLAGS(flags));
  77. len = NRB_FLAGS(flags);
  78. ptr = BLOCKS_FLAGS(flags);
  79. for ( i = 1; i <= len; i++ )
  80. SaveUInt(*ptr++);
  81. return;
  82. }
  83. /****************************************************************************
  84. **
  85. *F LoadFlags( <flags> ) . . . . . . . . . . . . . . . . . load a flags list
  86. **
  87. */
  88. void LoadFlags(
  89. Obj flags )
  90. {
  91. Obj sub;
  92. UInt i, len, *ptr;
  93. sub = LoadSubObj(); SET_TRUES_FLAGS( flags, sub );
  94. sub = LoadSubObj(); SET_HASH_FLAGS( flags, sub );
  95. ADDR_OBJ(flags)[2] = LoadSubObj(); /* length, as an object */
  96. sub = LoadSubObj(); SET_AND_CACHE_FLAGS( flags, sub );
  97. len = NRB_FLAGS(flags);
  98. ptr = BLOCKS_FLAGS(flags);
  99. for ( i = 1; i <= len; i++ )
  100. *ptr++ = LoadUInt();
  101. return;
  102. }
  103. /****************************************************************************
  104. **
  105. *F * * * * * * * * * * * * * GAP flags functions * * * * * * * * * * * * * *
  106. */
  107. /****************************************************************************
  108. **
  109. *F FuncLEN_FLAGS( <self>, <flags> ) . . . . . . . . length of a flags list
  110. **
  111. */
  112. Obj FuncLEN_FLAGS (
  113. Obj self,
  114. Obj flags )
  115. {
  116. /* do some trivial checks */
  117. while ( TNUM_OBJ(flags) != T_FLAGS ) {
  118. flags = ErrorReturnObj( "<flags> must be a flags list (not a %s)",
  119. (Int)TNAM_OBJ(flags), 0L,
  120. "you can replace <flags> via 'return <flags>;'" );
  121. }
  122. return INTOBJ_INT( LEN_FLAGS(flags) );
  123. }
  124. /****************************************************************************
  125. **
  126. *F FuncELM_FLAGS( <self>, <flags>, <pos> ) . . . . . element of a flags list
  127. */
  128. Obj FuncELM_FLAGS (
  129. Obj self,
  130. Obj flags,
  131. Obj pos )
  132. {
  133. /* do some trivial checks */
  134. while ( TNUM_OBJ(flags) != T_FLAGS ) {
  135. flags = ErrorReturnObj( "<flags> must be a flags list (not a %s)",
  136. (Int)TNAM_OBJ(flags), 0L,
  137. "you can replace <flags> via 'return <flags>;'" );
  138. }
  139. /* select and return the element */
  140. return ELM_FLAGS( flags, INT_INTOBJ(pos) );
  141. }
  142. /****************************************************************************
  143. **
  144. *F FuncHASH_FLAGS( <self>, <flags> ) . . . . . . hash value of a flags list
  145. **
  146. ** The hash value is independent of the size of a machine word (32 or 64).
  147. **
  148. ** The rather peculiar cast in the definition of HASH_FLAGS_SIZE is needed
  149. ** to get the calculation to work right on the alpha.
  150. **
  151. *T The 64 bit version depends on the byte order -- it assumes that
  152. ** the lower addressed half-word is the less significant
  153. **
  154. */
  155. #define HASH_FLAGS_SIZE (Int4)67108879L
  156. Obj FuncHASH_FLAGS (
  157. Obj self,
  158. Obj flags )
  159. {
  160. Int4 hash;
  161. Int4 x;
  162. Int len;
  163. UInt4 * ptr;
  164. Int i;
  165. /* do some trivial checks */
  166. while ( TNUM_OBJ(flags) != T_FLAGS ) {
  167. flags = ErrorReturnObj( "<flags> must be a flags list (not a %s)",
  168. (Int)TNAM_OBJ(flags), 0L,
  169. "you can replace <flags> via 'return <flags>;'" );
  170. }
  171. if ( HASH_FLAGS(flags) != 0 ) {
  172. return HASH_FLAGS(flags);
  173. }
  174. /* do the real work*/
  175. #ifndef SYS_IS_64_BIT
  176. /* 32 bit case -- this is the "defining" case, others are
  177. adjusted to comply with this */
  178. len = NRB_FLAGS(flags);
  179. ptr = (UInt4 *)BLOCKS_FLAGS(flags);
  180. hash = 0;
  181. x = 1;
  182. for ( i = len; i >= 1; i-- ) {
  183. hash = (hash + (*ptr % HASH_FLAGS_SIZE) * x) % HASH_FLAGS_SIZE;
  184. x = ((8*sizeof(UInt4)-1) * x) % HASH_FLAGS_SIZE;
  185. ptr++;
  186. }
  187. #else
  188. #ifdef WORDS_BIGENDIAN
  189. /* This is the hardest case */
  190. len = NRB_FLAGS(flags);
  191. ptr = (UInt4 *)BLOCKS_FLAGS(flags);
  192. hash = 0;
  193. x = 1;
  194. for ( i = len; i >= 1; i-- ) {
  195. /* least significant 32 bits first */
  196. hash = (hash + (ptr[1] % HASH_FLAGS_SIZE) * x) % HASH_FLAGS_SIZE;
  197. x = ((8*sizeof(UInt4)-1) * x) % HASH_FLAGS_SIZE;
  198. /* now the more significant */
  199. hash = (hash + (*ptr % HASH_FLAGS_SIZE) * x) % HASH_FLAGS_SIZE;
  200. x = ((8*sizeof(UInt4)-1) * x) % HASH_FLAGS_SIZE;
  201. ptr+= 2;
  202. }
  203. #else
  204. /* and the middle case -- for DEC alpha, the 32 bit chunks are
  205. in the right order, and we merely have to be sure to process them as
  206. 32 bit chunks */
  207. len = NRB_FLAGS(flags)*(sizeof(UInt)/sizeof(UInt4));
  208. ptr = (UInt4 *)BLOCKS_FLAGS(flags);
  209. hash = 0;
  210. x = 1;
  211. for ( i = len; i >= 1; i-- ) {
  212. hash = (hash + (*ptr % HASH_FLAGS_SIZE) * x) % HASH_FLAGS_SIZE;
  213. x = ((8*sizeof(UInt4)-1) * x) % HASH_FLAGS_SIZE;
  214. ptr++;
  215. }
  216. #endif
  217. #endif
  218. SET_HASH_FLAGS( flags, INTOBJ_INT((UInt)hash+1) );
  219. CHANGED_BAG(flags);
  220. return HASH_FLAGS(flags);
  221. }
  222. /****************************************************************************
  223. **
  224. *F FuncTRUES_FLAGS( <self>, <flags> ) . . . true positions of a flags list
  225. **
  226. ** see 'FuncPositionsTruesBlist' in "blister.c" for information.
  227. */
  228. Obj FuncTRUES_FLAGS (
  229. Obj self,
  230. Obj flags )
  231. {
  232. Obj sub; /* handle of the result */
  233. Int len; /* logical length of the list */
  234. UInt * ptr; /* pointer to flags */
  235. UInt nrb; /* number of blocks in flags */
  236. UInt m; /* number of bits in a block */
  237. UInt n; /* number of bits in flags */
  238. UInt nn;
  239. UInt i; /* loop variable */
  240. /* get and check the first argument */
  241. while ( TNUM_OBJ(flags) != T_FLAGS ) {
  242. flags = ErrorReturnObj( "<flags> must be a flags list (not a %s)",
  243. (Int)TNAM_OBJ(flags), 0L,
  244. "you can replace <flags> via 'return <flags>;'" );
  245. }
  246. if ( TRUES_FLAGS(flags) != 0 ) {
  247. return TRUES_FLAGS(flags);
  248. }
  249. /* compute the number of 'true'-s just as in 'FuncSizeBlist' */
  250. nrb = NRB_FLAGS(flags);
  251. ptr = (UInt*)BLOCKS_FLAGS(flags);
  252. n = 0;
  253. for ( i = 1; i <= nrb; i++ ) {
  254. m = *ptr++;
  255. COUNT_TRUES_BLOCK(m);
  256. n += m;
  257. }
  258. /* make the sublist (we now know its size exactely) */
  259. sub = NEW_PLIST( T_PLIST+IMMUTABLE, n );
  260. SET_LEN_PLIST( sub, n );
  261. /* loop over the boolean list and stuff elements into <sub> */
  262. len = LEN_FLAGS( flags );
  263. nn = 1;
  264. for ( i = 1; nn <= n && i <= len; i++ ) {
  265. if ( ELM_FLAGS( flags, i ) == True ) {
  266. SET_ELM_PLIST( sub, nn, INTOBJ_INT(i) );
  267. nn++;
  268. }
  269. }
  270. CHANGED_BAG(sub);
  271. /* return the sublist */
  272. SET_TRUES_FLAGS( flags, sub );
  273. CHANGED_BAG(flags);
  274. return sub;
  275. }
  276. /****************************************************************************
  277. **
  278. *F FuncSIZE_FLAGS( <self>, <flags> ) . . . . number of trues of a flags list
  279. **
  280. ** see 'FuncSIZE_FLAGS'
  281. */
  282. Obj FuncSIZE_FLAGS (
  283. Obj self,
  284. Obj flags )
  285. {
  286. UInt * ptr; /* pointer to flags */
  287. UInt nrb; /* number of blocks in flags */
  288. UInt m; /* number of bits in a block */
  289. UInt n; /* number of bits in flags */
  290. UInt i; /* loop variable */
  291. /* get and check the first argument */
  292. while ( TNUM_OBJ(flags) != T_FLAGS ) {
  293. flags = ErrorReturnObj( "<flags> must be a flags list (not a %s)",
  294. (Int)TNAM_OBJ(flags), 0L,
  295. "you can replace <flags> via 'return <flags>;'" );
  296. }
  297. if ( TRUES_FLAGS(flags) != 0 ) {
  298. return INTOBJ_INT( LEN_PLIST( TRUES_FLAGS(flags) ) );
  299. }
  300. /* get the number of blocks and a pointer */
  301. nrb = NRB_FLAGS(flags);
  302. ptr = BLOCKS_FLAGS(flags);
  303. /* loop over the blocks, adding the number of bits of each one */
  304. n = 0;
  305. for ( i = 1; i <= nrb; i++ ) {
  306. m = *ptr++;
  307. COUNT_TRUES_BLOCK(m);
  308. n += m;
  309. }
  310. /* return the number of bits */
  311. return INTOBJ_INT( n );
  312. }
  313. /****************************************************************************
  314. **
  315. *F FuncIS_EQUAL_FLAGS( <self>, <flags1>, <flags2> ) equality of flags lists
  316. */
  317. Obj FuncIS_EQUAL_FLAGS (
  318. Obj self,
  319. Obj flags1,
  320. Obj flags2 )
  321. {
  322. Int len1;
  323. Int len2;
  324. UInt * ptr1;
  325. UInt * ptr2;
  326. Int i;
  327. /* do some trivial checks */
  328. while ( TNUM_OBJ(flags1) != T_FLAGS ) {
  329. flags1 = ErrorReturnObj( "<flags1> must be a flags list (not a %s)",
  330. (Int)TNAM_OBJ(flags1), 0L,
  331. "you can replace <flags1> via 'return <flags1>;'" );
  332. }
  333. while ( TNUM_OBJ(flags2) != T_FLAGS ) {
  334. flags2 = ErrorReturnObj( "<flags2> must be a flags list (not a %s)",
  335. (Int)TNAM_OBJ(flags2), 0L,
  336. "you can replace <flags2> via 'return <flags2>;'" );
  337. }
  338. if ( flags1 == flags2 ) {
  339. return True;
  340. }
  341. /* do the real work */
  342. len1 = NRB_FLAGS(flags1);
  343. len2 = NRB_FLAGS(flags2);
  344. ptr1 = BLOCKS_FLAGS(flags1);
  345. ptr2 = BLOCKS_FLAGS(flags2);
  346. if ( len1 <= len2 ) {
  347. for ( i = 1; i <= len1; i++ ) {
  348. if ( *ptr1 != *ptr2 )
  349. return False;
  350. ptr1++; ptr2++;
  351. }
  352. for ( ; i <= len2; i++ ) {
  353. if ( 0 != *ptr2 )
  354. return False;
  355. ptr2++;
  356. }
  357. }
  358. else {
  359. for ( i = 1; i <= len2; i++ ) {
  360. if ( *ptr1 != *ptr2 )
  361. return False;
  362. ptr1++; ptr2++;
  363. }
  364. for ( ; i <= len1; i++ ) {
  365. if ( *ptr1 != 0 )
  366. return False;
  367. ptr1++;
  368. }
  369. }
  370. return True;
  371. }
  372. /****************************************************************************
  373. **
  374. *F FuncIS_SUBSET_FLAGS( <self>, <flags1>, <flags2> ) . . . . . . subset test
  375. */
  376. Int IsSubsetFlagsCalls;
  377. Int IsSubsetFlagsCalls1;
  378. Int IsSubsetFlagsCalls2;
  379. Obj FuncIS_SUBSET_FLAGS (
  380. Obj self,
  381. Obj flags1,
  382. Obj flags2 )
  383. {
  384. Int len1;
  385. Int len2;
  386. UInt * ptr1;
  387. UInt * ptr2;
  388. Int i;
  389. Obj trues;
  390. /* do some trivial checks */
  391. while ( TNUM_OBJ(flags1) != T_FLAGS ) {
  392. flags1 = ErrorReturnObj( "<flags1> must be a flags list (not a %s)",
  393. (Int)TNAM_OBJ(flags1), 0L,
  394. "you can replace <flags1> via 'return <flags1>;'" );
  395. }
  396. while ( TNUM_OBJ(flags2) != T_FLAGS ) {
  397. flags2 = ErrorReturnObj( "<flags2> must be a flags list (not a %s)",
  398. (Int)TNAM_OBJ(flags2), 0L,
  399. "you can replace <flags2> via 'return <flags2>;'" );
  400. }
  401. if ( flags1 == flags2 ) {
  402. return True;
  403. }
  404. /* do the real work */
  405. #ifdef COUNT_OPERS
  406. IsSubsetFlagsCalls++;
  407. #endif
  408. /* first check the trues */
  409. trues = TRUES_FLAGS(flags2);
  410. if ( trues != 0 ) {
  411. len2 = LEN_PLIST(trues);
  412. if ( TRUES_FLAGS(flags1) != 0 ) {
  413. if ( LEN_PLIST(TRUES_FLAGS(flags1)) < len2 ) {
  414. #ifdef COUNT_OPERS
  415. IsSubsetFlagsCalls1++;
  416. #endif
  417. return False;
  418. }
  419. }
  420. if ( len2 < 3 ) {
  421. #ifdef COUNT_OPERS
  422. IsSubsetFlagsCalls2++;
  423. #endif
  424. if ( LEN_FLAGS(flags1) < INT_INTOBJ(ELM_PLIST(trues,len2)) ) {
  425. return False;
  426. }
  427. for ( i = len2; 0 < i; i-- ) {
  428. if (ELM_FLAGS(flags1,INT_INTOBJ(ELM_PLIST(trues,i)))==False) {
  429. return False;
  430. }
  431. }
  432. return True;
  433. }
  434. }
  435. /* compare the bit lists */
  436. len1 = NRB_FLAGS(flags1);
  437. len2 = NRB_FLAGS(flags2);
  438. ptr1 = BLOCKS_FLAGS(flags1);
  439. ptr2 = BLOCKS_FLAGS(flags2);
  440. if ( len1 <= len2 ) {
  441. for ( i = 1; i <= len1; i++ ) {
  442. if ( (*ptr1 & *ptr2) != *ptr2 ) {
  443. return False;
  444. }
  445. ptr1++; ptr2++;
  446. }
  447. for ( ; i <= len2; i++ ) {
  448. if ( 0 != *ptr2 ) {
  449. return False;
  450. }
  451. ptr2++;
  452. }
  453. }
  454. else {
  455. for ( i = 1; i <= len2; i++ ) {
  456. if ( (*ptr1 & *ptr2) != *ptr2 ) {
  457. return False;
  458. }
  459. ptr1++; ptr2++;
  460. }
  461. }
  462. return True;
  463. }
  464. /****************************************************************************
  465. **
  466. *F FuncSUB_FLAGS( <self>, <flags1>, <flags2> ) . . . substract a flags list
  467. */
  468. Obj FuncSUB_FLAGS (
  469. Obj self,
  470. Obj flags1,
  471. Obj flags2 )
  472. {
  473. Obj flags;
  474. Int len1;
  475. Int len2;
  476. Int size1;
  477. Int size2;
  478. UInt * ptr;
  479. UInt * ptr1;
  480. UInt * ptr2;
  481. Int i;
  482. /* do some trivial checks */
  483. while ( TNUM_OBJ(flags1) != T_FLAGS ) {
  484. flags1 = ErrorReturnObj( "<flags1> must be a flags list (not a %s)",
  485. (Int)TNAM_OBJ(flags1), 0L,
  486. "you can replace <flags1> via 'return <flags1>;'" );
  487. }
  488. while ( TNUM_OBJ(flags2) != T_FLAGS ) {
  489. flags2 = ErrorReturnObj( "<flags2> must be a flags list (not a %s)",
  490. (Int)TNAM_OBJ(flags2), 0L,
  491. "you can replace <flags2> via 'return <flags2>;'" );
  492. }
  493. /* do the real work */
  494. len1 = LEN_FLAGS(flags1);
  495. size1 = NRB_FLAGS(flags1);
  496. len2 = LEN_FLAGS(flags2);
  497. size2 = NRB_FLAGS(flags2);
  498. if ( len1 < len2 ) {
  499. NEW_FLAGS( flags, len1 );
  500. SET_LEN_FLAGS( flags, len1 );
  501. ptr1 = BLOCKS_FLAGS(flags1);
  502. ptr2 = BLOCKS_FLAGS(flags2);
  503. ptr = BLOCKS_FLAGS(flags);
  504. for ( i = 1; i <= size1; i++ )
  505. *ptr++ = *ptr1++ & ~ *ptr2++;
  506. }
  507. else {
  508. NEW_FLAGS( flags, len1 );
  509. SET_LEN_FLAGS( flags, len1 );
  510. ptr1 = BLOCKS_FLAGS(flags1);
  511. ptr2 = BLOCKS_FLAGS(flags2);
  512. ptr = BLOCKS_FLAGS(flags);
  513. for ( i = 1; i <= size2; i++ )
  514. *ptr++ = *ptr1++ & ~ *ptr2++;
  515. for ( ; i <= size1; i++ )
  516. *ptr++ = *ptr1++;
  517. }
  518. return flags;
  519. }
  520. /****************************************************************************
  521. **
  522. *F FuncAND_FLAGS( <self>, <flags1>, <flags2> ) . . . . `and' of flags lists
  523. */
  524. #define AND_FLAGS_HASH_SIZE 50
  525. Int AndFlagsCacheHit;
  526. Int AndFlagsCacheMiss;
  527. Int AndFlagsCacheLost;
  528. Obj FuncAND_FLAGS (
  529. Obj self,
  530. Obj flags1,
  531. Obj flags2 )
  532. {
  533. Obj flags;
  534. Int len1;
  535. Int len2;
  536. Int size1;
  537. Int size2;
  538. UInt * ptr;
  539. UInt * ptr1;
  540. UInt * ptr2;
  541. Int i;
  542. #ifdef AND_FLAGS_HASH_SIZE
  543. Obj flagsX;
  544. Obj cache;
  545. Obj entry;
  546. UInt hash;
  547. UInt hash2;
  548. static UInt next = 0;
  549. #endif
  550. /* do some trivial checks */
  551. while ( TNUM_OBJ(flags1) != T_FLAGS ) {
  552. flags1 = ErrorReturnObj( "<flags1> must be a flags list (not a %s)",
  553. (Int)TNAM_OBJ(flags1), 0L,
  554. "you can replace <flags1> via 'return <flags1>;'" );
  555. }
  556. while ( TNUM_OBJ(flags2) != T_FLAGS ) {
  557. flags2 = ErrorReturnObj( "<flags2> must be a flags list (not a %s)",
  558. (Int)TNAM_OBJ(flags2), 0L,
  559. "you can replace <flags2> via 'return <flags2>;'" );
  560. }
  561. /* check the cache */
  562. # ifdef AND_FLAGS_HASH_SIZE
  563. if ( INT_INTOBJ(flags1) < INT_INTOBJ(flags2) ) {
  564. flagsX = flags2;
  565. cache = AND_CACHE_FLAGS(flags1);
  566. if ( cache == 0 ) {
  567. cache = NEW_PLIST( T_PLIST, 2*AND_FLAGS_HASH_SIZE );
  568. SET_AND_CACHE_FLAGS( flags1, cache );
  569. CHANGED_BAG(flags1);
  570. }
  571. }
  572. else {
  573. flagsX = flags1;
  574. cache = AND_CACHE_FLAGS(flags2);
  575. if ( cache == 0 ) {
  576. cache = NEW_PLIST( T_PLIST, 2*AND_FLAGS_HASH_SIZE );
  577. SET_AND_CACHE_FLAGS( flags2, cache );
  578. CHANGED_BAG(flags2);
  579. }
  580. }
  581. hash = (UInt)INT_INTOBJ(flagsX);
  582. for ( i = 0; i < 24; i++ ) {
  583. hash2 = (hash + 97*i) % AND_FLAGS_HASH_SIZE;
  584. entry = ELM_PLIST( cache, 2*hash2+1 );
  585. if ( entry == 0 ) {
  586. break;
  587. }
  588. if ( entry == flagsX ) {
  589. # ifdef COUNT_OPERS
  590. AndFlagsCacheHit++;
  591. # endif
  592. return ELM_PLIST( cache, 2*hash2+2 );
  593. }
  594. }
  595. if ( entry == 0 ) {
  596. hash = hash2;
  597. }
  598. else {
  599. next = (next+1) % 24;
  600. hash = (hash + 97*next) % AND_FLAGS_HASH_SIZE;
  601. }
  602. # ifdef COUNT_OPERS
  603. AndFlagsCacheMiss++;
  604. # endif
  605. # endif
  606. /* do the real work */
  607. len1 = LEN_FLAGS(flags1);
  608. size1 = NRB_FLAGS(flags1);
  609. len2 = LEN_FLAGS(flags2);
  610. size2 = NRB_FLAGS(flags2);
  611. if ( len1 == 0 ) {
  612. return flags2;
  613. }
  614. if ( len2 == 0 ) {
  615. return flags1;
  616. }
  617. if ( len1 < len2 ) {
  618. NEW_FLAGS( flags, len2 );
  619. SET_LEN_FLAGS( flags, len2 );
  620. ptr1 = BLOCKS_FLAGS(flags1);
  621. ptr2 = BLOCKS_FLAGS(flags2);
  622. ptr = BLOCKS_FLAGS(flags);
  623. for ( i = 1; i <= size1; i++ )
  624. *ptr++ = *ptr1++ | *ptr2++;
  625. for ( ; i <= size2; i++ )
  626. *ptr++ = *ptr2++;
  627. }
  628. else {
  629. NEW_FLAGS( flags, len1 );
  630. SET_LEN_FLAGS( flags, len1 );
  631. ptr1 = BLOCKS_FLAGS(flags1);
  632. ptr2 = BLOCKS_FLAGS(flags2);
  633. ptr = BLOCKS_FLAGS(flags);
  634. for ( i = 1; i <= size2; i++ )
  635. *ptr++ = *ptr1++ | *ptr2++;
  636. for ( ; i <= size1; i++ )
  637. *ptr++ = *ptr1++;
  638. }
  639. /* store result in the cache */
  640. # ifdef AND_FLAGS_HASH_SIZE
  641. # ifdef COUNT_OPERS
  642. if ( ELM_PLIST(cache,2*hash+1) != 0 ) {
  643. AndFlagsCacheLost++;
  644. }
  645. # endif
  646. SET_ELM_PLIST( cache, 2*hash+1, flagsX );
  647. SET_ELM_PLIST( cache, 2*hash+2, flags );
  648. CHANGED_BAG(cache);
  649. # endif
  650. /* and return the result */
  651. return flags;
  652. }
  653. /****************************************************************************
  654. **
  655. *F * * * * * * * * * * * internal filter functions * * * * * * * * * * * * *
  656. */
  657. /****************************************************************************
  658. **
  659. *V Countlags . . . . . . . . . . . . . . . . . . . . next free flag number
  660. */
  661. Int CountFlags;
  662. /****************************************************************************
  663. **
  664. *F SetterFilter( <oper> ) . . . . . . . . . . . . . . . setter of a filter
  665. */
  666. Obj SetterFilter (
  667. Obj oper )
  668. {
  669. Obj setter;
  670. setter = SETTR_FILT( oper );
  671. if ( setter == INTOBJ_INT(0xBADBABE) )
  672. setter = SetterAndFilter( oper );
  673. return setter;
  674. }
  675. /****************************************************************************
  676. **
  677. *F SetterAndFilter( <getter> ) . . . . . . setter of a concatenated filter
  678. */
  679. Obj DoSetAndFilter (
  680. Obj self,
  681. Obj obj,
  682. Obj val )
  683. {
  684. Obj op;
  685. while (val != True)
  686. val = ErrorReturnObj(
  687. "You cannot set an \"and-filter\" except to true", 0L, 0L,
  688. "you can type 'return true;' to set all components true\n"
  689. "(but you might really want to reset just one component)");
  690. /* call the first 'and'-ed function */
  691. op = FLAG1_FILT( self );
  692. CALL_2ARGS( op, obj, val );
  693. /* call the second 'and'-ed function */
  694. op = FLAG2_FILT( self );
  695. CALL_2ARGS( op, obj, val );
  696. /* return 'void' */
  697. return 0;
  698. }
  699. Obj SetterAndFilter (
  700. Obj getter )
  701. {
  702. Obj setter;
  703. if ( SETTR_FILT( getter ) == INTOBJ_INT(0xBADBABE) ) {
  704. setter = NewFunctionCT( T_FUNCTION, SIZE_OPER,
  705. "<<setter-and-filter>>", 2L, "obj, val",
  706. DoSetAndFilter );
  707. FLAG1_FILT(setter) = SetterFilter( FLAG1_FILT(getter) );
  708. FLAG2_FILT(setter) = SetterFilter( FLAG2_FILT(getter) );
  709. SETTR_FILT(getter) = setter;
  710. CHANGED_BAG(getter);
  711. }
  712. return SETTR_FILT(getter);
  713. }
  714. /****************************************************************************
  715. **
  716. *F TesterFilter( <oper> ) . . . . . . . . . . . . . . . tester of a filter
  717. */
  718. Obj TesterFilter (
  719. Obj oper )
  720. {
  721. Obj tester;
  722. tester = TESTR_FILT( oper );
  723. if ( tester == INTOBJ_INT(0xBADBABE) )
  724. tester = TesterAndFilter( oper );
  725. return tester;
  726. }
  727. /****************************************************************************
  728. **
  729. *F TestAndFilter( <getter> ) . . . . . . . .tester of a concatenated filter
  730. */
  731. Obj DoTestAndFilter (
  732. Obj self,
  733. Obj obj )
  734. {
  735. Obj val;
  736. Obj op;
  737. /* call the first 'and'-ed function */
  738. op = FLAG1_FILT( self );
  739. val = CALL_1ARGS( op, obj );
  740. if ( val != True ) return False;
  741. /* call the second 'and'-ed function */
  742. op = FLAG2_FILT( self );
  743. val = CALL_1ARGS( op, obj );
  744. if ( val != True ) return False;
  745. /* return 'true' */
  746. return True;
  747. }
  748. Obj TesterAndFilter (
  749. Obj getter )
  750. {
  751. Obj tester;
  752. if ( TESTR_FILT( getter ) == INTOBJ_INT(0xBADBABE) ) {
  753. tester = NewAndFilter( TesterFilter( FLAG1_FILT(getter) ),
  754. TesterFilter( FLAG2_FILT(getter) ) );
  755. TESTR_FILT(getter) = tester;
  756. CHANGED_BAG(getter);
  757. }
  758. return TESTR_FILT(getter);
  759. }
  760. /****************************************************************************
  761. **
  762. *F NewFilter( <name>, <narg>, <nams>, <hdlr> ) . . . . . make a new filter
  763. */
  764. Obj DoTestFilter (
  765. Obj self,
  766. Obj obj )
  767. {
  768. return True;
  769. }
  770. Obj NewTesterFilter (
  771. Obj getter )
  772. {
  773. Obj tester;
  774. tester = ReturnTrueFilter;
  775. return tester;
  776. }
  777. Obj DoSetFilter (
  778. Obj self,
  779. Obj obj,
  780. Obj val )
  781. {
  782. Int flag1;
  783. Obj kind;
  784. Obj flags;
  785. /* get the flag for the getter */
  786. flag1 = INT_INTOBJ( FLAG1_FILT( self ) );
  787. /* get the kind of the object and its flags */
  788. kind = TYPE_OBJ( obj );
  789. flags = FLAGS_TYPE( kind );
  790. /* return the value of the feature */
  791. if ( flag1 <= LEN_FLAGS( flags ) ) {
  792. if ( val != ELM_FLAGS( flags, flag1 ) ) {
  793. ErrorReturnVoid(
  794. "value feature is already set the other way",
  795. 0L, 0L,
  796. "you can 'return;' and ignore it" );
  797. }
  798. }
  799. else {
  800. if ( val != False ) {
  801. ErrorReturnVoid(
  802. "value feature is already set the other way",
  803. 0L, 0L,
  804. "you can 'return;' and ignore it" );
  805. }
  806. }
  807. /* return 'void' */
  808. return 0;
  809. }
  810. static Obj StringFilterSetter;
  811. static Obj ArglistObjVal;
  812. Obj NewSetterFilter (
  813. Obj getter )
  814. {
  815. Obj setter;
  816. setter = NewOperation( StringFilterSetter, 2, ArglistObjVal,
  817. DoSetFilter );
  818. FLAG1_FILT(setter) = FLAG1_FILT(getter);
  819. FLAG2_FILT(setter) = INTOBJ_INT( 0 );
  820. CHANGED_BAG(setter);
  821. return setter;
  822. }
  823. Obj DoFilter (
  824. Obj self,
  825. Obj obj )
  826. {
  827. Obj val;
  828. Int flag1;
  829. Obj kind;
  830. Obj flags;
  831. /* get the flag for the getter */
  832. flag1 = INT_INTOBJ( FLAG1_FILT( self ) );
  833. /* get the kind of the object and its flags */
  834. kind = TYPE_OBJ( obj );
  835. flags = FLAGS_TYPE( kind );
  836. /* return the value of the feature */
  837. if ( flag1 <= LEN_FLAGS( flags ) ) {
  838. val = ELM_FLAGS( flags, flag1 );
  839. }
  840. else {
  841. val = False;
  842. }
  843. /* return the value */
  844. return val;
  845. }
  846. Obj NewFilter (
  847. Obj name,
  848. Int narg,
  849. Obj nams,
  850. ObjFunc hdlr )
  851. {
  852. Obj getter;
  853. Obj setter;
  854. Obj tester;
  855. Int flag1;
  856. Obj flags;
  857. flag1 = ++CountFlags;
  858. getter = NewOperation( name, 1L, nams, (hdlr ? hdlr : DoFilter) );
  859. FLAG1_FILT(getter) = INTOBJ_INT( flag1 );
  860. FLAG2_FILT(getter) = INTOBJ_INT( 0 );
  861. NEW_FLAGS( flags, flag1 );
  862. SET_LEN_FLAGS( flags, flag1 );
  863. SET_ELM_FLAGS( flags, flag1, True );
  864. FLAGS_FILT(getter) = flags;
  865. CHANGED_BAG(getter);
  866. setter = NewSetterFilter( getter );
  867. SETTR_FILT(getter) = setter;
  868. CHANGED_BAG(getter);
  869. tester = NewTesterFilter( getter );
  870. TESTR_FILT(getter) = tester;
  871. CHANGED_BAG(getter);
  872. return getter;
  873. }
  874. /****************************************************************************
  875. **
  876. *F NewFilterC( <name>, <narg>, <nams>, <hdlr> ) . . . . . make a new filter
  877. */
  878. Obj NewFilterC (
  879. const Char * name,
  880. Int narg,
  881. const Char * nams,
  882. ObjFunc hdlr )
  883. {
  884. Obj getter;
  885. Obj setter;
  886. Obj tester;
  887. Int flag1;
  888. Obj flags;
  889. flag1 = ++CountFlags;
  890. getter = NewOperationC( name, 1L, nams, (hdlr ? hdlr : DoFilter) );
  891. FLAG1_FILT(getter) = INTOBJ_INT( flag1 );
  892. FLAG2_FILT(getter) = INTOBJ_INT( 0 );
  893. NEW_FLAGS( flags, flag1 );
  894. SET_LEN_FLAGS( flags, flag1 );
  895. SET_ELM_FLAGS( flags, flag1, True );
  896. FLAGS_FILT(getter) = flags;
  897. CHANGED_BAG(getter);
  898. setter = NewSetterFilter( getter );
  899. SETTR_FILT(getter) = setter;
  900. CHANGED_BAG(getter);
  901. tester = NewTesterFilter( getter );
  902. TESTR_FILT(getter) = tester;
  903. CHANGED_BAG(getter);
  904. return getter;
  905. }
  906. /****************************************************************************
  907. **
  908. *F NewAndFilter( <filt1>, <filt2> ) . . . . . make a new concatenated filter
  909. */
  910. Obj DoAndFilter (
  911. Obj self,
  912. Obj obj )
  913. {
  914. Obj val;
  915. Obj op;
  916. /* call the first 'and'-ed function */
  917. op = FLAG1_FILT( self );
  918. val = CALL_1ARGS( op, obj );
  919. if ( val != True ) return False;
  920. /* call the second 'and'-ed function */
  921. op = FLAG2_FILT( self );
  922. val = CALL_1ARGS( op, obj );
  923. if ( val != True ) return False;
  924. /* return 'true' */
  925. return True;
  926. }
  927. static Obj StringAndFilter;
  928. static Obj ArglistObj;
  929. Obj NewAndFilter (
  930. Obj oper1,
  931. Obj oper2 )
  932. {
  933. Obj getter;
  934. Obj flags;
  935. if ( oper1 == ReturnTrueFilter && oper2 == ReturnTrueFilter )
  936. return ReturnTrueFilter;
  937. getter = NewFunctionT( T_FUNCTION, SIZE_OPER, StringAndFilter, 1,
  938. ArglistObj, DoAndFilter );
  939. FLAG1_FILT(getter) = oper1;
  940. FLAG2_FILT(getter) = oper2;
  941. flags = FuncAND_FLAGS( 0, FLAGS_FILT(oper1), FLAGS_FILT(oper2) );
  942. FLAGS_FILT(getter) = flags;
  943. SETTR_FILT(getter) = INTOBJ_INT(0xBADBABE);
  944. TESTR_FILT(getter) = INTOBJ_INT(0xBADBABE);
  945. CHANGED_BAG(getter);
  946. return getter;
  947. }
  948. Obj FuncIS_AND_FILTER( Obj self, Obj filt )
  949. {
  950. return (IS_FUNC(filt) && HDLR_FUNC(filt, 1) == DoAndFilter) ? True : False;
  951. }
  952. /****************************************************************************
  953. **
  954. *V ReturnTrueFilter . . . . . . . . . . . . . . . . the return 'true' filter
  955. */
  956. Obj ReturnTrueFilter;
  957. /****************************************************************************
  958. **
  959. *F NewReturnTrueFilter() . . . . . . . . . . create a new return true filter
  960. */
  961. Obj DoTestReturnTrueFilter (
  962. Obj self,
  963. Obj obj )
  964. {
  965. return True;
  966. }
  967. Obj TesterReturnTrueFilter (
  968. Obj getter )
  969. {
  970. return getter;
  971. }
  972. Obj DoSetReturnTrueFilter (
  973. Obj self,
  974. Obj obj,
  975. Obj val )
  976. {
  977. if ( val != True ) {
  978. ErrorReturnVoid( "you cannot set this flag to 'false'",
  979. 0L, 0L,
  980. "you can 'return;' and ignore it" );
  981. }
  982. return 0;
  983. }
  984. Obj SetterReturnTrueFilter (
  985. Obj getter )
  986. {
  987. Obj setter;
  988. setter = NewFunctionCT( T_FUNCTION, SIZE_OPER,
  989. "<<setter-true-filter>>", 2L, "obj, val",
  990. DoSetReturnTrueFilter );
  991. FLAG1_FILT(setter) = INTOBJ_INT( 0 );
  992. FLAG2_FILT(setter) = INTOBJ_INT( 0 );
  993. CHANGED_BAG(setter);
  994. return setter;
  995. }
  996. Obj DoReturnTrueFilter (
  997. Obj self,
  998. Obj obj )
  999. {
  1000. return True;
  1001. }
  1002. Obj NewReturnTrueFilter ( void )
  1003. {
  1004. Obj getter;
  1005. Obj setter;
  1006. Obj tester;
  1007. Obj flags;
  1008. getter = NewFunctionCT( T_FUNCTION, SIZE_OPER,
  1009. "ReturnTrueFilter", 1L, "obj",
  1010. DoReturnTrueFilter );
  1011. FLAG1_FILT(getter) = INTOBJ_INT( 0 );
  1012. FLAG2_FILT(getter) = INTOBJ_INT( 0 );
  1013. NEW_FLAGS( flags, 0 );
  1014. SET_LEN_FLAGS( flags, 0 );
  1015. FLAGS_FILT(getter) = flags;
  1016. CHANGED_BAG(getter);
  1017. setter = SetterReturnTrueFilter( getter );
  1018. SETTR_FILT(getter) = setter;
  1019. CHANGED_BAG(getter);
  1020. tester = TesterReturnTrueFilter( getter );
  1021. TESTR_FILT(getter) = tester;
  1022. CHANGED_BAG(getter);
  1023. return getter;
  1024. }
  1025. /****************************************************************************
  1026. **
  1027. *F * * * * * * * * * * * * * GAP filter functions * * * * * * * * * * * * * *
  1028. */
  1029. /****************************************************************************
  1030. **
  1031. *F FuncNEW_FILTER( <self>, <name> ) . . . . . . . . . . . . . new filter
  1032. */
  1033. Obj FuncNEW_FILTER (
  1034. Obj self,
  1035. Obj name )
  1036. {
  1037. /* check the argument */
  1038. if ( ! IsStringConv(name) ) {
  1039. ErrorQuit("usage: NewFilter( <name> )",0L,0L);
  1040. return 0;
  1041. }
  1042. /* make the new operation */
  1043. return NewFilter( name, 1L, (Obj)0, (ObjFunc)0 );
  1044. }
  1045. /****************************************************************************
  1046. **
  1047. *F FuncFLAG1_FILTER( <self>, <oper> ) . . . . . . . . . . . . `FLAG1_FILT'
  1048. */
  1049. Obj FuncFLAG1_FILTER (
  1050. Obj self,
  1051. Obj oper )
  1052. {
  1053. Obj flag1;
  1054. if ( ! IS_OPERATION(oper) ) {
  1055. ErrorQuit("<oper> must be an operation",0L,0L);
  1056. return 0;
  1057. }
  1058. flag1 = FLAG1_FILT( oper );
  1059. if ( flag1 == 0 )
  1060. flag1 = INTOBJ_INT(0);
  1061. return flag1;
  1062. }
  1063. /****************************************************************************
  1064. **
  1065. *F FuncSET_FLAG1_FILTER( <self>, <oper>, <flag1> ) . . . . set `FLAG1_FILT'
  1066. */
  1067. Obj FuncSET_FLAG1_FILTER (
  1068. Obj self,
  1069. Obj oper,
  1070. Obj flag1 )
  1071. {
  1072. if ( ! IS_OPERATION(oper) ) {
  1073. ErrorQuit("<oper> must be an operation",0L,0L);
  1074. return 0;
  1075. }
  1076. FLAG1_FILT( oper ) = flag1;
  1077. return 0;
  1078. }
  1079. /****************************************************************************
  1080. **
  1081. *F FuncFLAG2_FILTER( <self>, <oper> ) . . . . . . . . . . . . `FLAG2_FILT'
  1082. */
  1083. Obj FuncFLAG2_FILTER (
  1084. Obj self,
  1085. Obj oper )
  1086. {
  1087. Obj flag2;
  1088. if ( ! IS_OPERATION(oper) ) {
  1089. ErrorQuit("<oper> must be an operation",0L,0L);
  1090. return 0;
  1091. }
  1092. flag2 = FLAG2_FILT( oper );
  1093. if ( flag2 == 0 )
  1094. flag2 = INTOBJ_INT(0);
  1095. return flag2;
  1096. }
  1097. /****************************************************************************
  1098. **
  1099. *F FuncSET_FLAG2_FILTER( <self>, <oper>, <flag2> ) . . . . set `FLAG2_FILT'
  1100. */
  1101. Obj FuncSET_FLAG2_FILTER (
  1102. Obj self,
  1103. Obj oper,
  1104. Obj flag2 )
  1105. {
  1106. if ( ! IS_OPERATION(oper) ) {
  1107. ErrorQuit("<oper> must be an operation",0L,0L);
  1108. return 0;
  1109. }
  1110. FLAG2_FILT( oper ) = flag2;
  1111. return 0;
  1112. }
  1113. /****************************************************************************
  1114. **
  1115. *F FuncFLAGS_FILTER( <self>, <oper> ) . . . . . . . . . . . . `FLAGS_FILT'
  1116. */
  1117. Obj FuncFLAGS_FILTER (
  1118. Obj self,
  1119. Obj oper )
  1120. {
  1121. Obj flags;
  1122. if ( ! IS_OPERATION(oper) ) {
  1123. ErrorQuit("<oper> must be an operation",0L,0L);
  1124. return 0;
  1125. }
  1126. flags = FLAGS_FILT( oper );
  1127. if ( flags == 0 )
  1128. flags = False;
  1129. return flags;
  1130. }
  1131. /****************************************************************************
  1132. **
  1133. *F FuncSET_FLAGS_FILTER( <self>, <oper>, <flags> ) . . . . set `FLAGS_FILT'
  1134. */
  1135. Obj FuncSET_FLAGS_FILTER (
  1136. Obj self,
  1137. Obj oper,
  1138. Obj flags )
  1139. {
  1140. if ( ! IS_OPERATION(oper) ) {
  1141. ErrorQuit("<oper> must be an operation",0L,0L);
  1142. return 0;
  1143. }
  1144. FLAGS_FILT( oper ) = flags;
  1145. return 0;
  1146. }
  1147. /****************************************************************************
  1148. **
  1149. *F FuncSETTER_FILTER( <self>, <oper> ) . . . . . . . . . setter of a filter
  1150. */
  1151. Obj FuncSETTER_FILTER (
  1152. Obj self,
  1153. Obj oper )
  1154. {
  1155. Obj setter;
  1156. if ( ! IS_OPERATION(oper) ) {
  1157. ErrorQuit("<oper> must be an operation",0L,0L);
  1158. return 0;
  1159. }
  1160. setter = SetterFilter( oper );
  1161. if ( setter == 0 ) setter = False;
  1162. return setter;
  1163. }
  1164. /****************************************************************************
  1165. **
  1166. *F FuncSET_SETTER_FILTER( <self>, <oper>, <setter> ) set setter of a filter
  1167. */
  1168. Obj FuncSET_SETTER_FILTER (
  1169. Obj self,
  1170. Obj oper,
  1171. Obj setter )
  1172. {
  1173. if ( ! IS_OPERATION(oper) ) {
  1174. ErrorQuit("<oper> must be an operation",0L,0L);
  1175. return 0;
  1176. }
  1177. SETTR_FILT( oper ) = setter;
  1178. return 0;
  1179. }
  1180. /****************************************************************************
  1181. **
  1182. *F FuncTESTER_FILTER( <self>, <oper> ) . . . . . . . . . tester of a filter
  1183. */
  1184. Obj FuncTESTER_FILTER (
  1185. Obj self,
  1186. Obj oper )
  1187. {
  1188. Obj tester;
  1189. if ( ! IS_OPERATION(oper) ) {
  1190. ErrorQuit("<oper> must be an operation",0L,0L);
  1191. return 0;
  1192. }
  1193. tester = TesterFilter( oper );
  1194. if ( tester == 0 ) tester = False;
  1195. return tester;
  1196. }
  1197. /****************************************************************************
  1198. **
  1199. *F FuncSET_TESTER_FILTER( <self>, <oper>, <tester> ) set tester of a filter
  1200. */
  1201. Obj FuncSET_TESTER_FILTER (
  1202. Obj self,
  1203. Obj oper,
  1204. Obj tester )
  1205. {
  1206. if ( ! IS_OPERATION(oper) ) {
  1207. ErrorQuit("<oper> must be an operation",0L,0L);
  1208. return 0;
  1209. }
  1210. if ( SIZE_OBJ(oper) != SIZE_OPER ) {
  1211. ResizeBag( oper, SIZE_OPER );
  1212. }
  1213. TESTR_FILT( oper ) = tester;
  1214. return 0;
  1215. }
  1216. /****************************************************************************
  1217. **
  1218. *F * * * * * * * * * * internal operation functions * * * * * * * * * * * *
  1219. */
  1220. /****************************************************************************
  1221. **
  1222. *F CallHandleMethodNotFound( <oper>, <nargs>, <args>, <verbose>, <constructor>)
  1223. **
  1224. */
  1225. static UInt RNamOperation;
  1226. static UInt RNamArguments;
  1227. static UInt RNamIsVerbose;
  1228. static UInt RNamIsConstructor;
  1229. static UInt RNamPrecedence;
  1230. static Obj HandleMethodNotFound;
  1231. Obj CallHandleMethodNotFound( Obj oper,
  1232. Int nargs,
  1233. Obj *args,
  1234. UInt verbose,
  1235. UInt constructor,
  1236. Obj precedence)
  1237. {
  1238. Obj r;
  1239. Obj arglist;
  1240. UInt i;
  1241. r = NEW_PREC(5);
  1242. if (RNamOperation == 0)
  1243. {
  1244. /* we can't do this in initialization because opers
  1245. is initialized BEFORE records */
  1246. RNamIsConstructor = RNamName("isConstructor");
  1247. RNamIsVerbose = RNamName("isVerbose");
  1248. RNamOperation = RNamName("Operation");
  1249. RNamArguments = RNamName("Arguments");
  1250. RNamPrecedence = RNamName("Precedence");
  1251. }
  1252. AssPRec(r,RNamOperation,oper);
  1253. arglist = NEW_PLIST(nargs ? T_PLIST_DENSE+IMMUTABLE:
  1254. T_PLIST_EMPTY+IMMUTABLE, nargs);
  1255. SET_LEN_PLIST(arglist,nargs);
  1256. for (i = 0; i < nargs; i++)
  1257. SET_ELM_PLIST( arglist, i+1, args[i]);
  1258. AssPRec(r,RNamArguments,arglist);
  1259. AssPRec(r,RNamIsVerbose,verbose ? True : False);
  1260. AssPRec(r,RNamIsConstructor,constructor ? True : False);
  1261. AssPRec(r,RNamPrecedence,precedence);
  1262. SortPRecRNam(r,0);
  1263. return CALL_1ARGS(HandleMethodNotFound, r);
  1264. }
  1265. /****************************************************************************
  1266. **
  1267. *F FuncCompactTypeIDs( <self> ) . . . garbage collect the type IDs
  1268. **
  1269. */
  1270. static Int NextTypeID;
  1271. Obj IsType;
  1272. static void FixTypeIDs( Bag b ) {
  1273. if ( (TNUM_OBJ( b ) == T_POSOBJ) &&
  1274. (DoFilter(IsType, b ) == True ))
  1275. {
  1276. ID_TYPE(b) = INTOBJ_INT(NextTypeID);
  1277. NextTypeID++;
  1278. }
  1279. }
  1280. Obj FuncCompactTypeIDs( Obj self )
  1281. {
  1282. NextTypeID = -(1L << NR_SMALL_INT_BITS);
  1283. CallbackForAllBags( FixTypeIDs );
  1284. return INTOBJ_INT(NextTypeID);
  1285. }
  1286. /****************************************************************************
  1287. **
  1288. *F DoOperation( <name> ) . . . . . . . . . . . . . . . make a new operation
  1289. */
  1290. UInt CacheIndex;
  1291. Obj Method0Args;
  1292. Obj NextMethod0Args;
  1293. Obj Method1Args;
  1294. Obj NextMethod1Args;
  1295. Obj Method2Args;
  1296. Obj NextMethod2Args;
  1297. Obj Method3Args;
  1298. Obj NextMethod3Args;
  1299. Obj Method4Args;
  1300. Obj NextMethod4Args;
  1301. Obj Method5Args;
  1302. Obj NextMethod5Args;
  1303. Obj Method6Args;
  1304. Obj NextMethod6Args;
  1305. Obj MethodXArgs;
  1306. Obj NextMethodXArgs;
  1307. Obj VMethod0Args;
  1308. Obj NextVMethod0Args;
  1309. Obj VMethod1Args;
  1310. Obj NextVMethod1Args;
  1311. Obj VMethod2Args;
  1312. Obj NextVMethod2Args;
  1313. Obj VMethod3Args;
  1314. Obj NextVMethod3Args;
  1315. Obj VMethod4Args;
  1316. Obj NextVMethod4Args;
  1317. Obj VMethod5Args;
  1318. Obj NextVMethod5Args;
  1319. Obj VMethod6Args;
  1320. Obj NextVMethod6Args;
  1321. Obj VMethodXArgs;
  1322. Obj NextVMethodXArgs;
  1323. /****************************************************************************
  1324. **
  1325. ** DoOperation0Args( <oper> )
  1326. */
  1327. Int OperationHit;
  1328. Int OperationMiss;
  1329. Int OperationNext;
  1330. /* This avoids a function call in the case of external objects with a
  1331. stored type */
  1332. static inline Obj TYPE_OBJ_FEO (
  1333. Obj obj
  1334. )
  1335. {
  1336. if ( TNUM_OBJ(obj) >= FIRST_EXTERNAL_TNUM &&
  1337. TNUM_OBJ(obj) <= T_DATOBJ) /* avoid T_WPOBJ */
  1338. return TYPE_ANYOBJ(obj);
  1339. else
  1340. return TYPE_OBJ(obj);
  1341. }
  1342. static inline Obj CacheOper (
  1343. Obj oper,
  1344. UInt i )
  1345. {
  1346. Obj cache;
  1347. UInt len;
  1348. cache = CACHE_OPER( oper, i );
  1349. if ( cache == 0 ) {
  1350. len = (i < 7 ? CACHE_SIZE * (i+2) : CACHE_SIZE * (1+2)) ;
  1351. cache = NEW_PLIST( T_PLIST, len);
  1352. SET_LEN_PLIST(cache, len );
  1353. CACHE_OPER( oper, i ) = cache;
  1354. CHANGED_BAG( oper );
  1355. }
  1356. return cache;
  1357. }
  1358. Obj DoOperation0Args (
  1359. Obj oper )
  1360. {
  1361. Obj res;
  1362. Obj * cache;
  1363. Obj method;
  1364. Int i;
  1365. Obj prec;
  1366. /* try to find an applicable method in the cache */
  1367. cache = 1+ADDR_OBJ( CacheOper( oper, 0 ) );
  1368. prec = INTOBJ_INT(-1);
  1369. do {
  1370. /* The next line depends on the implementation of INTOBJS */
  1371. prec = (Obj)(((Int)prec) +4);
  1372. method = 0;
  1373. /* Up to CACHE_SIZE methods might be in the cache */
  1374. if (prec < INTOBJ_INT(CACHE_SIZE))
  1375. {
  1376. for (i = 0; i < 2*CACHE_SIZE; i+= 2) {
  1377. if ( cache[i] != 0 && cache[i+1] == prec) {
  1378. method = cache[i];
  1379. #ifdef COUNT_OPERS
  1380. OperationHit++;
  1381. #endif
  1382. break;
  1383. }
  1384. }
  1385. }
  1386. /* otherwise try to find one in the list of methods */
  1387. if (!method)
  1388. {
  1389. if (prec == INTOBJ_INT(0))
  1390. method = CALL_1ARGS( Method0Args, oper );
  1391. else
  1392. method = CALL_2ARGS( NextMethod0Args, oper, prec );
  1393. /* If there was no method found, then pass the information needed for
  1394. the error reporting. This function rarely returns */
  1395. while (method == Fail)
  1396. method = CallHandleMethodNotFound( oper, 0, (Obj *) 0, 0, 0, prec);
  1397. /* update the cache */
  1398. if (method && prec < INTOBJ_INT(CACHE_SIZE))
  1399. {
  1400. cache = 1+ADDR_OBJ( CACHE_OPER( oper, 0 ) );
  1401. cache[2*CacheIndex] = method;
  1402. cache[2*CacheIndex+1] = prec;
  1403. CacheIndex = (CacheIndex + 1) % CACHE_SIZE;
  1404. CHANGED_BAG(CACHE_OPER(oper,0));
  1405. }
  1406. #ifdef COUNT_OPERS
  1407. OperationMiss++;
  1408. #endif
  1409. }
  1410. if ( !method ) {
  1411. ErrorQuit( "no method returned", 0L, 0L );
  1412. }
  1413. /* call this method */
  1414. res = CALL_0ARGS( method );
  1415. }
  1416. while (res == TRY_NEXT_METHOD );
  1417. /* return the result */
  1418. return res;
  1419. }
  1420. /****************************************************************************
  1421. **
  1422. ** DoOperation1Args( <oper>, <a1> )
  1423. */
  1424. Obj DoOperation1Args (
  1425. Obj oper,
  1426. Obj arg1 )
  1427. {
  1428. Obj res;
  1429. Obj kind1;
  1430. Obj id1;
  1431. Obj * cache;
  1432. Obj method;
  1433. Int i;
  1434. Obj prec;
  1435. /* get the kinds of the arguments */
  1436. kind1 = TYPE_OBJ_FEO( arg1 ); id1 = ID_TYPE( kind1 );
  1437. /* try to find an applicable method in the cache */
  1438. cache = 1+ADDR_OBJ( CacheOper( oper, 1 ) );
  1439. prec = INTOBJ_INT(-1);
  1440. do {
  1441. /* The next line depends on the implementation of INTOBJS */
  1442. prec = (Obj)(((Int)prec) +4);
  1443. method = 0;
  1444. /* Up to CACHE_SIZE methods might be in the cache */
  1445. if (prec < INTOBJ_INT(CACHE_SIZE))
  1446. {
  1447. for (i = 0; i < 3*CACHE_SIZE; i+= 3) {
  1448. if ( cache[i+1] == prec && cache[i+2] == id1 ) {
  1449. method = cache[i];
  1450. #ifdef COUNT_OPERS
  1451. OperationHit++;
  1452. #endif
  1453. break;
  1454. }
  1455. }
  1456. }
  1457. /* otherwise try to find one in the list of methods */
  1458. if (!method)
  1459. {
  1460. if (prec == INTOBJ_INT(0))
  1461. method = CALL_2ARGS( Method1Args, oper, kind1 );
  1462. else
  1463. method = CALL_3ARGS( NextMethod1Args, oper, prec, kind1 );
  1464. /* If there was no method found, then pass the information needed for
  1465. the error reporting. This function rarely returns */
  1466. if (method == Fail)
  1467. {
  1468. Obj args[1];
  1469. args[0] = arg1;
  1470. while (method == Fail)
  1471. method = CallHandleMethodNotFound( oper, 1, (Obj *) args, 0, 0, prec);
  1472. }
  1473. /* update the cache */
  1474. if (method && prec < INTOBJ_INT(CACHE_SIZE))
  1475. {
  1476. cache = 1+ADDR_OBJ( CACHE_OPER( oper, 1 ) );
  1477. cache[3*CacheIndex] = method;
  1478. cache[3*CacheIndex+1] = prec;
  1479. cache[3*CacheIndex+2] = id1;
  1480. CacheIndex = (CacheIndex + 1) % CACHE_SIZE;
  1481. CHANGED_BAG(CACHE_OPER(oper,1));
  1482. }
  1483. #ifdef COUNT_OPERS
  1484. OperationMiss++;
  1485. #endif
  1486. }
  1487. if ( !method ) {
  1488. ErrorQuit( "no method returned", 0L, 0L );
  1489. }
  1490. /* call this method */
  1491. res = CALL_1ARGS( method, arg1 );
  1492. }
  1493. while (res == TRY_NEXT_METHOD );
  1494. /* return the result */
  1495. return res;
  1496. }
  1497. /****************************************************************************
  1498. **
  1499. ** DoOperation2Args( <oper>, <a1>, <a2> )
  1500. */
  1501. Obj DoOperation2Args (
  1502. Obj

Large files files are truncated, but you can click here to view the full file