1*a2290a36SDan McDonald /* 2*a2290a36SDan McDonald * This file and its contents are supplied under the terms of the 3*a2290a36SDan McDonald * Common Development and Distribution License ("CDDL"), version 1.0. 4*a2290a36SDan McDonald * You may only use this file in accordance with the terms of version 5*a2290a36SDan McDonald * 1.0 of the CDDL. 6*a2290a36SDan McDonald * 7*a2290a36SDan McDonald * A full copy of the text of the CDDL should have accompanied this 8*a2290a36SDan McDonald * source. A copy of the CDDL is also available via the Internet at 9*a2290a36SDan McDonald * http://www.illumos.org/license/CDDL. 10*a2290a36SDan McDonald */ 11*a2290a36SDan McDonald 12*a2290a36SDan McDonald /* 13*a2290a36SDan McDonald * Copyright 2014 PALO, Richard. All rights reserved. 14*a2290a36SDan McDonald * Copyright 2014 OmniTI Computer Consulting, Inc. All rights reserved. 15*a2290a36SDan McDonald */ 16*a2290a36SDan McDonald 17*a2290a36SDan McDonald /* 18*a2290a36SDan McDonald * Test rounding of floating point numbers in libc's *printf() routines. 19*a2290a36SDan McDonald * 20*a2290a36SDan McDonald * C99 must be enabled to get DECIMAL_DIG defined, but it looks like all 21*a2290a36SDan McDonald * of usr/src/test/libc is compiled that way. 22*a2290a36SDan McDonald */ 23*a2290a36SDan McDonald 24*a2290a36SDan McDonald #include <float.h> 25*a2290a36SDan McDonald #include <fenv.h> 26*a2290a36SDan McDonald #include <stdio.h> 27*a2290a36SDan McDonald #include <strings.h> 28*a2290a36SDan McDonald #include "test_common.h" 29*a2290a36SDan McDonald 30*a2290a36SDan McDonald /* 31*a2290a36SDan McDonald * Returns negative if snprintf() fails. Returns 0 upon 32*a2290a36SDan McDonald * successful execution of the test, return 1 upon a failure. 33*a2290a36SDan McDonald * Spews output if verbose is TRUE. 34*a2290a36SDan McDonald */ 35*a2290a36SDan McDonald int 36*a2290a36SDan McDonald run_one(test_t t, int i, int j, int precision, boolean_t verbose) 37*a2290a36SDan McDonald { 38*a2290a36SDan McDonald const int size = 100; 39*a2290a36SDan McDonald char buffer[size], check[size]; 40*a2290a36SDan McDonald double val; 41*a2290a36SDan McDonald int status; 42*a2290a36SDan McDonald 43*a2290a36SDan McDonald val = (double)(0.0 + j) / i; 44*a2290a36SDan McDonald /* first get max precision for control check */ 45*a2290a36SDan McDonald status = snprintf(check, size, "%+-.*f", DECIMAL_DIG, val); 46*a2290a36SDan McDonald if (status < 0) { 47*a2290a36SDan McDonald test_failed(t, "Max precision snprintf() " 48*a2290a36SDan McDonald "(i = %d, j = %d) returned %d\n", i, j, status); 49*a2290a36SDan McDonald return (status); 50*a2290a36SDan McDonald } 51*a2290a36SDan McDonald /* then get specific precision */ 52*a2290a36SDan McDonald status = snprintf(buffer, size, "%+-#.*f", precision, val); 53*a2290a36SDan McDonald if (status < 0) { 54*a2290a36SDan McDonald test_failed(t, "Specific precision snprintf() " 55*a2290a36SDan McDonald "(i = %d, j = %d, precision = %d) returned %d\n", i, j, 56*a2290a36SDan McDonald precision, status); 57*a2290a36SDan McDonald return (status); 58*a2290a36SDan McDonald } 59*a2290a36SDan McDonald 60*a2290a36SDan McDonald if (strlen(check) > strlen(buffer) && 61*a2290a36SDan McDonald strncmp(buffer, check, strlen(buffer))) { 62*a2290a36SDan McDonald /* last check if correctly rounded up */ 63*a2290a36SDan McDonald if (check[strlen(buffer)] < '5' && 64*a2290a36SDan McDonald buffer[strlen(buffer) - 1] > check[strlen(buffer) - 1]) { 65*a2290a36SDan McDonald if (verbose) 66*a2290a36SDan McDonald (void) printf("failure:f precision %d " 67*a2290a36SDan McDonald "for %02d/%02d => %s (%s)\n", 68*a2290a36SDan McDonald precision, j, i, buffer, check); 69*a2290a36SDan McDonald return (1); 70*a2290a36SDan McDonald } 71*a2290a36SDan McDonald } 72*a2290a36SDan McDonald 73*a2290a36SDan McDonald return (0); 74*a2290a36SDan McDonald } 75*a2290a36SDan McDonald 76*a2290a36SDan McDonald int 77*a2290a36SDan McDonald main(int argc, char *argv[]) 78*a2290a36SDan McDonald { 79*a2290a36SDan McDonald int status, i, j, precision; 80*a2290a36SDan McDonald int failures = 0; 81*a2290a36SDan McDonald int runs = 0; 82*a2290a36SDan McDonald test_t t; 83*a2290a36SDan McDonald /* NOTE: Any argument after the command enables "VERBOSE" mode. */ 84*a2290a36SDan McDonald boolean_t verbose = (argc > 1); 85*a2290a36SDan McDonald 86*a2290a36SDan McDonald t = test_start("*printf() floating-point rounding tests."); 87*a2290a36SDan McDonald 88*a2290a36SDan McDonald (void) fesetround(FE_TONEAREST); 89*a2290a36SDan McDonald 90*a2290a36SDan McDonald for (j = 1; j < 100; j++) { 91*a2290a36SDan McDonald for (i = 2; i < 100; i++) { 92*a2290a36SDan McDonald for (precision = DBL_DIG - 1; precision <= DECIMAL_DIG; 93*a2290a36SDan McDonald precision++) { 94*a2290a36SDan McDonald runs++; 95*a2290a36SDan McDonald status = run_one(t, i, j, precision, verbose); 96*a2290a36SDan McDonald if (status < 0) 97*a2290a36SDan McDonald return (status); 98*a2290a36SDan McDonald failures += status; 99*a2290a36SDan McDonald } 100*a2290a36SDan McDonald } 101*a2290a36SDan McDonald } 102*a2290a36SDan McDonald 103*a2290a36SDan McDonald if (failures > 0) { 104*a2290a36SDan McDonald test_failed(t, "Tests failed %d times out of %d attempts.\n" 105*a2290a36SDan McDonald "Run '%s full' to see the %d failures individually.\n", 106*a2290a36SDan McDonald failures, runs, argv[0], failures); 107*a2290a36SDan McDonald } else 108*a2290a36SDan McDonald test_passed(t); 109*a2290a36SDan McDonald 110*a2290a36SDan McDonald return (0); 111*a2290a36SDan McDonald } 112