GNUnet  0.11.x
Macros | Functions
rps-test_util.h File Reference

Some utils faciliating the view into the internals for the sampler needed for evaluation. More...

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define TO_FILE   0
 
#define to_file(file_name, ...)
 This function is used to facilitate writing important information to disk. More...
 
#define to_file_w_len(file_name, len, ...)
 

Functions

char * auth_key_to_string (struct GNUNET_CRYPTO_AuthKey auth_key)
 
struct GNUNET_CRYPTO_AuthKey string_to_auth_key (const char *str)
 
struct GNUNET_DISK_FileHandleget_file_handle (const char *name)
 Get file handle. More...
 
int close_all_files ()
 Close all files that were opened with get_file_handle. More...
 
char * store_prefix_file_name (const unsigned int index, const char *prefix)
 
void to_file_raw (const char *file_name, const char *buf, size_t size_buf)
 
void to_file_raw_unaligned (const char *file_name, const char *buf, size_t size_buf, unsigned bits_needed)
 
uint32_t fac (uint32_t x)
 Factorial. More...
 
uint32_t binom (uint32_t n, uint32_t k)
 Binomial coefficient (n choose k) More...
 

Detailed Description

Some utils faciliating the view into the internals for the sampler needed for evaluation.

Author
Julius B√ľnger

Definition in file rps-test_util.h.

Macro Definition Documentation

◆ TO_FILE

#define TO_FILE   0

Definition at line 31 of file rps-test_util.h.

◆ to_file

#define to_file (   file_name,
  ... 
)
Value:
do { \
char tmp_buf[512] = ""; \
int size; \
if (NULL == file_name) break; \
size = GNUNET_snprintf (tmp_buf, sizeof(tmp_buf), __VA_ARGS__); \
if (0 > size) \
{ \
"Failed to create tmp_buf\n"); \
break; \
} \
(void) strncat (tmp_buf, "\n", 512); \
GNUNET_DISK_file_write (get_file_handle (file_name), \
tmp_buf, \
strnlen (tmp_buf, 512)); \
} while (0);
int GNUNET_snprintf(char *buf, size_t size, const char *format,...)
Like snprintf, just aborts if the buffer is of insufficient size.
static char * file_name
Dump file name.
struct GNUNET_DISK_FileHandle * get_file_handle(const char *name)
Get file handle.
Definition: rps-test_util.c:74
static unsigned int size
Size of the "table".
Definition: peer.c:67
static size_t strnlen(const char *s, size_t n)

This function is used to facilitate writing important information to disk.

Definition at line 65 of file rps-test_util.h.

Referenced by do_round(), hist_update(), insert_in_sampler(), stat_iterator(), view_update_cb(), and write_final_stats().

◆ to_file_w_len

#define to_file_w_len (   file_name,
  len,
  ... 
)
Value:
do { char tmp_buf [len]; \
int size; \
memset (tmp_buf, 0, len); \
size = GNUNET_snprintf (tmp_buf, \
sizeof( \
tmp_buf), \
__VA_ARGS__); \
if (0 > size) \
{ \
GNUNET_log ( \
"Failed to create tmp_buf\n"); \
break; \
} \
(void) strncat (tmp_buf, "\n", \
len); \
GNUNET_DISK_file_write ( \
tmp_buf, \
strnlen ( \
tmp_buf, len)); \
} while (0);
int GNUNET_snprintf(char *buf, size_t size, const char *format,...)
Like snprintf, just aborts if the buffer is of insufficient size.
static char * file_name
Dump file name.
struct GNUNET_DISK_FileHandle * get_file_handle(const char *name)
Get file handle.
Definition: rps-test_util.c:74
static unsigned int size
Size of the "table".
Definition: peer.c:67
static size_t strnlen(const char *s, size_t n)
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...

Definition at line 83 of file rps-test_util.h.

Referenced by compute_probabilities(), and write_histogram_to_file().

Function Documentation

◆ auth_key_to_string()

char* auth_key_to_string ( struct GNUNET_CRYPTO_AuthKey  auth_key)

Definition at line 376 of file rps-test_util.c.

References buf, end, GNUNET_break, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_malloc, GNUNET_snprintf(), GNUNET_STRINGS_data_to_string(), GNUNET_CRYPTO_AuthKey::key, LOG, and size.

