PrintfScanf.st
changeset 4394 c63e80fb5b12
parent 4094 f2c6fcb55d10
child 4401 a29669a0e2a1
--- a/PrintfScanf.st	Thu Jun 15 09:58:16 2017 +0200
+++ b/PrintfScanf.st	Sat Jun 17 03:09:27 2017 +0200
@@ -1,5 +1,3 @@
-"{ Encoding: utf8 }"
-
 "{ Package: 'stx:libbasic2' }"
 
 "{ NameSpace: Smalltalk }"
@@ -52,6 +50,12 @@
     self new printf:'%- 10.4s%.2e' arguments: { 'abcdefghijkl' . Float pi }  
 
     self new printf:'%8.3f' arguments: { 200 sqrt negated }
+    self printf:'%8.3f' on:Transcript arguments: { 200 sqrt negated }
+    self printf:'%10.4f' on:Transcript arguments: { 200 sqrt negated }
+    self printf:'%20.10f' on:Transcript arguments: { 200 sqrt negated }
+
+    self printf:'%20.10f' on:Transcript arguments: { 1.234567890123456789f  }
+    self printf:'%20.10f' on:Transcript arguments: { 1.234567890123456789q  }
 
     self new printf:'%x' arguments: #(16r41)  
     self new printf:'%#x' arguments: #(16r41)   
@@ -97,11 +101,102 @@
 
 !PrintfScanf class methodsFor:'printing'!
 
+printf:formatString argument:arg 
+    "Format and print the receiver with <arg> formatted in C style, 
+     as described in the UTek manual page for printf(3)."
+
+    ^ self printf:formatString arguments:{ arg }
+
+    "
+     self printf:'%e' on:Transcript argument:(1.234 asShortFloat)
+     self printf:'%e' on:Transcript argument:(1.234 asFloat)     
+     self printf:'%e' on:Transcript argument:(1.234 asLongFloat) 
+     self printf:'%e' on:Transcript argument:(1.234 asQDouble)   
+     self printf:'%e' on:Transcript argument:(1.234 asInteger)   
+
+     self printf:'%10e' on:Transcript argument:(1.234 asShortFloat)
+     self printf:'%10e' on:Transcript argument:(1.234 asFloat)     
+     self printf:'%10e' on:Transcript argument:(1.234 asLongFloat) 
+     self printf:'%10e' on:Transcript argument:(1.234 asQDouble)   
+     self printf:'%10e' on:Transcript argument:(1.234 asInteger)   
+
+     self printf:'%010e' on:Transcript argument:(1.234 asInteger)   
+     self printf:'%-10e' on:Transcript argument:(1.234 asInteger)   
+
+     self printf:'%10.9f' on:Transcript argument:(1.2345 asShortFloat)
+     self printf:'%10.9f' on:Transcript argument:(1.2345 asFloat)     
+     self printf:'%10.9f' on:Transcript argument:(1.2345 asLongFloat) 
+     self printf:'%10.9f' on:Transcript argument:(1.2345 asQDouble)   
+     self printf:'%10.9f' on:Transcript argument:(1.2345 asInteger)   
+    "
+
+    "Created: / 16-06-2017 / 14:50:08 / cg"
+!
+
 printf:formatString arguments:args 
     "Format and print the receiver with <args> formatted in C style, 
      as described in the UTek manual page for printf(3)."
 
     ^ self new printf:formatString arguments:args
