abc-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
cuddMatMult.c File Reference
#include "misc/util/util_hack.h"
#include "cuddInt.h"

Go to the source code of this file.

Functions

static DdNodeaddMMRecur (DdManager *dd, DdNode *A, DdNode *B, int topP, int *vars)
 
static DdNodeaddTriangleRecur (DdManager *dd, DdNode *f, DdNode *g, int *vars, DdNode *cube)
 
static DdNodecuddAddOuterSumRecur (DdManager *dd, DdNode *M, DdNode *r, DdNode *c)
 
DdNodeCudd_addMatrixMultiply (DdManager *dd, DdNode *A, DdNode *B, DdNode **z, int nz)
 
DdNodeCudd_addTimesPlus (DdManager *dd, DdNode *A, DdNode *B, DdNode **z, int nz)
 
DdNodeCudd_addTriangle (DdManager *dd, DdNode *f, DdNode *g, DdNode **z, int nz)
 
DdNodeCudd_addOuterSum (DdManager *dd, DdNode *M, DdNode *r, DdNode *c)
 

Variables

static
ABC_NAMESPACE_IMPL_START char
rcsid[] 
DD_UNUSED = "$Id: cuddMatMult.c,v 1.17 2004/08/13 18:04:50 fabio Exp $"
 

Function Documentation

static DdNode * addMMRecur ( DdManager dd,
DdNode A,
DdNode B,
int  topP,
int *  vars 
)
static

AutomaticStart

Function********************************************************************

Synopsis [Performs the recursive step of Cudd_addMatrixMultiply.]

Description [Performs the recursive step of Cudd_addMatrixMultiply. Returns a pointer to the result if successful; NULL otherwise.]

SideEffects [None]

Definition at line 333 of file cuddMatMult.c.

