BRL-CAD
bntester.c
Go to the documentation of this file.
1 /* B N T E S T E R . C
2  * BRL-CAD
3  *
4  * Copyright (c) 2004-2014 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * version 2.1 as published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
20 
21 #include "common.h"
22 
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <limits.h>
26 #include <math.h>
27 #include <string.h>
28 #include <errno.h>
29 
30 #include "bu/getopt.h"
31 #include "bu/log.h"
32 #include "bu/parallel.h"
33 #include "bu/str.h"
34 #include "bu/vls.h"
35 #include "vmath.h"
36 #include "bn.h"
37 
38 #define USAGE "Usage: bntester [-l test_case_line_number] [-f function_number] -i input_file [-o output_file]\n"
39 
40 
41 int
42 parse_case(char *buf_p, int *i, long *l, fastf_t *d, unsigned long *u, char *fmt_str, unsigned long line_num, FILE *stream)
43 {
44  int i_idx = 0;
45  int l_idx = 0;
46  int d_idx = 0;
47  int u_idx = 1; /* start index at 1 since function number is stored at 0 */
48  int idx;
49  int fmt_str_len;
50  char *endp;
51  long int l_tmp;
52 
53  fmt_str_len = strlen(fmt_str);
54 
55  for (idx = 0 ; idx < fmt_str_len ; idx++) {
56  buf_p = strtok(NULL, ", ");
57 
58  /* The variable buf_p should never become NULL since the for loop
59  * will exit just before we run out of data if all the required
60  * data is supplied in the data file.
61  */
62  if (buf_p == NULL) {
63  fprintf(stream, "ERROR: Missing parameter(s) for test case on line %lu, skipping test case.\n", line_num);
64  return EXIT_FAILURE;
65  }
66 
67  errno = 0;
68  switch (fmt_str[idx]) {
69  case 'd' : /* double */
70  d[d_idx] = strtod(buf_p, &endp);
71  if (errno) {
72  fprintf(stream, "Convert to double failed, function %lu test case on line %lu parameter %d error msg: '%s' string '%s'\n",
73  u[0], line_num, idx+2, strerror(errno), buf_p);
74  return EXIT_FAILURE;
75  }
76  if ((*endp != '\0') || (buf_p == endp)) {
77  fprintf(stream, "Convert to double failed, function %lu test case on line %lu parameter %d string '%s'\n",
78  u[0], line_num, idx+2, buf_p);
79  return EXIT_FAILURE;
80  }
81  d_idx++;
82  break;
83  case 'l' : /* long int */
84  l[l_idx] = strtol(buf_p, &endp, 10);
85  if (errno) {
86  fprintf(stream, "Convert to long int failed, function %lu test case on line %lu parameter %d error msg: '%s' string '%s'\n",
87  u[0], line_num, idx+2, strerror(errno), buf_p);
88  return EXIT_FAILURE;
89  }
90  if ((*endp != '\0') || (buf_p == endp)) {
91  fprintf(stream, "Convert to long int failed, function %lu test case on line %lu parameter %d string '%s'\n",
92  u[0], line_num, idx+2, buf_p);
93  return EXIT_FAILURE;
94  }
95  l_idx++;
96  break;
97  case 'i' : /* int */
98  l_tmp = strtol(buf_p, &endp, 10);
99  if (errno) {
100  fprintf(stream, "Convert to int failed, function %lu test case on line %lu parameter %d error msg: '%s' string '%s'\n",
101  u[0], line_num, idx+2, strerror(errno), buf_p);
102  return EXIT_FAILURE;
103  }
104  if ((*endp != '\0') || (buf_p == endp)) {
105  fprintf(stream, "Convert to int failed, function %lu test case on line %lu parameter %d string '%s'\n",
106  u[0], line_num, idx+2, buf_p);
107  return EXIT_FAILURE;
108  }
109  if (l_tmp > INT_MAX || l_tmp < INT_MIN) {
110  fprintf(stream, "Convert to int failed (under/over flow), function %lu test case on line %lu parameter %d string '%s'\n",
111  u[0], line_num, idx+2, buf_p);
112  return EXIT_FAILURE;
113  }
114  i[i_idx] = (int)l_tmp;
115  i_idx++;
116  break;
117  case 'u' : /* unsigned long */
118  u[u_idx] = strtoul(buf_p, &endp, 10);
119  if (errno) {
120  fprintf(stream, "Convert to unsigned long int failed, function %lu test case on line %lu parameter %d error msg: '%s' string '%s'\n",
121  u[0], line_num, idx+2, strerror(errno), buf_p);
122  return EXIT_FAILURE;
123  }
124  if ((*endp != '\0') || (buf_p == endp) || (strchr(buf_p, '-') != '\0')) {
125  fprintf(stream, "Convert to unsigned long int failed, function %lu test case on line %lu parameter %d string '%s'\n",
126  u[0], line_num, idx+2, buf_p);
127  return EXIT_FAILURE;
128  }
129  u_idx++;
130  break;
131  default:
132  fprintf(stream, "INTERNAL ERROR: Unknown data type '%c' for function %lu test case on line %lu, skipping test case.\n",
133  fmt_str[idx], u[0], line_num);
134  return EXIT_FAILURE;
135  break;
136  } /* End of data format switch */
137  } /* End of for loop traversing data format string */
138 
139  return 0;
140 }
141 
142 
143 int
144 main(int argc, char **argv)
145 {
146  /* static to prevent longjmp clobber warning */
147  static FILE *stream = NULL;
148  static unsigned long line_num = 0;
149  static unsigned long failed_cnt = 0;
150  static unsigned long bomb_cnt = 0;
151  static unsigned long success_cnt = 0;
152  static int ret = 0;
153 
154  char buf[BUFSIZ];
155  FILE *fp_in = NULL;
156  char *endp = NULL;
157  int string_length;
158  int argv_idx;
159  int c;
160  char dt_fmt[50]; /* data type format string */
161  char *buf_p1;
162  char *buf_p;
163  struct bn_tol tol;
164 
165  /* command line parameters */
166  static unsigned long test_case_line_num = 0; /* static due to longjmp */
167  static unsigned long function_num = 0; /* static due to longjmp */
168  struct bu_vls input_file_name = BU_VLS_INIT_ZERO;
169  struct bu_vls output_file_name = BU_VLS_INIT_ZERO;
170 
171  /* function parameter arrays */
172  int i[50] = {0};
173  long l[50] = {0};
174  fastf_t d[50] = {0.0};
175  unsigned long u[50] = {0};
176 
177  /* boolean variables */
178  static int output_file_name_defined = 0; /* static due to longjmp */
179  static int process_single_test_case = 0; /* static due to longjmp */
180  static int process_single_function = 0; /* static due to longjmp */
181  int input_file_name_defined = 0;
182  int valid_function_number = 0;
183  int process_test_case = 0;
184  int early_exit = 0;
185  int found_eof = 0;
186 
187  /* set initial values in tol structure */
188  tol.magic = BN_TOL_MAGIC;
189  tol.dist = BN_TOL_DIST;
190  tol.dist_sq = tol.dist * tol.dist;
191  tol.perp = 1e-6;
192  tol.para = 1.0 - tol.perp;
193 
194 
195  if (argc < 2) {
196  bu_log("Too few parameters, %d specified, at least 1 required\n", argc - 1);
197  bu_exit(EXIT_FAILURE, USAGE);
198  }
199 
200  while ((c = bu_getopt(argc, argv, "l:f:i:o:")) != -1) {
201  switch (c) {
202  case 'l': /* test case line number */
203  errno = 0;
204  test_case_line_num = strtoul(bu_optarg, &endp, 10);
205  if (errno) {
206  bu_log("Invalid test case line number '%s' '%s'\n", bu_optarg, strerror(errno));
207  bu_exit(EXIT_FAILURE, USAGE);
208  }
209  if ((*endp != '\0') || (bu_optarg == endp) || (strchr(bu_optarg, '-') != '\0')) {
210  bu_log("Invalid test case line number '%s'\n", bu_optarg);
211  bu_exit(EXIT_FAILURE, USAGE);
212  }
213  process_single_test_case = 1;
214  break;
215  case 'f': /* function number */
216  errno = 0;
217  function_num = strtoul(bu_optarg, &endp, 10);
218  if (errno) {
219  bu_log("Invalid function number '%s' '%s'\n", bu_optarg, strerror(errno));
220  bu_exit(EXIT_FAILURE, USAGE);
221  }
222  if ((*endp != '\0') || (bu_optarg == endp) || (strchr(bu_optarg, '-') != '\0')) {
223  bu_log("Invalid function number '%s'\n", bu_optarg);
224  bu_exit(EXIT_FAILURE, USAGE);
225  }
226  process_single_function = 1;
227  break;
228  case 'i': /* input file name */
229  string_length = strlen(bu_optarg);
230  if (string_length >= BUFSIZ) {
231  bu_log("Input file name too long, length was %d but must be less than %d\n",
232  string_length, BUFSIZ);
233  bu_exit(EXIT_FAILURE, USAGE);
234  }
235  bu_vls_strcpy(&input_file_name, bu_optarg);
236  input_file_name_defined = 1;
237  break;
238  case 'o': /* output file name */
239  string_length = strlen(bu_optarg);
240  if (string_length >= BUFSIZ) {
241  bu_log("Output file name too long, length was %d but must be less than %d\n",
242  string_length, BUFSIZ);
243  bu_exit(EXIT_FAILURE, USAGE);
244  }
245  bu_vls_strcpy(&output_file_name, bu_optarg);
246  output_file_name_defined = 1;
247  break;
248  default:
249  bu_log("Invalid option '%c'.\n", c);
250  bu_exit(EXIT_FAILURE, USAGE);
251  break;
252  }
253  }
254 
255  if (process_single_test_case && process_single_function) {
256  bu_log("Can not specify both test case line number and function number.\n");
257  early_exit = 1;
258  }
259 
260  if (!input_file_name_defined) {
261  bu_log("Input file name is required but was not specified.\n");
262  early_exit = 1;
263  }
264 
265  if (early_exit) {
266  bu_vls_free(&input_file_name);
267  bu_vls_free(&output_file_name);
268  bu_exit(EXIT_FAILURE, USAGE);
269  }
270 
271  if ((fp_in = fopen(bu_vls_addr(&input_file_name), "r")) == NULL) {
272  bu_log("Cannot open input file (%s)\n", bu_vls_addr(&input_file_name));
273  bu_vls_free(&input_file_name);
274  bu_vls_free(&output_file_name);
275  return EXIT_FAILURE;
276  }
277 
278 
279  if (output_file_name_defined) {
280  if ((stream = fopen(bu_vls_addr(&output_file_name), "w")) == NULL) {
281  bu_log("Cannot create output file (%s)\n", bu_vls_addr(&output_file_name));
282  if (fclose(fp_in) != 0) {
283  bu_log("Unable to close input file.\n");
284  }
285  bu_vls_free(&input_file_name);
286  bu_vls_free(&output_file_name);
287  return EXIT_FAILURE;
288  }
289  } else {
290  stream = stderr;
291  }
292 
293  /* all output after this point is sent to stream */
294 
295  fprintf(stream, "Command line parameters: bntester ");
296  for (argv_idx = 1 ; argv_idx < argc ; argv_idx++) {
297  fprintf(stream, "%s ", argv[argv_idx]);
298  }
299  fprintf(stream, "\n");
300 
301  if (process_single_test_case) {
302  fprintf(stream, "Processing only test case on line number: %lu\n", test_case_line_num);
303  }
304 
305  if (process_single_function) {
306  fprintf(stream, "Processing all test cases for function number: %lu\n", function_num);
307  }
308 
309  if (!process_single_test_case && !process_single_function) {
310  fprintf(stream, "Processing all test cases.\n");
311  }
312 
313 
314  while (!found_eof) {
315  if (line_num == ULONG_MAX) {
316  fprintf(stream, "ERROR: Input data file exceeded max %lu number of lines.\n", ULONG_MAX);
317  if (fclose(fp_in) != 0) {
318  fprintf(stream, "Unable to close input file.\n");
319  }
320  if (output_file_name_defined) {
321  if (fclose(stream) != 0) {
322  bu_log("Unable to close output file.\n");
323  }
324  }
325  bu_vls_free(&input_file_name);
326  bu_vls_free(&output_file_name);
327  return EXIT_FAILURE;
328  }
329  line_num++;
330  if (bu_fgets(buf, BUFSIZ, fp_in) == NULL) {
331  if (feof(fp_in)) {
332  found_eof = 1;
333  continue;
334  }
335  if (ferror(fp_in)) {
336  perror("ERROR: Problem reading file, system error message");
337  if (fclose(fp_in) != 0) {
338  fprintf(stream, "Unable to close input file.\n");
339  }
340  } else {
341  perror("Oddness reading input file");
342  }
343  bu_vls_free(&input_file_name);
344  bu_vls_free(&output_file_name);
345  return EXIT_FAILURE;
346  } else {
347  /* Skip input data file lines which start with a '#' character
348  * or a new line character.
349  */
350  if ((buf[0] != '#') && (buf[0] != '\n')) {
351  buf_p1 = strtok(buf, "\n");
352  buf_p = strtok(buf_p1, ", ");
353 
354  /* The 1st parameter of the test case is always an unsigned
355  * long int which represents the function number. This logic
356  * validates the test case function number to ensure it is
357  * an unsigned long int.
358  */
359  valid_function_number = 1;
360  errno = 0;
361  u[0] = strtoul(buf_p, &endp, 10);
362  if (errno) {
363  fprintf(stream, "Read function number failed, line %lu error msg: '%s' string '%s'\n",
364  line_num, strerror(errno), buf_p);
365  valid_function_number = 0;
366  } else if ((*endp != '\0') || (buf_p == endp) || (strchr(buf_p, '-') != '\0')) {
367  fprintf(stream, "Read function number failed, line %lu string '%s'\n", line_num, buf_p);
368  valid_function_number = 0;
369  }
370 
371  /* This logic restricts processing of the test case(s) to
372  * only those specified by the bntester input parameters.
373  */
374  process_test_case = 0;
375  if (valid_function_number && process_single_test_case && (test_case_line_num == line_num)) {
376  process_test_case = 1;
377  } else if (valid_function_number && process_single_function && (function_num == u[0])) {
378  process_test_case = 1;
379  } else if (valid_function_number && !process_single_test_case && !process_single_function) {
380  process_test_case = 1;
381  }
382 
383  if (process_test_case) {
384  /* Each case within this switch corresponds to each
385  * function to be tested.
386  */
387  switch (u[0]) {
388  case 1: /* function 'bn_distsq_line3_pt3' */
389  bu_strlcpy(dt_fmt, "dddddddddd", sizeof(dt_fmt)); /* defines parameter data types */
390  if (parse_case(buf_p, i, l, d, u, dt_fmt, line_num, stream)) {
391  /* Parse failed, skipping test case */
392  ret = 1;
393  } else {
394  double result;
395  if (!BU_SETJUMP) {
396  /* try */
397  result = bn_distsq_line3_pt3(&d[0], &d[3], &d[6]);
398  if (!NEAR_EQUAL(result, d[9], VUNITIZE_TOL)) {
399  ret = 1;
400  failed_cnt++;
401  fprintf(stream, "Failed function %lu test case on line %lu expected = %.15f result = %.15f\n",
402  u[0], line_num, d[9], result);
403  } else {
404  success_cnt++;
405  }
406  } else {
407  /* catch */
408  BU_UNSETJUMP;
409  ret = 1;
410  bomb_cnt++;
411  fprintf(stream, "Failed function %lu test case on line %lu bu_bomb encountered.\n", u[0], line_num);
412  } BU_UNSETJUMP;
413  }
414  break;
415  case 2: /* function 'bn_2line3_colinear' */
416  bu_strlcpy(dt_fmt, "ddddddddddddduddddi", sizeof(dt_fmt));
417  if (parse_case(buf_p, i, l, d, u, dt_fmt, line_num, stream)) {
418  /* Parse failed, skipping test case */
419  ret = 1;
420  } else {
421  int result;
422  if (!BU_SETJUMP) {
423  /* try */
424  tol.magic = u[1];
425  tol.dist = d[13];
426  tol.dist_sq = d[14];
427  tol.perp = d[15];
428  tol.para = d[16];
429  result = bn_2line3_colinear(&d[0], &d[3], &d[6], &d[9], d[12], &tol);
430  if (result != i[0]) {
431  ret = 1;
432  failed_cnt++;
433  fprintf(stream, "Failed function %lu test case on line %lu expected = %d result = %d\n",
434  u[0], line_num, i[0], result);
435  } else {
436  success_cnt++;
437  }
438  } else {
439  /* catch */
440  BU_UNSETJUMP;
441  ret = 1;
442  bomb_cnt++;
443  fprintf(stream, "Failed function %lu test case on line %lu bu_bomb encountered.\n", u[0], line_num);
444  } BU_UNSETJUMP;
445  }
446  break;
447  case 3: /* function 'bn_isect_line3_line3' */
448  bu_strlcpy(dt_fmt, "dddddddddddddduddddi", sizeof(dt_fmt));
449  if (parse_case(buf_p, i, l, d, u, dt_fmt, line_num, stream)) {
450  /* Parse failed, skipping test case */
451  ret = 1;
452  } else {
453  int result;
454  fastf_t t_out = 0.0;
455  fastf_t u_out = 0.0;
456  int t_fail = 0;
457  int u_fail = 0;
458 
459  if (!BU_SETJUMP) {
460  /* try */
461  tol.magic = u[1];
462  tol.dist = d[14];
463  tol.dist_sq = d[15];
464  tol.perp = d[16];
465  tol.para = d[17];
466  result = bn_isect_line3_line3(&t_out, &u_out, &d[2], &d[5], &d[8], &d[11], &tol);
467  if (result != i[0]) {
468  ret = 1;
469  failed_cnt++;
470  fprintf(stream, "Failed function %lu test case on line %lu expected = %d result = %d\n",
471  u[0], line_num, i[0], result);
472  } else if (result == 0) {
473  if (!NEAR_EQUAL(t_out, d[0], tol.dist)) {
474  ret = 1;
475  failed_cnt++;
476  fprintf(stream, "Failed function %lu test case on line %lu result = %d expected t = %.15f result t = %.15f\n",
477  u[0], line_num, result, d[0], t_out);
478  } else {
479  success_cnt++;
480  }
481  } else if (result == 1) {
482  t_fail = !NEAR_EQUAL(t_out, d[0], tol.dist);
483  u_fail = !NEAR_EQUAL(u_out, d[1], tol.dist);
484  if (t_fail) {
485  fprintf(stream, "Failed function %lu test case on line %lu result = %d expected t = %.15f result t = %.15f\n",
486  u[0], line_num, result, d[0], t_out);
487  }
488  if (u_fail) {
489  fprintf(stream, "Failed function %lu test case on line %lu result = %d expected u = %.15f result u = %.15f\n",
490  u[0], line_num, result, d[1], u_out);
491  }
492  if (t_fail || u_fail) {
493  ret = 1;
494  failed_cnt++;
495  } else {
496  /* No other output to validate when result matches expected and
497  * result is not 0 and not 1.
498  */
499  success_cnt++;
500  }
501  } else {
502  success_cnt++;
503  }
504  } else {
505  /* catch */
506  BU_UNSETJUMP;
507  ret = 1;
508  bomb_cnt++;
509  fprintf(stream, "Failed function %lu test case on line %lu bu_bomb encountered.\n", u[0], line_num);
510  } BU_UNSETJUMP;
511  }
512  break;
513  case 4: /* function 'bn_isect_lseg3_lseg3' */
514  bu_strlcpy(dt_fmt, "dddddddddddddduddddi", sizeof(dt_fmt));
515  if (parse_case(buf_p, i, l, d, u, dt_fmt, line_num, stream)) {
516  /* Parse failed, skipping test case */
517  ret = 1;
518  } else {
519  int result;
520  fastf_t dist[2] = {0.0, 0.0};
521  int d0_fail = 0;
522  int d1_fail = 0;
523 
524  if (!BU_SETJUMP) {
525  /* try */
526  tol.magic = u[1];
527  tol.dist = d[14];
528  tol.dist_sq = d[15];
529  tol.perp = d[16];
530  tol.para = d[17];
531  result = bn_isect_lseg3_lseg3(&dist[0], &d[2], &d[5], &d[8], &d[11], &tol);
532  if (result != i[0]) {
533  ret = 1;
534  failed_cnt++;
535  fprintf(stream, "Failed function %lu test case on line %lu expected = %d result = %d\n",
536  u[0], line_num, i[0], result);
537  } else if (result == 0 || result == 1) {
538  d0_fail = !NEAR_EQUAL(dist[0], d[0], VUNITIZE_TOL);
539  d1_fail = !NEAR_EQUAL(dist[1], d[1], VUNITIZE_TOL);
540  if (d0_fail) {
541  fprintf(stream, "Failed function %lu test case on line %lu result = %d expected dist[0] = %.15f result dist[0] = %.15f\n",
542  u[0], line_num, result, d[0], dist[0]);
543  }
544  if (d1_fail) {
545  fprintf(stream, "Failed function %lu test case on line %lu result = %d expected dist[1] = %.15f result dist[1] = %.15f\n",
546  u[0], line_num, result, d[1], dist[1]);
547  }
548  if (d0_fail || d1_fail) {
549  ret = 1;
550  failed_cnt++;
551  } else {
552  /* No other output to validate when result matches expected and
553  * result is not 0 and not 1.
554  */
555  success_cnt++;
556  }
557  } else {
558  success_cnt++;
559  }
560  } else {
561  /* catch */
562  BU_UNSETJUMP;
563  ret = 1;
564  bomb_cnt++;
565  fprintf(stream, "Failed function %lu test case on line %lu bu_bomb encountered.\n", u[0], line_num);
566  } BU_UNSETJUMP;
567  }
568  break;
569  default:
570  fprintf(stream, "ERROR: Unknown function number %lu test case on line %lu, skipping test case.\n", u[0], line_num);
571  bu_vls_free(&input_file_name);
572  bu_vls_free(&output_file_name);
573  return EXIT_FAILURE;
574  break;
575  } /* End of function number switch */
576  }
577  } /* End of if statement skipping lines starting with '#' or new line */
578  }
579  } /* End of while loop reading lines from data file */
580 
581  fprintf(stream, "Summary: %lu total test cases success.\n", success_cnt);
582  fprintf(stream, "Summary: %lu total test cases failed.\n", failed_cnt);
583  fprintf(stream, "Summary: %lu total test cases bomb.\n", bomb_cnt);
584 
585  if (output_file_name_defined) {
586  bu_log("Summary: %lu total test cases success.\n", success_cnt);
587  bu_log("Summary: %lu total test cases failed.\n", failed_cnt);
588  bu_log("Summary: %lu total test cases bomb.\n", bomb_cnt);
589  }
590 
591  fprintf(stream, "Done.\n");
592 
593  if (output_file_name_defined) {
594  bu_log("Done.\n");
595  }
596 
597  if (fclose(fp_in) != 0) {
598  fprintf(stream, "Unable to close input file.\n");
599  }
600 
601  if (output_file_name_defined) {
602  if (fclose(stream) != 0) {
603  bu_log("Unable to close output file.\n");
604  }
605  }
606 
607  bu_vls_free(&input_file_name);
608  bu_vls_free(&output_file_name);
609 
610  return ret;
611 }
612 
613 
614 /*
615  * Local Variables:
616  * mode: C
617  * tab-width: 8
618  * indent-tabs-mode: t
619  * c-file-style: "stroustrup"
620  * End:
621  * ex: shiftwidth=4 tabstop=8
622  */
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
double dist
>= 0
Definition: tol.h:73
double dist_sq
dist * dist
Definition: tol.h:74
#define BN_TOL_MAGIC
Definition: magic.h:74
char * bu_optarg
Definition: globals.c:91
Header file for the BRL-CAD common definitions.
int bu_getopt(int nargc, char *const nargv[], const char *ostr)
Definition: getopt.c:43
int main(int argc, char **argv)
Definition: bntester.c:144
char * strchr(const char *sp, int c)
void bu_vls_free(struct bu_vls *vp)
Definition: vls.c:248
void bu_exit(int status, const char *fmt,...) _BU_ATTR_NORETURN _BU_ATTR_PRINTF23
Definition: bomb.c:195
#define bu_strlcpy(dst, src, size)
Definition: str.h:60
char * strtok(char *s, const char *delim)
#define BN_TOL_DIST
Definition: tol.h:109
int bn_2line3_colinear(const point_t p1, const vect_t d1, const point_t p2, const vect_t d2, double range, const struct bn_tol *tol)
Returns non-zero if the 3 lines are collinear to within tol->dist over the given distance range...
Support for uniform tolerances.
Definition: tol.h:71
char * bu_vls_addr(const struct bu_vls *vp)
Definition: vls.c:111
int parse_case(char *buf_p, int *i, long *l, fastf_t *d, unsigned long *u, char *fmt_str, unsigned long line_num, FILE *stream)
Definition: bntester.c:42
double perp
nearly 0
Definition: tol.h:75
#define USAGE
Definition: bntester.c:38
uint32_t magic
Definition: tol.h:72
int bn_isect_lseg3_lseg3(fastf_t *dist, const point_t p, const vect_t pdir, const point_t q, const vect_t qdir, const struct bn_tol *tol)
Intersect two 3D line segments, defined by two points and two vectors. The vectors are unlikely to be...
#define BU_UNSETJUMP
Definition: parallel.h:193
int bn_isect_line3_line3(fastf_t *s, fastf_t *t, const point_t p0, const vect_t u, const point_t q0, const vect_t v, const struct bn_tol *tol)
void bu_vls_strcpy(struct bu_vls *vp, const char *s)
Definition: vls.c:310
#define BU_SETJUMP
Definition: parallel.h:192
char * bu_fgets(char *s, int size, FILE *stream)
Definition: fgets.c:31
#define BU_VLS_INIT_ZERO
Definition: vls.h:84
Definition: vls.h:56
double fastf_t
Definition: defines.h:300
double bn_distsq_line3_pt3(const point_t pt, const vect_t dir, const point_t a)
double para
nearly 1
Definition: tol.h:76