Mercurial > octave-nkf
comparison libinterp/corefcn/hex2num.cc @ 17178:f010db8b710c
hex2num: Add single precision conversion option (bug #39608)
* hex2num.cc (Fhex2num): Add optional argument to allow conversion of
single precision strings while remaining Matlab-compatible. Update docstring
to describe the new argument and behavior. Add test case.
author | Mike Miller <mtmiller@ieee.org> |
---|---|
date | Sun, 04 Aug 2013 20:35:55 -0400 |
parents | 81d3c4409645 |
children | bc924baa2c4e |
comparison
equal
deleted
inserted
replaced
17177:81d3c4409645 | 17178:f010db8b710c |
---|---|
32 #include "oct-obj.h" | 32 #include "oct-obj.h" |
33 #include "utils.h" | 33 #include "utils.h" |
34 | 34 |
35 DEFUN (hex2num, args, , | 35 DEFUN (hex2num, args, , |
36 "-*- texinfo -*-\n\ | 36 "-*- texinfo -*-\n\ |
37 @deftypefn {Built-in Function} {@var{n} =} hex2num (@var{s})\n\ | 37 @deftypefn {Built-in Function} {@var{n} =} hex2num (@var{s})\n\ |
38 @deftypefnx {Built-in Function} {@var{n} =} hex2num (@var{s}, @var{class})\n\ | |
38 Typecast the 16 character hexadecimal character string to an IEEE 754\n\ | 39 Typecast the 16 character hexadecimal character string to an IEEE 754\n\ |
39 double precision number. If fewer than 16 characters are given the\n\ | 40 double precision number. If fewer than 16 characters are given the\n\ |
40 strings are right padded with '0' characters.\n\ | 41 strings are right padded with '0' characters.\n\ |
41 \n\ | 42 \n\ |
42 Given a string matrix, @code{hex2num} treats each row as a separate\n\ | 43 Given a string matrix, @code{hex2num} treats each row as a separate\n\ |
43 number.\n\ | 44 number.\n\ |
44 \n\ | 45 \n\ |
45 @example\n\ | 46 @example\n\ |
46 @group\n\ | 47 @group\n\ |
47 hex2num ([\"4005bf0a8b145769\"; \"4024000000000000\"])\n\ | 48 hex2num ([\"4005bf0a8b145769\"; \"4024000000000000\"])\n\ |
49 @result{} [2.7183; 10.000]\n\ | |
50 @end group\n\ | |
51 @end example\n\ | |
52 \n\ | |
53 The optional argument @var{class} can be passed as the string \"single\" to\n\ | |
54 specify that the given string should be interpreted as a single precision\n\ | |
55 number. In this case, @var{s} should be an 8 character hexadecimal string.\n\ | |
56 For example:\n\ | |
57 @example\n\ | |
58 @group\n\ | |
59 hex2num ([\"402df854\"; \"41200000\"], \"single\")\n\ | |
48 @result{} [2.7183; 10.000]\n\ | 60 @result{} [2.7183; 10.000]\n\ |
49 @end group\n\ | 61 @end group\n\ |
50 @end example\n\ | 62 @end example\n\ |
51 @seealso{num2hex, hex2dec, dec2hex}\n\ | 63 @seealso{num2hex, hex2dec, dec2hex}\n\ |
52 @end deftypefn") | 64 @end deftypefn") |
53 { | 65 { |
54 int nargin = args.length (); | 66 int nargin = args.length (); |
55 octave_value retval; | 67 octave_value retval; |
56 | 68 |
57 if (nargin != 1) | 69 if (nargin < 1 || nargin > 2) |
58 print_usage (); | 70 print_usage (); |
71 else if (nargin == 2 && ! args(1).is_string ()) | |
72 error ("hex2num: CLASS must be a string"); | |
59 else | 73 else |
60 { | 74 { |
61 const charMatrix cmat = args(0).char_matrix_value (); | 75 const charMatrix cmat = args(0).char_matrix_value (); |
62 | 76 std::string prec = (nargin == 2) ? args(1).string_value () : "double"; |
63 if (cmat.columns () > 16) | 77 bool is_single = (prec == "single"); |
64 error ("hex2num: S must be no more than 16 characters"); | 78 octave_idx_type nchars = (is_single) ? 8 : 16; |
79 | |
80 if (cmat.columns () > nchars) | |
81 error ("hex2num: S must be no more than %d characters", nchars); | |
82 else if (prec != "double" && prec != "single") | |
83 error ("hex2num: CLASS must be either \"double\" or \"single\""); | |
65 else if (! error_state) | 84 else if (! error_state) |
66 { | 85 { |
67 octave_idx_type nr = cmat.rows (); | 86 octave_idx_type nr = cmat.rows (); |
68 octave_idx_type nc = cmat.columns (); | 87 octave_idx_type nc = cmat.columns (); |
69 ColumnVector m (nr); | 88 |
70 | 89 if (is_single) |
71 for (octave_idx_type i = 0; i < nr; i++) | |
72 { | 90 { |
73 union | 91 FloatColumnVector m (nr); |
74 { | 92 |
75 uint64_t ival; | 93 for (octave_idx_type i = 0; i < nr; i++) |
76 double dval; | |
77 } num; | |
78 | |
79 num.ival = 0; | |
80 | |
81 for (octave_idx_type j = 0; j < nc; j++) | |
82 { | 94 { |
83 unsigned char ch = cmat.elem (i, j); | 95 union |
84 | 96 { |
85 if (isxdigit (ch)) | 97 uint32_t ival; |
98 float dval; | |
99 } num; | |
100 | |
101 num.ival = 0; | |
102 | |
103 for (octave_idx_type j = 0; j < nc; j++) | |
86 { | 104 { |
87 num.ival <<= 4; | 105 unsigned char ch = cmat.elem (i, j); |
88 if (ch >= 'a') | 106 |
89 num.ival += static_cast<uint64_t> (ch - 'a' + 10); | 107 if (isxdigit (ch)) |
90 else if (ch >= 'A') | 108 { |
91 num.ival += static_cast<uint64_t> (ch - 'A' + 10); | 109 num.ival <<= 4; |
110 if (ch >= 'a') | |
111 num.ival += static_cast<uint32_t> (ch - 'a' + 10); | |
112 else if (ch >= 'A') | |
113 num.ival += static_cast<uint32_t> (ch - 'A' + 10); | |
114 else | |
115 num.ival += static_cast<uint32_t> (ch - '0'); | |
116 } | |
92 else | 117 else |
93 num.ival += static_cast<uint64_t> (ch - '0'); | 118 { |
119 error ("hex2num: illegal character found in string S"); | |
120 break; | |
121 } | |
94 } | 122 } |
123 | |
124 if (error_state) | |
125 break; | |
95 else | 126 else |
96 { | 127 { |
97 error ("hex2num: illegal character found in string S"); | 128 if (nc < nchars) |
98 break; | 129 num.ival <<= (nchars - nc) * 4; |
130 | |
131 m(i) = num.dval; | |
99 } | 132 } |
100 } | 133 } |
101 | 134 |
102 if (error_state) | 135 if (! error_state) |
103 break; | 136 retval = m; |
104 else | 137 } |
138 else | |
139 { | |
140 ColumnVector m (nr); | |
141 | |
142 for (octave_idx_type i = 0; i < nr; i++) | |
105 { | 143 { |
106 if (nc < 16) | 144 union |
107 num.ival <<= (16 - nc) * 4; | 145 { |
108 | 146 uint64_t ival; |
109 m(i) = num.dval; | 147 double dval; |
148 } num; | |
149 | |
150 num.ival = 0; | |
151 | |
152 for (octave_idx_type j = 0; j < nc; j++) | |
153 { | |
154 unsigned char ch = cmat.elem (i, j); | |
155 | |
156 if (isxdigit (ch)) | |
157 { | |
158 num.ival <<= 4; | |
159 if (ch >= 'a') | |
160 num.ival += static_cast<uint64_t> (ch - 'a' + 10); | |
161 else if (ch >= 'A') | |
162 num.ival += static_cast<uint64_t> (ch - 'A' + 10); | |
163 else | |
164 num.ival += static_cast<uint64_t> (ch - '0'); | |
165 } | |
166 else | |
167 { | |
168 error ("hex2num: illegal character found in string S"); | |
169 break; | |
170 } | |
171 } | |
172 | |
173 if (error_state) | |
174 break; | |
175 else | |
176 { | |
177 if (nc < nchars) | |
178 num.ival <<= (nchars - nc) * 4; | |
179 | |
180 m(i) = num.dval; | |
181 } | |
110 } | 182 } |
183 | |
184 if (! error_state) | |
185 retval = m; | |
111 } | 186 } |
112 | |
113 if (! error_state) | |
114 retval = m; | |
115 } | 187 } |
116 } | 188 } |
117 | 189 |
118 return retval; | 190 return retval; |
119 } | 191 } |
120 | 192 |
121 /* | 193 /* |
122 %!assert (hex2num (["c00";"bff";"000";"3ff";"400"]), [-2:2]') | 194 %!assert (hex2num (["c00";"bff";"000";"3ff";"400"]), [-2:2]') |
195 %!assert (hex2num (["c00";"bf8";"000";"3f8";"400"], "single"), single([-2:2])') | |
123 */ | 196 */ |
124 | 197 |
125 DEFUN (num2hex, args, , | 198 DEFUN (num2hex, args, , |
126 "-*- texinfo -*-\n\ | 199 "-*- texinfo -*-\n\ |
127 @deftypefn {Built-in Function} {@var{s} =} num2hex (@var{n})\n\ | 200 @deftypefn {Built-in Function} {@var{s} =} num2hex (@var{n})\n\ |