# HG changeset patch
# User Willem Atsma <willem.atsma@tanglebridge.com>
# Date 1421451658 28800
#      Fri Jan 16 15:40:58 2015 -0800
# Node ID 73821bfb18744a53dd35f0189f6c25b69a7f769f
# Parent  d6a6e8d751780230dbdd44f5ac13da62c08f8ea0
Fix for issues around interaction cellfun and subsasgn

diff -r d6a6e8d75178 -r 73821bfb1874 inst/@quaternion/blkdiag.m
--- a/inst/@quaternion/blkdiag.m	Tue Apr 29 15:34:38 2014 +0200
+++ b/inst/@quaternion/blkdiag.m	Fri Jan 16 15:40:58 2015 -0800
@@ -1,4 +1,5 @@
 ## Copyright (C) 2010-2014   Lukas F. Reichlin
+## Copyright (C) 2015   Willem Atsma
 ##
 ## This program is free software: you can redistribute it and/or modify
 ## it under the terms of the GNU General Public License as published by
@@ -20,16 +21,22 @@
 
 ## Author: Lukas Reichlin <lukas.reichlin@gmail.com>
 ## Created: December 2011
-## Version: 0.1
+## Version: 0.2
+## 2015-01-12 - Willem Atsma
+##  Rewrote code to avoid problem with cs-list input to subsasgn from cellfun.
 
 function q = blkdiag (varargin)
 
-  tmp = cellfun (@quaternion, varargin);  # uniformoutput = true !
+  qargs = cellfun(@quaternion, varargin, 'UniformOutput', false);
 
-  w = blkdiag (tmp.w);
-  x = blkdiag (tmp.x);
-  y = blkdiag (tmp.y);
-  z = blkdiag (tmp.z);
+  tmp = cellfun (@subsref, qargs, {substruct('.','w')}, 'UniformOutput', false);
+  w = blkdiag (tmp{:});
+  tmp = cellfun (@subsref, qargs, {substruct('.','x')}, 'UniformOutput', false);
+  x = blkdiag (tmp{:});
+  tmp = cellfun (@subsref, qargs, {substruct('.','y')}, 'UniformOutput', false);
+  y = blkdiag (tmp{:});
+  tmp = cellfun (@subsref, qargs, {substruct('.','z')}, 'UniformOutput', false);
+  z = blkdiag (tmp{:});
 
   q = quaternion (w, x, y, z);
 
diff -r d6a6e8d75178 -r 73821bfb1874 inst/@quaternion/cat.m
--- a/inst/@quaternion/cat.m	Tue Apr 29 15:34:38 2014 +0200
+++ b/inst/@quaternion/cat.m	Fri Jan 16 15:40:58 2015 -0800
@@ -1,4 +1,5 @@
 ## Copyright (C) 2010-2014   Lukas F. Reichlin
+## Copyright (C) 2015   Willem Atsma
 ##
 ## This program is free software: you can redistribute it and/or modify
 ## it under the terms of the GNU General Public License as published by
@@ -20,17 +21,46 @@
 
 ## Author: Lukas Reichlin <lukas.reichlin@gmail.com>
 ## Created: November 2011
-## Version: 0.1
+## Version: 0.2
+## 2015-01-12 - Willem Atsma
+##  Rewrote code to avoid problem with cs-list input to subsasgn from cellfun.
+##  Added tests.
 
 function q = cat (dim, varargin)
 
-  tmp = cellfun (@quaternion, varargin);  # uniformoutput = true !
+  qargs = cellfun(@quaternion, varargin, 'UniformOutput', false);
 
-  w = cat (dim, tmp.w);
-  x = cat (dim, tmp.x);
-  y = cat (dim, tmp.y);
-  z = cat (dim, tmp.z);
+  tmp = cellfun (@subsref, qargs, {substruct('.','w')}, 'UniformOutput', false);
+  w = cat (dim, tmp{:});
+  tmp = cellfun (@subsref, qargs, {substruct('.','x')}, 'UniformOutput', false);
+  x = cat (dim, tmp{:});
+  tmp = cellfun (@subsref, qargs, {substruct('.','y')}, 'UniformOutput', false);
+  y = cat (dim, tmp{:});
+  tmp = cellfun (@subsref, qargs, {substruct('.','z')}, 'UniformOutput', false);
+  z = cat (dim, tmp{:});
 
   q = quaternion (w, x, y, z);
 
 endfunction
