Actual source code: taovec.c

  1: #include "tao_general.h"          /*I "tao_solver.h"  I*/
  2: #include "taovec.h"

  6: /*@C
  7:    TaoVecDestroy - Destroys the TaoVec object.

  9:    Input Parameter:
 10: .  vv - the vector

 12:    Level: beginner
 13: @*/
 14: int TaoVecDestroy( TaoVec* vv){
 15:   TaoFunctionBegin;
 16:   if (vv!=TAO_NULL && vv!=0){ 
 17:     delete vv;
 18:   }
 19:   vv=TAO_NULL;
 20:   TaoFunctionReturn(0);
 21: }

 25: /*@C
 26:    CloneVecs - Creates an array of pointers to new TaoVec objects. The new 
 27:    objects have the same structure as this one.

 29:    Input Parameter:
 30: .  nn -  number of new vectors

 32:    Output Parameter:
 33: .  tvs -  pointer to array TaoVec pointers

 35: .seealso TaoVec::Clone()

 37:    Level: intermediate
 38: @*/
 39: int TaoVec::CloneVecs(int nn, TaoVec***tvs){
 40:   int i,info;
 41:   TaoVec ** ntv;
 42:   TaoFunctionBegin;
 43:   ntv = new TaoVec*[nn];
 44:   for (i=0;i<nn;i++){
 45:     info = this->Clone(&ntv[i]);CHKERRQ(info);
 46:   }
 47:   *tvs=ntv;
 48:   TaoFunctionReturn(0);
 49: }

 53: /*@C
 54:    DestroyVecs - Destroys an array TaoVec objects.

 56:    Input Parameter:
 57: +  nn -  number of new vectors
 58: -  tvs -  pointer to array TaoVec pointers

 60:    Level: advanced

 62: .seealso TaoVec::CloneVecs()
 63: @*/
 64: int TaoVec::DestroyVecs(int nn, TaoVec**ntv){
 65:   int i,info;
 66:   TaoFunctionBegin;
 67:   for (i=0;i<nn;i++){
 68:     info = TaoVecDestroy( ntv[i] );CHKERRQ(info);
 69:   }
 70:   delete[] ntv;
 71:   TaoFunctionReturn(0);
 72: }

 76: /*@C
 77:    Clone - Creates a new TaoVec object with the same structure as this one.  It does not
 78:    copy the value to the new vector.

 80:    Input:
 81: .  vv - address of a pointer to a TaoVec

 83:    Output Parameter:
 84: .  vv - address of a pointer to new TaoVec object

 86: .seealso TaoVec::CloneVecs(), TaoVec::CopyFrom()

 88:    Level: intermediate
 89: @*/
 90: int TaoVec::Clone( TaoVec* *vv ){
 91:   TaoFunctionBegin;
 92:   SETERRQ(56,"Operation not defined");
 93:   /* TaoFunctionReturn(1); */
 94: }

 98: /*@C
 99:    Compatible - Determines whether this vector belongs to the same space as another,
100:    and operations such as inner product and sum are well defined.

102:    Input Parameter:
103: .  vv -  TAO vector to which to the comparison is made

105:    Output Value:
106: .  flag - TAO_TRUE if the two vectors are Compatible and TAO_FALSE otherwise.

108:    Level: advanced

110: .seealso TaoVec::GetDimension()
111: @*/
112: int TaoVec::Compatible(TaoVec* vv, TaoTruth *flag){
113:   TaoFunctionBegin;
114:   if (!flag){
115:     TaoFunctionReturn(1);
116:   }
117:   *flag=TAO_FALSE;
118:   TaoFunctionReturn(0);
119: }

123: /*@C
124:    SetToConstant - Sets each element of this vector equal to the specified constant.

126:    Input Parameter:
127: .  c -  a constant

129:    Level: intermediate

131: .seealso TaoVec::Scale()
132: @*/
133: int TaoVec::SetToConstant( double c ){
134:   int i,nn,info;
135:   TaoScalar *tptr;

137:   TaoFunctionBegin;
138:   info = this->GetArray(&tptr,&nn);CHKERRQ(info);
139:   for (i=0;i<nn;i++){ tptr[i]=c; }
140:   info = this->RestoreArray(&tptr,&nn);CHKERRQ(info);
141:   TaoFunctionReturn(0);
142: }

146: /*@C
147:    SetToZero - Sets each element of this vector equal to zero.

149:    Input Parameters: none

151:    Level: intermediate

153: .seealso TaoVec::SetToConstant()
154: @*/
155: int TaoVec::SetToZero(){
156:   int i,nn,info;
157:   TaoScalar *tptr;

159:   TaoFunctionBegin;
160:   info = this->GetArray(&tptr,&nn);CHKERRQ(info);
161:   for (i=0;i<nn;i++){ tptr[i]=0; }
162:   info = this->RestoreArray(&tptr,&nn);CHKERRQ(info);
163:   TaoFunctionReturn(0);
164: }

168: /*@C
169:    CopyFrom - Copies the contents of one vector into this vector.

171:    Input Parameter:
172: .  vv -  A TaoVec from which the contents will be copied.

174:    Level: intermediate

176: .seealso TaoVec::Axpy(), TaoVec::ScaleCopyFrom()
177: @*/
178: int TaoVec::CopyFrom( TaoVec* vv ){
179:   int i,nn1,nn2,info;
180:   TaoScalar *tptr1,*tptr2;

182:   TaoFunctionBegin;
183:   info = this->GetArray(&tptr1,&nn1);CHKERRQ(info);
184:   if (vv!=this){
185:     info = vv->GetArray(&tptr2,&nn2);CHKERRQ(info);
186:     if (nn1!=nn2) {TaoFunctionReturn(1);}
187:     for (i=0;i<nn1;i++){ tptr1[i]=tptr2[i]; }
188:     info = vv->RestoreArray(&tptr2,&nn2);CHKERRQ(info);
189:   }
190:   info = this->RestoreArray(&tptr1,&nn1);CHKERRQ(info);
191:   TaoFunctionReturn(0);
192: }

