GNU Octave  3.8.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
hex2num.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2008-2013 David Bateman
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 
27 #include <algorithm>
28 
29 #include "defun.h"
30 #include "error.h"
31 #include "gripes.h"
32 #include "oct-obj.h"
33 #include "utils.h"
34 
35 DEFUN (hex2num, args, ,
36  "-*- texinfo -*-\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\
39 Typecast the 16 character hexadecimal character string to an IEEE 754\n\
40 double precision number. If fewer than 16 characters are given the\n\
41 strings are right padded with @qcode{'0'} characters.\n\
42 \n\
43 Given a string matrix, @code{hex2num} treats each row as a separate\n\
44 number.\n\
45 \n\
46 @example\n\
47 @group\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\n\
54 @qcode{\"single\"} to specify that the given string should be interpreted as\n\
55 a single precision number. In this case, @var{s} should be an 8 character\n\
56 hexadecimal string. For example: \n\
57 \n\
58 @example\n\
59 @group\n\
60 hex2num ([\"402df854\"; \"41200000\"], \"single\")\n\
61  @result{} [2.7183; 10.000]\n\
62 @end group\n\
63 @end example\n\
64 @seealso{num2hex, hex2dec, dec2hex}\n\
65 @end deftypefn")
66 {
67  int nargin = args.length ();
68  octave_value retval;
69 
70  if (nargin < 1 || nargin > 2)
71  print_usage ();
72  else if (nargin == 2 && ! args(1).is_string ())
73  error ("hex2num: CLASS must be a string");
74  else
75  {
76  const charMatrix cmat = args(0).char_matrix_value ();
77  std::string prec = (nargin == 2) ? args(1).string_value () : "double";
78  bool is_single = (prec == "single");
79  octave_idx_type nchars = (is_single) ? 8 : 16;
80 
81  if (cmat.columns () > nchars)
82  error ("hex2num: S must be no more than %d characters", nchars);
83  else if (prec != "double" && prec != "single")
84  error ("hex2num: CLASS must be either \"double\" or \"single\"");
85  else if (! error_state)
86  {
87  octave_idx_type nr = cmat.rows ();
88  octave_idx_type nc = cmat.columns ();
89 
90  if (is_single)
91  {
92  FloatColumnVector m (nr);
93 
94  for (octave_idx_type i = 0; i < nr; i++)
95  {
96  union
97  {
98  uint32_t ival;
99  float dval;
100  } num;
101 
102  num.ival = 0;
103 
104  for (octave_idx_type j = 0; j < nc; j++)
105  {
106  unsigned char ch = cmat.elem (i, j);
107 
108  if (isxdigit (ch))
109  {
110  num.ival <<= 4;
111  if (ch >= 'a')
112  num.ival += static_cast<uint32_t> (ch - 'a' + 10);
113  else if (ch >= 'A')
114  num.ival += static_cast<uint32_t> (ch - 'A' + 10);
115  else
116  num.ival += static_cast<uint32_t> (ch - '0');
117  }
118  else
119  {
120  error ("hex2num: illegal character found in string S");
121  break;
122  }
123  }
124 
125  if (error_state)
126  break;
127  else
128  {
129  if (nc < nchars)
130  num.ival <<= (nchars - nc) * 4;
131 
132  m(i) = num.dval;
133  }
134  }
135 
136  if (! error_state)
137  retval = m;
138  }
139  else
140  {
141  ColumnVector m (nr);
142 
143  for (octave_idx_type i = 0; i < nr; i++)
144  {
145  union
146  {
147  uint64_t ival;
148  double dval;
149  } num;
150 
151  num.ival = 0;
152 
153  for (octave_idx_type j = 0; j < nc; j++)
154  {
155  unsigned char ch = cmat.elem (i, j);
156 
157  if (isxdigit (ch))
158  {
159  num.ival <<= 4;
160  if (ch >= 'a')
161  num.ival += static_cast<uint64_t> (ch - 'a' + 10);
162  else if (ch >= 'A')
163  num.ival += static_cast<uint64_t> (ch - 'A' + 10);
164  else
165  num.ival += static_cast<uint64_t> (ch - '0');
166  }
167  else
168  {
169  error ("hex2num: illegal character found in string S");
170  break;
171  }
172  }
173 
174  if (error_state)
175  break;
176  else
177  {
178  if (nc < nchars)
179  num.ival <<= (nchars - nc) * 4;
180 
181  m(i) = num.dval;
182  }
183  }
184 
185  if (! error_state)
186  retval = m;
187  }
188  }
189  }
190 
191  return retval;
192 }
193 
194 /*
195 %!assert (hex2num (["c00";"bff";"000";"3ff";"400"]), [-2:2]')
196 %!assert (hex2num (["c00";"bf8";"000";"3f8";"400"], "single"), single([-2:2])')
197 */
198 
199 DEFUN (num2hex, args, ,
200  "-*- texinfo -*-\n\
201 @deftypefn {Built-in Function} {@var{s} =} num2hex (@var{n})\n\
202 Typecast a double or single precision number or vector to a 8 or 16\n\
203 character hexadecimal string of the IEEE 754 representation of the number.\n\
204 For example:\n\
205 \n\
206 @example\n\
207 @group\n\
208 num2hex ([-1, 1, e, Inf])\n\
209 @result{} \"bff0000000000000\n\
210  3ff0000000000000\n\
211  4005bf0a8b145769\n\
212  7ff0000000000000\"\n\
213 @end group\n\
214 @end example\n\
215 \n\
216 If the argument @var{n} is a single precision number or vector, the returned\n\
217 string has a length of 8. For example:\n\
218 \n\
219 @example\n\
220 @group\n\
221 num2hex (single ([-1, 1, e, Inf]))\n\
222 @result{} \"bf800000\n\
223  3f800000\n\
224  402df854\n\
225  7f800000\"\n\
226 @end group\n\
227 @end example\n\
228 @seealso{hex2num, hex2dec, dec2hex}\n\
229 @end deftypefn")
230 {
231  int nargin = args.length ();
232  octave_value retval;
233 
234  if (nargin != 1)
235  print_usage ();
236  else if (args(0).is_single_type ())
237  {
238  const FloatColumnVector v (args(0).float_vector_value ());
239 
240  if (! error_state)
241  {
242  octave_idx_type nchars = 8;
243  octave_idx_type nr = v.length ();
244  charMatrix m (nr, nchars);
245  const float *pv = v.fortran_vec ();
246 
247  for (octave_idx_type i = 0; i < nr; i++)
248  {
249  union
250  {
251  uint32_t ival;
252  float dval;
253  } num;
254 
255  num.dval = *pv++;
256 
257  for (octave_idx_type j = 0; j < nchars; j++)
258  {
259  unsigned char ch =
260  static_cast<char>(num.ival >> ((nchars - 1 - j) * 4) & 0xF);
261  if (ch >= 10)
262  ch += 'a' - 10;
263  else
264  ch += '0';
265 
266  m.elem (i, j) = ch;
267  }
268  }
269 
270  retval = m;
271  }
272  }
273  else
274  {
275  const ColumnVector v (args(0).vector_value ());
276 
277  if (! error_state)
278  {
279  octave_idx_type nchars = 16;
280  octave_idx_type nr = v.length ();
281  charMatrix m (nr, nchars);
282  const double *pv = v.fortran_vec ();
283 
284  for (octave_idx_type i = 0; i < nr; i++)
285  {
286  union
287  {
288  uint64_t ival;
289  double dval;
290  } num;
291 
292  num.dval = *pv++;
293 
294  for (octave_idx_type j = 0; j < nchars; j++)
295  {
296  unsigned char ch =
297  static_cast<char>(num.ival >> ((nchars - 1 - j) * 4) & 0xF);
298  if (ch >= 10)
299  ch += 'a' - 10;
300  else
301  ch += '0';
302 
303  m.elem (i, j) = ch;
304  }
305  }
306 
307  retval = m;
308  }
309  }
310 
311  return retval;
312 }
313 
314 /*
315 %!assert (num2hex (-2:2), ["c000000000000000";"bff0000000000000";"0000000000000000";"3ff0000000000000";"4000000000000000"])
316 %!assert (num2hex (single (-2:2)), ["c0000000";"bf800000";"00000000";"3f800000";"40000000"])
317 */