+
+%!test
+%!  q1 = quaternion(1);
+%!  q2 = quaternion(2);
+%!  q12 = cat(1,q1,q2);
+%!  assert( isequal(size(q12),[2 1]) );
+%!  q12 = cat(2,q1,q2);
+%!  assert( isequal(size(q12),[1 2]) );
+%!  q12 = cat(5,q1,q2);
+%!  assert( isequal(size(q12),[1 1 1 1 2]) );
+%!test
+%!  q1 = quaternion(randn(2,3,4),randn(2,3,4),randn(2,3,4),randn(2,3,4));
+%!  q2 = quaternion(randn(2,3,4),randn(2,3,4),randn(2,3,4),randn(2,3,4));
+%!  q12 = cat(1,q1,q2);
+%!  assert( isequal(size(q12),[4 3 4]) );
+%!  q12 = cat(2,q1,q2);
+%!  assert( isequal(size(q12),[2 6 4]) );
+%!  q12 = cat(3,q1,q2);
+%!  assert( isequal(size(q12),[2 3 8]) );
+%!  q12 = cat(5,q1,q2);
+%!  assert( isequal(size(q12),[2 3 4 1 2]) );
+
diff -r d6a6e8d75178 -r 73821bfb1874 inst/@quaternion/horzcat.m
--- a/inst/@quaternion/horzcat.m	Tue Apr 29 15:34:38 2014 +0200
+++ b/inst/@quaternion/horzcat.m	Fri Jan 16 15:40:58 2015 -0800
@@ -1,4 +1,5 @@
 ## Copyright (C) 2010-2014   Lukas F. Reichlin
+## Copyright (C) 2015   Willem Atsma
 ##
 ## This program is free software: you can redistribute it and/or modify
 ## it under the terms of the GNU General Public License as published by
@@ -18,17 +19,52 @@
 
 ## Author: Lukas Reichlin <lukas.reichlin@gmail.com>
 ## Created: May 2010
-## Version: 0.1
+## Version: 0.2
+## 2015-01-12 - Willem Atsma
+##  Rewrote code to avoid problem with cs-list input to subsasgn from cellfun.
+##  Added tests.
 
 function q = horzcat (varargin)
 
-  tmp = cellfun (@quaternion, varargin);  # uniformoutput = true !
+  qargs = cellfun(@quaternion, varargin, 'UniformOutput', false);
 
-  w = horzcat (tmp.w);
-  x = horzcat (tmp.x);
-  y = horzcat (tmp.y);
-  z = horzcat (tmp.z);
+  tmp = cellfun (@subsref, qargs, {substruct('.','w')}, 'UniformOutput', false);
+  w = horzcat (tmp{:});
+  tmp = cellfun (@subsref, qargs, {substruct('.','x')}, 'UniformOutput', false);
+  x = horzcat (tmp{:});
+  tmp = cellfun (@subsref, qargs, {substruct('.','y')}, 'UniformOutput', false);
+  y = horzcat (tmp{:});
+  tmp = cellfun (@subsref, qargs, {substruct('.','z')}, 'UniformOutput', false);
+  z = horzcat (tmp{:});
 
   q = quaternion (w, x, y, z);
 
 endfunction
+
+%!test
+%!  q1 = quaternion(1,2,3,4);
+%!  q12 = horzcat(q1,[]);
+%!  assert( isequal(q12,q1) );
+%!  q12 = horzcat([],q1);
+%!  assert( isequal(q12,q1) );
+%!test
+%!  q1 = quaternion(1,2,3,4);
+%!  q2 = quaternion(5,6,7,8);
+%!  q12 = horzcat(q1,q2);
+%!  assert( isequal(size(q12),[1 2]) );
+%!  q12alt = quaternion([1 5],[2 6],[3 7],[4 8]);
+%!  assert( isequal(q12,q12alt) );
+%!test
+%!  q1 = quaternion(randn(2,3,4),randn(2,3,4),randn(2,3,4),randn(2,3,4));
+%!  q12 = horzcat(q1,[]);
+%!  assert( isequal(q1,q12) );
+%!  q12 = horzcat([],q1);
+%!  assert( isequal(q1,q12) );
+%!test
+%!  q1 = quaternion(randn(2,3,4),randn(2,3,4),randn(2,3,4),randn(2,3,4));
+%!  q2 = quaternion(randn(2,3,4),randn(2,3,4),randn(2,3,4),randn(2,3,4));
+%!  q12 = horzcat(q1,q2);
+%!  assert( isequal(size(q12),[2 6 4]) );
+%!  q12alt = quaternion([q1.w q2.w],[q1.x q2.x],[q1.y q2.y],[q1.z q2.z]);
+%!  assert( isequal(q12,q12alt) );
+
diff -r d6a6e8d75178 -r 73821bfb1874 inst/@quaternion/plus.m
--- a/inst/@quaternion/plus.m	Tue Apr 29 15:34:38 2014 +0200
+++ b/inst/@quaternion/plus.m	Fri Jan 16 15:40:58 2015 -0800
@@ -1,4 +1,5 @@
 ## Copyright (C) 2010-2014   Lukas F. Reichlin