196: /*@C
197:    ScaleCopyFrom - Copies the contents of one vector into this vector and scales it.

199:    Input Parameter:
200: +  a - the scalar 
201: -  vv -  A TaoVec from which the contents will be copied.

203:    Level: intermediate

205: .seealso TaoVec::Axpy(), TaoVec::Aypx()
206: @*/
207: int TaoVec::ScaleCopyFrom( double a, TaoVec* vv ){
208:   int i,nn1,nn2,info;
209:   TaoScalar *tptr1,*tptr2;

211:   TaoFunctionBegin;
212:   info = this->GetArray(&tptr1,&nn1);CHKERRQ(info);
213:   if (vv!=this){
214:     info = vv->GetArray(&tptr2,&nn2);CHKERRQ(info);
215:     if (nn1!=nn2) {TaoFunctionReturn(1);}
216:     for (i=0;i<nn1;i++){ tptr1[i]=a*tptr2[i]; }
217:     info = vv->RestoreArray(&tptr2,&nn2);CHKERRQ(info);
218:   } else {
219:     this->Scale(a);
220:   }
221:   info = this->RestoreArray(&tptr1,&nn1);CHKERRQ(info);
222:   TaoFunctionReturn(0);
223: }

227: /*@C
228:    NormInfinity - Computes the infinity norm of this vector.

230:    Ouput Parameter:
231: .  vnorm -  the infinity norm of this vector

233:    Level: intermediate

235: .seealso TaoVec::Norm1(), TaoVec::Norm2()
236: @*/
237: int TaoVec::NormInfinity(double *vnorm){
238:   int i,nn,info;
239:   TaoScalar dd=0, *v;

241:   TaoFunctionBegin;
242:   info = this->GetArray(&v,&nn);CHKERRQ(info);
243:   for (i=0;i<nn;i++){
244:     if (v[i]<0 && v[i]<-dd) dd=-v[i];
245:     else if (v[i]>0 && v[i]>dd) dd=v[i];
246:   }
247:   info = this->RestoreArray(&v,&nn);CHKERRQ(info);
248:   *vnorm=dd;
249:   TaoFunctionReturn(0);
250: }

254: /*@C
255:    Norm1 - Computes the one-norm of this vector.

257:    Ouput Parameter:
258: .  vnorm -  the one-norm of this vector

260:    Level: intermediate

262: .seealso TaoVec::NormInfinity(), TaoVec::Norm2()
263: @*/
264: int TaoVec::Norm1(double *vnorm){
265:   int i,nn,info;
266:   TaoScalar dd=0, *v;

268:   TaoFunctionBegin;
269:   info = this->GetArray(&v,&nn);CHKERRQ(info);
270:   for (i=0;i<nn;i++){ 
271:     if (v[i]<0) dd-=v[i]; 
272:     else dd+=v[i];
273:   }
274:   info = this->RestoreArray(&v,&nn);CHKERRQ(info);
275:   TaoFunctionReturn(0);
276: }

280: /*@C
281:    Norm2 - Compute the two-norm of this vector.

283:    Ouput Parameter:
284: .  vnorm -  the two-norm of this vector

286:    Level: intermediate

288: .seealso TaoVec::Norm1(), TaoVec::NormInfinity(), TaoVec::Norm2squared()
289: @*/
290: int TaoVec::Norm2(double *vnorm){
291:   int i,nn,info;
292:   TaoScalar dd=0, *v;

294:   TaoFunctionBegin;
295:   info = this->GetArray(&v,&nn);CHKERRQ(info);
296:   for (i=0;i<nn;i++) dd+=v[i]*v[i];
297:   *vnorm=sqrt(dd);
298:   info = this->RestoreArray(&v,&nn);CHKERRQ(info);
299:   TaoFunctionReturn(0);
300: }

304: /*@C
305:    Norm2squared - Computes the square of the two norm of this vector.

307:    Ouput Parameter:
308: .  vnorm2 -  the square of the two norm of this vector

310:    Level: intermediate

312: .seealso TaoVec::Norm2()
313: @*/
314: int TaoVec::Norm2squared(double *vnorm2){
315:   int i,nn,info;
316:   TaoScalar dd=0, *v;

318:   TaoFunctionBegin;
319:   info = this->GetArray(&v,&nn);CHKERRQ(info);
320:   for (i=0;i<nn;i++) dd+=v[i]*v[i];
321:   *vnorm2=dd;
322:   info = this->RestoreArray(&v,&nn);CHKERRQ(info);
323:   TaoFunctionReturn(0);
324: }

328: /*@C
329:    Scale - Multiplies this vector by a scalar.

331:    Input Parameter:
332: .  alpha -  the scalar

334:    Level: intermediate

336: .seealso TaoVec::SetToConstant(),  TaoVec::Aypx()
337: @*/
338: int TaoVec::Scale( double alpha ){
339:   int i,nn,info;
340:   TaoScalar *v;

342:   TaoFunctionBegin;
343:   info = this->GetArray(&v,&nn);CHKERRQ(info);
344:   for (i=0;i<nn;i++) v[i]*=alpha;
345:   info = this->RestoreArray(&v,&nn);CHKERRQ(info);
346:   TaoFunctionReturn(0);
347: }

351: /*@C
352:    Axpy - Adds a scalar multiple of a vector to this vector. (this += alpha * xx)

354:    Input Parameter:
355: +  alpha -  the scalar 
356: -  xx - the vector

358:    Level: intermediate

360: .seealso TaoVec::CopyFrom(), TaoVec::Aypx() 
361: @*/
362: int TaoVec::Axpy( double alpha, TaoVec* xx ){
363:   int i,nn1,nn2,info;
364:   TaoScalar *tptr1,*tptr2;

366:   TaoFunctionBegin;
367:   info = this->GetArray(&tptr1,&nn1);CHKERRQ(info);
368:   info = xx->GetArray(&tptr2,&nn2);CHKERRQ(info);
369:   if (nn1!=nn2) {TaoFunctionReturn(1);}
370:   for (i=0;i<nn1;i++){ tptr1[i]+= alpha * tptr2[i]; }
371:   info = this->RestoreArray(&tptr1,&nn1);CHKERRQ(info);
372:   info = xx->RestoreArray(&tptr2,&nn2);CHKERRQ(info);
373:   TaoFunctionReturn(0);
374: }