339 {
340  DdNode *zero,
341  *At, /* positive cofactor of first operand */
342  *Ae, /* negative cofactor of first operand */
343  *Bt, /* positive cofactor of second operand */
344  *Be, /* negative cofactor of second operand */
345  *t, /* positive cofactor of result */
346  *e, /* negative cofactor of result */
347  *scaled, /* scaled result */
348  *add_scale, /* ADD representing the scaling factor */
349  *res;
350  int i; /* loop index */
351  double scale; /* scaling factor */
352  int index; /* index of the top variable */
354  unsigned int topA, topB, topV;
355  DD_CTFP cacheOp;
356 
357  statLine(dd);
358  zero = DD_ZERO(dd);
359 
360  if (A == zero || B == zero) {
361  return(zero);
362  }
363 
364  if (cuddIsConstant(A) && cuddIsConstant(B)) {
365  /* Compute the scaling factor. It is 2^k, where k is the
366  ** number of summation variables below the current variable.
367  ** Indeed, these constants represent blocks of 2^k identical
368  ** constant values in both A and B.
369  */
370  value = cuddV(A) * cuddV(B);
371  for (i = 0; i < dd->size; i++) {
372  if (vars[i]) {
373  if (dd->perm[i] > topP) {
374  value *= (CUDD_VALUE_TYPE) 2;
375  }
376  }
377  }
378  res = cuddUniqueConst(dd, value);
379  return(res);
380  }
381 
382  /* Standardize to increase cache efficiency. Clearly, A*B != B*A
383  ** in matrix multiplication. However, which matrix is which is
384  ** determined by the variables appearing in the ADDs and not by
385  ** which one is passed as first argument.
386  */
387  if (A > B) {
388  DdNode *tmp = A;
389  A = B;
390  B = tmp;
391  }
392 
393  topA = cuddI(dd,A->index); topB = cuddI(dd,B->index);
394  topV = ddMin(topA,topB);
395 
396  cacheOp = (DD_CTFP) addMMRecur;
397  res = cuddCacheLookup2(dd,cacheOp,A,B);
398  if (res != NULL) {
399  /* If the result is 0, there is no need to normalize.
400  ** Otherwise we count the number of z variables between
401  ** the current depth and the top of the ADDs. These are
402  ** the missing variables that determine the size of the
403  ** constant blocks.
404  */
405  if (res == zero) return(res);
406  scale = 1.0;
407  for (i = 0; i < dd->size; i++) {
408  if (vars[i]) {
409  if (dd->perm[i] > topP && (unsigned) dd->perm[i] < topV) {
410  scale *= 2;
411  }
412  }
413  }
414  if (scale > 1.0) {
415  cuddRef(res);
416  add_scale = cuddUniqueConst(dd,(CUDD_VALUE_TYPE)scale);
417  if (add_scale == NULL) {
418  Cudd_RecursiveDeref(dd, res);
419  return(NULL);
420  }
421  cuddRef(add_scale);
422  scaled = cuddAddApplyRecur(dd,Cudd_addTimes,res,add_scale);
423  if (scaled == NULL) {
424  Cudd_RecursiveDeref(dd, add_scale);
425  Cudd_RecursiveDeref(dd, res);
426  return(NULL);
427  }
428  cuddRef(scaled);
429  Cudd_RecursiveDeref(dd, add_scale);
430  Cudd_RecursiveDeref(dd, res);
431  res = scaled;
432  cuddDeref(res);
433  }
434  return(res);
435  }
436 
437  /* compute the cofactors */
438  if (topV == topA) {
439  At = cuddT(A);
440  Ae = cuddE(A);
441  } else {
442  At = Ae = A;
443  }
444  if (topV == topB) {
445  Bt = cuddT(B);
446  Be = cuddE(B);
447  } else {
448  Bt = Be = B;
449  }
450 
451  t = addMMRecur(dd, At, Bt, (int)topV, vars);
452  if (t == NULL) return(NULL);
453  cuddRef(t);
454  e = addMMRecur(dd, Ae, Be, (int)topV, vars);
455  if (e == NULL) {
456  Cudd_RecursiveDeref(dd, t);
457  return(NULL);
458  }
459  cuddRef(e);
460 
461  index = dd->invperm[topV];
462  if (vars[index] == 0) {
463  /* We have split on either the rows of A or the columns
464  ** of B. We just need to connect the two subresults,
465  ** which correspond to two submatrices of the result.
466  */
467  res = (t == e) ? t : cuddUniqueInter(dd,index,t,e);
468  if (res == NULL) {
469  Cudd_RecursiveDeref(dd, t);
470  Cudd_RecursiveDeref(dd, e);
471  return(NULL);
472  }
473  cuddRef(res);
474  cuddDeref(t);
475  cuddDeref(e);
476  } else {
477  /* we have simultaneously split on the columns of A and
478  ** the rows of B. The two subresults must be added.
479  */
480  res = cuddAddApplyRecur(dd,Cudd_addPlus,t,e);
481  if (res == NULL) {
482  Cudd_RecursiveDeref(dd, t);
483  Cudd_RecursiveDeref(dd, e);
484  return(NULL);
485  }
486  cuddRef(res);
487  Cudd_RecursiveDeref(dd, t);
488  Cudd_RecursiveDeref(dd, e);
489  }
490 
491  cuddCacheInsert2(dd,cacheOp,A,B,res);
492 
493  /* We have computed (and stored in the computed table) a minimal
494  ** result; that is, a result that assumes no summation variables
495  ** between the current depth of the recursion and its top
496  ** variable. We now take into account the z variables by properly
497  ** scaling the result.
498  */
499  if (res != zero) {
500  scale = 1.0;
501  for (i = 0; i < dd->size; i++) {
502  if (vars[i]) {
503  if (dd->perm[i] > topP && (unsigned) dd->perm[i] < topV) {
504  scale *= 2;
505  }
506  }
507  }
508  if (scale > 1.0) {
509  add_scale = cuddUniqueConst(dd,(CUDD_VALUE_TYPE)scale);
510  if (add_scale == NULL) {
511  Cudd_RecursiveDeref(dd, res);
512  return(NULL);
513  }
514  cuddRef(add_scale);
515  scaled = cuddAddApplyRecur(dd,Cudd_addTimes,res,add_scale);
516  if (scaled == NULL) {
517  Cudd_RecursiveDeref(dd, res);
518  Cudd_RecursiveDeref(dd, add_scale);
519  return(NULL);
520  }
521  cuddRef(scaled);
522  Cudd_RecursiveDeref(dd, add_scale);
523  Cudd_RecursiveDeref(dd, res);
524  res = scaled;
525  }
526  }
527  cuddDeref(res);
528  return(res);
529 
530 } /* end of addMMRecur */
#define cuddRef(n)
Definition: cuddInt.h:584
#define cuddDeref(n)
Definition: cuddInt.h:604
void Cudd_RecursiveDeref(DdManager *table, DdNode *n)
Definition: cuddRef.c:154
Definition: cudd.h:278
void cuddCacheInsert2(DdManager *table, DD_CTFP op, DdNode *f, DdNode *g, DdNode *data)
Definition: cuddCache.c:277
DdNode * cuddUniqueConst(DdManager *unique, CUDD_VALUE_TYPE value)
Definition: cuddTable.c:1450
int size
Definition: cuddInt.h:361
DdNode * cuddAddApplyRecur(DdManager *dd, DD_AOP op, DdNode *f, DdNode *g)
Definition: cuddAddApply.c:809
DdNode *(* DD_CTFP)(DdManager *, DdNode *, DdNode *)
Definition: cudd.h:321
#define statLine(dd)
Definition: cuddInt.h:1037
#define cuddV(node)
Definition: cuddInt.h:668
DdNode * cuddCacheLookup2(DdManager *table, DD_CTFP op, DdNode *f, DdNode *g)
Definition: cuddCache.c:502
DdNode * Cudd_addPlus(DdManager *dd, DdNode **f, DdNode **g)
Definition: cuddAddApply.c:168
#define cuddIsConstant(node)
Definition: cuddInt.h:620
#define ddMin(x, y)
Definition: cuddInt.h:818
#define cuddT(node)
Definition: cuddInt.h:636
#define cuddI(dd, index)
Definition: cuddInt.h:686
#define CUDD_VALUE_TYPE
Definition: cudd.h:94
DdHalfWord index
Definition: cudd.h:279
#define cuddE(node)
Definition: cuddInt.h:652
int value
int * invperm
Definition: cuddInt.h:388
static DdNode * addMMRecur(DdManager *dd, DdNode *A, DdNode *B, int topP, int *vars)
Definition: cuddMatMult.c:333
DdNode * Cudd_addTimes(DdManager *dd, DdNode **f, DdNode **g)
Definition: cuddAddApply.c:208
int * perm
Definition: cuddInt.h:386
DdNode * cuddUniqueInter(DdManager *unique, int index, DdNode *T, DdNode *E)
Definition: cuddTable.c:1128
static DdNode * zero
Definition: cuddApa.c:100
#define DD_ZERO(dd)
Definition: cuddInt.h:927
static DdNode * addTriangleRecur ( DdManager dd,
DdNode f,
DdNode g,
int *  vars,
DdNode cube 
)
static