+## Copyright (C) 2015   Willem Atsma
 ##
 ## This program is free software: you can redistribute it and/or modify
 ## it under the terms of the GNU General Public License as published by
@@ -18,16 +19,22 @@
 
 ## Author: Lukas Reichlin <lukas.reichlin@gmail.com>
 ## Created: May 2010
-## Version: 0.2
+## Version: 0.3
+## 2015-01-12 - Willem Atsma
+##  Rewrote code to avoid problem with cs-list input to subsasgn from cellfun.
 
 function q = plus (varargin)
 
-  tmp = cellfun (@quaternion, varargin);  # uniformoutput = true !
+  qargs = cellfun(@quaternion, varargin, 'UniformOutput', false);
 
-  w = plus (tmp.w);
-  x = plus (tmp.x);
-  y = plus (tmp.y);
-  z = plus (tmp.z);
+  tmp = cellfun (@subsref, qargs, {substruct('.','w')}, 'UniformOutput', false);
+  w = plus (tmp{:});
+  tmp = cellfun (@subsref, qargs, {substruct('.','x')}, 'UniformOutput', false);
+  x = plus (tmp{:});
+  tmp = cellfun (@subsref, qargs, {substruct('.','y')}, 'UniformOutput', false);
+  y = plus (tmp{:});
+  tmp = cellfun (@subsref, qargs, {substruct('.','z')}, 'UniformOutput', false);
+  z = plus (tmp{:});
 
   q = quaternion (w, x, y, z);
 
diff -r d6a6e8d75178 -r 73821bfb1874 inst/@quaternion/size.m
--- a/inst/@quaternion/size.m	Tue Apr 29 15:34:38 2014 +0200
+++ b/inst/@quaternion/size.m	Fri Jan 16 15:40:58 2015 -0800
@@ -1,4 +1,5 @@
 ## Copyright (C) 2010-2014   Lukas F. Reichlin
+## Copyright (C) 2015   Willem Atsma
 ##
 ## This program is free software: you can redistribute it and/or modify
 ## it under the terms of the GNU General Public License as published by
@@ -48,27 +49,23 @@
 
 ## Author: Lukas Reichlin <lukas.reichlin@gmail.com>
 ## Created: May 2010
-## Version: 0.2
+## Version: 0.3
+## 2015-01-12 - Willem Atsma <willem.atsma@tanglebridge.com>
+##  Adjusted behaviour to match that of standard size() - was causing errors
+##  with whos.
 
-function varargout = size (a, b)
+function varargout = size (varargin)
 
+  sz = size (varargin{1}.w, varargin{2:end});
   switch (nargout)
     case {0, 1}
-      switch (nargin)
-        case 1                          # nvec = size (q)
-          varargout{1} = size (a.w);
-        case 2                          # n = size (q, dim)
-          varargout{1} = size (a.w, b);
-        otherwise
-          print_usage ();
-      endswitch
-
+      varargout{1} = sz;
     otherwise
-      if (nargin == 1)                  # [nx, ny, ...] = size (q)
-        varargout = num2cell (size (a.w));
+      if (nargout<=length(sz))
+        varargout = num2cell(sz(1:nargout));
       else
-        print_usage ();
+        print_usage();
       endif
   endswitch
-
+  
 endfunction
diff -r d6a6e8d75178 -r 73821bfb1874 inst/@quaternion/subsasgn.m
--- a/inst/@quaternion/subsasgn.m	Tue Apr 29 15:34:38 2014 +0200
+++ b/inst/@quaternion/subsasgn.m	Fri Jan 16 15:40:58 2015 -0800
@@ -1,4 +1,5 @@
 ## Copyright (C) 2010-2014   Lukas F. Reichlin
+## Copyright (C) 2015   Willem Atsma
 ##
 ## This program is free software: you can redistribute it and/or modify
 ## it under the terms of the GNU General Public License as published by
@@ -40,22 +41,21 @@
 
 ## Author: Lukas Reichlin <lukas.reichlin@gmail.com>
 ## Created: November 2011
-## Version: 0.3
+## Version: 0.4
+## 2015-01-12 - Willem Atsma
+##  Removed code that made use of cellfun work in *cat functions.
+##  Added test that caused error in previous version subsasgn.
 
 function q = subsasgn (q, idx, val)
 
   switch (idx(1).type)
     case "()"                                                    # q(...) = val
-      if (length (idx(1).subs) == 1 && isa (val, "quaternion"))  # required by horzcat, vertcat, cat, ...
-        q(idx(1).subs{:}) = val;                                 # q = cellfun (@quaternion, varargin)
-      else                                                       # general case
         val = quaternion (val);
         w = subsasgn (q.w, idx, val.w);
         x = subsasgn (q.x, idx, val.x);
         y = subsasgn (q.y, idx, val.y);
         z = subsasgn (q.z, idx, val.z);
         q = quaternion (w, x, y, z);