378: /*@C
379:    Axpby - Adds a scalar multiple of a vector to a multiple of this vector. (this=alpha*xx + beta*this)

381:    Input Parameter:
382: +  alpha -  the scalar of tx
383: .  xx - the vector
384: -  beta -  the scalar multiple of this vector

386:    Level: intermediate

388: .seealso TaoVec::Axpy(), TaoVec::Aypx() 
389: @*/
390: int TaoVec::Axpby( double alpha, TaoVec* xx, double beta ){
391:   int i,nn1,nn2,info;
392:   TaoScalar *tptr1,*tptr2;

394:   TaoFunctionBegin;
395:   info = this->GetArray(&tptr1,&nn1);CHKERRQ(info);
396:   info = xx->GetArray(&tptr2,&nn2);CHKERRQ(info);
397:   if (nn1!=nn2) {TaoFunctionReturn(1);}
398:   for (i=0;i<nn1;i++){ tptr1[i] = beta * tptr1[i] + alpha * tptr2[i]; }
399:   info = this->RestoreArray(&tptr1,&nn1);CHKERRQ(info);
400:   info = xx->RestoreArray(&tptr2,&nn2);CHKERRQ(info);
401:   TaoFunctionReturn(0);
402: }

406: /*@C
407:    Aypx - Adds a vector to a scalar multiple of this vector. (this=alpha*this+xx)

409:    Input Parameter:
410: +  alpha -  the scalar 
411: -  xx - the vector

413:    Level: intermediate

415: .seealso TaoVec::Scale(), TaoVec::Axpy()
416: @*/
417: int TaoVec::Aypx( double alpha, TaoVec* xx ){
418:   int i,nn1,nn2,info;
419:   TaoScalar *tptr1,*tptr2;

421:   TaoFunctionBegin;
422:   info = this->GetArray(&tptr1,&nn1);CHKERRQ(info);
423:   info = xx->GetArray(&tptr2,&nn2);CHKERRQ(info);
424:   if (nn1!=nn2) {TaoFunctionReturn(1);}
425:   for (i=0;i<nn1;i++){ tptr1[i] = alpha * tptr1[i] + tptr2[i]; }
426:   info = this->RestoreArray(&tptr1,&nn1);CHKERRQ(info);
427:   info = xx->RestoreArray(&tptr2,&nn2);CHKERRQ(info);
428:   TaoFunctionReturn(0);
429: }
430:  
433: /*@C
434:    AddConstant - Adds a constant to each element of this vector.

436:    Input Parameter:
437: .  alpha -  the scalar 

439:    Level: intermediate

441: .seealso TaoVec::SetToConstant(), TaoVec::Axpy() 
442: @*/
443: int TaoVec::AddConstant( double alpha ){
444:   int i,nn,info;
445:   TaoScalar *v;

447:   TaoFunctionBegin;
448:   info = this->GetArray(&v,&nn);CHKERRQ(info);
449:   for (i=0;i<nn;i++) v[i]+=alpha;
450:   info = this->RestoreArray(&v,&nn);CHKERRQ(info);
451:   TaoFunctionReturn(0);
452: }

456: /*@C
457:    Dot - Computes the inner product of this vector with another vector.

459:    Input Parameter:
460: .  vv -  another TaoVec object

462:    Output Parameter:
463: .  vDotv -  the inner product of the two vectors

465:    Level: intermediate

467: .seealso TaoVec::Norm() 
468: @*/
469: int TaoVec::Dot( TaoVec* vv, double *vDotv ){
470:   int i,nn1,nn2,info;
471:   TaoScalar dd=0,*tptr1,*tptr2;

473:   TaoFunctionBegin;
474:   info = this->GetArray(&tptr1,&nn1);CHKERRQ(info);
475:   info = vv->GetArray(&tptr2,&nn2);CHKERRQ(info);
476:   if (nn1!=nn2) {TaoFunctionReturn(1);}
477:   for (i=0;i<nn1;i++) dd+=tptr1[i]*tptr2[i];
478:   info = this->RestoreArray(&tptr1,&nn1);CHKERRQ(info);
479:   info = vv->RestoreArray(&tptr2,&nn2);CHKERRQ(info);
480:   *vDotv=dd;
481:   TaoFunctionReturn(0);
482: }

486: /*@C
487:    Negate - Multiplies the elements of this vector by negative one.

489:    Input Parameters: none

491:    Level: intermediate

493: .seealso TaoVec::Scale()
494: @*/
495: int TaoVec::Negate(){ 
496:   int i,nn,info;
497:   TaoScalar *v;

499:   TaoFunctionBegin;
500:   info = this->GetArray(&v,&nn);CHKERRQ(info);
501:   for (i=0;i<nn;i++) v[i]=-v[i];
502:   info = this->RestoreArray(&v,&nn);CHKERRQ(info);
503:   TaoFunctionReturn(0);
504: }

508: /*@C
509:    Reciprocal - Sets each element of this vector to its Reciprocal.

511:    Input Parameters: none

513:    Level: intermediate

515: .seealso TaoVec::PointwiseDivide()
516: @*/
517: int TaoVec::Reciprocal(){ 
518:   int i,nn,info;
519:   TaoScalar *v;

521:   TaoFunctionBegin;
522:   info = this->GetArray(&v,&nn);CHKERRQ(info);
523:   for (i=0;i<nn;i++){ 
524:     if (v[i]!=0)  v[i]= 1.0/v[i];
525:     else v[i]=TAO_INFINITY;
526:   }
527:   info = this->RestoreArray(&v,&nn);CHKERRQ(info);
528:   TaoFunctionReturn(0);
529: }

533: /*@C
534:    Sqrt - Sets each element of this vector to its square root.

536:    Input Parameters: none

538:    Level: intermediate

540: @*/
541: int TaoVec::Sqrt(){ 
542:   int i,nn,info;
543:   TaoScalar *v;

545:   TaoFunctionBegin;
546:   info = this->GetArray(&v,&nn);CHKERRQ(info);
547:   for (i=0;i<nn;i++){ 
548:     if (v[i] >= 0) {
549:       v[i] = sqrt(v[i]);
550:     }
551:     else {
552:       v[i] = TAO_INFINITY;
553:     }
554:   }
555:   info = this->RestoreArray(&v,&nn);CHKERRQ(info);
556:   TaoFunctionReturn(0);
557: }

561: /*@C
562:    Pow - Raises each element of this vector to a power.

564:    Input Parameters: none

566:    Level: intermediate

568: @*/
569: int TaoVec::Pow(double p){ 
570:   int i,nn,info;
571:   TaoScalar *v;

573:   TaoFunctionBegin;
574:   info = this->GetArray(&v,&nn);CHKERRQ(info);
575:   for (i=0;i<nn;i++){ 
576:     if (v[i] >= 0) {
577:       v[i] = pow(v[i], p);
578:     }
579:     else {
580:       v[i] = TAO_INFINITY;
581:     }
582:   }
583:   info = this->RestoreArray(&v,&nn);CHKERRQ(info);
584:   TaoFunctionReturn(0);
585: }