+
+    "
+     self printf:'%e' on:Transcript arguments:{ (1.234 asShortFloat) }
+     self printf:'%e' on:Transcript arguments:{ (1.234 asFloat)      }
+     self printf:'%e' on:Transcript arguments:{ (1.234 asLongFloat)  }
+     self printf:'%e' on:Transcript arguments:{ (1.234 asQDouble)    }
+     self printf:'%e' on:Transcript arguments:{ (1.234 asInteger)    }
+
+     self printf:'%10e' on:Transcript arguments:{ (1.234 asShortFloat) }
+     self printf:'%10e' on:Transcript arguments:{ (1.234 asFloat)      }
+     self printf:'%10e' on:Transcript arguments:{ (1.234 asLongFloat)  }
+     self printf:'%10e' on:Transcript arguments:{ (1.234 asQDouble)    }
+     self printf:'%10e' on:Transcript arguments:{ (1.234 asInteger)    }
+
+     self printf:'%010e' on:Transcript arguments:{ (1.234 asInteger)    }
+     self printf:'%-10e' on:Transcript arguments:{ (1.234 asInteger)    }
+
+     self printf:'%10.9f' on:Transcript arguments:{ (1.2345 asShortFloat) }
+     self printf:'%10.9f' on:Transcript arguments:{ (1.2345 asFloat)      }
+     self printf:'%10.9f' on:Transcript arguments:{ (1.2345 asLongFloat)  }
+     self printf:'%10.9f' on:Transcript arguments:{ (1.2345 asQDouble)    }
+     self printf:'%10.9f' on:Transcript arguments:{ (1.2345 asInteger)    }
+    "
+
+    "Modified (comment): / 16-06-2017 / 10:37:44 / cg"
+!
+
+printf:formatString on:outStream argument: arg
+    "Format and print formatString on <outStream> with <arg>
+     formatted in C style, as described in the UTek manual page for
+     printf(3).  This method is designed for producing output
+     suitable for a machine."     
+
+    ^ self printf:formatString on:outStream arguments:{ arg }
+
+    "
+     self printf:'%e' on:Transcript argument:(1.234 asShortFloat). Transcript cr.
+     self printf:'%e' on:Transcript argument:(1.234 asFloat)     . Transcript cr.
+     self printf:'%e' on:Transcript argument:(1.234 asLongFloat) . Transcript cr.
+     self printf:'%e' on:Transcript argument:(1.234 asQDouble)   . Transcript cr.
+     self printf:'%e' on:Transcript argument:(1.234 asInteger)   . Transcript cr.
+
+     self printf:'%10e' on:Transcript argument:(1.234 asShortFloat). Transcript cr.
+     self printf:'%10e' on:Transcript argument:(1.234 asFloat)     . Transcript cr.
+     self printf:'%10e' on:Transcript argument:(1.234 asLongFloat) . Transcript cr.
+     self printf:'%10e' on:Transcript argument:(1.234 asQDouble)   . Transcript cr.
+     self printf:'%10e' on:Transcript argument:(1.234 asInteger)   . Transcript cr.
+
+     self printf:'%010e' on:Transcript argument:(1.234 asInteger)  . Transcript cr.
+     self printf:'%-10e' on:Transcript argument:(1.234 asInteger)  . Transcript cr.
+
+     self printf:'%10.9f' on:Transcript argument:(1.2345 asShortFloat). Transcript cr.
+     self printf:'%10.9f' on:Transcript argument:(1.2345 asFloat)     . Transcript cr.
+     self printf:'%10.9f' on:Transcript argument:(1.2345 asLongFloat) . Transcript cr.
+     self printf:'%10.9f' on:Transcript argument:(1.2345 asQDouble)   . Transcript cr.
+     self printf:'%10.9f' on:Transcript argument:(1.2345 asInteger)   . Transcript cr.
+    "
+
+    "Created: / 16-06-2017 / 14:50:40 / cg"
 !
 
 printf:formatString on:outStream arguments: args
@@ -111,6 +206,31 @@
      suitable for a machine."     
 
     ^ self new printf:formatString on:outStream arguments: args
+
+    "
+     self printf:'%e' on:Transcript arguments:{ (1.234 asShortFloat) }
+     self printf:'%e' on:Transcript arguments:{ (1.234 asFloat)      }
+     self printf:'%e' on:Transcript arguments:{ (1.234 asLongFloat)  }
+     self printf:'%e' on:Transcript arguments:{ (1.234 asQDouble)    }
+     self printf:'%e' on:Transcript arguments:{ (1.234 asInteger)    }
+
+     self printf:'%10e' on:Transcript arguments:{ (1.234 asShortFloat) }
+     self printf:'%10e' on:Transcript arguments:{ (1.234 asFloat)      }
+     self printf:'%10e' on:Transcript arguments:{ (1.234 asLongFloat)  }
+     self printf:'%10e' on:Transcript arguments:{ (1.234 asQDouble)    }
+     self printf:'%10e' on:Transcript arguments:{ (1.234 asInteger)    }
+
+     self printf:'%010e' on:Transcript arguments:{ (1.234 asInteger)    }
+     self printf:'%-10e' on:Transcript arguments:{ (1.234 asInteger)    }
+
+     self printf:'%10.9f' on:Transcript arguments:{ (1.2345 asShortFloat) }
+     self printf:'%10.9f' on:Transcript arguments:{ (1.2345 asFloat)      }
+     self printf:'%10.9f' on:Transcript arguments:{ (1.2345 asLongFloat)  }
+     self printf:'%10.9f' on:Transcript arguments:{ (1.2345 asQDouble)    }
+     self printf:'%10.9f' on:Transcript arguments:{ (1.2345 asInteger)    }
+    "
+
+    "Modified (comment): / 16-06-2017 / 14:51:08 / cg"
 ! !
 
 !PrintfScanf class methodsFor:'scanning'!
@@ -136,17 +256,25 @@
 !PrintfScanf methodsFor:'helpers'!
 
 absDecimalPrintFloat:aFloat on:aStream digits:digits 
