@@ -148,75 +148,79 @@ my module sprintf {
148
148
make $ int
149
149
}
150
150
151
- sub pad-with-sign ($ num , $ size , $ pad , $ suffix ) {
151
+ sub pad-with-sign ($ sign , $ num , $ size , $ pad ) {
152
152
if $ pad ne ' ' && $ size {
153
- my $ sign := $ num < 0 ?? ' -' !! ' ' ;
154
- $ num := nqp ::abs_n($ num );
155
- $ num := $ num ~ $ suffix ;
156
- $ num := $ sign ~ infix_x($ pad , $ size - nqp :: chars ($ num ) - 1 ) ~ $ num ;
153
+ $ sign ~ infix_x($ pad , $ size - nqp :: chars ($ num ) - 1 ) ~ $ num ;
157
154
} else {
158
- $ num := $ num ~ $ suffix ;
155
+ $ sign ~ $ num ;
159
156
}
160
- $ num ;
161
157
}
162
- sub round-to-precision ($ float , $ precision ) {
163
- $ float := $ float * $ precision ;
164
- $ float := $ float - nqp ::floor_n($ float ) >= 0.5 ?? nqp ::ceil_n($ float ) !! nqp ::floor_n($ float );
165
- $ float := $ float / $ precision ;
158
+ sub stringify-to-precision ($ float , $ precision ) {
159
+ $ float := nqp ::abs_n($ float );
160
+ my $ lhs := nqp ::floor_n($ float );
161
+ my $ rhs := $ float - $ lhs ;
162
+
163
+ my $ knowhow := nqp ::knowhow(). new_type(: repr(" P6bigint" ));
164
+ my $ int := nqp ::box_i($ lhs , $ knowhow );
165
+ $ lhs := nqp ::tostr_I($ int );
166
+
167
+ $ float := $ rhs + 1 ;
168
+ $ float := $ float * nqp ::pow_n(10 , $ precision );
169
+ $ float := ~ nqp ::floor_n($ float + 0.5 );
170
+ $ float := $ float - nqp ::pow_n(10 , $ precision );
171
+ $ rhs := infix_x(' 0' , $ precision - nqp :: chars ($ float )) ~ $ float ;
172
+ $ rhs := nqp :: substr ($ rhs , nqp :: chars ($ rhs ) - $ precision );
173
+
174
+ $ float := $ lhs ~ ' .' ~ $ rhs ;
166
175
}
167
176
sub fixed-point ($ float , $ precision , $ size , $ pad ) {
168
- $ float := round-to-precision($ float , $ precision );
169
- pad-with-sign($ float , $ size , $ pad , ' ' );
177
+ my $ sign := $ float < 0 ?? ' -' !! ' ' ;
178
+ $ float := stringify-to-precision(nqp ::abs_n($ float ), $ precision );
179
+ pad-with-sign($ sign , $ float , $ size , $ pad );
170
180
}
171
181
sub scientific ($ float , $ e , $ precision , $ size , $ pad ) {
172
- my $ exp := nqp ::floor_n(nqp ::log_n(nqp ::abs_n($ float )) / nqp ::log_n(10 ));
182
+ my $ sign := $ float < 0 ?? ' -' !! ' ' ;
183
+ $ float := nqp ::abs_n($ float );
184
+ my $ exp := nqp ::floor_n(nqp ::log_n($ float ) / nqp ::log_n(10 ));
173
185
$ float := $ float / nqp ::pow_n(10 , $ exp );
174
- my $ suffix := $ e ~ ' + ' ~ $ exp ;
175
- $ float := round-to-precision( $ float , $ precision ) ;
176
- pad-with-sign($ float , $ size , $ pad , $ suffix );
186
+ $ float := stringify-to-precision( $ float , $ precision );
187
+ $ float := $ float ~ $ e ~ ( $ exp < 0 ?? ' ' !! ' + ' ) ~ $ exp ;
188
+ pad-with-sign($ sign , $ float , $ size , $ pad );
177
189
}
178
190
sub shortest ($ float , $ e , $ precision , $ size , $ pad ) {
179
- my $ fixed := round-to-precision($ float , $ precision );
191
+ my $ sign := $ float < 0 ?? ' -' !! ' ' ;
192
+ $ float := nqp ::abs_n($ float );
193
+
194
+ my $ fixed := stringify-to-precision($ float , $ precision );
180
195
181
196
my $ exp := nqp ::floor_n(nqp ::log_n(nqp ::abs_n($ float )) / nqp ::log_n(10 ));
182
197
$ float := $ float / nqp ::pow_n(10 , $ exp );
183
- my $ suffix := $ e ~ ' +' ~ $ exp ;
184
- my $ sci := round-to-precision($ float , $ precision );
198
+ my $ sci := stringify-to-precision($ float , $ precision ) ~ $ e ~ ' +' ~ $ exp ;
185
199
186
200
if nqp :: chars ($ sci ) < nqp :: chars ($ fixed ) {
187
- pad-with-sign($ sci , $ size , $ pad , $ suffix );
201
+ pad-with-sign($ sign , $ sci , $ size , $ pad );
188
202
} else {
189
- pad-with-sign($ fixed , $ size , $ pad , ' ' );
203
+ pad-with-sign($ sign , $ fixed , $ size , $ pad );
190
204
}
191
205
}
192
206
193
207
method directive :sym <e >($/ ) {
194
208
my $ float := next_argument();
195
- my $ precision := nqp ::pow_n( 10 , $ < precision > ?? $ < precision > . ast !! 6 ) ;
209
+ my $ precision := $ < precision > ?? $ < precision > . ast !! 6 ;
196
210
my $ pad := padding_char($/ );
197
211
my $ size := $ < size > ?? $ < size > . ast !! 0 ;
198
212
make scientific($ float , $ < sym > , $ precision , $ size , $ pad );
199
213
}
200
214
method directive :sym <f >($/ ) {
201
215
my $ int := next_argument();
202
- my $ sign := $ int < 0 ?? ' -' !! ' ' ;
203
216
my $ precision := $ < precision > ?? $ < precision > . ast !! 6 ;
204
- $ int := nqp ::abs_n($ int ) + 1 ;
205
- $ int := $ int * nqp ::pow_n(10 , $ precision );
206
- $ int := ~ nqp ::floor_n($ int + 0.5 );
207
- $ int := $ int - nqp ::pow_n(10 , $ precision );
208
- my $ lhs := nqp :: chars ($ int ) > $ precision ?? nqp :: substr ($ int , 0 , nqp :: chars ($ int ) - $ precision ) !! ' 0' ;
209
- my $ rhs := infix_x(' 0' , $ precision - nqp :: chars ($ int )) ~ $ int ;
210
- $ rhs := nqp :: substr ($ rhs , nqp :: chars ($ rhs ) - $ precision );
211
- $ int := $ lhs ~ ' .' ~ $ rhs ;
212
217
my $ pad := padding_char($/ );
213
- make $ pad ne ' ' && $ < size >
214
- ?? $ sign ~ infix_x($ pad , $ < size > . ast - nqp :: chars ($ int ) - 1 ) ~ $ int
215
- !! $ sign ~ $ int
218
+ my $ size := $ < size > ?? $ < size > . ast !! 0 ;
219
+ make fixed-point($ int , $ precision , $ size , $ pad );
216
220
}
217
221
method directive :sym <g >($/ ) {
218
222
my $ float := next_argument();
219
- my $ precision := nqp ::pow_n( 10 , $ < precision > ?? $ < precision > . ast !! 6 ) ;
223
+ my $ precision := $ < precision > ?? $ < precision > . ast !! 6 ;
220
224
my $ pad := padding_char($/ );
221
225
my $ size := $ < size > ?? $ < size > . ast !! 0 ;
222
226
make shortest($ float , ' e' , $ precision , $ size , $ pad );
0 commit comments