589: /*@C
590:    GetDimension - Gets the dimension of the vector space where this vector belongs.

592:    Output Parameter:
593: .  n - the dimension of the vector space

595:    Level: intermediate

597: .seealso TaoVec::Compatible()
598: @*/
599: int TaoVec::GetDimension(int *n){
600:   TaoFunctionBegin;
601:   SETERRQ(56,"Operation not defined");
602:   /* TaoFunctionReturn(1); */
603: }

607: /*@C
608:    PointwiseMultiply - Computes the componentwise multiplication of two vectors 
609:    and stores the result in this vector.

611:    Input Parameters:
612: .   vv, ww - the two vectors

614:    Level: intermediate

616: .seealso TaoVec::PointwiseDivide()
617: @*/
618: int TaoVec::PointwiseMultiply( TaoVec* vv, TaoVec* ww ){
619:   int i,nn1,nn2,nn3,info;
620:   TaoScalar *tptr1,*tptr2,*tptr3;

622:   TaoFunctionBegin;
623:   info = this->GetArray(&tptr1,&nn1);CHKERRQ(info);
624:   if (this!=vv){ 
625:     info = vv->GetArray(&tptr2,&nn2);CHKERRQ(info);
626:   } else {
627:     tptr2=tptr1; nn2=nn1;
628:   }
629:   if (this!=ww && vv!=ww){ 
630:     info = ww->GetArray(&tptr3,&nn3);CHKERRQ(info);
631:   } else if (vv==ww){ 
632:     tptr3=tptr2; nn3=nn2;
633:   } else {
634:     tptr3=tptr1; nn3=nn1;
635:   }
636:   if (nn1!=nn2 || nn2!=nn3) {TaoFunctionReturn(1);}
637:   for (i=0;i<nn1;i++) tptr1[i]=tptr2[i] * tptr3[i];
638:   info = this->RestoreArray(&tptr1,&nn1);CHKERRQ(info);
639:   if (this!=vv){ 
640:     info = vv->RestoreArray(&tptr2,&nn2);CHKERRQ(info);
641:   }
642:   if (this!=ww && vv!=ww){ 
643:     info = ww->RestoreArray(&tptr3,&nn3);CHKERRQ(info);
644:   }

646:   TaoFunctionReturn(0);
647: }

651: /*@C
652:    PointwiseDivide - Computes the componentwise division of two vectors 
653:    and stores the result in this vector.

655:    Input Parameters:
656: +  vv - the vector of numerators
657: -  ww - the vector of denominators

659:    Level: intermediate

661: .seealso TaoVec::PointwiseMultiply()
662: @*/
663: int TaoVec::PointwiseDivide( TaoVec* vv , TaoVec* ww){
664:   int i,nn1,nn2,nn3,info;
665:   TaoScalar *tptr1,*tptr2,*tptr3;

667:   TaoFunctionBegin;
668:   info = this->GetArray(&tptr1,&nn1);CHKERRQ(info);
669:   if (this!=vv){ 
670:     info = vv->GetArray(&tptr2,&nn2);CHKERRQ(info);
671:   } else {
672:     tptr2=tptr1; nn2=nn1;
673:   }
674:   if (this!=ww && vv!=ww){ 
675:     info = ww->GetArray(&tptr3,&nn3);CHKERRQ(info);
676:   } else if (vv==ww){
677:     tptr3=tptr2; nn3=nn2;
678:   } else {
679:     tptr3=tptr1; nn3=nn1;
680:   }
681:   if (nn1!=nn2 || nn2!=nn3) {TaoFunctionReturn(1);}
682:   for (i=0;i<nn1;i++) tptr1[i]=tptr2[i] / tptr3[i];
683:   info = this->RestoreArray(&tptr1,&nn1);CHKERRQ(info);
684:   if (this!=vv){ 
685:     info = vv->RestoreArray(&tptr2,&nn2);CHKERRQ(info);
686:   }
687:   if (this!=ww && vv!=ww){ 
688:     info = ww->RestoreArray(&tptr3,&nn3);CHKERRQ(info);
689:   }
690:   TaoFunctionReturn(0);
691: }

695: /*@C
696:    Median - Computes the componentwise median of three vectors 
697:    and stores the result in this vector.

699:    Input Parameters:
700: .   vv, ww, xx - the three vectors

702:    Level: intermediate

704: @*/
705: int TaoVec::Median( TaoVec* vv, TaoVec* ww, TaoVec* xx){
706:   int i,nn1,nn2,nn3,nn4,info;
707:   TaoScalar *tptr1,*tptr2,*tptr3,*tptr4;

709:   TaoFunctionBegin;
710:   info = this->GetArray(&tptr1,&nn1);CHKERRQ(info);
711:   if (this!=vv){
712:     info = vv->GetArray(&tptr2,&nn2);CHKERRQ(info);
713:   } else {
714:     tptr2=tptr1; nn2=nn1;
715:   }
716:   if (this!=ww){
717:     info = ww->GetArray(&tptr3,&nn3);CHKERRQ(info);
718:   } else {
719:     tptr3=tptr1; nn3=nn1;
720:   }
721:   if (this!=xx){
722:     info = xx->GetArray(&tptr4,&nn4);CHKERRQ(info);
723:   } else {
724:     tptr4=tptr1; nn4=nn1;
725:   }

727:   if (nn1!=nn2 || nn2!=nn3 || nn3!=nn4) {TaoFunctionReturn(1);}
728:   for (i=0;i<nn1;i++){
729:     if (tptr2[i]<=tptr3[i] && tptr3[i] <= tptr4[i]){
730:       tptr1[i]=tptr3[i];
731:     } else if (tptr4[i]<=tptr3[i] && tptr3[i] <= tptr2[i]){
732:       tptr1[i]=tptr3[i];
733:     } else if (tptr3[i]<=tptr2[i] && tptr2[i] <= tptr4[i]){
734:       tptr1[i]=tptr2[i];
735:     } else if (tptr4[i]<=tptr2[i] && tptr2[i] <= tptr3[i]){
736:       tptr1[i]=tptr2[i];
737:     } else {
738:       tptr1[i]=tptr4[i];
739:     }
740:   }
741:   info = this->RestoreArray(&tptr1,&nn1);CHKERRQ(info);
742:   if (this!=vv){
743:     info = vv->RestoreArray(&tptr2,&nn2);CHKERRQ(info);
744:   }
745:   if (this!=ww){
746:     info = ww->RestoreArray(&tptr3,&nn3);CHKERRQ(info);
747:   }
748:   if (this!=xx){
749:     info = xx->RestoreArray(&tptr4,&nn4);CHKERRQ(info);
750:   }
751:   TaoFunctionReturn(0);
752: }