Function********************************************************************

Synopsis [Performs the recursive step of Cudd_addTriangle.]

Description [Performs the recursive step of Cudd_addTriangle. Returns a pointer to the result if successful; NULL otherwise.]

SideEffects [None]

Definition at line 544 of file cuddMatMult.c.

550 {
551  DdNode *fv, *fvn, *gv, *gvn, *t, *e, *res;
553  int top, topf, topg, index;
554 
555  statLine(dd);
556  if (f == DD_PLUS_INFINITY(dd) || g == DD_PLUS_INFINITY(dd)) {
557  return(DD_PLUS_INFINITY(dd));
558  }
559 
560  if (cuddIsConstant(f) && cuddIsConstant(g)) {
561  value = cuddV(f) + cuddV(g);
562  res = cuddUniqueConst(dd, value);
563  return(res);
564  }
565  if (f < g) {
566  DdNode *tmp = f;
567  f = g;
568  g = tmp;
569  }
570 
571  if (f->ref != 1 || g->ref != 1) {
572  res = cuddCacheLookup(dd, DD_ADD_TRIANGLE_TAG, f, g, cube);
573  if (res != NULL) {
574  return(res);
575  }
576  }
577 
578  topf = cuddI(dd,f->index); topg = cuddI(dd,g->index);
579  top = ddMin(topf,topg);
580 
581  if (top == topf) {fv = cuddT(f); fvn = cuddE(f);} else {fv = fvn = f;}
582  if (top == topg) {gv = cuddT(g); gvn = cuddE(g);} else {gv = gvn = g;}
583 
584  t = addTriangleRecur(dd, fv, gv, vars, cube);
585  if (t == NULL) return(NULL);
586  cuddRef(t);
587  e = addTriangleRecur(dd, fvn, gvn, vars, cube);
588  if (e == NULL) {
589  Cudd_RecursiveDeref(dd, t);
590  return(NULL);
591  }
592  cuddRef(e);
593 
594  index = dd->invperm[top];
595  if (vars[index] < 0) {
596  res = (t == e) ? t : cuddUniqueInter(dd,index,t,e);
597  if (res == NULL) {
598  Cudd_RecursiveDeref(dd, t);
599  Cudd_RecursiveDeref(dd, e);
600  return(NULL);
601  }
602  cuddDeref(t);
603  cuddDeref(e);
604  } else {
605  res = cuddAddApplyRecur(dd,Cudd_addMinimum,t,e);
606  if (res == NULL) {
607  Cudd_RecursiveDeref(dd, t);
608  Cudd_RecursiveDeref(dd, e);
609  return(NULL);
610  }
611  cuddRef(res);
612  Cudd_RecursiveDeref(dd, t);
613  Cudd_RecursiveDeref(dd, e);
614  cuddDeref(res);
615  }
616 
617  if (f->ref != 1 || g->ref != 1) {
618  cuddCacheInsert(dd, DD_ADD_TRIANGLE_TAG, f, g, cube, res);
619  }
620 
621  return(res);
622 
623 } /* end of addTriangleRecur */
DdHalfWord ref
Definition: cudd.h:280
#define cuddRef(n)
Definition: cuddInt.h:584
#define DD_ADD_TRIANGLE_TAG
Definition: cuddInt.h:189
#define cuddDeref(n)
Definition: cuddInt.h:604
void Cudd_RecursiveDeref(DdManager *table, DdNode *n)
Definition: cuddRef.c:154
Definition: cudd.h:278
DdNode * cuddUniqueConst(DdManager *unique, CUDD_VALUE_TYPE value)
Definition: cuddTable.c:1450
DdNode * cuddAddApplyRecur(DdManager *dd, DD_AOP op, DdNode *f, DdNode *g)
Definition: cuddAddApply.c:809
void cuddCacheInsert(DdManager *table, ptruint op, DdNode *f, DdNode *g, DdNode *h, DdNode *data)
Definition: cuddCache.c:222
#define statLine(dd)
Definition: cuddInt.h:1037
#define cuddV(node)
Definition: cuddInt.h:668
static DdNode * addTriangleRecur(DdManager *dd, DdNode *f, DdNode *g, int *vars, DdNode *cube)
Definition: cuddMatMult.c:544
#define cuddIsConstant(node)
Definition: cuddInt.h:620
#define ddMin(x, y)
Definition: cuddInt.h:818
#define cuddT(node)
Definition: cuddInt.h:636
#define cuddI(dd, index)
Definition: cuddInt.h:686
#define CUDD_VALUE_TYPE
Definition: cudd.h:94
DdHalfWord index
Definition: cudd.h:279
#define cuddE(node)
Definition: cuddInt.h:652
#define DD_PLUS_INFINITY(dd)
Definition: cuddInt.h:941
int value
int * invperm
Definition: cuddInt.h:388
DdNode * Cudd_addMinimum(DdManager *dd, DdNode **f, DdNode **g)
Definition: cuddAddApply.c:385
DdNode * cuddUniqueInter(DdManager *unique, int index, DdNode *T, DdNode *E)
Definition: cuddTable.c:1128
DdNode * cuddCacheLookup(DdManager *table, ptruint op, DdNode *f, DdNode *g, DdNode *h)
Definition: cuddCache.c:369
DdNode* Cudd_addMatrixMultiply ( DdManager dd,
DdNode A,
DdNode B,
DdNode **  z,
int  nz 
)

