GNU Octave  4.2.1
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-2017 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 #if defined (HAVE_CONFIG_H)
24 # include "config.h"
25 #endif
26 
27 #include <algorithm>
28 
29 #include "defun.h"
30 #include "error.h"
31 #include "errwarn.h"
32 #include "ovl.h"
33 #include "utils.h"
34 
35 DEFUN (hex2num, args, ,
36  doc: /* -*- texinfo -*-
37 @deftypefn {} {@var{n} =} hex2num (@var{s})
38 @deftypefnx {} {@var{n} =} hex2num (@var{s}, @var{class})
39 Typecast the 16 character hexadecimal character string to an IEEE 754
40 double precision number.
41 
42 If fewer than 16 characters are given the strings are right padded with
43 @qcode{'0'} characters.
44 
45 Given a string matrix, @code{hex2num} treats each row as a separate number.
46 
47 @example
48 @group
49 hex2num (["4005bf0a8b145769"; "4024000000000000"])
50  @result{} [2.7183; 10.000]
51 @end group
52 @end example
53 
54 The optional argument @var{class} can be passed as the string
55 @qcode{"single"} to specify that the given string should be interpreted as
56 a single precision number. In this case, @var{s} should be an 8 character
57 hexadecimal string. For example:
58 
59 @example
60 @group
61 hex2num (["402df854"; "41200000"], "single")
62  @result{} [2.7183; 10.000]
63 @end group
64 @end example
65 @seealso{num2hex, hex2dec, dec2hex}
66 @end deftypefn */)
67 {
68  int nargin = args.length ();
69 
70  if (nargin < 1 || nargin > 2)
71  print_usage ();
72 
73  if (nargin == 2 && ! args(1).is_string ())
74  error ("hex2num: CLASS must be a string");
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 
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  error ("hex2num: illegal character found in string S");
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 
120  if (nc < nchars)
121  num.ival <<= (nchars - nc) * 4;
122 
123  m(i) = num.dval;
124  }
125 
126  retval = m;
127  }
128  else
129  {
130  ColumnVector m (nr);
131 
132  for (octave_idx_type i = 0; i < nr; i++)
133  {
134  union
135  {
136  uint64_t ival;
137  double dval;
138  } num;
139 
140  num.ival = 0;
141 
142  for (octave_idx_type j = 0; j < nc; j++)
143  {
144  unsigned char ch = cmat.elem (i, j);
145 
146  if (! isxdigit (ch))
147  error ("hex2num: illegal character found in string S");
148 
149  num.ival <<= 4;
150  if (ch >= 'a')
151  num.ival += static_cast<uint64_t> (ch - 'a' + 10);
152  else if (ch >= 'A')
153  num.ival += static_cast<uint64_t> (ch - 'A' + 10);
154  else
155  num.ival += static_cast<uint64_t> (ch - '0');
156  }
157 
158  if (nc < nchars)
159  num.ival <<= (nchars - nc) * 4;
160 
161  m(i) = num.dval;
162  }
163 
164  retval = m;
165  }
166 
167  return retval;
168 }
169 
170 /*
171 %!assert (hex2num (["c00";"bff";"000";"3ff";"400"]), [-2:2]')
172 %!assert (hex2num (["c00";"bf8";"000";"3f8";"400"], "single"), single([-2:2])')
173 */
174 
175 DEFUN (num2hex, args, ,
176  doc: /* -*- texinfo -*-
177 @deftypefn {} {@var{s} =} num2hex (@var{n})
178 Typecast a double or single precision number or vector to a 8 or 16
179 character hexadecimal string of the IEEE 754 representation of the number.
180 
181 For example:
182 
183 @example
184 @group
185 num2hex ([-1, 1, e, Inf])
186 @result{} "bff0000000000000
187  3ff0000000000000
188  4005bf0a8b145769
189  7ff0000000000000"
190 @end group
191 @end example
192 
193 If the argument @var{n} is a single precision number or vector, the returned
194 string has a length of 8. For example:
195 
196 @example
197 @group
198 num2hex (single ([-1, 1, e, Inf]))
199 @result{} "bf800000
200  3f800000
201  402df854
202  7f800000"
203 @end group
204 @end example
205 @seealso{hex2num, hex2dec, dec2hex}
206 @end deftypefn */)
207 {
208  if (args.length () != 1)
209  print_usage ();
210 
211  if (args(0).is_complex_type ())
212  error ("num2hex: N must be real");
213 
215 
216  if (args(0).is_single_type ())
217  {
218  const FloatColumnVector v (args(0).float_vector_value ());
219 
220  octave_idx_type nchars = 8;
221  octave_idx_type nr = v.numel ();
222  charMatrix m (nr, nchars);
223  const float *pv = v.fortran_vec ();
224 
225  for (octave_idx_type i = 0; i < nr; i++)
226  {
227  union
228  {
229  uint32_t ival;
230  float dval;
231  } num;
232 
233  num.dval = *pv++;
234 
235  for (octave_idx_type j = 0; j < nchars; j++)
236  {
237  unsigned char ch =
238  static_cast<char>(num.ival >> ((nchars - 1 - j) * 4) & 0xF);
239  if (ch >= 10)
240  ch += 'a' - 10;
241  else
242  ch += '0';
243 
244  m.elem (i, j) = ch;
245  }
246  }
247 
248  retval = m;
249  }
250  else
251  {
252  const ColumnVector v (args(0).vector_value ());
253 
254  octave_idx_type nchars = 16;
255  octave_idx_type nr = v.numel ();
256  charMatrix m (nr, nchars);
257  const double *pv = v.fortran_vec ();
258 
259  for (octave_idx_type i = 0; i < nr; i++)
260  {
261  union
262  {
263  uint64_t ival;
264  double dval;
265  } num;
266 
267  num.dval = *pv++;
268 
269  for (octave_idx_type j = 0; j < nchars; j++)
270  {
271  unsigned char ch =
272  static_cast<char>(num.ival >> ((nchars - 1 - j) * 4) & 0xF);
273  if (ch >= 10)
274  ch += 'a' - 10;
275  else
276  ch += '0';
277 
278  m.elem (i, j) = ch;
279  }
280  }
281 
282  retval = m;
283  }
284 
285  return retval;
286 }
287 
288 /*
289 %!assert (num2hex (-2:2), ["c000000000000000";"bff0000000000000";"0000000000000000";"3ff0000000000000";"4000000000000000"])
290 %!assert (num2hex (single (-2:2)), ["c0000000";"bf800000";"00000000";"3f800000";"40000000"])
291 
292 %!error num2hex ()
293 %!error num2hex (1,2)
294 %!error num2hex (1j)
295 */
treats each row as a separate number xample roup hex2num(["4005bf0a8b145769";"4024000000000000"]) esult
Definition: hex2num.cc:66
OCTINTERP_API void print_usage(void)
Definition: defun.cc:52
#define DEFUN(name, args_name, nargout_name, doc)
Definition: defun.h:46
void error(const char *fmt,...)
Definition: error.cc:570
T & elem(octave_idx_type n)
Definition: Array.h:482
octave_idx_type rows(void) const
Definition: Array.h:401
JNIEnv void * args
Definition: ov-java.cc:67
nd deftypefn *octave_map m
Definition: ov-struct.cc:2058
int nargin
Definition: graphics.cc:10115
octave_value retval
Definition: data.cc:6294
=val(i)}if ode{val(i)}occurs in table i
Definition: lookup.cc:239
If this string is the system will ring the terminal sometimes it is useful to be able to print the original representation of the string
Definition: utils.cc:854
octave_idx_type columns(void) const
Definition: Array.h:410