-    "Place a string representation of the receiver on <aStream> using <digits> significant digits, using decimal notation."
+    "Place a string representation of the receiver on <aStream>,
+     using <digits> significant digits, using decimal notation."
     
-    |exp x fuzz i|
+"
+    self printf:'%20.10f' on:Transcript arguments: { 1.234567890123456789f  }
+    self printf:'%20.10f' on:Transcript arguments: { 1.234567890123456789q  }
+"
+
+    |absVal exp x fuzz i|
+
+    absVal := aFloat abs.
 
     "x is myself normalized to (1.0, 10.0), exp is my exponent"
-    exp := aFloat abs < 1.0 ifTrue:[
-                (10.0 / aFloat abs) log floor negated
-            ] ifFalse:[
-                aFloat abs log floor
-            ].
-    x := aFloat abs / (10.0 raisedTo:exp).
+    exp := absVal < 1.0 
+            ifTrue:[ 
+                (10.0 / absVal) log floor negated ] 
+            ifFalse:[
+                absVal log floor].
+    x := absVal / (10.0 raisedTo:exp).
     fuzz := 10.0 raisedTo:1 - digits.
     x := 0.5 * fuzz + x.
     x >= 10.0 ifTrue:[ 
@@ -154,10 +282,14 @@
         x := x / 10.0.
         exp := exp + 1
     ].
+    
     exp < 0 ifTrue:[
-        1 to:1 - exp do:[:j | 
-            aStream nextPut:('0.000000000000' at:j)
-        ]
+        1 to:(1 - exp) do:[:j | 
+            "/ cg: huh - what sort of code is that????
+            "/ aStream nextPut:('0.000000000000' at:j)
+            aStream nextPut:(j == 2 ifTrue:[$.] ifFalse:[$0])
+        ].
+        
     ].
     [ x >= fuzz ] whileTrue:[ 
         "use fuzz to track significance" 
@@ -177,10 +309,13 @@
             aStream nextPut:$.
         ]
     ]
+
+    "Modified (comment): / 16-06-2017 / 10:40:28 / cg"
 !
 
 absPrintFloat:aFloat on:aStream digits:digits 
-    "Place a string representation of the receiver on <aStream> using <digits> significant digits."
+    "Place a string representation of the receiver on <aStream>,
+     using <digits> significant digits."
     
     (aFloat < 1.0e6 and:[ aFloat > 1.0e-4 ]) ifTrue:[
         self 
@@ -193,20 +328,25 @@
             on:aStream
             digits:digits
     ]
+
+    "Modified (comment): / 16-06-2017 / 10:25:33 / cg"
 !
 
 absScientificPrintFloat:aFloat on:aStream digits:digits 
-    "Place a string representation of the receiver on <aStream> using <digits> significant digits, using scientific notation."
+    "Place a string representation of the receiver on <aStream>,
+     using <digits> significant digits, using scientific notation."
     
-    |exp fuzz x q i|
+    |absVal exp fuzz x q i|
 
+    absVal := aFloat abs.
+    
     "x is myself normalized to [1.0, 10.0), exp is my exponent"
-    exp := aFloat abs < 1.0 ifTrue:[
-                (10.0 / aFloat abs) log floor negated
-            ] ifFalse:[
-                aFloat abs log floor
-            ].
-    x := aFloat abs / (10.0 raisedTo:exp).
+    exp := absVal < 1.0 
+                ifTrue:[
+                    (10.0 / absVal) log floor asInteger negated]
+                ifFalse:[
+                    absVal log floor asInteger].
+    x := absVal / (10.0 raisedTo:exp).
     fuzz := 10.0 raisedTo:1 - digits.
     x := 0.5 * fuzz + x.
     x >= 10.0 ifTrue:[ "check if rounding has unnormalized x" 
@@ -235,6 +375,8 @@
     ].
     aStream nextPut:$e.
     q printOn:aStream
+
+    "Modified: / 16-06-2017 / 10:27:03 / cg"
 !
 
 formatArgCountFor:aFormatString