AutomaticEnd Function********************************************************************

Synopsis [Calculates the product of two matrices represented as ADDs.]

Description [Calculates the product of two matrices, A and B, represented as ADDs. This procedure implements the quasiring multiplication algorithm. A is assumed to depend on variables x (rows) and z (columns). B is assumed to depend on variables z (rows) and y (columns). The product of A and B then depends on x (rows) and y (columns). Only the z variables have to be explicitly identified; they are the "summation" variables. Returns a pointer to the result if successful; NULL otherwise.]

SideEffects [None]

SeeAlso [Cudd_addTimesPlus Cudd_addTriangle Cudd_bddAndAbstract]

Definition at line 132 of file cuddMatMult.c.

138 {
139  int i, nvars, *vars;
140  DdNode *res;
141 
142  /* Array vars says what variables are "summation" variables. */
143  nvars = dd->size;
144  vars = ABC_ALLOC(int,nvars);
145  if (vars == NULL) {
147  return(NULL);
148  }
149  for (i = 0; i < nvars; i++) {
150  vars[i] = 0;
151  }
152  for (i = 0; i < nz; i++) {
153  vars[z[i]->index] = 1;
154  }
155 
156  do {
157  dd->reordered = 0;
158  res = addMMRecur(dd,A,B,-1,vars);
159  } while (dd->reordered == 1);
160  ABC_FREE(vars);
161  return(res);
162 
163 } /* end of Cudd_addMatrixMultiply */
Definition: cudd.h:278
int size
Definition: cuddInt.h:361
#define ABC_ALLOC(type, num)
Definition: abc_global.h:229
int reordered
Definition: cuddInt.h:409
DdHalfWord index
Definition: cudd.h:279
#define ABC_FREE(obj)
Definition: abc_global.h:232
static DdNode * addMMRecur(DdManager *dd, DdNode *A, DdNode *B, int topP, int *vars)
Definition: cuddMatMult.c:333
Cudd_ErrorType errorCode
Definition: cuddInt.h:447
DdNode* Cudd_addOuterSum ( DdManager dd,
DdNode M,
DdNode r,
DdNode c 
)

