GNU Octave  4.0.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-2015 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.\n\
41 \n\
42 If fewer than 16 characters are given the strings are right padded with\n\
43 @qcode{'0'} characters.\n\
44 \n\
45 Given a string matrix, @code{hex2num} treats each row as a separate number.\n\
46 \n\
47 @example\n\
48 @group\n\
49 hex2num ([\"4005bf0a8b145769\"; \"4024000000000000\"])\n\
50  @result{} [2.7183; 10.000]\n\
51 @end group\n\
52 @end example\n\
53 \n\
54 The optional argument @var{class} can be passed as the string\n\
55 @qcode{\"single\"} to specify that the given string should be interpreted as\n\
56 a single precision number. In this case, @var{s} should be an 8 character\n\
57 hexadecimal string. For example:\n\
58 \n\
59 @example\n\
60 @group\n\
61 hex2num ([\"402df854\"; \"41200000\"], \"single\")\n\
62  @result{} [2.7183; 10.000]\n\
63 @end group\n\
64 @end example\n\
65 @seealso{num2hex, hex2dec, dec2hex}\n\
66 @end deftypefn")
67 {
68  int nargin = args.length ();
69  octave_value retval;
70 
71  if (nargin < 1 || nargin > 2)
72  print_usage ();
73  else if (nargin == 2 && ! args(1).is_string ())
74  error ("hex2num: CLASS must be a string");
75  else
76  {
77  const charMatrix cmat = args(0).char_matrix_value ();
78  std::string prec = (nargin == 2) ? args(1).string_value () : "double";
79  bool is_single = (prec == "single");
80  octave_idx_type nchars = (is_single) ? 8 : 16;
81 
82  if (cmat.columns () > nchars)
83  error ("hex2num: S must be no more than %d characters", nchars);
84  else if (prec != "double" && prec != "single")
85  error ("hex2num: CLASS must be either \"double\" or \"single\"");
86  else if (! error_state)
87  {
88  octave_idx_type nr = cmat.rows ();
89  octave_idx_type nc = cmat.columns ();
90 
91  if (is_single)
92  {
93  FloatColumnVector m (nr);
94 
95  for (octave_idx_type i = 0; i < nr; i++)
96  {
97  union
98  {
99  uint32_t ival;
100  float dval;
101  } num;
102 
103  num.ival = 0;
104 
105  for (octave_idx_type j = 0; j < nc; j++)
106  {
107  unsigned char ch = cmat.elem (i, j);
108 
109  if (isxdigit (ch))
110  {
111  num.ival <<= 4;
112  if (ch >= 'a')
113  num.ival += static_cast<uint32_t> (ch - 'a' + 10);
114  else if (ch >= 'A')
115  num.ival += static_cast<uint32_t> (ch - 'A' + 10);
116  else
117  num.ival += static_cast<uint32_t> (ch - '0');
118  }
119  else
120  {
121  error ("hex2num: illegal character found in string S");
122  break;
123  }
124  }
125 
126  if (error_state)
127  break;
128  else
129  {
130  if (nc < nchars)
131  num.ival <<= (nchars - nc) * 4;
132 
133  m(i) = num.dval;
134  }
135  }
136 
137  if (! error_state)
138  retval = m;
139  }
140  else
141  {
142  ColumnVector m (nr);
143 
144  for (octave_idx_type i = 0; i < nr; i++)
145  {
146  union
147  {
148  uint64_t ival;
149  double dval;
150  } num;
151 
152  num.ival = 0;
153 
154  for (octave_idx_type j = 0; j < nc; j++)
155  {
156  unsigned char ch = cmat.elem (i, j);
157 
158  if (isxdigit (ch))
159  {
160  num.ival <<= 4;
161  if (ch >= 'a')
162  num.ival += static_cast<uint64_t> (ch - 'a' + 10);
163  else if (ch >= 'A')
164  num.ival += static_cast<uint64_t> (ch - 'A' + 10);
165  else
166  num.ival += static_cast<uint64_t> (ch - '0');
167  }
168  else
169  {
170  error ("hex2num: illegal character found in string S");
171  break;
172  }
173  }
174 
175  if (error_state)
176  break;
177  else
178  {
179  if (nc < nchars)
180  num.ival <<= (nchars - nc) * 4;
181 
182  m(i) = num.dval;
183  }
184  }
185 
186  if (! error_state)
187  retval = m;
188  }
189  }
190  }
191 
192  return retval;
193 }
194 
195 /*
196 %!assert (hex2num (["c00";"bff";"000";"3ff";"400"]), [-2:2]')
197 %!assert (hex2num (["c00";"bf8";"000";"3f8";"400"], "single"), single([-2:2])')
198 */
199 
200 DEFUN (num2hex, args, ,
201  "-*- texinfo -*-\n\
202 @deftypefn {Built-in Function} {@var{s} =} num2hex (@var{n})\n\
203 Typecast a double or single precision number or vector to a 8 or 16\n\
204 character hexadecimal string of the IEEE 754 representation of the number.\n\
205 \n\
206 For example:\n\
207 \n\
208 @example\n\
209 @group\n\
210 num2hex ([-1, 1, e, Inf])\n\
211 @result{} \"bff0000000000000\n\
212  3ff0000000000000\n\
213  4005bf0a8b145769\n\
214  7ff0000000000000\"\n\
215 @end group\n\
216 @end example\n\
217 \n\
218 If the argument @var{n} is a single precision number or vector, the returned\n\
219 string has a length of 8. For example:\n\
220 \n\
221 @example\n\
222 @group\n\
223 num2hex (single ([-1, 1, e, Inf]))\n\
224 @result{} \"bf800000\n\
225  3f800000\n\
226  402df854\n\
227  7f800000\"\n\
228 @end group\n\
229 @end example\n\
230 @seealso{hex2num, hex2dec, dec2hex}\n\
231 @end deftypefn")
232 {
233  int nargin = args.length ();
234  octave_value retval;
235 
236  if (nargin != 1)
237  print_usage ();
238  else if (args(0).is_single_type ())
239  {
240  const FloatColumnVector v (args(0).float_vector_value ());
241 
242  if (! error_state)
243  {
244  octave_idx_type nchars = 8;
245  octave_idx_type nr = v.length ();
246  charMatrix m (nr, nchars);
247  const float *pv = v.fortran_vec ();
248 
249  for (octave_idx_type i = 0; i < nr; i++)
250  {
251  union
252  {
253  uint32_t ival;
254  float dval;
255  } num;
256 
257  num.dval = *pv++;
258 
259  for (octave_idx_type j = 0; j < nchars; j++)
260  {
261  unsigned char ch =
262  static_cast<char>(num.ival >> ((nchars - 1 - j) * 4) & 0xF);
263  if (ch >= 10)
264  ch += 'a' - 10;
265  else
266  ch += '0';
267 
268  m.elem (i, j) = ch;
269  }
270  }
271 
272  retval = m;
273  }
274  }
275  else
276  {
277  const ColumnVector v (args(0).vector_value ());
278 
279  if (! error_state)
280  {
281  octave_idx_type nchars = 16;
282  octave_idx_type nr = v.length ();
283  charMatrix m (nr, nchars);
284  const double *pv = v.fortran_vec ();
285 
286  for (octave_idx_type i = 0; i < nr; i++)
287  {
288  union
289  {
290  uint64_t ival;
291  double dval;
292  } num;
293 
294  num.dval = *pv++;
295 
296  for (octave_idx_type j = 0; j < nchars; j++)
297  {
298  unsigned char ch =
299  static_cast<char>(num.ival >> ((nchars - 1 - j) * 4) & 0xF);
300  if (ch >= 10)
301  ch += 'a' - 10;
302  else
303  ch += '0';
304 
305  m.elem (i, j) = ch;
306  }
307  }
308 
309  retval = m;
310  }
311  }
312 
313  return retval;
314 }
315 
316 /*
317 %!assert (num2hex (-2:2), ["c000000000000000";"bff0000000000000";"0000000000000000";"3ff0000000000000";"4000000000000000"])
318 %!assert (num2hex (single (-2:2)), ["c0000000";"bf800000";"00000000";"3f800000";"40000000"])
319 */
OCTINTERP_API void print_usage(void)
Definition: defun.cc:51
#define DEFUN(name, args_name, nargout_name, doc)
Definition: defun.h:44
void error(const char *fmt,...)
Definition: error.cc:476
T & elem(octave_idx_type n)
Definition: Array.h:380
octave_idx_type rows(void) const
Definition: Array.h:313
int error_state
Definition: error.cc:101
octave_idx_type length(void) const
Number of elements in the array.
Definition: Array.h:267
const T * fortran_vec(void) const
Definition: Array.h:481
octave_idx_type columns(void) const
Definition: Array.h:322