756: /*@C
757:    PointwiseMinimum - Computes the componentwise minimum of two vectors 
758:    and stores the result in this vector.

760:    Input Parameters:
761: .   vv, ww - the two vectors

763:    Level: intermediate

765: .seealso TaoVec::PointwiseMaximum()
766: @*/
767: int TaoVec::PointwiseMinimum( TaoVec* vv, TaoVec* ww){
768:   int i,nn1,nn2,nn3,info;
769:   TaoScalar *tptr1,*tptr2,*tptr3;

771:   TaoFunctionBegin;
772:   info = this->GetArray(&tptr1,&nn1);CHKERRQ(info);
773:   if (vv!=this){
774:     info = vv->GetArray(&tptr2,&nn2);CHKERRQ(info);
775:   } else {
776:     tptr2=tptr1;  nn2=nn1;
777:   }
778:   if (ww!=this){
779:     info = ww->GetArray(&tptr3,&nn3);CHKERRQ(info);
780:   } else {
781:     tptr3=tptr1;  nn3=nn1;
782:   }

784:   if (nn1!=nn2 || nn2!=nn3) {TaoFunctionReturn(1);}
785:   for (i=0;i<nn1;i++) tptr1[i] = TaoMin( tptr2[i] , tptr3[i]);
786:   info = this->RestoreArray(&tptr1,&nn1);CHKERRQ(info);
787:   if (vv!=this){
788:     info = vv->RestoreArray(&tptr2,&nn2);CHKERRQ(info);
789:   }
790:   if (ww!=this){
791:     info = ww->RestoreArray(&tptr3,&nn3);CHKERRQ(info);
792:   }
793:   TaoFunctionReturn(0);
794: }

798: /*@C
799:    PointwiseMaximum - Computes the componentwise minimum of two vectors 
800:    and stores the result in this vector.

802:    Input Parameters:
803: .  vv, ww - the two vectors

805:    Level: intermediate

807: .seealso TaoVec::PointwiseMinimum()
808: @*/
809: int TaoVec::PointwiseMaximum( TaoVec* vv, TaoVec* ww){
810:   int i,nn1,nn2,nn3,info;
811:   TaoScalar *tptr1,*tptr2,*tptr3;

813:   TaoFunctionBegin;
814:   info = this->GetArray(&tptr1,&nn1);CHKERRQ(info);
815:   if (vv!=this){
816:     info = vv->GetArray(&tptr2,&nn2);CHKERRQ(info);
817:   } else {
818:     tptr2=tptr1;  nn2=nn1;
819:   }
820:   if (ww!=this){
821:     info = ww->GetArray(&tptr3,&nn3);CHKERRQ(info);
822:   } else {
823:     tptr3=tptr1;  nn3=nn1;
824:   }
825:   if (nn1!=nn2 || nn2!=nn3) {TaoFunctionReturn(1);}
826:   for (i=0;i<nn1;i++) tptr1[i] = TaoMax( tptr2[i] , tptr3[i]);
827:   info = this->RestoreArray(&tptr1,&nn1);CHKERRQ(info);
828:   if (vv!=this){
829:     info = vv->RestoreArray(&tptr2,&nn2);CHKERRQ(info);
830:   }
831:   if (ww!=this){
832:     info = ww->RestoreArray(&tptr3,&nn3);CHKERRQ(info);
833:   }
834:   TaoFunctionReturn(0);
835: }

839: /*@C
840:    Waxpby - Sums two scaled vectors and stores the result in this vector. (this=alpha*xx+beta*yy)

842:    Input Parameters:
843: +  a - the multiple of the first vector
844: .  xx - the first vector
845: .  b - the multiple of the second vector
846: -  yy - the second vector

848:    Level: intermediate

850: .seealso TaoVec::Axpy(), TaoVec::Axpby(), TaoVec::Aypx();
851: @*/
852: int TaoVec::Waxpby  ( double a, TaoVec* xx, double b, TaoVec* yy){
853:   int i,nn1,nn2,nn3,info;
854:   TaoScalar *tptr1,*tptr2,*tptr3;

856:   TaoFunctionBegin;
857:   info = this->GetArray(&tptr1,&nn1);CHKERRQ(info);
858:   info = xx->GetArray(&tptr2,&nn2);CHKERRQ(info);
859:   info = yy->GetArray(&tptr3,&nn3);CHKERRQ(info);
860:   if (nn1!=nn2 || nn2!=nn3) {TaoFunctionReturn(1);}
861:   for (i=0;i<nn1;i++){ tptr1[i] = a * tptr2[i] + b * tptr3[i]; }
862:   info = this->RestoreArray(&tptr1,&nn1);CHKERRQ(info);
863:   info = xx->RestoreArray(&tptr2,&nn2);CHKERRQ(info);
864:   info = yy->RestoreArray(&tptr3,&nn3);CHKERRQ(info);
865:   TaoFunctionReturn(0);
866: }

870: /*@C
871:    AbsoluteValue - Sets each element of this vector equal to its magnitude.

873:    Input Parameters: none

875:    Level: intermediate
876: @*/
877: int TaoVec::AbsoluteValue(){
878:   int i,nn,info;
879:   TaoScalar *v;

881:   TaoFunctionBegin;
882:   info = this->GetArray(&v,&nn);CHKERRQ(info);
883:   for (i=0;i<nn;i++){ 
884:     v[i]= TaoAbsScalar(v[i]);
885:   }
886:   info = this->RestoreArray(&v,&nn);CHKERRQ(info);
887:   TaoFunctionReturn(0);
888: }

892: /*@C
893:    MinElement - Finds the smallest element of this vector.

895:    Output Parameter:
896: .  val - the smallest value in the vector

898:    Level: intermediate
899: @*/
900: int TaoVec::MinElement(double *val){
901:   int i,nn,info;
902:   TaoScalar dd=TAO_INFINITY,*v;

904:   TaoFunctionBegin;
905:   info = this->GetArray(&v,&nn);CHKERRQ(info);
906:   for (i=0;i<nn;i++){ 
907:     if (v[i]<dd) dd=v[i];
908:   }
909:   info = this->RestoreArray(&v,&nn);CHKERRQ(info);
910:   *val = dd;
911:   TaoFunctionReturn(0);
912: }