377 {
378  int size;
379  size_t name_buf_size;
380  char *end;
381  char *buf;
382  char *name_buf;
383  size_t keylen = (sizeof(struct GNUNET_CRYPTO_AuthKey)) * 8;
384 
385  name_buf_size = 512 * sizeof(char);
386  name_buf = GNUNET_malloc (name_buf_size);
387 
388  if (keylen % 5 > 0)
389  keylen += 5 - keylen % 5;
390  keylen /= 5;
391  buf = GNUNET_malloc (keylen + 1);
392 
393  end = GNUNET_STRINGS_data_to_string (&(auth_key.key),
394  sizeof(struct GNUNET_CRYPTO_AuthKey),
395  buf,
396  keylen);
397 
398  if (NULL == end)
399  {
400  GNUNET_free (buf);
401  GNUNET_break (0);
402  }
403  else
404  {
405  *end = '\0';
406  }
407 
408  size = GNUNET_snprintf (name_buf, name_buf_size, "sampler_el-%s", buf);
409  if (0 > size)
410  LOG (GNUNET_ERROR_TYPE_WARNING, "Failed to create name_buf\n");
411 
412  GNUNET_free (buf);
413 
414  return name_buf;
415 }
static int end
Set if we are to shutdown all services (including ARM).
Definition: gnunet-arm.c:34
int GNUNET_snprintf(char *buf, size_t size, const char *format,...)
Like snprintf, just aborts if the buffer is of insufficient size.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
#define LOG(kind,...)
Definition: rps-test_util.c:35
static char buf[2048]
unsigned char key[(512/8)]
static unsigned int size
Size of the "table".
Definition: peer.c:67
type for (message) authentication keys
#define GNUNET_malloc(size)
Wrapper around malloc.
char * GNUNET_STRINGS_data_to_string(const void *data, size_t size, char *out, size_t out_size)
Convert binary data to ASCII encoding using CrockfordBase32.
Definition: strings.c:856
#define GNUNET_free(ptr)
Wrapper around free.
Here is the call graph for this function:

◆ string_to_auth_key()

struct GNUNET_CRYPTO_AuthKey string_to_auth_key ( const char *  str)

Definition at line 422 of file rps-test_util.c.

References GNUNET_ERROR_TYPE_WARNING, GNUNET_OK, GNUNET_STRINGS_string_to_data(), GNUNET_CRYPTO_AuthKey::key, and LOG.

Referenced by file_name_cb().

423 {
424  struct GNUNET_CRYPTO_AuthKey auth_key;
425 
426  if (GNUNET_OK !=
428  strlen (str),
429  &auth_key.key,
430  sizeof(struct GNUNET_CRYPTO_AuthKey)))
431  {
432  LOG (GNUNET_ERROR_TYPE_WARNING, "Failed to convert string to data\n");
433  }
434 
435  return auth_key;
436 }
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define LOG(kind,...)
Definition: rps-test_util.c:35
type for (message) authentication keys
int GNUNET_STRINGS_string_to_data(const char *enc, size_t enclen, void *out, size_t out_size)
Convert CrockfordBase32 encoding back to data.
Definition: strings.c:952
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_file_handle()

struct GNUNET_DISK_FileHandle* get_file_handle ( const char *  name)

Get file handle.

If necessary, create file handle and store it with the other file handles.

Parameters
nameName of the file
Returns
File handle

Definition at line 74 of file rps-test_util.c.

References fh, GNUNET_assert, GNUNET_CONTAINER_multihashmap_create(), GNUNET_CONTAINER_multihashmap_get(), GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_CRYPTO_hash(), GNUNET_DISK_file_open(), GNUNET_DISK_OPEN_APPEND, GNUNET_DISK_OPEN_CREATE, GNUNET_DISK_OPEN_WRITE, GNUNET_DISK_PERM_GROUP_READ, GNUNET_DISK_PERM_USER_READ, GNUNET_DISK_PERM_USER_WRITE, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_NO, GNUNET_YES, and LOG.

75 {
76  struct GNUNET_HashCode hash;
77  struct GNUNET_DISK_FileHandle *fh;
78 
79  if (NULL == open_files)
80  {
82  GNUNET_NO);
84  "Created map of open files.\n");
85  }
87  strlen (name),
88  &hash);
90  &hash)))
91  return fh;
99  if (NULL == fh)
100  {
102  "Opening file `%s' failed.\n",
103  name);
104  GNUNET_assert (0);
105  }
108  &hash,
109  fh,
111  return fh;
112 }
Create file if it doesn't exist.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
static struct GNUNET_CONTAINER_MultiHashMap * open_files
Definition: rps-test_util.c:61
Append to the file.
#define GNUNET_NO
Definition: gnunet_common.h:78
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
#define LOG(kind,...)
Definition: rps-test_util.c:35
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:48
static int fh
Handle to the unique file.
A 512-bit hashcode.
There must only be one value per key; storing a value should fail if a value under the same key alrea...
Open the file for writing.
int GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
const char * name
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
#define GNUNET_YES
Definition: gnunet_common.h:77
struct GNUNET_DISK_FileHandle * GNUNET_DISK_file_open(const char *fn, enum GNUNET_DISK_OpenFlags flags, enum GNUNET_DISK_AccessPermissions perm)
Open a file.
Definition: disk.c:1268
Handle used to access files (and pipes).
Here is the call graph for this function:

