summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rwxr-xr-xlib/pure/math.nim13
-rwxr-xr-xlib/pure/strutils.nim60
-rwxr-xr-xlib/system/ansi_c.nim5
-rwxr-xr-xrod/ast.nim2
-rwxr-xr-xrod/astalgo.nim44
-rwxr-xr-xrod/ccgexprs.nim16
-rwxr-xr-xrod/cgen.nim3
-rwxr-xr-xrod/ecmasgen.nim8
-rw-r--r--rod/rodutils.nim27
-rwxr-xr-xrod/ropes.nim14
-rwxr-xr-xtests/accept/run/spec.csv1
-rw-r--r--tests/accept/run/tfloat3.nim18
-rwxr-xr-xtodo.txt1
13 files changed, 156 insertions, 56 deletions
diff --git a/lib/pure/math.nim b/lib/pure/math.nim
index 89a0ccd25..dc6133901 100755
--- a/lib/pure/math.nim
+++ b/lib/pure/math.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nimrod's Runtime Library
-#        (c) Copyright 2010 Andreas Rumpf
+#        (c) Copyright 2011 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -24,6 +24,17 @@ const
   PI* = 3.1415926535897932384626433 ## the circle constant PI (Ludolph's number)
   E* = 2.71828182845904523536028747 ## Euler's number
 
+  MaxFloat64Precision* = 16 ## maximum number of meaningful digits
+                            ## after the decimal point for Nimrod's
+                            ## ``float64`` type.
+  MaxFloat32Precision* = 8  ## maximum number of meaningful digits
+                            ## after the decimal point for Nimrod's
+                            ## ``float32`` type.
+  MaxFloatPrecision* = MaxFloat64Precision ## maximum number of 
+                                           ## meaningful digits
+                                           ## after the decimal point 
+                                           ## for Nimrod's ``float`` type.
+
 type
   TFloatClass* = enum ## describes the class a floating point value belongs to.
                       ## This is the type that is returned by `classify`.
diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim
index f6de035a8..c794b5a74 100755
--- a/lib/pure/strutils.nim
+++ b/lib/pure/strutils.nim
@@ -935,6 +935,60 @@ proc editDistance*(a, b: string): int {.noSideEffect,
       row[p] = x

   result = row[e]

   #dealloc(row)

+
+
+# floating point formating:
+
+proc c_sprintf(buf, frmt: CString) {.nodecl, importc: "sprintf", varargs,
+                                     noSideEffect.}
+
+type
+  TFloatFormat* = enum
+    ffDefault,    ## use the shorter floating point notation
+    ffDecimal,    ## use decimal floating point notation
+    ffScientific  ## use scientific notation (using ``e``) character
+
+proc formatBiggestFloat*(f: BiggestFloat, format: TFloatFormat = ffDefault,
+                         precision = 16): string {.noSideEffect,

+                                                  rtl, extern: "nsu$1".} = 
+  ## converts a floating point value `f` to a string. 
+  ##
+  ## If ``format == ffDecimal`` then precision is the number of digits to 
+  ## be printed after the decimal point.
+  ## If ``format == ffScientific`` then precision is the maximum number 
+  ## of significant digits to be printed.
+  ## `precision`'s default value is the maximum number of meaningful digits
+  ## after the decimal point for Nimrod's ``biggestFloat`` type. 
+  const floatFormatToChar: array[TFloatFormat, char] = ['g', 'f', 'e']
+  var 
+    frmtstr: array[0..5, char]
+    buf: array[0..80, char]
+  frmtstr[0] = '%'
+  frmtstr[1] = '#'
+  if precision > 0:
+    frmtstr[2] = '.'
+    frmtstr[3] = '*'
+    frmtstr[4] = floatFormatToChar[format]
+    frmtstr[5] = '\0'
+    c_sprintf(buf, frmtstr, precision, f)
+  else: 
+    frmtstr[2] = floatFormatToChar[format]
+    frmtstr[3] = '\0'
+    c_sprintf(buf, frmtstr, f)
+  result = $buf
+
+proc formatFloat*(f: float, format: TFloatFormat = ffDefault,
+                  precision = 16): string {.noSideEffect,

+                                           rtl, extern: "nsu$1".} = 
+  ## converts a floating point value `f` to a string. 
+  ##
+  ## If ``format == ffDecimal`` then precision is the number of digits to 
+  ## be printed after the decimal point.
+  ## If ``format == ffScientific`` then precision is the maximum number 
+  ## of significant digits to be printed.
+  ## `precision`'s default value is the maximum number of meaningful digits
+  ## after the decimal point for Nimrod's ``float`` type. 
+  result = formatBiggestFloat(f, format, precision)
 

 {.pop.}

 

@@ -944,5 +998,7 @@ when isMainModule:
   assert align("1232", 6) == "  1232"

   echo wordWrap(""" this is a long text --  muchlongerthan10chars and here

                    it goes""", 10, false)

-  

-  

+  assert formatBiggestFloat(0.00000000001, ffDecimal, 11) == "0.00000000001"
+  assert formatBiggestFloat(0.00000000001, ffScientific, 1) == "1.0e-11"
+  
+
diff --git a/lib/system/ansi_c.nim b/lib/system/ansi_c.nim
index e9300949b..362b73297 100755
--- a/lib/system/ansi_c.nim
+++ b/lib/system/ansi_c.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nimrod's Runtime Library
-#        (c) Copyright 2009 Andreas Rumpf
+#        (c) Copyright 2011 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -34,7 +34,8 @@ var
   c_stdout {.importc: "stdout", noDecl.}: C_TextFileStar
   c_stderr {.importc: "stderr", noDecl.}: C_TextFileStar
 
-var # constants faked as variables:
+# constants faked as variables:
+var 
   SIGINT {.importc: "SIGINT", nodecl.}: cint
   SIGSEGV {.importc: "SIGSEGV", nodecl.}: cint
   SIGABRT {.importc: "SIGABRT", nodecl.}: cint
diff --git a/rod/ast.nim b/rod/ast.nim
index 4b16078fc..47d3d8621 100755
--- a/rod/ast.nim
+++ b/rod/ast.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2009 Andreas Rumpf
+#        (c) Copyright 2011 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
diff --git a/rod/astalgo.nim b/rod/astalgo.nim
index 894af5b05..27e3ccfea 100755
--- a/rod/astalgo.nim
+++ b/rod/astalgo.nim
@@ -12,7 +12,7 @@
 # the data structures here are used in various places of the compiler.
 
 import 
-  ast, nhashes, strutils, options, msgs, ropes, idents
+  ast, nhashes, strutils, options, msgs, ropes, idents, rodutils
 
 proc hashNode*(p: PObject): THash
 proc treeToYaml*(n: PNode, indent: int = 0, maxRecDepth: int = - 1): PRope
@@ -327,7 +327,8 @@ proc treeToYamlAux(n: PNode, marker: var TIntSet, indent: int,
       of nkCharLit..nkInt64Lit: 
         appf(result, ",$n$1\"intVal\": $2", [istr, toRope(n.intVal)])
       of nkFloatLit, nkFloat32Lit, nkFloat64Lit: 
-        appf(result, ",$n$1\"floatVal\": $2", [istr, toRopeF(n.floatVal)])
+        appf(result, ",$n$1\"floatVal\": $2", 
+            [istr, toRope(n.floatVal.ToStrMaxPrecision)])
       of nkStrLit..nkTripleStrLit: 
         appf(result, ",$n$1\"strVal\": $2", [istr, makeYamlString(n.strVal)])
       of nkSym: 
@@ -396,7 +397,8 @@ proc debugTree(n: PNode, indent: int, maxRecDepth: int): PRope =
       of nkCharLit..nkInt64Lit: 
         appf(result, ",$n$1\"intVal\": $2", [istr, toRope(n.intVal)])
       of nkFloatLit, nkFloat32Lit, nkFloat64Lit: 
-        appf(result, ",$n$1\"floatVal\": $2", [istr, toRopeF(n.floatVal)])
+        appf(result, ",$n$1\"floatVal\": $2", 
+            [istr, toRope(n.floatVal.ToStrMaxPrecision)])
       of nkStrLit..nkTripleStrLit: 
         appf(result, ",$n$1\"strVal\": $2", [istr, makeYamlString(n.strVal)])
       of nkSym: 
@@ -430,12 +432,13 @@ proc debug(n: PNode) =
   writeln(stdout, ropeToStr(debugTree(n, 0, 100)))
 
 const 
-  EmptySeq = @ []
+  EmptySeq = @[]
 
 proc nextTry(h, maxHash: THash): THash = 
-  result = ((5 * h) + 1) and maxHash # For any initial h in range(maxHash), repeating that maxHash times
-                                     # generates each int in range(maxHash) exactly once (see any text on
-                                     # random-number generation for proof).
+  result = ((5 * h) + 1) and maxHash 
+  # For any initial h in range(maxHash), repeating that maxHash times
+  # generates each int in range(maxHash) exactly once (see any text on
+  # random-number generation for proof).
   
 proc objectSetContains(t: TObjectSet, obj: PObject): bool = 
   # returns true whether n is in t
@@ -498,7 +501,8 @@ proc TableRawGet(t: TTable, key: PObject): int =
     h = nextTry(h, high(t.data))
   result = - 1
 
-proc TableSearch(t: TTable, key, closure: PObject, comparator: TCmpProc): PObject = 
+proc TableSearch(t: TTable, key, closure: PObject, 
+                 comparator: TCmpProc): PObject = 
   var h: THash
   h = hashNode(key) and high(t.data) # start with real hash value
   while t.data[h].key != nil: 
@@ -510,8 +514,7 @@ proc TableSearch(t: TTable, key, closure: PObject, comparator: TCmpProc): PObjec
   result = nil
 
 proc TableGet(t: TTable, key: PObject): PObject = 
-  var index: int
-  index = TableRawGet(t, key)
+  var index = TableRawGet(t, key)
   if index >= 0: result = t.data[index].val
   else: result = nil
   
@@ -533,8 +536,7 @@ proc TableEnlarge(t: var TTable) =
   swap(t.data, n)
 
 proc TablePut(t: var TTable, key, val: PObject) = 
-  var index: int
-  index = TableRawGet(t, key)
+  var index = TableRawGet(t, key)
   if index >= 0: 
     t.data[index].val = val
   else: 
@@ -692,20 +694,17 @@ proc IdTableRawGet(t: TIdTable, key: int): int =
   result = - 1
 
 proc IdTableHasObjectAsKey(t: TIdTable, key: PIdObj): bool = 
-  var index: int
-  index = IdTableRawGet(t, key.id)
+  var index = IdTableRawGet(t, key.id)
   if index >= 0: result = t.data[index].key == key
   else: result = false
   
 proc IdTableGet(t: TIdTable, key: PIdObj): PObject = 
-  var index: int
-  index = IdTableRawGet(t, key.id)
+  var index = IdTableRawGet(t, key.id)
   if index >= 0: result = t.data[index].val
   else: result = nil
   
 proc IdTableGet(t: TIdTable, key: int): PObject = 
-  var index: int
-  index = IdTableRawGet(t, key)
+  var index = IdTableRawGet(t, key)
   if index >= 0: result = t.data[index].val
   else: result = nil
   
@@ -797,8 +796,7 @@ proc IITableRawGet(t: TIITable, key: int): int =
   result = - 1
 
 proc IITableGet(t: TIITable, key: int): int = 
-  var index: int
-  index = IITableRawGet(t, key)
+  var index = IITableRawGet(t, key)
   if index >= 0: result = t.data[index].val
   else: result = InvalidKey
   
@@ -813,15 +811,13 @@ proc IITableRawInsert(data: var TIIPairSeq, key, val: int) =
   data[h].val = val
 
 proc IITablePut(t: var TIITable, key, val: int) = 
-  var 
-    index: int
-    n: TIIPairSeq
-  index = IITableRawGet(t, key)
+  var index = IITableRawGet(t, key)
   if index >= 0: 
     assert(t.data[index].key != InvalidKey)
     t.data[index].val = val
   else: 
     if mustRehash(len(t.data), t.counter): 
+      var n: TIIPairSeq
       newSeq(n, len(t.data) * growthFactor)
       for i in countup(0, high(n)): n[i].key = InvalidKey
       for i in countup(0, high(t.data)): 
diff --git a/rod/ccgexprs.nim b/rod/ccgexprs.nim
index aaf3a51ed..294b3e510 100755
--- a/rod/ccgexprs.nim
+++ b/rod/ccgexprs.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2010 Andreas Rumpf
+#        (c) Copyright 2011 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -12,7 +12,8 @@
 proc intLiteral(i: biggestInt): PRope =
   if (i > low(int32)) and (i <= high(int32)):
     result = toRope(i)
-  elif i == low(int32):       # Nimrod has the same bug for the same reasons :-)
+  elif i == low(int32):       
+    # Nimrod has the same bug for the same reasons :-)
     result = toRope("(-2147483647 -1)")
   elif i > low(int64):
     result = ropef("IL64($1)", [toRope(i)])
@@ -76,16 +77,7 @@ proc genLiteral(p: BProc, v: PNode, ty: PType): PRope =
     else:
       result = makeCString(v.strVal)
   of nkFloatLit..nkFloat64Lit:
-    var f = v.floatVal
-    if f != f:
-      result = toRope("NAN")
-    elif f == 0.0:
-      result = toRopeF(f)
-    elif f == 0.5 * f:
-      if f > 0.0: result = toRope("INF")
-      else: result = toRope("-INF")
-    else:
-      result = toRopeF(f)
+    result = toRope(v.floatVal.ToStrMaxPrecision)
   else:
     InternalError(v.info, "genLiteral(" & $v.kind & ')')
     result = nil
diff --git a/rod/cgen.nim b/rod/cgen.nim
index d57d5250a..360b46a3b 100755
--- a/rod/cgen.nim
+++ b/rod/cgen.nim
@@ -13,7 +13,8 @@
 import 
   ast, astalgo, strutils, nhashes, trees, platform, magicsys, extccomp, options, 
   nversion, nimsets, msgs, crc, bitsets, idents, lists, types, ccgutils, os, 
-  times, ropes, math, passes, rodread, wordrecg, rnimsyn, treetab, cgmeth
+  times, ropes, math, passes, rodread, wordrecg, rnimsyn, treetab, cgmeth,
+  rodutils
 
 when options.hasTinyCBackend:
   import tccgen
diff --git a/rod/ecmasgen.nim b/rod/ecmasgen.nim
index 62cb5b781..ca3ab8ddb 100755
--- a/rod/ecmasgen.nim
+++ b/rod/ecmasgen.nim
@@ -14,7 +14,7 @@
 import 
   ast, astalgo, strutils, nhashes, trees, platform, magicsys, extccomp,
   options, nversion, nimsets, msgs, crc, bitsets, idents, lists, types, os,
-  times, ropes, math, passes, ccgutils, wordrecg, rnimsyn, rodread
+  times, ropes, math, passes, ccgutils, wordrecg, rnimsyn, rodread, rodutils
 
 proc ecmasgenPass*(): TPass
 # implementation
@@ -115,7 +115,7 @@ proc mapType(typ: PType): TEcmasTypeKind =
   
 proc mangle(name: string): string = 
   result = ""
-  for i in countup(0, len(name) + 0 - 1): 
+  for i in countup(0, len(name) - 1): 
     case name[i]
     of 'A'..'Z': 
       add(result, chr(ord(name[i]) - ord('A') + ord('a')))
@@ -1357,11 +1357,11 @@ proc gen(p: var TProc, n: PNode, r: var TCompRes) =
   of nkFloatLit..nkFloat64Lit: 
     f = n.floatVal
     if f != f: r.res = toRope("NaN")
-    elif f == 0.0: r.res = toRopeF(f)
+    elif f == 0.0: r.res = toRope("0.0")
     elif f == 0.5 * f: 
       if f > 0.0: r.res = toRope("Infinity")
       else: r.res = toRope("-Infinity")
-    else: r.res = toRopeF(f)
+    else: r.res = toRope(f.ToStrMaxPrecision)
   of nkBlockExpr: genBlock(p, n, r)
   of nkIfExpr: genIfExpr(p, n, r)
   of nkCall, nkHiddenCallConv, nkCommand, nkCallStrLit: 
diff --git a/rod/rodutils.nim b/rod/rodutils.nim
new file mode 100644
index 000000000..dad5d679f
--- /dev/null
+++ b/rod/rodutils.nim
@@ -0,0 +1,27 @@
+#
+#
+#           The Nimrod Compiler
+#        (c) Copyright 2011 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## Utilities for the compiler. Aim is to reduce the coupling between 
+## the compiler and the evolving stdlib.
+
+proc c_sprintf(buf, frmt: cstring) {.importc: "sprintf", nodecl, varargs.}
+
+proc ToStrMaxPrecision*(f: BiggestFloat): string = 
+  if f != f:
+    result = "NAN"
+  elif f == 0.0:
+    result = "0.0"
+  elif f == 0.5 * f:
+    if f > 0.0: result = "INF"
+    else: result = "-INF"
+  else:
+    var buf: array [0..80, char]    
+    c_sprintf(buf, "%#.16e", f) 
+    result = $buf
+
diff --git a/rod/ropes.nim b/rod/ropes.nim
index 542c6b3b3..eb7022110 100755
--- a/rod/ropes.nim
+++ b/rod/ropes.nim
@@ -87,7 +87,6 @@ proc app*(a: var PRope, b: PRope)
 proc app*(a: var PRope, b: string)
 proc prepend*(a: var PRope, b: PRope)
 proc toRope*(s: string): PRope
-proc toRopeF*(r: BiggestFloat): PRope
 proc toRope*(i: BiggestInt): PRope
 proc ropeLen*(a: PRope): int
 proc WriteRope*(head: PRope, filename: string)
@@ -270,7 +269,7 @@ proc con(a: openarray[PRope]): PRope =
   for i in countup(0, high(a)): result = con(result, a[i])
 
 proc toRope(i: BiggestInt): PRope = result = toRope($i)
-proc toRopeF(r: BiggestFloat): PRope = result = toRope($r)
+#proc toRopeF*(r: BiggestFloat): PRope = result = toRope($r)
 proc app(a: var PRope, b: PRope) = a = con(a, b)
 proc app(a: var PRope, b: string) = a = con(a, b)
 proc prepend(a: var PRope, b: PRope) = a = con(b, a)
@@ -303,11 +302,10 @@ proc WriteRope(head: PRope, filename: string) =
     rawMessage(errCannotOpenFile, filename)
 
 proc ropef(frmt: TFormatStr, args: openarray[PRope]): PRope = 
-  var i, j, length, start, num: int
-  i = 0
-  length = len(frmt)
+  var i = 0
+  var length = len(frmt)
   result = nil
-  num = 0
+  var num = 0
   while i <= length - 1: 
     if frmt[i] == '$': 
       inc(i)                  # skip '$'
@@ -320,7 +318,7 @@ proc ropef(frmt: TFormatStr, args: openarray[PRope]): PRope =
         app(result, args[num])
         inc(num)
       of '0'..'9': 
-        j = 0
+        var j = 0
         while true: 
           j = (j * 10) + Ord(frmt[i]) - ord('0')
           inc(i)
@@ -333,7 +331,7 @@ proc ropef(frmt: TFormatStr, args: openarray[PRope]): PRope =
         app(result, tnl)
         inc(i)
       else: InternalError("ropes: invalid format string $" & frmt[i])
-    start = i
+    var start = i
     while (i <= length - 1): 
       if (frmt[i] != '$'): inc(i)
       else: break 
diff --git a/tests/accept/run/spec.csv b/tests/accept/run/spec.csv
index 4bb94ed74..075e4e67e 100755
--- a/tests/accept/run/spec.csv
+++ b/tests/accept/run/spec.csv
@@ -27,6 +27,7 @@ tfinally2.nim;ABCD
 tfinally3.nim;false
 tfloat1.nim;Error: unhandled exception: FPU operation caused an overflow [EFloatOverflow]
 tfloat2.nim;Error: unhandled exception: FPU operation caused a NaN result [EFloatInvalidOp]
+tfloat3.nim;Nimrod    3.4368930843, 0.3299290698 C double: 3.4368930843, 0.3299290698
 tformat.nim;Hi Andreas! How do you feel, Rumpf?
 thintoff.nim;0
 tinit.nim;Hello from module! Hello from main module!
diff --git a/tests/accept/run/tfloat3.nim b/tests/accept/run/tfloat3.nim
new file mode 100644
index 000000000..72acce958
--- /dev/null
+++ b/tests/accept/run/tfloat3.nim
@@ -0,0 +1,18 @@
+
+import math, strutils
+
+{.emit: """
+void printFloats(void) {
+    double y = 1.234567890123456789;
+    
+    printf("C double: %.10f, %.10f ", exp(y), cos(y));
+}
+""".}
+
+proc c_printf(frmt: CString) {.importc: "printf", header: "<stdio.h>", varargs.}
+proc printFloats {.importc, nodecl.}
+
+var x: float = 1.234567890123456789
+c_printf("Nimrod    %.10f, %.10f ", exp(x), cos(x))
+printFloats()
+
diff --git a/todo.txt b/todo.txt
index d958fb321..0c77c484e 100755
--- a/todo.txt
+++ b/todo.txt
@@ -59,7 +59,6 @@ Low priority
 Library
 -------
 
-- float formatting
 - locale support
 - conversion between character sets
 - bignums