916: /*@C
917:    Sign - Replace each element of this vector with -1, 0, or 1, depending on its sign.

919:    Level: intermediate
920: @*/
921: int TaoVec::Sign(){
922:   int i,nn,info;
923:   TaoScalar *v;

925:   TaoFunctionBegin;
926:   info = this->GetArray(&v,&nn);CHKERRQ(info);
927:   for (i=0;i<nn;i++){
928:     if (v[i]<0){ 
929:       v[i]=-1;
930:     } else if (v[i]>0){
931:       v[i]=1.0;
932:     } else {
933:       v[i]=0.0;
934:     }
935:   }
936:   info = this->RestoreArray(&v,&nn);CHKERRQ(info);
937:   TaoFunctionReturn(0);
938: }

942: /*@C
943:    SetReducedVec - Sets the reduced space of the vector that this
944:    vector should represent.  The index set describes which
945:    elements of the vector should be used.  This routine also
946:    copies  the appropriate elements from the full space vector
947:    into the reduced space vector.

949:    Input Parameters:
950: +  vv -  a vector
951: -  ss -  an index set

953:    Level: advanced

955: .seealso TaoVec::CreateReducedVec(),  TaoVec::ReducedCopyFromFull(), TaoVec::ReducedXPY(), TaoSelectSubset()
956: @*/
957: int TaoVec::SetReducedVec(TaoVec* vv,TaoIndexSet* ss){
958:   TaoFunctionBegin;
959:   SETERRQ(56,"Operation not defined");
960:   /* TaoFunctionReturn(1); */
961: }

965: /*@C
966:   ReducedCopyFromFull - Copies the appropriate elements of the vector into
967:   this reduced vector.
968:   
969:   Input Parameters:
970: +  ss -  an index set
971: -  vv -  a full vector

973:    Level: advanced

975: .seealso TaoVec::CreateReducedVec(), TaoVec::ReducedXPY()
976: @*/
977: int TaoVec::ReducedCopyFromFull(TaoVec* vv, TaoIndexSet* ss){
978:   TaoFunctionBegin;
979:   SETERRQ(56,"Operation not defined");
980:   /* TaoFunctionReturn(1); */
981: }

985: /*@C
986:   ReducedXPY - Adds a reduced vector to the appropriate elements of this vector.
987:   
988:   Input Parameters:
989: +  vv -  the reduced vector
990: -  ss -  the index set identifying which elements of this vector should be supplemented

992:    Level: advanced

994: .seealso TaoVec::CreateReducedVec(), TaoVec::ReducedCopyFromFull()
995: @*/
996: int TaoVec::ReducedXPY(TaoVec* vv, TaoIndexSet* ss){
997:   TaoFunctionBegin;
998:   SETERRQ(56,"Operation not defined");
999:   /* TaoFunctionReturn(1); */
1000: }

1004: /*@C
1005:   StepMax - Calculates the largest multiple of a vector that can be added to
1006:   this vector while keeping each element of this vector nonnegative.
1007:   
1008:   Input Parameters:
1009: . vv - the step direction

1011:   Input Parameters:
1012: . step1 - the maximum stepsize

1014:   Note:
1015:   This vector should contain all positive elements.

1017:   Note:
1018:   If there is no maximum steplength, the output scalar may be set
1019:   to TAO_INFINITY.

1021:   Level: advanced
1022: @*/
1023: int TaoVec::StepMax(TaoVec* vv,double *step1){
1024:   int i,nn1,nn2,info;
1025:   TaoScalar *xx,*dx;
1026:   double stepmax1=TAO_INFINITY;

1028:   TaoFunctionBegin;
1029:   info = this->GetArray(&xx,&nn1);CHKERRQ(info);
1030:   if (this!=vv){
1031:     info = vv->GetArray(&dx,&nn2);CHKERRQ(info);
1032:     if (nn1!=nn2) {TaoFunctionReturn(1);}
1033:     for (i=0;i<nn1;i++){
1034:       if (xx[i] < 0){
1035:         TaoFunctionReturn(1);
1036:       } else if (dx[i]<0){ 
1037:         stepmax1=TaoMin(stepmax1,-xx[i]/dx[i]);
1038:       }
1039:     }
1040:     info = vv->RestoreArray(&dx,&nn2);CHKERRQ(info);
1041:     *step1=stepmax1;
1042:   } else {
1043:     *step1=1.0;
1044:   }
1045:   info = this->RestoreArray(&xx,&nn1);CHKERRQ(info);
1046:   TaoFunctionReturn(0);
1047:   }

1049: /*@C
1050:   StepBoundInfo - Calculates the largest multiple of a vector that can be added to
1051:   this vector while keeping each element of this vector nonnegative.
1052:   
1053:   Input Parameters:
1054: + txl - the lower bounds on this vector
1055: . txu - the upper bounds on this vector
1056: - tdx - the step direction for this vector

1058:   Output Parameters:
1059: + boundmin - the step to closest bound i.e min(a1, ..., an);
1060: . wolfemin - the step to closest bound not equal i.e min(b1, ..., bn);
1061: - boundmax - the step to farthest bound   i.e. max(c1, ..., cn);

1063:   Where:
1064:   if tdx[i] > 0;  ai = (txu[i] - this[i])/tdx[i] ; bi=ai, ci=ai;
1065:   if tdx[i] < 0;  ai = (txl[i] - this[i])/tdx[i] ; bi=ai, ci=ai
1066:   if tdx[i] == 0 && txl[i] < x[i] < txu[i] ; ai=TAO_INFINITY, bi=ai, ci=ai;
1067:   if tdx[i] == 0 && (txl[i] == x[i] || txu[i] == x[i]) ; ai= 0, bi=TAO_INFINITY, ci=0;
1068:  
1069:   Note:
1070:   If there is no maximum steplength, the output scalar may be set
1071:   to TAO_INFINITY.

1073:   Level: advanced
1074: @*/
1075: int TaoVec::StepBoundInfo(TaoVec* XL ,TaoVec* XU, TaoVec*S, double *bmin1,double *bmin2, double *bmax){
1076:   TaoFunctionBegin;
1077:   SETERRQ(56,"Operation not defined");
1078:   /* TaoFunctionReturn(1); */
1079: }

