comparison src/DLD-FUNCTIONS/cellfun.cc @ 13230:c73cc5b67feb

fix nargout handling for functions called by cellfun * cellfun.cc (Fcellfun): Handle functions that produce zero outputs. Set nargout = 0 when calling functions if nargout for cellfun itself is 0.
author John W. Eaton <jwe@octave.org>
date Mon, 26 Sep 2011 13:08:42 -0400
parents 983720941822
children 20ed9548070f
comparison
equal deleted inserted replaced
13229:983720941822 13230:c73cc5b67feb
536 error_handler); 536 error_handler);
537 537
538 if (error_state) 538 if (error_state)
539 return retval; 539 return retval;
540 540
541 if (tmp.length () < nargout1) 541 if (nargout > 0 && tmp.length () < nargout)
542 { 542 {
543 if (tmp.length () < nargout) 543 error ("cellfun: function returned fewer than nargout values");
544 return retval;
545 }
546
547 if (nargout > 0
548 || (nargout == 0
549 && tmp.length () > 0 && tmp(0).is_defined ()))
550 {
551 int num_to_copy = tmp.length ();
552
553 if (num_to_copy > nargout1)
554 num_to_copy = nargout1;
555
556 if (count == 0)
544 { 557 {
545 error ("cellfun: too many output arguments"); 558 for (int j = 0; j < num_to_copy; j++)
546 return octave_value_list (); 559 {
560 if (tmp(j).is_defined ())
561 {
562 octave_value val = tmp(j);
563
564 if (val.numel () == 1)
565 retv[j] = val.resize (fdims);
566 else
567 {
568 error ("cellfun: all values must be scalars when UniformOutput = true");
569 break;
570 }
571 }
572 }
547 } 573 }
548 else 574 else
549 nargout1 = 0;
550 }
551
552 if (count == 0)
553 {
554 for (int j = 0; j < nargout1; j++)
555 { 575 {
556 octave_value val = tmp(j); 576 for (int j = 0; j < num_to_copy; j++)
557
558 if (val.numel () == 1)
559 retv[j] = val.resize (fdims);
560 else
561 { 577 {
562 error ("cellfun: all values must be scalars when UniformOutput = true"); 578 if (tmp(j).is_defined ())
563 break;
564 }
565 }
566 }
567 else
568 {
569 for (int j = 0; j < nargout1; j++)
570 {
571 octave_value val = tmp(j);
572
573 if (! retv[j].fast_elem_insert (count, val))
574 {
575 if (val.numel () == 1)
576 { 579 {
577 idx_list.front ()(0) = count + 1.0; 580 octave_value val = tmp(j);
578 retv[j].assign (octave_value::op_asn_eq, 581
579 idx_type, idx_list, val); 582 if (! retv[j].fast_elem_insert (count, val))
580 583 {
581 if (error_state) 584 if (val.numel () == 1)
582 break; 585 {
583 } 586 idx_list.front ()(0) = count + 1.0;
584 else 587 retv[j].assign (octave_value::op_asn_eq,
585 { 588 idx_type, idx_list, val);
586 error ("cellfun: all values must be scalars when UniformOutput = true"); 589
587 break; 590 if (error_state)
591 break;
592 }
593 else
594 {
595 error ("cellfun: all values must be scalars when UniformOutput = true");
596 break;
597 }
598 }
588 } 599 }
589 } 600 }
590 } 601 }
591 } 602 }
592 603
605 } 616 }
606 } 617 }
607 else 618 else
608 { 619 {
609 OCTAVE_LOCAL_BUFFER (Cell, results, nargout1); 620 OCTAVE_LOCAL_BUFFER (Cell, results, nargout1);
621
610 for (int j = 0; j < nargout1; j++) 622 for (int j = 0; j < nargout1; j++)
611 results[j].resize (fdims); 623 results[j].resize (fdims, Matrix ());
612 624
613 for (octave_idx_type count = 0; count < k ; count++) 625 bool have_some_output = false;
626
627 for (octave_idx_type count = 0; count < k; count++)
614 { 628 {
615 for (int j = 0; j < nargin; j++) 629 for (int j = 0; j < nargin; j++)
616 { 630 {
617 if (mask[j]) 631 if (mask[j])
618 inputlist.xelem (j) = cinputs[j](count); 632 inputlist.xelem (j) = cinputs[j](count);
619 } 633 }
620 634
621 const octave_value_list tmp = get_output_list (count, nargout, inputlist, 635 const octave_value_list tmp
622 func, error_handler); 636 = get_output_list (count, nargout, inputlist, func,
637 error_handler);
623 638
624 if (error_state) 639 if (error_state)
625 return retval; 640 return retval;
626 641
627 if (tmp.length () < nargout1) 642 if (nargout > 0 && tmp.length () < nargout)
628 { 643 {
629 if (tmp.length () < nargout) 644 error ("cellfun: function returned fewer than nargout values");
630 { 645 return retval;
631 error ("cellfun: too many output arguments");
632 return octave_value_list ();
633 }
634 else
635 nargout1 = 0;
636 } 646 }
637 647
648 if (nargout > 0
649 || (nargout == 0
650 && tmp.length () > 0 && tmp(0).is_defined ()))
651 {
652 int num_to_copy = tmp.length ();
653
654 if (num_to_copy > nargout1)
655 num_to_copy = nargout1;
656
657 if (num_to_copy > 0)
658 have_some_output = true;
659
660 for (int j = 0; j < num_to_copy; j++)
661 results[j](count) = tmp(j);
662 }
663 }
664
665 if (have_some_output || fdims.any_zero ())
666 {
667 retval.resize (nargout1);
638 668
639 for (int j = 0; j < nargout1; j++) 669 for (int j = 0; j < nargout1; j++)
640 results[j](count) = tmp(j); 670 retval(j) = results[j];
641 } 671 }
642
643 retval.resize(nargout1);
644 for (int j = 0; j < nargout1; j++)
645 retval(j) = results[j];
646 } 672 }
647 } 673 }
648 else 674 else
649 error ("cellfun: argument NAME must be a string or function handle"); 675 error ("cellfun: argument NAME must be a string or function handle");
650 676
651 return retval; 677 return retval;
652 } 678 }
653 679
654 /* 680 /*
681
682 %!function r = f11 (x)
683 %! global __cellfun_test_num_outputs__
684 %! __cellfun_test_num_outputs__ = nargout;
685 %! r = x;
686 %! endfunction
687
688 %!function f01 (x)
689 %! global __cellfun_test_num_outputs__
690 %! __cellfun_test_num_outputs__ = nargout;
691 %! endfunction
692
693 %!test
694 %! global __cellfun_test_num_outputs__
695 %! cellfun (@f11, {1});
696 %! assert (__cellfun_test_num_outputs__, 0)
697 %! x = cellfun (@f11, {1});
698 %! assert (__cellfun_test_num_outputs__, 1)
699
700 %!test
701 %! global __cellfun_test_num_outputs__
702 %! cellfun (@f01, {1});
703 %! assert (__cellfun_test_num_outputs__, 0)
704
705 %!error x = cellfun (@f01, {1, 2});
706
707 %!test
708 %! assert (cellfun (@f11, {1, 2}), [1, 2])
709 %! assert (cellfun (@f11, {1, 2}, 'uniformoutput', false), {1, 2})
655 710
656 %!test 711 %!test
657 %! [a,b] = cellfun (@(x) x, cell (2, 0)); 712 %! [a,b] = cellfun (@(x) x, cell (2, 0));
658 %! assert (a, zeros (2, 0)); 713 %! assert (a, zeros (2, 0));
659 %! assert (b, zeros (2, 0)); 714 %! assert (b, zeros (2, 0));