1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License, Version 1.0 only
   6  * (the "License").  You may not use this file except in compliance
   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 /*      Copyright (c) 1988 AT&T     */
  23 /*        All Rights Reserved   */
  24 
  25 
  26 /*
  27  * Copyright 2014 Garrett D'Amore <garrett@damore.org>
  28  *
  29  * Copyright (c) 1996, by Sun Microsystems, Inc.
  30  * All Rights Reserved
  31  */
  32 
  33 #ifndef _NAN_H
  34 #define _NAN_H
  35 
  36 /*
  37  * Handling of Not_a_Number's (only in IEEE floating-point standard)
  38  */
  39 
  40 #include <sys/isa_defs.h>
  41 #include <values.h>
  42 
  43 #ifdef  __cplusplus
  44 extern "C" {
  45 #endif
  46 
  47 #if defined(_IEEE_754)
  48 /*
  49  * Structure order is endian dependent.  Only the common variants of
  50  * big and little endian are supported.
  51  */
  52 
  53 #if defined(_BIG_ENDIAN)
  54 
  55 typedef union
  56 {
  57         struct
  58         {
  59                 unsigned sign           : 1;
  60                 unsigned exponent       :11;
  61                 unsigned bits           :20;
  62                 unsigned fraction_low   :32;
  63         } inf_parts;
  64         struct
  65         {
  66                 unsigned sign           : 1;
  67                 unsigned exponent       :11;
  68                 unsigned qnan_bit       : 1;
  69                 unsigned bits           :19;
  70                 unsigned fraction_low   :32;
  71         } nan_parts;
  72         double d;
  73 
  74 } dnan;
  75 
  76 #else   /* Must be _LITTLE_ENDIAN */
  77 
  78 typedef union
  79 {
  80         struct {
  81                 unsigned fraction_low   :32;
  82                 unsigned bits           :20;
  83                 unsigned exponent       :11;
  84                 unsigned sign           : 1;
  85         } inf_parts;
  86         struct {
  87                 unsigned fraction_low   :32;
  88                 unsigned bits           :19;
  89                 unsigned qnan_bit       : 1;
  90                 unsigned exponent       :11;
  91                 unsigned sign           : 1;
  92         } nan_parts;
  93         double d;
  94 } dnan;
  95 
  96 #endif  /* Endian based selection */
  97 
  98 /*
  99  * IsNANorINF checks that exponent of double == 2047
 100  * i.e. that number is a NaN or an infinity
 101  */
 102 #define IsNANorINF(X)  (((dnan *)&(X))->nan_parts.exponent == 0x7ff)
 103 
 104 /*
 105  * IsINF must be used after IsNANorINF has checked the exponent
 106  */
 107 #define IsINF(X)        (((dnan *)&(X))->inf_parts.bits == 0 && \
 108                             ((dnan *)&(X))->inf_parts.fraction_low == 0)
 109 
 110 /*
 111  * IsPosNAN and IsNegNAN can be used to check the sign of infinities too
 112  */
 113 #define IsPosNAN(X)     (((dnan *)&(X))->nan_parts.sign == 0)
 114 
 115 #define IsNegNAN(X)     (((dnan *)&(X))->nan_parts.sign == 1)
 116 
 117 /*
 118  * GETNaNPC gets the leftmost 32 bits of the fraction part
 119  */
 120 #define GETNaNPC(dval)  (((dnan *)&(dval))->inf_parts.bits << 12 | \
 121                             ((dnan *)&(dval))->nan_parts.fraction_low >> 20)
 122 
 123 #define KILLFPE()       (void) _kill(_getpid(), 8)
 124 #define NaN(X)          (((dnan *)&(X))->nan_parts.exponent == 0x7ff)
 125 #define KILLNaN(X)      if (NaN(X)) KILLFPE()
 126 
 127 #else   /* defined(_IEEE_754) */
 128 /* #error is strictly ansi-C, but works as well as anything for K&R systems. */
 129 #error ISA not supported
 130 #endif  /* defined(_IEEE_754) */
 131 
 132 #ifdef  __cplusplus
 133 }
 134 #endif
 135 
 136 #endif  /* _NAN_H */