1083: /*@C
1084:   View - Views the contents of the vector.
1085:   
1086:   Input Parameters: none
1087:   
1088:   Level: intermediate
1089: @*/
1090: int TaoVec::View(){
1091:   TaoFunctionBegin;
1092:   SETERRQ(56,"Operation not defined");
1093:   /* TaoFunctionReturn(1); */
1094: }

1098: /*@C
1099:   BoundGradientProjection - Projects this vector according to this definition.
1100:   If XX[i]==XXL[i], then this[i] = min(G[i],0);   
1101:   If XX[i]==XXU[i], then this[i] = max(G[i],0);
1102:   else this[i] = G[i];

1104:   Input Parameters:
1105: . GG,XX,XXL,XXU - the vectors.

1107:   Level: advanced
1108: @*/
1109: int TaoVec::BoundGradientProjection(TaoVec* gg,TaoVec* xxll,TaoVec* xx, TaoVec* xxuu){
1110:   int i,nn1,nn2,nn3,nn4,nn5,info;
1111:   TaoScalar *xptr,*xlptr,*xuptr,*gptr,*gpptr;

1113:   TaoFunctionBegin;
1114:   info = this->GetArray(&gpptr,&nn1);CHKERRQ(info);
1115:   if (this != gg){
1116:     info = gg->GetArray(&gptr,&nn2);CHKERRQ(info);
1117:   } else {
1118:     gptr=gpptr; nn2=nn1;
1119:   }
1120:   info = xxll->GetArray(&xlptr,&nn3);CHKERRQ(info);
1121:   info = xx->GetArray(&xptr,&nn4);CHKERRQ(info);
1122:   info = xxuu->GetArray(&xuptr,&nn5);CHKERRQ(info);
1123:   if (nn1!=nn2 || nn2!=nn3 || nn3!=nn4 || nn4!=nn5) {TaoFunctionReturn(1);}

1125:   for (i=0; i<nn1; i++){

1127:     gpptr[i] = gptr[i];
1128:     if (gpptr[i]>0 && xptr[i]<=xlptr[i]){
1129:       gpptr[i] = 0;
1130:     } else if (gpptr[i]<0 && xptr[i]>=xuptr[i]){
1131:       gpptr[i] = 0;
1132:     }
1133:   }
1134:   info = this->RestoreArray(&gpptr,&nn1);CHKERRQ(info);
1135:   if (this!=gg){
1136:     info = gg->RestoreArray(&gptr,&nn2);CHKERRQ(info);
1137:   }
1138:   info = xxll->RestoreArray(&xlptr,&nn3);CHKERRQ(info);
1139:   info = xx->RestoreArray(&xptr,&nn4);CHKERRQ(info);
1140:   info = xxuu->RestoreArray(&xuptr,&nn5);CHKERRQ(info);

1142:   TaoFunctionReturn(0);
1143: }

1147: /*@C
1148:    GetArray - Sets a pointer to the first element in the vector array.

1150:    Output Parameters:
1151: +  dptr -  pointer an the array of numbers
1152: -  n -  the length of the array

1154:    Note:
1155:    This operation may not be defined the same for all vector types.

1157:    Level: intermediate

1159: .seealso TaoVec::RestoreArray()
1160: @*/
1161: int TaoVec::GetArray(TaoScalar **dptr, int *n){
1162:   TaoFunctionBegin;
1163:   SETERRQ(56,"Operation not defined");
1164:   /* TaoFunctionReturn(1); */
1165: }

1169: /*@C
1170:    RestoreArray - Returns a pointer to the first element in the vector array.

1172:    Input Parameters:
1173: +  dptr -  pointer an the array of numbers obtained from TaoVec::GetArray
1174: -  n -  the length of the array

1176:    Note:
1177:    This routine is not used within TAO solvers.  Rather, it is used to
1178:    implement other routines.

1180:    Level: intermediate

1182: .seealso TaoVec::GetArray()
1183: @*/
1184: int TaoVec::RestoreArray(TaoScalar **dptr, int *n){
1185:   TaoFunctionBegin;
1186:   *dptr=NULL;
1187:   *n=0;
1188:   TaoFunctionReturn(0);
1189: }

1193: /*@C
1194:    CreateIndexSet - Creates an index set that may be used to describe sets of
1195:    elements of this vector.

1197:    Output Parameters:
1198: .  ss -  a new index set

1200:    Level: advanced
1201: @*/
1202: int TaoVec::CreateIndexSet(TaoIndexSet **ss){
1203:   TaoFunctionBegin;
1204:   SETERRQ(56,"Operation not defined");
1205:   /* TaoFunctionReturn(1); */
1206: }

1208: inline static double fischer(double a, double b) 
1209: {
1210:    // Method suggested by Bob Vanderbei
1211:    if (a + b <= 0) {
1212:      return sqrt(a*a + b*b) - (a + b);
1213:    }
1214:    return -2.0*a*b / (sqrt(a*a + b*b) + (a + b));
1215: }

