@@ -7,14 +7,14 @@ use std::ffi::OsString;
77use std:: io:: { stdout, BufWriter , ErrorKind , Write } ;
88
99use clap:: { Arg , ArgAction , Command } ;
10- use num_traits:: { ToPrimitive , Zero } ;
10+ use num_traits:: Zero ;
1111
1212use uucore:: error:: { FromIo , UResult } ;
13- use uucore:: format:: { num_format, sprintf, Format , FormatArgument } ;
13+ use uucore:: format:: num_format:: FloatVariant ;
14+ use uucore:: format:: { num_format, ExtendedBigDecimal , Format } ;
1415use uucore:: { format_usage, help_about, help_usage} ;
1516
1617mod error;
17- mod extendedbigdecimal;
1818mod hexadecimalfloat;
1919
2020// public to allow fuzzing
@@ -24,7 +24,6 @@ pub mod number;
2424mod number;
2525mod numberparse;
2626use crate :: error:: SeqError ;
27- use crate :: extendedbigdecimal:: ExtendedBigDecimal ;
2827use crate :: number:: PreciseNumber ;
2928
3029const ABOUT : & str = help_about ! ( "seq.md" ) ;
@@ -142,26 +141,52 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
142141 }
143142 } ;
144143
145- let padding = first
146- . num_integral_digits
147- . max ( increment. num_integral_digits )
148- . max ( last. num_integral_digits ) ;
149-
150144 let precision = select_precision ( first_precision, increment_precision, last_precision) ;
151145
152- let format = options
153- . format
154- . map ( Format :: < num_format:: Float > :: parse)
155- . transpose ( ) ?;
146+ // If a format was passed on the command line, use that.
147+ // If not, use some default format based on parameters precision.
148+ let format = match options. format {
149+ Some ( str) => Format :: < num_format:: Float , & ExtendedBigDecimal > :: parse ( str) ?,
150+ None => {
151+ let padding = if options. equal_width {
152+ let precision_value = precision. unwrap_or ( 0 ) ;
153+ first
154+ . num_integral_digits
155+ . max ( increment. num_integral_digits )
156+ . max ( last. num_integral_digits )
157+ + if precision_value > 0 {
158+ precision_value + 1
159+ } else {
160+ 0
161+ }
162+ } else {
163+ 0
164+ } ;
165+
166+ let formatter = match precision {
167+ // format with precision: decimal floats and integers
168+ Some ( precision) => num_format:: Float {
169+ variant : FloatVariant :: Decimal ,
170+ width : padding,
171+ alignment : num_format:: NumberAlignment :: RightZero ,
172+ precision,
173+ ..Default :: default ( )
174+ } ,
175+ // format without precision: hexadecimal floats
176+ None => num_format:: Float {
177+ variant : FloatVariant :: Shortest ,
178+ ..Default :: default ( )
179+ } ,
180+ } ;
181+ Format :: from_formatter ( formatter)
182+ }
183+ } ;
156184
157185 let result = print_seq (
158186 ( first. number , increment. number , last. number ) ,
159- precision,
160187 & options. separator ,
161188 & options. terminator ,
162- options. equal_width ,
163- padding,
164- format. as_ref ( ) ,
189+ & format,
165190 ) ;
166191 match result {
167192 Ok ( ( ) ) => Ok ( ( ) ) ,
@@ -220,93 +245,24 @@ fn done_printing<T: Zero + PartialOrd>(next: &T, increment: &T, last: &T) -> boo
220245 }
221246}
222247
223- fn format_bigdecimal ( value : & bigdecimal:: BigDecimal ) -> Option < String > {
224- let format_arguments = & [ FormatArgument :: Float ( value. to_f64 ( ) ?) ] ;
225- let value_as_bytes = sprintf ( "%g" , format_arguments) . ok ( ) ?;
226- String :: from_utf8 ( value_as_bytes) . ok ( )
227- }
228-
229- /// Write a big decimal formatted according to the given parameters.
230- fn write_value_float (
231- writer : & mut impl Write ,
232- value : & ExtendedBigDecimal ,
233- width : usize ,
234- precision : Option < usize > ,
235- ) -> std:: io:: Result < ( ) > {
236- let value_as_str = match precision {
237- // format with precision: decimal floats and integers
238- Some ( precision) => match value {
239- ExtendedBigDecimal :: Infinity | ExtendedBigDecimal :: MinusInfinity => {
240- format ! ( "{value:>width$.precision$}" )
241- }
242- _ => format ! ( "{value:>0width$.precision$}" ) ,
243- } ,
244- // format without precision: hexadecimal floats
245- None => match value {
246- ExtendedBigDecimal :: BigDecimal ( bd) => {
247- format_bigdecimal ( bd) . unwrap_or_else ( || "{value}" . to_owned ( ) )
248- }
249- _ => format ! ( "{value:>0width$}" ) ,
250- } ,
251- } ;
252- write ! ( writer, "{value_as_str}" )
253- }
254-
255248/// Floating point based code path
256249fn print_seq (
257250 range : RangeFloat ,
258- precision : Option < usize > ,
259251 separator : & str ,
260252 terminator : & str ,
261- pad : bool ,
262- padding : usize ,
263- format : Option < & Format < num_format:: Float > > ,
253+ format : & Format < num_format:: Float , & ExtendedBigDecimal > ,
264254) -> std:: io:: Result < ( ) > {
265255 let stdout = stdout ( ) . lock ( ) ;
266256 let mut stdout = BufWriter :: new ( stdout) ;
267257 let ( first, increment, last) = range;
268258 let mut value = first;
269- let padding = if pad {
270- let precision_value = precision. unwrap_or ( 0 ) ;
271- padding
272- + if precision_value > 0 {
273- precision_value + 1
274- } else {
275- 0
276- }
277- } else {
278- 0
279- } ;
259+
280260 let mut is_first_iteration = true ;
281261 while !done_printing ( & value, & increment, & last) {
282262 if !is_first_iteration {
283263 write ! ( stdout, "{separator}" ) ?;
284264 }
285- // If there was an argument `-f FORMAT`, then use that format
286- // template instead of the default formatting strategy.
287- //
288- // TODO The `printf()` method takes a string as its second
289- // parameter but we have an `ExtendedBigDecimal`. In order to
290- // satisfy the signature of the function, we convert the
291- // `ExtendedBigDecimal` into a string. The `printf()`
292- // logic will subsequently parse that string into something
293- // similar to an `ExtendedBigDecimal` again before rendering
294- // it as a string and ultimately writing to `stdout`. We
295- // shouldn't have to do so much converting back and forth via
296- // strings.
297- match & format {
298- Some ( f) => {
299- let float = match & value {
300- ExtendedBigDecimal :: BigDecimal ( bd) => bd. to_f64 ( ) . unwrap ( ) ,
301- ExtendedBigDecimal :: Infinity => f64:: INFINITY ,
302- ExtendedBigDecimal :: MinusInfinity => f64:: NEG_INFINITY ,
303- ExtendedBigDecimal :: MinusZero => -0.0 ,
304- ExtendedBigDecimal :: Nan => f64:: NAN ,
305- } ;
306- f. fmt ( & mut stdout, float) ?;
307- }
308- None => write_value_float ( & mut stdout, & value, padding, precision) ?,
309- }
265+ format. fmt ( & mut stdout, & value) ?;
310266 // TODO Implement augmenting addition.
311267 value = value + increment. clone ( ) ;
312268 is_first_iteration = false ;
0 commit comments