Mercurial > octave
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)); |