1219: /*@C
1220:    Fischer - Evaluates the Fischer-Burmeister function for complementarity 
1221:    problems.
1222:    
1223:    Input Parameters:
1224: +  xx - current point
1225: .  ff - function evaluated at x
1226: .  ll - lower bounds 
1227: -  uu - upper bounds

1229:    Notes: 
1230:    The Fischer-Burmeister function is defined as
1231: $        phi(a,b) := sqrt(a*a + b*b) - a - b
1232:    and is used reformulate a complementarity problem as a semismooth
1233:    system of equations.

1235:    The result of this function is done by cases:
1236: +  l[i] == -infinity, u[i] == infinity  -- fb[i] = -f[i]
1237: .  l[i] == -infinity, u[i] finite       -- fb[i] = phi(u[i]-x[i], -f[i])
1238: .  l[i] finite,       u[i] == infinity  -- fb[i] = phi(x[i]-l[i],  f[i])
1239: .  l[i] finite < u[i] finite -- fb[i] = phi(x[i]-l[i], phi(u[i]-x[i], -f[u]))
1240: -  otherwise l[i] == u[i] -- fb[i] = l[i] - x[i]

1242:    Level: advanced

1244: .seealso TaoMat::D_Fischer()
1245: @*/
1246: int TaoVec::Fischer(TaoVec* xx, TaoVec* ff, TaoVec* ll, TaoVec* uu)
1247: {
1248:   int i,nn1,nn2,nn3,nn4,nn5,info;
1249:   TaoScalar *v,*x,*f,*l,*u;

1251:   TaoFunctionBegin;
1252:   info = this->GetArray(&v,&nn1); CHKERRQ(info);
1253:   info = xx->GetArray(&x,&nn2); CHKERRQ(info);
1254:   info = ff->GetArray(&f,&nn3); CHKERRQ(info);
1255:   info = ll->GetArray(&l,&nn4); CHKERRQ(info);
1256:   info = uu->GetArray(&u,&nn5); CHKERRQ(info);
1257:   if (nn1!=nn2 || nn2!=nn3 || nn3!=nn4 || nn4!=nn5) { 
1258:     TaoFunctionReturn(1); 
1259:   }

1261:   for (i=0;i<nn1;i++) {

1263:     if ((l[i] <= -TAO_INFINITY) && (u[i] >= TAO_INFINITY)) {
1264:       v[i] = -f[i];
1265:     } 
1266:     else if (l[i] <= -TAO_INFINITY) {
1267:       v[i] = -fischer(u[i] - x[i], -f[i]);
1268:     } 
1269:     else if (u[i] >=  TAO_INFINITY) {
1270:       v[i] =  fischer(x[i] - l[i],  f[i]);
1271:     } 
1272:     else if (l[i] == u[i]) {
1273:       v[i] = l[i] - x[i];
1274:     } 
1275:     else {
1276:       v[i] =  fischer(u[i] - x[i], -f[i]);
1277:       v[i] =  fischer(x[i] - l[i],  v[i]);
1278:     }

1280:   }

1282:   info = this->RestoreArray(&v,&nn1);CHKERRQ(info);
1283:   info = xx->RestoreArray(&x,&nn2);CHKERRQ(info);
1284:   info = ff->RestoreArray(&f,&nn3);CHKERRQ(info);
1285:   info = ll->RestoreArray(&l,&nn4);CHKERRQ(info);
1286:   info = uu->RestoreArray(&u,&nn5);CHKERRQ(info);

1288:   TaoFunctionReturn(0);
1289: }

1291: inline static double sfischer(double a, double b, double c)
1292: {
1293:    // Method suggested by Bob Vanderbei
1294:    if (a + b <= 0) {
1295:      return sqrt(a*a + b*b + 2.0*c*c) - (a + b);
1296:    }
1297:    return 2.0*(c*c - a*b) / (sqrt(a*a + b*b + 2.0*c*c) + (a + b));
1298: }

1302: /*@C
1303:    SFischer - Evaluates the Smoothed Fischer-Burmeister function for
1304:    complementarity problems.

1306:    Input Parameters:
1307: +  xx - current point
1308: .  ff - function evaluated at x
1309: .  ll - lower bounds
1310: .  uu - upper bounds
1311: -  mu - smoothing parameter

1313:    Notes:
1314:    The Smoothed Fischer-Burmeister function is defined as
1315: $        phi(a,b) := sqrt(a*a + b*b + 2*mu*mu) - a - b
1316:    and is used reformulate a complementarity problem as a semismooth
1317:    system of equations.

1319:    The result of this function is done by cases:
1320: +  l[i] == -infinity, u[i] == infinity  -- fb[i] = -f[i] - 2*mu*x[i]
1321: .  l[i] == -infinity, u[i] finite       -- fb[i] = phi(u[i]-x[i], -f[i], mu)
1322: .  l[i] finite,       u[i] == infinity  -- fb[i] = phi(x[i]-l[i],  f[i], mu)
1323: .  l[i] finite < u[i] finite -- fb[i] = phi(x[i]-l[i], phi(u[i]-x[i], -f[u], mu), mu)
1324: -  otherwise l[i] == u[i] -- fb[i] = l[i] - x[i]

1326:    Level: advanced

1328: .seealso TaoMat::SD_Fischer()
1329: @*/
1330: int TaoVec::SFischer(TaoVec* xx, TaoVec* ff, TaoVec* ll, TaoVec* uu, double mu)
1331: {

1333:   int i, nn1, nn2, nn3, nn4, nn5, info;
1334:   TaoScalar *v, *x, *f, *l, *u;

1336:   TaoFunctionBegin;

1338:   if ((mu >= -TAO_EPSILON) && (mu <= TAO_EPSILON)) {
1339:     Fischer(xx, ff, ll, uu);
1340:   }
1341:   else {
1342:     info = this->GetArray(&v, &nn1); CHKERRQ(info);
1343:     info = xx->GetArray(&x, &nn2); CHKERRQ(info);
1344:     info = ff->GetArray(&f, &nn3); CHKERRQ(info);
1345:     info = ll->GetArray(&l, &nn4); CHKERRQ(info);
1346:     info = uu->GetArray(&u, &nn5); CHKERRQ(info);

1348:     if (nn1!=nn2 || nn2!=nn3 || nn3!=nn4 || nn4!=nn5) {
1349:       TaoFunctionReturn(1);
1350:     }

1352:     for (i = 0; i < nn1; ++i) {
1353:       if ((l[i] <= -TAO_INFINITY) && (u[i] >= TAO_INFINITY)) {
1354:         v[i] = -f[i] - mu*x[i];
1355:       } 
1356:       else if (l[i] <= -TAO_INFINITY) {
1357:         v[i] = -sfischer(u[i] - x[i], -f[i], mu);
1358:       } 
1359:       else if (u[i] >=  TAO_INFINITY) {
1360:         v[i] =  sfischer(x[i] - l[i],  f[i], mu);
1361:       } 
1362:       else if (l[i] == u[i]) {
1363:         v[i] = l[i] - x[i];
1364:       } 
1365:       else {
1366:         v[i] =  sfischer(u[i] - x[i], -f[i], mu);
1367:         v[i] =  sfischer(x[i] - l[i],  v[i], mu);
1368:       }
1369:     }

1371:     info = this->RestoreArray(&v, &nn1); CHKERRQ(info);
1372:     info = xx->RestoreArray(&x, &nn2); CHKERRQ(info);
1373:     info = ff->RestoreArray(&f, &nn3); CHKERRQ(info);
1374:     info = ll->RestoreArray(&l, &nn4); CHKERRQ(info);
1375:     info = uu->RestoreArray(&u, &nn5); CHKERRQ(info);
1376:   }
1377:   TaoFunctionReturn(0);
1378: }