◆ close_all_files()

int close_all_files ( )

Close all files that were opened with get_file_handle.

Returns
Success of iterating over files

Definition at line 151 of file rps-test_util.c.

References close_files_iter(), GNUNET_CONTAINER_multihashmap_destroy(), GNUNET_CONTAINER_multihashmap_iterate(), and ret.

Referenced by shutdown_op(), and shutdown_task().

152 {
153  int ret;
154 
157  NULL);
159  open_files = NULL;
160  return ret;
161 }
int close_files_iter(void *cls, const struct GNUNET_HashCode *key, void *value)
Closes the file of the current entry.
static struct GNUNET_CONTAINER_MultiHashMap * open_files
Definition: rps-test_util.c:61
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MulitHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ store_prefix_file_name()

char* store_prefix_file_name ( const unsigned int  index,
const char *  prefix 
)

Definition at line 460 of file rps-test_util.c.

References ensure_folder_exist(), file_name, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, GNUNET_malloc, GNUNET_snprintf(), and GNUNET_SYSERR.

Referenced by new_sub(), post_profiler(), pre_profiler(), and write_histogram_to_file().

462 {
463  int len_file_name;
464  int out_size;
465  char *file_name;
466  char index_str[64];
467 
469  return NULL;
470  out_size = GNUNET_snprintf (index_str,
471  64,
472  "%u",
473  index);
474  if ((64 < out_size) ||
475  (0 > out_size) )
476  {
478  "Failed to write string to buffer (size: %i, out_size: %i)\n",
479  64,
480  out_size);
481  }
482  len_file_name = (strlen (prefix)
483  + strlen (index_str)
484  + 11)
485  * sizeof(char);
486  file_name = GNUNET_malloc (len_file_name);
487  out_size = GNUNET_snprintf (file_name,
488  len_file_name,
489  "/tmp/rps/%s-%s",
490  prefix,
491  index_str);
492  if ((len_file_name < out_size) ||
493  (0 > out_size) )
494  {
496  "Failed to write string to buffer (size: %i, out_size: %i)\n",
497  len_file_name,
498  out_size);
499  }
500  return file_name;
501 }
int GNUNET_snprintf(char *buf, size_t size, const char *format,...)
Like snprintf, just aborts if the buffer is of insufficient size.
static char * file_name
Dump file name.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
static int ensure_folder_exist(void)
Try to ensure that /tmp/rps exists.
#define GNUNET_log(kind,...)
#define GNUNET_malloc(size)
Wrapper around malloc.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ to_file_raw()

void to_file_raw ( const char *  file_name,
const char *  buf,
size_t  size_buf 
)

Definition at line 165 of file rps-test_util.c.

References removetrailingwhitespace::f, GNUNET_DISK_file_close(), GNUNET_DISK_file_open(), GNUNET_DISK_file_write(), GNUNET_DISK_OPEN_APPEND, GNUNET_DISK_OPEN_CREATE, GNUNET_DISK_OPEN_WRITE, GNUNET_DISK_PERM_GROUP_READ, GNUNET_DISK_PERM_OTHER_READ, GNUNET_DISK_PERM_USER_READ, GNUNET_DISK_PERM_USER_WRITE, GNUNET_ERROR_TYPE_WARNING, GNUNET_YES, and LOG.

Referenced by profiler_reply_handle(), profiler_reply_handle_info(), and to_file_raw_unaligned().

166 {
167  struct GNUNET_DISK_FileHandle *f;
168  size_t size_written;
169 
170  if (NULL == (f = GNUNET_DISK_file_open (file_name,
178  {
180  "Not able to open file %s\n",
181  file_name);
182  return;
183  }
184 
185  size_written = GNUNET_DISK_file_write (f, buf, size_buf);
186  if (size_buf != size_written)
187  {
189  "Unable to write to file! (Size: %u, size_written: %u)\n",
190  size_buf,
191  size_written);
192 
195  "Unable to close file\n");
196 
197  return;
198  }
200  "Wrote %u bytes raw.\n",
201  size_written);
204  "Unable to close file\n");
205 }
Create file if it doesn&#39;t exist.
int GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition: disk.c:1345
static char * file_name
Dump file name.
Append to the file.
#define LOG(kind,...)
Definition: rps-test_util.c:35
ssize_t GNUNET_DISK_file_write(const struct GNUNET_DISK_FileHandle *h, const void *buffer, size_t n)
Write a buffer to a file.
Definition: disk.c:820
static char buf[2048]
Open the file for writing.
Everybody can read.
#define GNUNET_YES
Definition: gnunet_common.h:77
struct GNUNET_DISK_FileHandle * GNUNET_DISK_file_open(const char *fn, enum GNUNET_DISK_OpenFlags flags, enum GNUNET_DISK_AccessPermissions perm)
Open a file.
Definition: disk.c:1268
Handle used to access files (and pipes).
Here is the call graph for this function:
Here is the caller graph for this function:

