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