comparison scripts/general/bitset.m @ 14633:056ea51070b8

Rewrite bitset.m (bug #36458) * bitset.m: Revamp the function. Make it work with arrays and scalars. No broadcasting yet. Add a test.
author Jordi Gutiérrez Hermoso <jordigh@octave.org>
date Mon, 14 May 2012 00:46:51 -0400
parents f3d52523cde1
children 7e10eb490b87
comparison
equal deleted inserted replaced
14632:954e1a180375 14633:056ea51070b8
1 ## Copyright (C) 2004-2012 David Bateman 1 ## Copyright (C) 2004-2012 David Bateman
2 ## Copyright (C) 2012 Jordi GutiƩrrez Hermoso
2 ## 3 ##
3 ## This file is part of Octave. 4 ## This file is part of Octave.
4 ## 5 ##
5 ## Octave is free software; you can redistribute it and/or modify it 6 ## Octave is free software; you can redistribute it and/or modify it
6 ## under the terms of the GNU General Public License as published by 7 ## under the terms of the GNU General Public License as published by
19 ## -*- texinfo -*- 20 ## -*- texinfo -*-
20 ## @deftypefn {Function File} {@var{C} =} bitset (@var{A}, @var{n}) 21 ## @deftypefn {Function File} {@var{C} =} bitset (@var{A}, @var{n})
21 ## @deftypefnx {Function File} {@var{C} =} bitset (@var{A}, @var{n}, @var{val}) 22 ## @deftypefnx {Function File} {@var{C} =} bitset (@var{A}, @var{n}, @var{val})
22 ## Set or reset bit(s) @var{n} of unsigned integers in @var{A}. 23 ## Set or reset bit(s) @var{n} of unsigned integers in @var{A}.
23 ## @var{val} = 0 resets and @var{val} = 1 sets the bits. 24 ## @var{val} = 0 resets and @var{val} = 1 sets the bits.
24 ## The lowest significant bit is: @var{n} = 1 25 ## The lowest significant bit is: @var{n} = 1. All variables must be the
26 ## same size or scalars.
25 ## 27 ##
26 ## @example 28 ## @example
27 ## @group 29 ## @group
28 ## dec2bin (bitset (10, 1)) 30 ## dec2bin (bitset (10, 1))
29 ## @result{} 1011 31 ## @result{} 1011
30 ## @end group 32 ## @end group
31 ## @end example 33 ## @end example
32 ## @seealso{bitand, bitor, bitxor, bitget, bitcmp, bitshift, bitmax} 34 ## @seealso{bitand, bitor, bitxor, bitget, bitcmp, bitshift, bitmax}
33 ## @end deftypefn 35 ## @end deftypefn
34 36
35 ## Liberally based on the version by Kai Habel from octave-forge 37 function A = bitset (A, n, val)
36
37 function C = bitset (A, n, val)
38 38
39 if (nargin < 2 || nargin > 3) 39 if (nargin < 2 || nargin > 3)
40 print_usage (); 40 print_usage ();
41 endif 41 endif
42 42
43 sz = size (A);
44
43 if (nargin == 2) 45 if (nargin == 2)
44 val = 1; 46 val = true (sz);
45 endif 47 endif
46 48
47 if (isa (A, "double")) 49 cl = class (A);
48 Bmax = bitmax; 50
49 Amax = log2 (Bmax) + 1; 51 if (isfloat (A) && isreal (A))
50 _conv = @double; 52 Bmax = bitmax (cl);
53 Amax = log2 (Bmax);
54 elseif (isinteger (A))
55 Bmax = intmax (cl);
56 ## FIXME: Better way to get number of bits than regexping?
57 Amax = str2num (nthargout (4, @regexp, cl, "\d{1,2}"){1});
51 else 58 else
52 if (isa (A, "uint8")) 59 error ("bitset: invalid class %s", cl);
53 Amax = 8;
54 _conv = @uint8;
55 elseif (isa (A, "uint16"))
56 Amax = 16;
57 _conv = @uint16;
58 elseif (isa (A, "uint32"))
59 Amax = 32;
60 _conv = @uint32;
61 elseif (isa (A, "uint64"))
62 Amax = 64;
63 _conv = @uint64;
64 elseif (isa (A, "int8"))
65 Amax = 8;
66 _conv = @int8;
67 elseif (isa (A, "int16"))
68 Amax = 16;
69 _conv = @int16;
70 elseif (isa (A, "int32"))
71 Amax = 32;
72 _conv = @int32;
73 elseif (isa (A, "int64"))
74 Amax = 64;
75 _conv = @int64;
76 else
77 error ("bitset: invalid class %s", class (A));
78 endif
79 Bmax = intmax (class (A));
80 endif 60 endif
81 61
82 m = double (n(:)); 62 if (any ((n < 1)(:)) || any ((n > Amax)(:)))
83 if (any (m < 1) || any (m > Amax))
84 error ("bitset: N must be in the range [1,%d]", Amax); 63 error ("bitset: N must be in the range [1,%d]", Amax);
85 endif 64 endif
86 65
87 mask = bitshift (_conv (1), uint8 (n) - uint8 (1)); 66 mask = bitshift (cast (1, cl), uint8 (n) - uint8 (1));
88 C = bitxor (A, bitand (A, mask));
89 67
90 if (val) 68 on = logical (val);
91 C = bitor (A, mask); 69 off = !on;
70
71 if (isscalar (mask))
72 onmask = mask;
73 offmask = mask;
74 else
75 if (! size_equal (A, n))
76 error ("bitset: N must be scalar or the same size as A");
77 endif
78 onmask = mask(on);
79 offmask = mask(off);
92 endif 80 endif
81
82 A(on) = bitor (A(on), onmask);
83 A(off) = bitand (A(off), bitcmp (offmask));
93 84
94 endfunction 85 endfunction
95 86
96 87
97 %!test 88 %!test
101 %! for prec = [8, 16, 32, 64] 92 %! for prec = [8, 16, 32, 64]
102 %! fcn = str2func (sprintf ("%sint%d", pfx{i}, prec)); 93 %! fcn = str2func (sprintf ("%sint%d", pfx{i}, prec));
103 %! assert (bitset (fcn ([0, 10]), [3, 3]), fcn ([4, 14])); 94 %! assert (bitset (fcn ([0, 10]), [3, 3]), fcn ([4, 14]));
104 %! endfor 95 %! endfor
105 %! endfor 96 %! endfor
97
98 ## Bug #36458
99 %!assert (bitset(uint8 ([1, 2;3 4]), 1, [0 1; 0 1]), uint8 ([0, 3; 2 5]))
106 100
107 %!error bitset (0, 0) 101 %!error bitset (0, 0)
108 %!error bitset (0, 55) 102 %!error bitset (0, 55)
109 %!error bitset (int8 (0), 9) 103 %!error bitset (int8 (0), 9)
110 %!error bitset (uint8 (0), 9) 104 %!error bitset (uint8 (0), 9)