summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKeepCoolWithCoolidge <37387200+KeepCoolWithCoolidge@users.noreply.github.com>2019-12-08 12:17:11 -0700
committerAndreas Rumpf <rumpf_a@web.de>2019-12-08 20:17:11 +0100
commitae7b53ec51c474b8da4fbfc2778352b07ddb7b53 (patch)
treeae5339b0ced19d172134e6f574479547dff7f740
parent5da27a891c99de462fd8d5019662c47b311c8ff9 (diff)
downloadNim-ae7b53ec51c474b8da4fbfc2778352b07ddb7b53.tar.gz
Fixes classify function to detect subnormal floating points (#12836)
* Fix classify to test for subnormality.
* Minor fix.
* Modified to maintain existing API.
* Minor change.
* Removed 32-bit case since float is always 64-bit.
-rw-r--r--lib/pure/math.nim36
1 files changed, 20 insertions, 16 deletions
diff --git a/lib/pure/math.nim b/lib/pure/math.nim
index 27e3e507d..362472584 100644
--- a/lib/pure/math.nim
+++ b/lib/pure/math.nim
@@ -103,21 +103,23 @@ when defined(Posix) and not defined(genode):
   {.passl: "-lm".}
 
 const
-  PI* = 3.1415926535897932384626433        ## The circle constant PI (Ludolph's number)
-  TAU* = 2.0 * PI                          ## The circle constant TAU (= 2 * PI)
-  E* = 2.71828182845904523536028747        ## Euler's number
-
-  MaxFloat64Precision* = 16                ## Maximum number of meaningful digits
-                                           ## after the decimal point for Nim's
-                                           ## ``float64`` type.
-  MaxFloat32Precision* = 8                 ## Maximum number of meaningful digits
-                                           ## after the decimal point for Nim's
-                                           ## ``float32`` type.
-  MaxFloatPrecision* = MaxFloat64Precision ## Maximum number of
-                                           ## meaningful digits
-                                           ## after the decimal point
-                                           ## for Nim's ``float`` type.
-  RadPerDeg = PI / 180.0                   ## Number of radians per degree
+  PI* = 3.1415926535897932384626433          ## The circle constant PI (Ludolph's number)
+  TAU* = 2.0 * PI                            ## The circle constant TAU (= 2 * PI)
+  E* = 2.71828182845904523536028747          ## Euler's number
+
+  MaxFloat64Precision* = 16                  ## Maximum number of meaningful digits
+                                             ## after the decimal point for Nim's
+                                             ## ``float64`` type.
+  MaxFloat32Precision* = 8                   ## Maximum number of meaningful digits
+                                             ## after the decimal point for Nim's
+                                             ## ``float32`` type.
+  MaxFloatPrecision* = MaxFloat64Precision   ## Maximum number of
+                                             ## meaningful digits
+                                             ## after the decimal point
+                                             ## for Nim's ``float`` type.
+  MinFloatNormal* = 2.225073858507201e-308   ## Smallest normal number for Nim's
+                                             ## ``float`` type. (= 2^-1022).
+  RadPerDeg = PI / 180.0                     ## Number of radians per degree
 
 type
   FloatClass* = enum ## Describes the class a floating point value belongs to.
@@ -140,6 +142,7 @@ proc classify*(x: float): FloatClass =
     doAssert classify(0.0) == fcZero
     doAssert classify(0.3/0.0) == fcInf
     doAssert classify(-0.3/0.0) == fcNegInf
+    doAssert classify(5.0e-324) == fcSubnormal
 
   # JavaScript and most C compilers have no classify:
   if x == 0.0:
@@ -151,8 +154,9 @@ proc classify*(x: float): FloatClass =
     if x > 0.0: return fcInf
     else: return fcNegInf
   if x != x: return fcNan
+  if abs(x) < MinFloatNormal:
+    return fcSubnormal
   return fcNormal
-  # XXX: fcSubnormal is not detected!
 
 proc isPowerOfTwo*(x: int): bool {.noSideEffect.} =
   ## Returns ``true``, if ``x`` is a power of two, ``false`` otherwise.