34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# CDDL HEADER START
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# The contents of this file are subject to the terms of the
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# Common Development and Distribution License (the "License").
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# You may not use this file except in compliance with the License.
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# or http://www.opensolaris.org/os/licensing.
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# See the License for the specific language governing permissions
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# and limitations under the License.
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# When distributing Covered Code, include this CDDL HEADER in each
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# If applicable, add the following below this CDDL HEADER, with the
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# fields enclosed by brackets "[]" replaced with your own identifying
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# information: Portions Copyright [yyyy] [name of copyright owner]
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# CDDL HEADER END
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# This test checks whether arithmetric math correctly
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# converts a IEEE 754-2008 floating-point value to the C99 hexfloat format
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# and back _without_ using digits.
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# This was reported as CR #6855875 ("typeset -X x ; print $x # does not
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# print sufficient digits to restore value"):
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# ------------ snip ------------
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# $ typeset -X varname # was added to ksh93 to get a reliable way
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# (using the C99 "hexfloat" format (see printf(3c)'s "%a" format)) to
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# serialise a IEEE754-2008 floating-point value to a string and later feed
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# it back into a application _without_ loosing any precision (normal
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# base10 floating-point values (e.g. used by $ typeset -E/-F-G #) cause
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# rounding errors since IEEE754-2008 |long double| uses base2).
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# However $ typeset -l -X x ; ... ; print $x # currently does not print
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# sufficient number of digits to restore the full |long double| value as
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# expected, instead some digits are missing, resulting in an unwanted
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# rounding.
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# Example:
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# -- snip --
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# $ ksh93 -c 'typeset -l -X y y_ascii; (( y=sin(90) )) ; y_ascii=$y ; (( y
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# == y_ascii )) || print "no match,\n\t$(printf "%a\n" y)\n!=\n\t$(printf
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# "%a\n" y_ascii)"'
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# no match,
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# 0x1.c9b9ee41cb8665c7890a136ace6bp-01
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# !=
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# 0x1.c9b9ee41cc000000000000000000p-01
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# -- snip --
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# Frequency
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# Always
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# Regression
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# No
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# Steps to Reproduce
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# [See description]
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# Expected Result
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# [See description]
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# Actual Result
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# [See description]
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# Error Message(s)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# -
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# Test Case
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# typeset -l -X y y_ascii
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# (( y=sin(90) ))
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# y_ascii=$y # convert y to string and store it in "y_ascii"
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# if (( y == y_ascii )) ; then
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# print "no match,\n\t$(printf "%a\n" y)\n!=\n\t$(printf "%a\n"
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# y_ascii)"
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# fi
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# Workaround
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# 1. Manually increase the number of digits via typeset
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# -X<numdigits>
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# OR
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# 2. Use $ printf "%a" varname #
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# ------------ snip ------------
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# test setup
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainzfunction err_exit
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz{
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz print -u2 -n "\t"
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz print -u2 -r ${Command}[$1]: "${@:2}"
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner (( Errors < 127 && Errors++ ))
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz}
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainzalias err_exit='err_exit $LINENO'
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainzset -o nounset
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland MainzCommand=${0##*/}
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainzinteger Errors=0
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# declare variables
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainztypeset str
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainzinteger i
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainzfloat x
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainzfloat -a test_values
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainztypeset -l -X y # hexfloat
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainztypeset -l -E y_restored1
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainztypeset -l -F y_restored2
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainztypeset -l -X y_restored3
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# create array of test values
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainzfor (( x=-181. ; x < 361. ; x+=.1 )) ; do
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz test_values+=( x )
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainzdone
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainztest_values+=( 0 -0 +0 ) # (nan -nan inf -inf) are excluded since nan!=nan is always "true"
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# run the tests
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainzfor (( i=0 ; i < ${#test_values[@]} ; i++ )) ; do
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz (( y=sin(test_values[i]) ))
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz # convert floating-point value to string (using the hexfloat format) and store it in "str"
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz str="${y}"
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz # convert it back (via string assignment)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz y_restored1="${str}"
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz y_restored2="${str}"
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz y_restored3="${str}"
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz (( y == y_restored1 )) || err_exit "no match,"$'\n\t'"$(printf "%a\n" y)"$'\n'"!="$'\n\t'"$(printf "%a\n" y_restored1)"
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz (( y == y_restored2 )) || err_exit "no match,"$'\n\t'"$(printf "%a\n" y)"$'\n'"!="$'\n\t'"$(printf "%a\n" y_restored2)"
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz (( y == y_restored3 )) || err_exit "no match,"$'\n\t'"$(printf "%a\n" y)"$'\n'"!="$'\n\t'"$(printf "%a\n" y_restored3)"
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz # convert it back (using arithmetric expression)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz (( y_restored1=str ))
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz (( y_restored2=str ))
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz (( y_restored3=str ))
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz (( y == y_restored1 )) || err_exit "no match,"$'\n\t'"$(printf "%a\n" y)"$'\n'"!="$'\n\t'"$(printf "%a\n" y_restored1)"
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz (( y == y_restored2 )) || err_exit "no match,"$'\n\t'"$(printf "%a\n" y)"$'\n'"!="$'\n\t'"$(printf "%a\n" y_restored2)"
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz (( y == y_restored3 )) || err_exit "no match,"$'\n\t'"$(printf "%a\n" y)"$'\n'"!="$'\n\t'"$(printf "%a\n" y_restored3)"
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz # we exit if we get more than 8 errors (126 would be the maximum)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz (( Errors > 8 )) && exit $((Errors))
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainzdone
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz# tests done
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainzexit $((Errors))