Function********************************************************************

Synopsis [Takes the minimum of a matrix and the outer sum of two vectors.]

Description [Takes the pointwise minimum of a matrix and the outer sum of two vectors. This procedure is used in the Floyd-Warshall all-pair shortest path algorithm. Returns a pointer to the result if successful; NULL otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 296 of file cuddMatMult.c.

301 {
302  DdNode *res;
303 
304  do {
305  dd->reordered = 0;
306  res = cuddAddOuterSumRecur(dd, M, r, c);
307  } while (dd->reordered == 1);
308  return(res);
309 
310 } /* end of Cudd_addOuterSum */
Definition: cudd.h:278
int reordered
Definition: cuddInt.h:409
static DdNode * cuddAddOuterSumRecur(DdManager *dd, DdNode *M, DdNode *r, DdNode *c)
Definition: cuddMatMult.c:639
DdNode* Cudd_addTimesPlus ( DdManager dd,
DdNode A,
DdNode B,
DdNode **  z,
int  nz 
)

Function********************************************************************

Synopsis [Calculates the product of two matrices represented as ADDs.]

Description [Calculates the product of two matrices, A and B, represented as ADDs, using the CMU matrix by matrix multiplication procedure by Clarke et al.. Matrix A has x's as row variables and z's as column variables, while matrix B has z's as row variables and y's as column variables. Returns the pointer to the result if successful; NULL otherwise. The resulting matrix has x's as row variables and y's as column variables.]

SideEffects [None]

SeeAlso [Cudd_addMatrixMultiply]

Definition at line 185 of file cuddMatMult.c.

191 {
192  DdNode *w, *cube, *tmp, *res;
193  int i;
194  tmp = Cudd_addApply(dd,Cudd_addTimes,A,B);
195  if (tmp == NULL) return(NULL);
196  Cudd_Ref(tmp);
197  Cudd_Ref(cube = DD_ONE(dd));
198  for (i = nz-1; i >= 0; i--) {
199  w = Cudd_addIte(dd,z[i],cube,DD_ZERO(dd));
200  if (w == NULL) {
201  Cudd_RecursiveDeref(dd,tmp);
202  return(NULL);
203  }
204  Cudd_Ref(w);
205  Cudd_RecursiveDeref(dd,cube);
206  cube = w;
207  }
208  res = Cudd_addExistAbstract(dd,tmp,cube);
209  if (res == NULL) {
210  Cudd_RecursiveDeref(dd,tmp);
211  Cudd_RecursiveDeref(dd,cube);
212  return(NULL);
213  }
214  Cudd_Ref(res);
215  Cudd_RecursiveDeref(dd,cube);
216  Cudd_RecursiveDeref(dd,tmp);
217  Cudd_Deref(res);
218  return(res);
219 
220 } /* end of Cudd_addTimesPlus */
void Cudd_RecursiveDeref(DdManager *table, DdNode *n)
Definition: cuddRef.c:154
Definition: cudd.h:278
void Cudd_Deref(DdNode *node)
Definition: cuddRef.c:438
DdNode * Cudd_addApply(DdManager *dd, DdNode *(*)(DdManager *, DdNode **, DdNode **), DdNode *f, DdNode *g)
DdNode * Cudd_addIte(DdManager *dd, DdNode *f, DdNode *g, DdNode *h)
Definition: cuddAddIte.c:129
DdNode * Cudd_addExistAbstract(DdManager *manager, DdNode *f, DdNode *cube)
Definition: cuddAddAbs.c:129
void Cudd_Ref(DdNode *n)
Definition: cuddRef.c:129
#define DD_ONE(dd)
Definition: cuddInt.h:911
DdNode * Cudd_addTimes(DdManager *dd, DdNode **f, DdNode **g)
Definition: cuddAddApply.c:208
#define DD_ZERO(dd)
Definition: cuddInt.h:927
DdNode* Cudd_addTriangle ( DdManager dd,
DdNode f,
DdNode g,
DdNode **  z,
int  nz 
)

Function********************************************************************

Synopsis [Performs the triangulation step for the shortest path computation.]

Description [Implements the semiring multiplication algorithm used in the triangulation step for the shortest path computation. f is assumed to depend on variables x (rows) and z (columns). g is assumed to depend on variables z (rows) and y (columns). The product of f and g then depends on x (rows) and y (columns). Only the z variables have to be explicitly identified; they are the "abstraction" variables. Returns a pointer to the result if successful; NULL otherwise. ]

SideEffects [None]

SeeAlso [Cudd_addMatrixMultiply Cudd_bddAndAbstract]

Definition at line 243 of file cuddMatMult.c.

249 {
250  int i, nvars, *vars;
251  DdNode *res, *cube;
252 
253  nvars = dd->size;
254  vars = ABC_ALLOC(int, nvars);
255  if (vars == NULL) {
257  return(NULL);
258  }
259  for (i = 0; i < nvars; i++) vars[i] = -1;
260  for (i = 0; i < nz; i++) vars[z[i]->index] = i;
261  cube = Cudd_addComputeCube(dd, z, NULL, nz);
262  if (cube == NULL) {
263  ABC_FREE(vars);
264  return(NULL);
265  }
266  cuddRef(cube);
267 
268  do {
269  dd->reordered = 0;
270  res = addTriangleRecur(dd, f, g, vars, cube);
271  } while (dd->reordered == 1);
272  if (res != NULL) cuddRef(res);
273  Cudd_RecursiveDeref(dd,cube);
274  if (res != NULL) cuddDeref(res);
275  ABC_FREE(vars);
276  return(res);
277 
278 } /* end of Cudd_addTriangle */
#define cuddRef(n)
Definition: cuddInt.h:584
#define cuddDeref(n)
Definition: cuddInt.h:604
void Cudd_RecursiveDeref(DdManager *table, DdNode *n)
Definition: cuddRef.c:154
Definition: cudd.h:278
DdNode * Cudd_addComputeCube(DdManager *dd, DdNode **vars, int *phase, int n)
Definition: cuddUtil.c:2246
int size
Definition: cuddInt.h:361
#define ABC_ALLOC(type, num)
Definition: abc_global.h:229
int reordered
Definition: cuddInt.h:409
static DdNode * addTriangleRecur(DdManager *dd, DdNode *f, DdNode *g, int *vars, DdNode *cube)
Definition: cuddMatMult.c:544
#define ABC_FREE(obj)
Definition: abc_global.h:232
Cudd_ErrorType errorCode
Definition: cuddInt.h:447
static DdNode * cuddAddOuterSumRecur ( DdManager dd,
DdNode M,
DdNode r,
DdNode c 
)
static

Function********************************************************************

Synopsis [Performs the recursive step of Cudd_addOuterSum.]

Description [Performs the recursive step of Cudd_addOuterSum. Returns a pointer to the result if successful; NULL otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 639 of file cuddMatMult.c.

644 {
645  DdNode *P, *R, *Mt, *Me, *rt, *re, *ct, *ce, *Rt, *Re;
646  int topM, topc, topr;
647  int v, index;
648 
649  statLine(dd);
650  /* Check special cases. */
651  if (r == DD_PLUS_INFINITY(dd) || c == DD_PLUS_INFINITY(dd)) return(M);
652 
653  if (cuddIsConstant(c) && cuddIsConstant(r)) {
654  R = cuddUniqueConst(dd,Cudd_V(c)+Cudd_V(r));
655  cuddRef(R);
656  if (cuddIsConstant(M)) {
657  if (cuddV(R) <= cuddV(M)) {
658  cuddDeref(R);
659  return(R);
660  } else {
661  Cudd_RecursiveDeref(dd,R);
662  return(M);
663  }
664  } else {
665  P = Cudd_addApply(dd,Cudd_addMinimum,R,M);
666  cuddRef(P);
667  Cudd_RecursiveDeref(dd,R);
668  cuddDeref(P);
669  return(P);
670  }
671  }
672 
673  /* Check the cache. */
674  R = cuddCacheLookup(dd,DD_ADD_OUT_SUM_TAG,M,r,c);
675  if (R != NULL) return(R);
676 
677  topM = cuddI(dd,M->index); topr = cuddI(dd,r->index);
678  topc = cuddI(dd,c->index);
679  v = ddMin(topM,ddMin(topr,topc));
680 
681  /* Compute cofactors. */
682  if (topM == v) { Mt = cuddT(M); Me = cuddE(M); } else { Mt = Me = M; }
683  if (topr == v) { rt = cuddT(r); re = cuddE(r); } else { rt = re = r; }
684  if (topc == v) { ct = cuddT(c); ce = cuddE(c); } else { ct = ce = c; }
685 
686  /* Recursively solve. */
687  Rt = cuddAddOuterSumRecur(dd,Mt,rt,ct);
688  if (Rt == NULL) return(NULL);
689  cuddRef(Rt);
690  Re = cuddAddOuterSumRecur(dd,Me,re,ce);
691  if (Re == NULL) {
692  Cudd_RecursiveDeref(dd, Rt);
693  return(NULL);
694  }
695  cuddRef(Re);
696  index = dd->invperm[v];
697  R = (Rt == Re) ? Rt : cuddUniqueInter(dd,index,Rt,Re);
698  if (R == NULL) {
699  Cudd_RecursiveDeref(dd, Rt);
700  Cudd_RecursiveDeref(dd, Re);
701  return(NULL);
702  }
703  cuddDeref(Rt);
704  cuddDeref(Re);
705 
706  /* Store the result in the cache. */
708 
709  return(R);
710 
711 } /* end of cuddAddOuterSumRecur */
#define cuddRef(n)
Definition: cuddInt.h:584
#define DD_ADD_OUT_SUM_TAG
Definition: cuddInt.h:187
#define cuddDeref(n)
Definition: cuddInt.h:604
void Cudd_RecursiveDeref(DdManager *table, DdNode *n)
Definition: cuddRef.c:154
Definition: cudd.h:278
DdNode * cuddUniqueConst(DdManager *unique, CUDD_VALUE_TYPE value)
Definition: cuddTable.c:1450
static byte P[256]
Definition: kitPerm.c:76
void cuddCacheInsert(DdManager *table, ptruint op, DdNode *f, DdNode *g, DdNode *h, DdNode *data)
Definition: cuddCache.c:222
DdNode * Cudd_addApply(DdManager *dd, DdNode *(*)(DdManager *, DdNode **, DdNode **), DdNode *f, DdNode *g)
word M(word f1, word f2, int n)
Definition: kitPerm.c:240
#define statLine(dd)
Definition: cuddInt.h:1037
#define cuddV(node)
Definition: cuddInt.h:668
static DdNode * cuddAddOuterSumRecur(DdManager *dd, DdNode *M, DdNode *r, DdNode *c)
Definition: cuddMatMult.c:639
#define cuddIsConstant(node)
Definition: cuddInt.h:620
#define ddMin(x, y)
Definition: cuddInt.h:818
#define cuddT(node)
Definition: cuddInt.h:636
#define Cudd_V(node)
Definition: cudd.h:470
#define cuddI(dd, index)
Definition: cuddInt.h:686
DdHalfWord index
Definition: cudd.h:279
#define cuddE(node)
Definition: cuddInt.h:652
#define DD_PLUS_INFINITY(dd)
Definition: cuddInt.h:941
int * invperm
Definition: cuddInt.h:388
DdNode * Cudd_addMinimum(DdManager *dd, DdNode **f, DdNode **g)
Definition: cuddAddApply.c:385
DdNode * cuddUniqueInter(DdManager *unique, int index, DdNode *T, DdNode *E)
Definition: cuddTable.c:1128
DdNode * cuddCacheLookup(DdManager *table, ptruint op, DdNode *f, DdNode *g, DdNode *h)
Definition: cuddCache.c:369

Variable Documentation

ABC_NAMESPACE_IMPL_START char rcsid [] DD_UNUSED = "$Id: cuddMatMult.c,v 1.17 2004/08/13 18:04:50 fabio Exp $"
static

CFile***********************************************************************

FileName [cuddMatMult.c]

PackageName [cudd]

Synopsis [Matrix multiplication functions.]

Description [External procedures included in this module:

Static procedures included in this module:

]

Author [Fabio Somenzi]

Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado

All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.]

Definition at line 87 of file cuddMatMult.c.