-      endif
 
     case "."                                                     # q.w = val
       if (is_real_array (val))
@@ -101,3 +101,8 @@
   endswitch
 
 endfunction
+
+%!test
+%! q = quaternion(1);
+%! q(2) = quaternion(2);
+%! assert (isequal(size(q),[1 2]));
diff -r d6a6e8d75178 -r 73821bfb1874 inst/@quaternion/vertcat.m
--- a/inst/@quaternion/vertcat.m	Tue Apr 29 15:34:38 2014 +0200
+++ b/inst/@quaternion/vertcat.m	Fri Jan 16 15:40:58 2015 -0800
@@ -1,4 +1,5 @@
 ## Copyright (C) 2010-2014   Lukas F. Reichlin
+## Copyright (C) 2015   Willem Atsma
 ##
 ## This program is free software: you can redistribute it and/or modify
 ## it under the terms of the GNU General Public License as published by
@@ -19,16 +20,51 @@
 ## Author: Lukas Reichlin <lukas.reichlin@gmail.com>
 ## Created: May 2010
 ## Version: 0.1
+## 2015-01-12 - Willem Atsma
+##  Rewrote code to avoid problem with cs-list input to subsasgn from cellfun.
+##  Added tests.
 
 function q = vertcat (varargin)
 
-  tmp = cellfun (@quaternion, varargin);  # uniformoutput = true !
+  qargs = cellfun(@quaternion, varargin, 'UniformOutput', false);
 
-  w = vertcat (tmp.w);
-  x = vertcat (tmp.x);
-  y = vertcat (tmp.y);
-  z = vertcat (tmp.z);
+  tmp = cellfun (@subsref, qargs, {substruct('.','w')}, 'UniformOutput', false);
+  w = vertcat (tmp{:});
+  tmp = cellfun (@subsref, qargs, {substruct('.','x')}, 'UniformOutput', false);
+  x = vertcat (tmp{:});
+  tmp = cellfun (@subsref, qargs, {substruct('.','y')}, 'UniformOutput', false);
+  y = vertcat (tmp{:});
+  tmp = cellfun (@subsref, qargs, {substruct('.','z')}, 'UniformOutput', false);
+  z = vertcat (tmp{:});
 
   q = quaternion (w, x, y, z);
 
 endfunction
+
+%!test
+%!  q1 = quaternion(1,2,3,4);
+%!  q12 = vertcat(q1,[]);
+%!  assert( isequal(q12,q1) );
+%!  q12 = vertcat([],q1);
+%!  assert( isequal(q12,q1) );
+%!test
+%!  q1 = quaternion(1,2,3,4);
+%!  q2 = quaternion(5,6,7,8);
+%!  q12 = vertcat(q1,q2);
+%!  assert( isequal(size(q12),[2 1]) );
+%!  q12alt = quaternion([1;5],[2;6],[3;7],[4;8]);
+%!  assert( isequal(q12,q12alt) );
+%!test
+%!  q1 = quaternion(randn(2,3,4),randn(2,3,4),randn(2,3,4),randn(2,3,4));
+%!  q12 = vertcat(q1,[]);
+%!  assert( isequal(q1,q12) );
+%!  q12 = vertcat([],q1);
+%!  assert( isequal(q1,q12) );
+%!test
+%!  q1 = quaternion(randn(2,3,4),randn(2,3,4),randn(2,3,4),randn(2,3,4));
+%!  q2 = quaternion(randn(2,3,4),randn(2,3,4),randn(2,3,4),randn(2,3,4));
+%!  q12 = vertcat(q1,q2);
+%!  assert( isequal(size(q12),[4 3 4]) );
+%!  q12alt = quaternion([q1.w;q2.w],[q1.x;q2.x],[q1.y;q2.y],[q1.z;q2.z]);
+%!  assert( isequal(q12,q12alt) );
+
diff -r d6a6e8d75178 -r 73821bfb1874 inst/test_quaternion.m
--- a/inst/test_quaternion.m	Tue Apr 29 15:34:38 2014 +0200
+++ b/inst/test_quaternion.m	Fri Jan 16 15:40:58 2015 -0800
@@ -20,7 +20,7 @@
 
 ## Author: Lukas Reichlin <lukas.reichlin@gmail.com>
 ## Created: December 2011
-## Version: 0.1
+## Version: 0.2
 
 test @quaternion/blkdiag
 test @quaternion/diag
@@ -34,3 +34,8 @@
 test @quaternion/lt
 test @quaternion/ndims
 test @quaternion/ne
+test @quaternion/vertcat
+test @quaternion/horzcat
+test @quaternion/cat
+test @quaternion/subsasgn
+