@@ -342,34 +484,39 @@
     ].
 
     ('feg' includes: char) ifTrue:[
-            arg := argStream next asFloat.
-            precision := precision min: 6.
-            argString := WriteStream on:''.
-            char == $g ifTrue:
-                    [self absPrintFloat:arg on: argString digits: precision + 1].
-            char == $f ifTrue:
-                    [self absDecimalPrintFloat:arg on: argString digits: precision + arg abs log + 1].
-            char == $e ifTrue:
-                    [self absScientificPrintFloat:arg on: argString digits: precision + 1].
-            argString := argString contents.
-            arg < 0
-                    ifTrue: [argString := '-', argString]
-                    ifFalse: [plus ifTrue: [argString := '+', argString]].
-            (precision = 0 and: [pound not]) ifTrue:
-                    [(argString includes: $e)
-                            ifTrue: ["self halt"]
-                            ifFalse:
-                                    [argString := arg truncated printString]].
-            pound ifTrue:
-                    [(argString includes: $e)
-                            ifTrue: ["self halt"]
-                            ifFalse:
-                                    [precision - (argString size - (argString indexOf: $.)) timesRepeat:
-                                            [argString := argString, '0']]].
-            ljust ifTrue: [outStream nextPutAll: argString].
-            width - argString size timesRepeat: [outStream nextPut: pad].
-            ljust ifFalse: [outStream nextPutAll: argString].
-            ^inStream next
+        arg := argStream next asFloat.
+        arg isLimitedPrecisionReal ifTrue:[
+            precision := precision min: (arg defaultPrintPrecision).
+        ] ifFalse:[    
+            precision := precision min:(Float defaultPrintPrecision).
+        ].    
+        argString := WriteStream on:''.
+        char == $g ifTrue: [ 
+            self absPrintFloat:arg on: argString digits: precision + 1 ].
+        char == $f ifTrue: [ 
+            self absDecimalPrintFloat:arg on: argString digits: precision + arg abs log + 1].
+        char == $e ifTrue: [
+            self absScientificPrintFloat:arg on: argString digits: precision + 1].
+        argString := argString contents.
+        arg < 0
+            ifTrue: [argString := '-', argString]
+            ifFalse: [plus ifTrue: [argString := '+', argString]].
+        (precision = 0 and: [pound not]) ifTrue:[
+            (argString includes: $e)
+                ifTrue: ["self halt"]
+                ifFalse: [
+                    argString := arg truncated printString]].
+        pound ifTrue:[
+            (argString includes: $e)
+                ifTrue: ["self halt"]
+                ifFalse:[
+                    precision - (argString size - (argString indexOf: $.)) 
+                        timesRepeat:[
+                            argString := argString, '0']]].
+        ljust ifTrue: [outStream nextPutAll: argString].
+        width - argString size timesRepeat: [outStream nextPut: pad].
+        ljust ifFalse: [outStream nextPutAll: argString].
+        ^inStream next
     ].
 
     char == $c ifTrue:[
@@ -392,7 +539,7 @@
 
     char == $o ifTrue:[
         arg := argStream next asInteger abs printStringRadix: 8.
-            pound ifTrue: [arg := '0', arg]
+        pound ifTrue: [arg := '0', arg]
     ].
 
     ('xX' includes: char) ifTrue:[
@@ -406,8 +553,9 @@
 
     char == $x ifTrue:[
         1 to: arg size do: [:i |
-                    ('ABCDEF' includes: (arg at: i)) ifTrue:
-                            [arg at: i put: (arg at: i) asLowercase]
+            ('ABCDEF' includes: (arg at: i)) ifTrue:[
+                arg at: i put: (arg at: i) asLowercase
+            ]
         ]
     ].
 
@@ -417,32 +565,32 @@
     ljust ifFalse: [outStream nextPutAll: (arg copyFrom: 1 to: precision)].
     ^ inStream next
 
-    "Modified (format): / 24-07-2011 / 08:39:04 / cg"
+    "Modified: / 17-06-2017 / 03:00:07 / cg"
 !
 
 printf:aString arguments:args 
     "Format and print the receiver with <args> formatted in C style, 
-     as described in the UTek manual page for printf(3)."
+     as described in the UTek manual page for printf(3).
+     Returns the formatted printString."
     
     |aStream|
 
     aStream := WriteStream on:(aString species new:100).
-    self 
-        printf:aString
-        on:aStream
-        arguments:args.
+    self printf:aString on:aStream arguments:args.
     ^ aStream contents
 
     "
      self new printf:'%d %x' arguments:#(1234 45054) 
     "
+
+    "Modified (comment): / 16-06-2017 / 15:09:01 / cg"
 !
 
 printf:aFormatString on:outStream arguments: args
     "Format and print aFormatString on <outStream> with <args>
      formatted in C style, as described in the UTek manual page for
-     printf(3).  This method is designed for producing output
-     suitable for a machine."     
+     printf(3).  
+     This method is designed for producing output suitable for a machine."     
 
     | argStream inStream char |
 
@@ -455,6 +603,8 @@
             self printArgFrom:inStream to:outStream arguments:argStream
         ]
     ]
+
+    "Modified (comment): / 16-06-2017 / 15:09:10 / cg"
 ! !
 
 !PrintfScanf methodsFor:'scanning'!