◆ to_file_raw_unaligned()

void to_file_raw_unaligned ( const char *  file_name,
const char *  buf,
size_t  size_buf,
unsigned  bits_needed 
)

Definition at line 209 of file rps-test_util.c.

References B2B, B2B_PAT, bits_needed, buf_unaligned, GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_MIN, LOG, num_bits_buf_unaligned, and to_file_raw().

Referenced by profiler_reply_handle(), and profiler_reply_handle_info().

213 {
214  // TODO endianness!
215  GNUNET_assert (size_buf >= (bits_needed / 8));
216  // if (0 == num_bits_buf_unaligned)
217  // {
218  // if (0 == (bits_needed % 8))
219  // {
220  // to_file_raw (file_name, buf, size_buf);
221  // return;
222  // }
223  // to_file_raw (file_name, buf, size_buf - 1);
224  // buf_unaligned = buf[size_buf - 1];
225  // num_bits_buf_unaligned = bits_needed % 8;
226  // return;
227  // }
229  "Was asked to write %u bits\n", bits_needed);
230 
231  char buf_write[size_buf + 1];
232  const unsigned bytes_iter = (0 != bits_needed % 8 ?
233  (bits_needed / 8) + 1 :
234  bits_needed / 8);
235  // TODO what if no iteration happens?
236  unsigned size_buf_write = 0;
238  "num_bits_buf_unaligned: %u\n",
241  "ua args: size_buf: %u, bits_needed: %u -> iter: %u\n",
242  size_buf,
243  bits_needed,
244  bytes_iter);
245  buf_write[0] = buf_unaligned;
246  /* Iterate over input bytes */
247  for (unsigned i = 0; i < bytes_iter; i++)
248  {
249  /* Number of bits needed in this iteration - 8 for all except last iter */
250  unsigned num_bits_needed_iter;
251  /* Mask for bits to actually use */
252  unsigned mask_bits_needed_iter;
253  char byte_input;
254  /* Number of bits needed to align unaligned byte */
255  unsigned num_bits_to_align;
256  /* Number of bits that are to be moved */
257  unsigned num_bits_to_move;
258  /* Mask for bytes to be moved */
259  char mask_input_to_move;
260  /* Masked bits to be moved */
261  char bits_to_move;
262  /* The amount of bits needed to fit the bits to shift to the nearest spot */
263  unsigned distance_shift_bits;
264  /* Shifted bits on the move */
265  char bits_moving;
266  /* (unaligned) byte being filled with bits */
267  char byte_to_fill;
268  /* mask for needed bits of the input byte that have not been moved */
269  char mask_input_leftover;
270  /* needed bits of the input byte that have not been moved */
271  char byte_input_leftover;
272  unsigned num_bits_leftover;
273  // unsigned num_bits_discard;
274  char byte_unaligned_new;
275 
276  if ((bits_needed - (i * 8)) <= 8)
277  {
278  /* last iteration */
279  num_bits_needed_iter = bits_needed - (i * 8);
280  }
281  else
282  {
283  num_bits_needed_iter = 8;
284  }
286  "number of bits needed in this iteration: %u\n",
287  num_bits_needed_iter);
288  mask_bits_needed_iter = ((char) 1 << num_bits_needed_iter) - 1;
290  "mask needed bits (current iter): "B2B_PAT "\n",
291  B2B (mask_bits_needed_iter));
293  "Unaligned byte: "B2B_PAT " (%u bits)\n",
294  B2B (buf_unaligned),
296  byte_input = buf[i];
298  "next whole input byte: "B2B_PAT "\n",
299  B2B (byte_input));
300  byte_input &= mask_bits_needed_iter;
301  num_bits_to_align = 8 - num_bits_buf_unaligned;
303  "input byte, needed bits: "B2B_PAT "\n",
304  B2B (byte_input));
306  "number of bits needed to align unaligned bit: %u\n",
307  num_bits_to_align);
308  num_bits_to_move = GNUNET_MIN (num_bits_to_align, num_bits_needed_iter);
310  "number of bits of new byte to move: %u\n",
311  num_bits_to_move);
312  mask_input_to_move = ((char) 1 << num_bits_to_move) - 1;
314  "mask of bits of new byte to take for moving: "B2B_PAT "\n",
315  B2B (mask_input_to_move));
316  bits_to_move = byte_input & mask_input_to_move;
318  "masked bits of new byte to take for moving: "B2B_PAT "\n",
319  B2B (bits_to_move));
320  distance_shift_bits = num_bits_buf_unaligned;
322  "distance needed to shift bits to their correct spot: %u\n",
323  distance_shift_bits);
324  bits_moving = bits_to_move << distance_shift_bits;
326  "shifted, masked bits of new byte being moved: "B2B_PAT "\n",
327  B2B (bits_moving));
328  byte_to_fill = buf_unaligned | bits_moving;
330  "byte being filled: "B2B_PAT "\n",
331  B2B (byte_to_fill));
333  "pending bytes: %u\n",
334  num_bits_buf_unaligned + num_bits_needed_iter);
335  if (num_bits_buf_unaligned + num_bits_needed_iter >= 8)
336  {
337  /* buf_unaligned was aligned by filling
338  * -> can be written to storage */
339  buf_write[i] = byte_to_fill;
340  size_buf_write++;
341 
342  /* store the leftover, unaligned bits in buffer */
343  mask_input_leftover = mask_bits_needed_iter & (~mask_input_to_move);
345  "mask of leftover bits of new byte: "B2B_PAT "\n",
346  B2B (mask_input_leftover));
347  byte_input_leftover = byte_input & mask_input_leftover;
349  "masked, leftover bits of new byte: "B2B_PAT "\n",
350  B2B (byte_input_leftover));
351  num_bits_leftover = num_bits_needed_iter - num_bits_to_move;
353  "number of unaligned bits left: %u\n",
354  num_bits_leftover);
355  // num_bits_discard = 8 - num_bits_needed_iter;
356  byte_unaligned_new = byte_input_leftover >> num_bits_to_move;
358  "new unaligned byte: "B2B_PAT "\n",
359  B2B (byte_unaligned_new));
360  buf_unaligned = byte_unaligned_new;
361  num_bits_buf_unaligned = num_bits_leftover % 8;
362  }
363  else
364  {
365  /* unaligned buffer still unaligned but 'fuller' */
366  buf_unaligned = byte_to_fill;
368  }
369  }
370  to_file_raw (file_name, buf_write, size_buf_write);
372 }
void to_file_raw(const char *file_name, const char *buf, size_t size_buf)
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
static char * file_name
Dump file name.
static unsigned bits_needed
numer of bits required to represent the largest peer id
static unsigned num_bits_buf_unaligned
number of bits in unaligned buffer
Definition: rps-test_util.c:59
#define B2B_PAT
Definition: rps-test_util.c:37
#define LOG(kind,...)
Definition: rps-test_util.c:35
#define GNUNET_MIN(a, b)
Definition: gnunet_common.h:80
static char buf[2048]
static char buf_unaligned
buffer for storing the unaligned bits for the next write
Definition: rps-test_util.c:54
#define B2B(byte)
Definition: rps-test_util.c:38
Here is the call graph for this function:
Here is the caller graph for this function:

◆ fac()

uint32_t fac ( uint32_t  x)

Factorial.

Parameters
xNumber of which to compute the factorial
Returns
Factorial of x

Definition at line 512 of file rps-test_util.c.

References fac().

Referenced by binom(), fac(), and find_address_cb().

513 {
514  if (1 >= x)
515  {
516  return x;
517  }
518  return x * fac (x - 1);
519 }
uint32_t fac(uint32_t x)
Factorial.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ binom()

uint32_t binom ( uint32_t  n,
uint32_t  k 
)

Binomial coefficient (n choose k)

Parameters
n
k
Returns
Binomial coefficient of n and k

Definition at line 531 of file rps-test_util.c.

References fac().

Referenced by compute_probabilities(), and prob_observed_n_peers().

532 {
533  // GNUNET_assert (n >= k);
534  if (k > n)
535  return 0;
536  /* if (0 > n) return 0; - always false */
537  /* if (0 > k) return 0; - always false */
538  if (0 == k)
539  return 1;
540  return fac (n)
541  /
542  fac (k) * fac (n - k);
543 }
uint32_t fac(uint32_t x)
Factorial.
Here is the call graph for this function:
Here is the caller graph for this function: