int FTOASTR (char *buf, size_t bufsize, int flags, int width, FLOAT x) { /* The following method is simple but slow. For ideas about speeding things up, please see: Florian Loitsch, Printing floating-point numbers quickly and accurately with integers. ACM SIGPLAN notices 46, 6 (June 2010), 233-243 <http://dx.doi.org/10.1145/1809028.1806623>; also see the 2010-03-21 draft <http://florian.loitsch.com/tmp/article.pdf>. */ PROMOTED_FLOAT promoted_x = x; char format[sizeof "%-+ 0*.*Lg"]; FLOAT abs_x = x < 0 ? -x : x; int prec; char *p = format; *p++ = '%'; /* Support flags that generate output parsable by strtof. */ *p = '-'; p += (flags & FTOASTR_LEFT_JUSTIFY ) != 0; *p = '+'; p += (flags & FTOASTR_ALWAYS_SIGNED ) != 0; *p = ' '; p += (flags & FTOASTR_SPACE_POSITIVE) != 0; *p = '0'; p += (flags & FTOASTR_ZERO_PAD ) != 0; *p++ = '*'; *p++ = '.'; *p++ = '*'; *p = 'L'; p += 2 < LENGTH; *p++ = flags & FTOASTR_UPPER_E ? 'G' : 'g'; *p = '\0'; for (prec = abs_x < FLOAT_MIN ? 1 : FLOAT_DIG; ; prec++) { int n = snprintf (buf, bufsize, format, width, prec, promoted_x); if (n < 0 || FLOAT_PREC_BOUND <= prec || (n < bufsize && STRTOF (buf, NULL) == x)) return n; } }
int main(int argc, char **argv) { armas_conf_t conf; armas_x_dense_t B0, A, B; int ok, opt; int N = 301; int verbose = 1; int fails = 0; DTYPE alpha = 1.0; DTYPE n0, n1; while ((opt = getopt(argc, argv, "vC:")) != -1) { switch (opt) { case 'v': verbose++; break; case 'C': Aconstant = STRTOF(optarg); break; default: fprintf(stderr, "usage: trsm [-P nproc] [size]\n"); exit(1); } } if (optind < argc) N = atoi(argv[optind]); conf = *armas_conf_default(); armas_x_init(&A, N, N); armas_x_init(&B, N, N); armas_x_init(&B0, N, N); // Upper triangular matrix armas_x_set_values(&A, one, ARMAS_UPPER); if (N < 10) { printf("A:\n"); armas_x_printf(stdout, "%8.1e", &A); } armas_x_set_values(&B, one, ARMAS_NULL); armas_x_mcopy(&B0, &B); armas_x_mult_trm(&B, alpha, &A, ARMAS_UPPER|ARMAS_LEFT, &conf); if (N < 10) { printf("A*B:\n"); armas_x_printf(stdout, "%8.1e", &B); } armas_x_solve_trm(&B, alpha, &A, ARMAS_UPPER|ARMAS_LEFT, &conf); if (N < 10) { printf("A.-1*B:\n"); armas_x_printf(stdout, "%8.1e", &B); } n0 = rel_error(&n1, &B, &B0, ARMAS_NORM_ONE, ARMAS_NONE, &conf); ok = n0 == 0.0 || isOK(n0, N) ? 1 : 0; printf("%6s: B = solve_trm(mult_trm(B, A, L|U|N), A, L|U|N)\n", PASS(ok)); if (verbose > 0) { printf(" || rel error || : %e, [%d]\n", n0, ndigits(n0)); } fails += 1 - ok; armas_x_set_values(&B, one, ARMAS_NULL); armas_x_mcopy(&B0, &B); armas_x_mult_trm(&B, alpha, &A, ARMAS_UPPER|ARMAS_RIGHT, &conf); armas_x_solve_trm(&B, alpha, &A, ARMAS_UPPER|ARMAS_RIGHT, &conf); n0 = rel_error(&n1, &B, &B0, ARMAS_NORM_ONE, ARMAS_NONE, &conf); ok = n0 == 0.0 || isOK(n0, N) ? 1 : 0; printf("%6s: B = solve_trm(mult_trm(B, A, R|U|N), A, R|U|N)\n", PASS(ok)); if (verbose > 0) { printf(" || rel error || : %e, [%d]\n", n0, ndigits(n0)); } fails += 1 - ok; armas_x_set_values(&B, one, ARMAS_NULL); armas_x_mcopy(&B0, &B); armas_x_mult_trm(&B, alpha, &A, ARMAS_UPPER|ARMAS_LEFT|ARMAS_TRANSA, &conf); armas_x_solve_trm(&B, alpha, &A, ARMAS_UPPER|ARMAS_LEFT|ARMAS_TRANSA, &conf); n0 = rel_error(&n1, &B, &B0, ARMAS_NORM_ONE, ARMAS_NONE, &conf); ok = n0 == 0.0 || isOK(n0, N) ? 1 : 0; printf("%6s: B = solve_trm(mult_trm(B, A, L|U|T), A, L|U|T)\n", PASS(ok)); if (verbose > 0) { printf(" || rel error || : %e, [%d]\n", n0, ndigits(n0)); } fails += 1 - ok; armas_x_set_values(&B, one, ARMAS_NULL); armas_x_mcopy(&B0, &B); armas_x_mult_trm(&B, alpha, &A, ARMAS_UPPER|ARMAS_RIGHT|ARMAS_TRANSA, &conf); armas_x_solve_trm(&B, alpha, &A, ARMAS_UPPER|ARMAS_RIGHT|ARMAS_TRANSA, &conf); n0 = rel_error(&n1, &B, &B0, ARMAS_NORM_ONE, ARMAS_NONE, &conf); ok = n0 == 0.0 || isOK(n0, N) ? 1 : 0; printf("%6s: B = solve_trm(mult_trm(B, A, R|U|T), A, R|U|T)\n", PASS(ok)); if (verbose > 0) { printf(" || rel error || : %e, [%d]\n", n0, ndigits(n0)); } fails += 1 - ok; // Lower triangular matrix armas_x_set_values(&A, one, ARMAS_LOWER); armas_x_set_values(&B, one, ARMAS_NULL); armas_x_mcopy(&B0, &B); armas_x_mult_trm(&B, alpha, &A, ARMAS_LOWER|ARMAS_LEFT, &conf); armas_x_solve_trm(&B, alpha, &A, ARMAS_LOWER|ARMAS_LEFT, &conf); n0 = rel_error(&n1, &B, &B0, ARMAS_NORM_ONE, ARMAS_NONE, &conf); ok = n0 == 0.0 || isOK(n0, N) ? 1 : 0; printf("%6s: B = solve_trm(mult_trm(B, A, L|L|N), A, L|L|N)\n", PASS(ok)); if (verbose > 0) { printf(" || rel error || : %e, [%d]\n", n0, ndigits(n0)); } fails += 1 - ok; armas_x_set_values(&B, one, ARMAS_NULL); armas_x_mcopy(&B0, &B); armas_x_mult_trm(&B, alpha, &A, ARMAS_LOWER|ARMAS_RIGHT, &conf); armas_x_solve_trm(&B, alpha, &A, ARMAS_LOWER|ARMAS_RIGHT, &conf); n0 = rel_error(&n1, &B, &B0, ARMAS_NORM_ONE, ARMAS_NONE, &conf); ok = n0 == 0.0 || isOK(n0, N) ? 1 : 0; printf("%6s: B = solve_trm(mult_trm(B, A, R|L|N), A, R|L|N)\n", PASS(ok)); if (verbose > 0) { printf(" || rel error || : %e, [%d]\n", n0, ndigits(n0)); } fails += 1 - ok; armas_x_set_values(&B, one, ARMAS_NULL); armas_x_mcopy(&B0, &B); armas_x_mult_trm(&B, alpha, &A, ARMAS_LOWER|ARMAS_LEFT|ARMAS_TRANSA, &conf); armas_x_solve_trm(&B, alpha, &A, ARMAS_LOWER|ARMAS_LEFT|ARMAS_TRANSA, &conf); n0 = rel_error(&n1, &B, &B0, ARMAS_NORM_ONE, ARMAS_NONE, &conf); ok = n0 == 0.0 || isOK(n0, N) ? 1 : 0; printf("%6s: B = solve_trm(mult_trm(B, A, L|L|T), A, L|L|T)\n", PASS(ok)); if (verbose > 0) { printf(" || rel error || : %e, [%d]\n", n0, ndigits(n0)); } fails += 1 - ok; armas_x_set_values(&B, one, ARMAS_NULL); armas_x_mcopy(&B0, &B); armas_x_mult_trm(&B, alpha, &A, ARMAS_LOWER|ARMAS_RIGHT|ARMAS_TRANSA, &conf); armas_x_solve_trm(&B, alpha, &A, ARMAS_LOWER|ARMAS_RIGHT|ARMAS_TRANSA, &conf); n0 = rel_error(&n1, &B, &B0, ARMAS_NORM_ONE, ARMAS_NONE, &conf); ok = n0 == 0.0 || isOK(n0, N) ? 1 : 0; printf("%6s: B = solve_trm(mult_trm(B, A, R|L|T), A, R|L|T)\n", PASS(ok)); if (verbose > 0) { printf(" || rel error || : %e, [%d]\n", n0, ndigits(n0)); } fails += 1 - ok; test_left_right(N, verbose); exit(fails); }