1 //! Utilities to parse, extract, and interpret exponent components. 2 3 use crate::atoi; 4 use crate::lib::slice; 5 use crate::util::*; 6 use super::traits::*; 7 8 /// The actual float-type doesn't matter, it just needs to be used for 9 /// signed/unsigned detection during sign parsing. 10 type FloatType = f64; 11 12 // EXPONENT CALCULATION 13 14 // Calculate the scientific notation exponent without overflow. 15 // 16 // For example, 0.1 would be -1, and 10 would be 1 in base 10. 17 perftools_inline!{ 18 #[cfg(feature = "correct")] 19 pub(super) fn scientific_exponent(exponent: i32, integer_digits: usize, fraction_start: usize) 20 -> i32 21 { 22 if integer_digits == 0 { 23 let fraction_start = fraction_start.try_i32_or_max(); 24 exponent.saturating_sub(fraction_start).saturating_sub(1) 25 } else { 26 let integer_shift = (integer_digits - 1).try_i32_or_max(); 27 exponent.saturating_add(integer_shift) 28 } 29 }} 30 31 // Calculate the mantissa exponent without overflow. 32 // 33 // Remove the number of digits that contributed to the mantissa past 34 // the dot, and add the number of truncated digits from the mantissa, 35 // to calculate the scaling factor for the mantissa from a raw exponent. 36 perftools_inline!{ 37 #[cfg(feature = "correct")] 38 pub(super) fn mantissa_exponent(raw_exponent: i32, fraction_digits: usize, truncated: usize) 39 -> i32 40 { 41 if fraction_digits > truncated { 42 raw_exponent.saturating_sub((fraction_digits - truncated).try_i32_or_max()) 43 } else { 44 raw_exponent.saturating_add((truncated - fraction_digits).try_i32_or_max()) 45 } 46 }} 47 48 // EXPONENT EXTRACTORS 49 50 // Extract exponent substring and parse exponent. 51 // Uses an abstract iterator to allow generic implementations 52 // iterators to work. This only works with greedy iterators, where we 53 // know exactly when we should stop upon encountering a given character. 54 // 55 // Precondition: 56 // Iter should not implement ConsumedIterator, since it would break 57 // the assumption in `extract_exponent_iltc`. 58 perftools_inline!{ 59 #[allow(unused_unsafe)] 60 fn extract_and_parse_exponent<'a, Data, Iter>( 61 data: &mut Data, 62 iter: Iter, 63 bytes: &'a [u8], 64 radix: u32, 65 sign: Sign 66 ) 67 -> &'a [u8] 68 where Data: FastDataInterface<'a>, 69 Iter: AsPtrIterator<'a, u8> 70 { 71 let (raw_exponent, ptr) = atoi::standalone_exponent(iter, radix, sign); 72 data.set_raw_exponent(raw_exponent); 73 74 unsafe { 75 // Extract the exponent subslice. 76 let first = bytes.as_ptr(); 77 data.set_exponent(Some(slice::from_raw_parts(first, distance(first, ptr)))); 78 79 // Return the remaining bytes. 80 let last = index!(bytes[bytes.len()..]).as_ptr(); 81 slice::from_raw_parts(ptr, distance(ptr, last)) 82 } 83 }} 84 85 // Parse exponent. 86 // This only works with exponents that may contain digit separators, 87 // where the invalid (trailing) data has already been determined. 88 perftools_inline!{ 89 #[cfg(feature = "format")] 90 fn parse_exponent<'a, Data>( 91 data: &mut Data, 92 bytes: &'a [u8], 93 leading: &'a [u8], 94 trailing: &'a [u8], 95 radix: u32, 96 digit_separator: u8, 97 sign: Sign 98 ) 99 where Data: FastDataInterface<'a> 100 { 101 // Get an iterator over our digits and sign bits, and parse the exponent. 102 let iter = iterate_digits_ignore_separator(leading, digit_separator); 103 104 // Parse the exponent and store the extracted digits. 105 let bytes_len = bytes.len() - trailing.len(); 106 data.set_raw_exponent(atoi::standalone_exponent(iter, radix, sign).0); 107 data.set_exponent(Some(&index!(bytes[..bytes_len]))); 108 }} 109 110 // PARSE THEN EXTRACT 111 112 // These algorithms are slightly more efficient, since they only 113 // require a single pass of the exponent string. These algorithms 114 // must be able to parse until they reach an invalid character, 115 // without any backsteps to find the correct subslice, that is, 116 // they must be greedy. 117 118 // Extract exponent substring and parse exponent. 119 // Does not consume any digit separators. 120 perftools_inline!{ 121 fn extract_exponent<'a, Data>( 122 data: &mut Data, 123 bytes: &'a [u8], 124 radix: u32, 125 digit_separator: u8 126 ) 127 -> &'a [u8] 128 where Data: FastDataInterface<'a> 129 { 130 // Remove leading exponent character and parse exponent. 131 let bytes = &index!(bytes[1..]); 132 let (sign, digits) = parse_sign_no_separator::<FloatType>(bytes, digit_separator); 133 let iter = iterate_digits_no_separator(digits, digit_separator); 134 extract_and_parse_exponent(data, iter, bytes, radix, sign) 135 }} 136 137 // Extract exponent substring and parse exponent. 138 // Consumes leading, internal, trailing, and consecutive digit separators. 139 perftools_inline!{ 140 #[cfg(feature = "format")] 141 fn extract_exponent_iltc<'a, Data>( 142 data: &mut Data, 143 bytes: &'a [u8], 144 radix: u32, 145 digit_separator: u8 146 ) 147 -> &'a [u8] 148 where Data: FastDataInterface<'a> 149 { 150 // Remove leading exponent character and parse exponent. 151 // We're not calling `consumed()`, so it's fine to have trailing underscores. 152 let bytes = &index!(bytes[1..]); 153 let (sign, digits) = parse_sign_lc_separator::<FloatType>(bytes, digit_separator); 154 let iter = iterate_digits_ignore_separator(digits, digit_separator); 155 extract_and_parse_exponent(data, iter, bytes, radix, sign) 156 }} 157 158 // EXTRACT THEN PARSE 159 160 // These algorithms are less efficient, since they first extract the 161 // subslice of valid data in the exponent, and then parse it, 162 // using 2 passes over the input data. However, because they first extract 163 // the data, they allow consumers that are not greedy, where there may 164 // be backsteps to determine if an input is actually valid after reaching 165 // the end or an invalid character. 166 167 // Generate function definition to extraction exponent with digit separators. 168 macro_rules! extract_exponent_separator { 169 ( 170 fn $name:ident, 171 sign => $sign:ident, 172 consume => $consume:ident 173 ) => ( 174 perftools_inline!{ 175 #[cfg(feature = "format")] 176 fn $name<'a, Data>( 177 data: &mut Data, 178 bytes: &'a [u8], 179 radix: u32, 180 digit_separator: u8 181 ) 182 -> &'a [u8] 183 where Data: FastDataInterface<'a> 184 { 185 let bytes = &index!(bytes[1..]); 186 let (sign, digits) = $sign::<FloatType>(bytes, digit_separator); 187 let (leading, trailing) = $consume(digits, radix, digit_separator); 188 parse_exponent(data, bytes, leading, trailing, radix, digit_separator, sign); 189 190 trailing 191 }} 192 ); 193 } 194 195 extract_exponent_separator!( 196 fn extract_exponent_i, 197 sign => parse_sign_no_separator, 198 consume => consume_digits_i 199 ); 200 201 extract_exponent_separator!( 202 fn extract_exponent_ic, 203 sign => parse_sign_no_separator, 204 consume => consume_digits_ic 205 ); 206 207 extract_exponent_separator!( 208 fn extract_exponent_l, 209 sign => parse_sign_l_separator, 210 consume => consume_digits_l 211 ); 212 213 extract_exponent_separator!( 214 fn extract_exponent_lc, 215 sign => parse_sign_lc_separator, 216 consume => consume_digits_lc 217 ); 218 219 extract_exponent_separator!( 220 fn extract_exponent_t, 221 sign => parse_sign_no_separator, 222 consume => consume_digits_t 223 ); 224 225 extract_exponent_separator!( 226 fn extract_exponent_tc, 227 sign => parse_sign_no_separator, 228 consume => consume_digits_tc 229 ); 230 231 extract_exponent_separator!( 232 fn extract_exponent_il, 233 sign => parse_sign_l_separator, 234 consume => consume_digits_il 235 ); 236 237 extract_exponent_separator!( 238 fn extract_exponent_ilc, 239 sign => parse_sign_lc_separator, 240 consume => consume_digits_ilc 241 ); 242 243 extract_exponent_separator!( 244 fn extract_exponent_it, 245 sign => parse_sign_no_separator, 246 consume => consume_digits_it 247 ); 248 249 extract_exponent_separator!( 250 fn extract_exponent_itc, 251 sign => parse_sign_no_separator, 252 consume => consume_digits_itc 253 ); 254 255 extract_exponent_separator!( 256 fn extract_exponent_lt, 257 sign => parse_sign_l_separator, 258 consume => consume_digits_lt 259 ); 260 261 extract_exponent_separator!( 262 fn extract_exponent_ltc, 263 sign => parse_sign_lc_separator, 264 consume => consume_digits_ltc 265 ); 266 267 extract_exponent_separator!( 268 fn extract_exponent_ilt, 269 sign => parse_sign_l_separator, 270 consume => consume_digits_ilt 271 ); 272 273 // API 274 275 // Extract exponent without a digit separator. 276 perftools_inline!{ 277 pub(crate) fn extract_exponent_no_separator<'a, Data>(data: &mut Data, bytes: &'a [u8], radix: u32, format: NumberFormat) 278 -> &'a [u8] 279 where Data: FastDataInterface<'a> 280 { 281 extract_exponent(data, bytes, radix, format.digit_separator()) 282 }} 283 284 // Extract exponent while ignoring the digit separator. 285 perftools_inline!{ 286 #[cfg(feature = "format")] 287 pub(crate) fn extract_exponent_ignore_separator<'a, Data>(data: &mut Data, bytes: &'a [u8], radix: u32, format: NumberFormat) 288 -> &'a [u8] 289 where Data: FastDataInterface<'a> 290 { 291 extract_exponent_iltc(data, bytes, radix, format.digit_separator()) 292 }} 293 294 // Extract exponent with a digit separator in the exponent component. 295 perftools_inline!{ 296 #[cfg(feature = "format")] 297 pub(super) fn extract_exponent_separator<'a, Data>(data: &mut Data, bytes: &'a [u8], radix: u32, format: NumberFormat) 298 -> &'a [u8] 299 where Data: FastDataInterface<'a> 300 { 301 const I: NumberFormat = NumberFormat::EXPONENT_INTERNAL_DIGIT_SEPARATOR; 302 const L: NumberFormat = NumberFormat::EXPONENT_LEADING_DIGIT_SEPARATOR; 303 const T: NumberFormat = NumberFormat::EXPONENT_TRAILING_DIGIT_SEPARATOR; 304 const C: NumberFormat = NumberFormat::EXPONENT_CONSECUTIVE_DIGIT_SEPARATOR; 305 const IL: NumberFormat = NumberFormat::from_bits_truncate(I.bits() | L.bits()); 306 const IT: NumberFormat = NumberFormat::from_bits_truncate(I.bits() | T.bits()); 307 const LT: NumberFormat = NumberFormat::from_bits_truncate(L.bits() | T.bits()); 308 const ILT: NumberFormat = NumberFormat::from_bits_truncate(IL.bits() | T.bits()); 309 const IC: NumberFormat = NumberFormat::from_bits_truncate(I.bits() | C.bits()); 310 const LC: NumberFormat = NumberFormat::from_bits_truncate(L.bits() | C.bits()); 311 const TC: NumberFormat = NumberFormat::from_bits_truncate(T.bits() | C.bits()); 312 const ILC: NumberFormat = NumberFormat::from_bits_truncate(IL.bits() | C.bits()); 313 const ITC: NumberFormat = NumberFormat::from_bits_truncate(IT.bits() | C.bits()); 314 const LTC: NumberFormat = NumberFormat::from_bits_truncate(LT.bits() | C.bits()); 315 const ILTC: NumberFormat = NumberFormat::from_bits_truncate(ILT.bits() | C.bits()); 316 317 let digit_separator = format.digit_separator(); 318 match format & NumberFormat::EXPONENT_DIGIT_SEPARATOR_FLAG_MASK { 319 I => extract_exponent_i(data, bytes, radix, digit_separator), 320 IC => extract_exponent_ic(data, bytes, radix, digit_separator), 321 L => extract_exponent_l(data, bytes, radix, digit_separator), 322 LC => extract_exponent_lc(data, bytes, radix, digit_separator), 323 T => extract_exponent_t(data, bytes, radix, digit_separator), 324 TC => extract_exponent_tc(data, bytes, radix, digit_separator), 325 IL => extract_exponent_il(data, bytes, radix, digit_separator), 326 ILC => extract_exponent_ilc(data, bytes, radix, digit_separator), 327 IT => extract_exponent_it(data, bytes, radix, digit_separator), 328 ITC => extract_exponent_itc(data, bytes, radix, digit_separator), 329 LT => extract_exponent_lt(data, bytes, radix, digit_separator), 330 LTC => extract_exponent_ltc(data, bytes, radix, digit_separator), 331 ILT => extract_exponent_ilt(data, bytes, radix, digit_separator), 332 ILTC => extract_exponent_iltc(data, bytes, radix, digit_separator), 333 _ => unreachable!() 334 } 335 }} 336 337 // TESTS 338 // ----- 339 340 #[cfg(test)] 341 mod test { 342 use super::*; 343 use super::super::standard::*; 344 345 #[cfg(feature = "format")] 346 use super::super::ignore::*; 347 348 #[cfg(feature = "correct")] 349 #[test] scientific_exponent_test()350 fn scientific_exponent_test() { 351 // 0 digits in the integer 352 assert_eq!(scientific_exponent(0, 0, 5), -6); 353 assert_eq!(scientific_exponent(10, 0, 5), 4); 354 assert_eq!(scientific_exponent(-10, 0, 5), -16); 355 356 // >0 digits in the integer 357 assert_eq!(scientific_exponent(0, 1, 5), 0); 358 assert_eq!(scientific_exponent(0, 2, 5), 1); 359 assert_eq!(scientific_exponent(0, 2, 20), 1); 360 assert_eq!(scientific_exponent(10, 2, 20), 11); 361 assert_eq!(scientific_exponent(-10, 2, 20), -9); 362 363 // Underflow 364 assert_eq!(scientific_exponent(i32::min_value(), 0, 0), i32::min_value()); 365 assert_eq!(scientific_exponent(i32::min_value(), 0, 5), i32::min_value()); 366 367 // Overflow 368 assert_eq!(scientific_exponent(i32::max_value(), 0, 0), i32::max_value()-1); 369 assert_eq!(scientific_exponent(i32::max_value(), 5, 0), i32::max_value()); 370 } 371 372 #[cfg(feature = "correct")] 373 #[test] mantissa_exponent_test()374 fn mantissa_exponent_test() { 375 assert_eq!(mantissa_exponent(10, 5, 0), 5); 376 assert_eq!(mantissa_exponent(0, 5, 0), -5); 377 assert_eq!(mantissa_exponent(i32::max_value(), 5, 0), i32::max_value()-5); 378 assert_eq!(mantissa_exponent(i32::max_value(), 0, 5), i32::max_value()); 379 assert_eq!(mantissa_exponent(i32::min_value(), 5, 0), i32::min_value()); 380 assert_eq!(mantissa_exponent(i32::min_value(), 0, 5), i32::min_value()+5); 381 } 382 383 #[test] extract_exponent_test()384 fn extract_exponent_test() { 385 // Allows present exponents. 386 type Data<'a> = StandardFastDataInterface<'a>; 387 let mut data = Data::new(NumberFormat::standard().unwrap()); 388 extract_exponent(&mut data, b"e+23", 10, b'_'); 389 assert_eq!(data.exponent(), Some(b!("+23"))); 390 assert_eq!(data.raw_exponent(), 23); 391 392 // Allows absent exponents. 393 let mut data = Data::new(NumberFormat::standard().unwrap()); 394 extract_exponent(&mut data, b"e", 10, b'_'); 395 assert_eq!(data.exponent(), Some(b!(""))); 396 assert_eq!(data.raw_exponent(), 0); 397 } 398 399 #[test] 400 #[cfg(feature = "format")] extract_exponent_iltc_test()401 fn extract_exponent_iltc_test() { 402 // Allows present exponents. 403 type Data<'a> = IgnoreFastDataInterface<'a>; 404 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 405 extract_exponent_iltc(&mut data, b"e__+__2__3____", 10, b'_'); 406 assert_eq!(data.exponent(), Some(b!("__+__2__3____"))); 407 assert_eq!(data.raw_exponent(), 23); 408 409 // Allows present exponents. 410 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 411 extract_exponent_iltc(&mut data, b"e__+_2_3_", 10, b'_'); 412 assert_eq!(data.exponent(), Some(b!("__+_2_3_"))); 413 assert_eq!(data.raw_exponent(), 23); 414 415 // Allows present exponents. 416 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 417 extract_exponent_iltc(&mut data, b"e_+__2_3_", 10, b'_'); 418 assert_eq!(data.exponent(), Some(b!("_+__2_3_"))); 419 assert_eq!(data.raw_exponent(), 23); 420 421 // Allows absent exponents. 422 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 423 extract_exponent_iltc(&mut data, b"e", 10, b'_'); 424 assert_eq!(data.exponent(), Some(b!(""))); 425 assert_eq!(data.raw_exponent(), 0); 426 } 427 428 #[test] 429 #[cfg(feature = "format")] extract_exponent_i_test()430 fn extract_exponent_i_test() { 431 // Allows present exponents. 432 type Data<'a> = IgnoreFastDataInterface<'a>; 433 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 434 extract_exponent_i(&mut data, b"e+2_3", 10, b'_'); 435 assert_eq!(data.exponent(), Some(b!("+2_3"))); 436 assert_eq!(data.raw_exponent(), 23); 437 438 // Allows absent exponents. 439 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 440 extract_exponent_i(&mut data, b"e", 10, b'_'); 441 assert_eq!(data.exponent(), Some(b!(""))); 442 assert_eq!(data.raw_exponent(), 0); 443 444 // Ignores invalid data. 445 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 446 extract_exponent_i(&mut data, b"e+_2_3", 10, b'_'); 447 assert_eq!(data.exponent(), Some(b!("+"))); 448 assert_eq!(data.raw_exponent(), 0); 449 450 // Ignores invalid data. 451 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 452 extract_exponent_i(&mut data, b"e+2__3", 10, b'_'); 453 assert_eq!(data.exponent(), Some(b!("+2"))); 454 assert_eq!(data.raw_exponent(), 2); 455 } 456 457 #[test] 458 #[cfg(feature = "format")] extract_exponent_ic_test()459 fn extract_exponent_ic_test() { 460 // Allows present exponents. 461 type Data<'a> = IgnoreFastDataInterface<'a>; 462 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 463 extract_exponent_ic(&mut data, b"e+2__3", 10, b'_'); 464 assert_eq!(data.exponent(), Some(b!("+2__3"))); 465 assert_eq!(data.raw_exponent(), 23); 466 467 // Allows absent exponents. 468 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 469 extract_exponent_ic(&mut data, b"e", 10, b'_'); 470 assert_eq!(data.exponent(), Some(b!(""))); 471 assert_eq!(data.raw_exponent(), 0); 472 473 // Ignores invalid data. 474 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 475 extract_exponent_ic(&mut data, b"e+_2_3", 10, b'_'); 476 assert_eq!(data.exponent(), Some(b!("+"))); 477 assert_eq!(data.raw_exponent(), 0); 478 479 // Ignores invalid data. 480 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 481 extract_exponent_ic(&mut data, b"e_+2__3", 10, b'_'); 482 assert_eq!(data.exponent(), Some(b!(""))); 483 assert_eq!(data.raw_exponent(), 0); 484 } 485 486 #[test] 487 #[cfg(feature = "format")] extract_exponent_l_test()488 fn extract_exponent_l_test() { 489 // Allows present exponents. 490 type Data<'a> = IgnoreFastDataInterface<'a>; 491 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 492 extract_exponent_l(&mut data, b"e+_23", 10, b'_'); 493 assert_eq!(data.exponent(), Some(b!("+_23"))); 494 assert_eq!(data.raw_exponent(), 23); 495 496 // Allows absent exponents. 497 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 498 extract_exponent_l(&mut data, b"e", 10, b'_'); 499 assert_eq!(data.exponent(), Some(b!(""))); 500 assert_eq!(data.raw_exponent(), 0); 501 502 // Ignores invalid data. 503 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 504 extract_exponent_l(&mut data, b"e+_2_3", 10, b'_'); 505 assert_eq!(data.exponent(), Some(b!("+_2"))); 506 assert_eq!(data.raw_exponent(), 2); 507 508 // Ignores invalid data. 509 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 510 extract_exponent_l(&mut data, b"e_+__2__3", 10, b'_'); 511 assert_eq!(data.exponent(), Some(b!("_+"))); 512 assert_eq!(data.raw_exponent(), 0); 513 } 514 515 #[test] 516 #[cfg(feature = "format")] extract_exponent_lc_test()517 fn extract_exponent_lc_test() { 518 // Allows present exponents. 519 type Data<'a> = IgnoreFastDataInterface<'a>; 520 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 521 extract_exponent_lc(&mut data, b"e+__23", 10, b'_'); 522 assert_eq!(data.exponent(), Some(b!("+__23"))); 523 assert_eq!(data.raw_exponent(), 23); 524 525 // Allows absent exponents. 526 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 527 extract_exponent_lc(&mut data, b"e", 10, b'_'); 528 assert_eq!(data.exponent(), Some(b!(""))); 529 assert_eq!(data.raw_exponent(), 0); 530 531 // Ignores invalid data. 532 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 533 extract_exponent_lc(&mut data, b"e+_2_3", 10, b'_'); 534 assert_eq!(data.exponent(), Some(b!("+_2"))); 535 assert_eq!(data.raw_exponent(), 2); 536 537 // Ignores invalid data. 538 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 539 extract_exponent_lc(&mut data, b"e_+__2__3", 10, b'_'); 540 assert_eq!(data.exponent(), Some(b!("_+__2"))); 541 assert_eq!(data.raw_exponent(), 2); 542 } 543 544 #[test] 545 #[cfg(feature = "format")] extract_exponent_t_test()546 fn extract_exponent_t_test() { 547 // Allows present exponents. 548 type Data<'a> = IgnoreFastDataInterface<'a>; 549 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 550 extract_exponent_t(&mut data, b"e+23_", 10, b'_'); 551 assert_eq!(data.exponent(), Some(b!("+23_"))); 552 assert_eq!(data.raw_exponent(), 23); 553 554 // Allows absent exponents. 555 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 556 extract_exponent_t(&mut data, b"e", 10, b'_'); 557 assert_eq!(data.exponent(), Some(b!(""))); 558 assert_eq!(data.raw_exponent(), 0); 559 560 // Ignores invalid data. 561 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 562 extract_exponent_t(&mut data, b"e+23__", 10, b'_'); 563 assert_eq!(data.exponent(), Some(b!("+23"))); 564 assert_eq!(data.raw_exponent(), 23); 565 566 // Ignores invalid data. 567 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 568 extract_exponent_t(&mut data, b"e_+__2__3", 10, b'_'); 569 assert_eq!(data.exponent(), Some(b!("_"))); 570 assert_eq!(data.raw_exponent(), 0); 571 } 572 573 #[test] 574 #[cfg(feature = "format")] extract_exponent_tc_test()575 fn extract_exponent_tc_test() { 576 // Allows present exponents. 577 type Data<'a> = IgnoreFastDataInterface<'a>; 578 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 579 extract_exponent_tc(&mut data, b"e+23__", 10, b'_'); 580 assert_eq!(data.exponent(), Some(b!("+23__"))); 581 assert_eq!(data.raw_exponent(), 23); 582 583 // Allows absent exponents. 584 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 585 extract_exponent_tc(&mut data, b"e", 10, b'_'); 586 assert_eq!(data.exponent(), Some(b!(""))); 587 assert_eq!(data.raw_exponent(), 0); 588 589 // Ignores invalid data. 590 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 591 extract_exponent_tc(&mut data, b"e+_2_3", 10, b'_'); 592 assert_eq!(data.exponent(), Some(b!("+"))); 593 assert_eq!(data.raw_exponent(), 0); 594 595 // Ignores invalid data. 596 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 597 extract_exponent_tc(&mut data, b"e_+__2__3", 10, b'_'); 598 assert_eq!(data.exponent(), Some(b!("_"))); 599 assert_eq!(data.raw_exponent(), 0); 600 } 601 602 #[test] 603 #[cfg(feature = "format")] extract_exponent_il_test()604 fn extract_exponent_il_test() { 605 // Allows present exponents. 606 type Data<'a> = IgnoreFastDataInterface<'a>; 607 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 608 extract_exponent_il(&mut data, b"e+_2_3", 10, b'_'); 609 assert_eq!(data.exponent(), Some(b!("+_2_3"))); 610 assert_eq!(data.raw_exponent(), 23); 611 612 // Allows absent exponents. 613 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 614 extract_exponent_il(&mut data, b"e", 10, b'_'); 615 assert_eq!(data.exponent(), Some(b!(""))); 616 assert_eq!(data.raw_exponent(), 0); 617 618 // Ignores invalid data. 619 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 620 extract_exponent_il(&mut data, b"e+23__", 10, b'_'); 621 assert_eq!(data.exponent(), Some(b!("+23"))); 622 assert_eq!(data.raw_exponent(), 23); 623 624 // Ignores invalid data. 625 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 626 extract_exponent_il(&mut data, b"e+2__3__", 10, b'_'); 627 assert_eq!(data.exponent(), Some(b!("+2"))); 628 assert_eq!(data.raw_exponent(), 2); 629 } 630 631 #[test] 632 #[cfg(feature = "format")] extract_exponent_ilc_test()633 fn extract_exponent_ilc_test() { 634 // Allows present exponents. 635 type Data<'a> = IgnoreFastDataInterface<'a>; 636 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 637 extract_exponent_ilc(&mut data, b"e+__2__3", 10, b'_'); 638 assert_eq!(data.exponent(), Some(b!("+__2__3"))); 639 assert_eq!(data.raw_exponent(), 23); 640 641 // Allows absent exponents. 642 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 643 extract_exponent_ilc(&mut data, b"e", 10, b'_'); 644 assert_eq!(data.exponent(), Some(b!(""))); 645 assert_eq!(data.raw_exponent(), 0); 646 647 // Ignores invalid data. 648 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 649 extract_exponent_ilc(&mut data, b"e+23__", 10, b'_'); 650 assert_eq!(data.exponent(), Some(b!("+23"))); 651 assert_eq!(data.raw_exponent(), 23); 652 653 // Ignores invalid data. 654 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 655 extract_exponent_ilc(&mut data, b"e+2__3__", 10, b'_'); 656 assert_eq!(data.exponent(), Some(b!("+2__3"))); 657 assert_eq!(data.raw_exponent(), 23); 658 } 659 660 #[test] 661 #[cfg(feature = "format")] extract_exponent_it_test()662 fn extract_exponent_it_test() { 663 // Allows present exponents. 664 type Data<'a> = IgnoreFastDataInterface<'a>; 665 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 666 extract_exponent_it(&mut data, b"e+2_3_", 10, b'_'); 667 assert_eq!(data.exponent(), Some(b!("+2_3_"))); 668 assert_eq!(data.raw_exponent(), 23); 669 670 // Allows absent exponents. 671 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 672 extract_exponent_it(&mut data, b"e", 10, b'_'); 673 assert_eq!(data.exponent(), Some(b!(""))); 674 assert_eq!(data.raw_exponent(), 0); 675 676 // Ignores invalid data. 677 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 678 extract_exponent_it(&mut data, b"e+_23", 10, b'_'); 679 assert_eq!(data.exponent(), Some(b!("+"))); 680 assert_eq!(data.raw_exponent(), 0); 681 682 // Ignores invalid data. 683 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 684 extract_exponent_it(&mut data, b"e+2__3__", 10, b'_'); 685 assert_eq!(data.exponent(), Some(b!("+2"))); 686 assert_eq!(data.raw_exponent(), 2); 687 } 688 689 #[test] 690 #[cfg(feature = "format")] extract_exponent_itc_test()691 fn extract_exponent_itc_test() { 692 // Allows present exponents. 693 type Data<'a> = IgnoreFastDataInterface<'a>; 694 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 695 extract_exponent_itc(&mut data, b"e+2__3__", 10, b'_'); 696 assert_eq!(data.exponent(), Some(b!("+2__3__"))); 697 assert_eq!(data.raw_exponent(), 23); 698 699 // Allows absent exponents. 700 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 701 extract_exponent_itc(&mut data, b"e", 10, b'_'); 702 assert_eq!(data.exponent(), Some(b!(""))); 703 assert_eq!(data.raw_exponent(), 0); 704 705 // Ignores invalid data. 706 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 707 extract_exponent_itc(&mut data, b"e+_23", 10, b'_'); 708 assert_eq!(data.exponent(), Some(b!("+"))); 709 assert_eq!(data.raw_exponent(), 0); 710 711 // Ignores invalid data. 712 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 713 extract_exponent_itc(&mut data, b"e_+2__3__", 10, b'_'); 714 assert_eq!(data.exponent(), Some(b!("_"))); 715 assert_eq!(data.raw_exponent(), 0); 716 } 717 718 #[test] 719 #[cfg(feature = "format")] extract_exponent_lt_test()720 fn extract_exponent_lt_test() { 721 // Allows present exponents. 722 type Data<'a> = IgnoreFastDataInterface<'a>; 723 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 724 extract_exponent_lt(&mut data, b"e_+_23_", 10, b'_'); 725 assert_eq!(data.exponent(), Some(b!("_+_23_"))); 726 assert_eq!(data.raw_exponent(), 23); 727 728 // Allows absent exponents. 729 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 730 extract_exponent_lt(&mut data, b"e", 10, b'_'); 731 assert_eq!(data.exponent(), Some(b!(""))); 732 assert_eq!(data.raw_exponent(), 0); 733 734 // Ignores invalid data. 735 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 736 extract_exponent_lt(&mut data, b"e+2_3", 10, b'_'); 737 assert_eq!(data.exponent(), Some(b!("+2"))); 738 assert_eq!(data.raw_exponent(), 2); 739 740 // Ignores invalid data. 741 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 742 extract_exponent_lt(&mut data, b"e__+__2__3__", 10, b'_'); 743 assert_eq!(data.exponent(), Some(b!(""))); 744 } 745 746 #[test] 747 #[cfg(feature = "format")] extract_exponent_ltc_test()748 fn extract_exponent_ltc_test() { 749 // Allows present exponents. 750 type Data<'a> = IgnoreFastDataInterface<'a>; 751 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 752 extract_exponent_ltc(&mut data, b"e__+__23__", 10, b'_'); 753 assert_eq!(data.exponent(), Some(b!("__+__23__"))); 754 assert_eq!(data.raw_exponent(), 23); 755 756 // Allows absent exponents. 757 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 758 extract_exponent_ltc(&mut data, b"e", 10, b'_'); 759 assert_eq!(data.exponent(), Some(b!(""))); 760 assert_eq!(data.raw_exponent(), 0); 761 762 // Ignores invalid data. 763 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 764 extract_exponent_ltc(&mut data, b"e+2_3", 10, b'_'); 765 assert_eq!(data.exponent(), Some(b!("+2"))); 766 assert_eq!(data.raw_exponent(), 2); 767 768 // Ignores invalid data. 769 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 770 extract_exponent_ltc(&mut data, b"e__+__2__3__", 10, b'_'); 771 assert_eq!(data.exponent(), Some(b!("__+__2"))); 772 assert_eq!(data.raw_exponent(), 2); 773 } 774 775 #[test] 776 #[cfg(feature = "format")] extract_exponent_ilt_test()777 fn extract_exponent_ilt_test() { 778 // Allows present exponents. 779 type Data<'a> = IgnoreFastDataInterface<'a>; 780 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 781 extract_exponent_ilt(&mut data, b"e_+_2_3_", 10, b'_'); 782 assert_eq!(data.exponent(), Some(b!("_+_2_3_"))); 783 assert_eq!(data.raw_exponent(), 23); 784 785 // Allows absent exponents. 786 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 787 extract_exponent_ilt(&mut data, b"e", 10, b'_'); 788 assert_eq!(data.exponent(), Some(b!(""))); 789 assert_eq!(data.raw_exponent(), 0); 790 791 // Ignores invalid data. 792 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 793 extract_exponent_ilt(&mut data, b"e__+_2_3_", 10, b'_'); 794 assert_eq!(data.exponent(), Some(b!(""))); 795 796 // Ignores invalid data. 797 let mut data = Data::new(NumberFormat::ignore(b'_').unwrap()); 798 extract_exponent_ilt(&mut data, b"e_+__2_3_", 10, b'_'); 799 assert_eq!(data.exponent(), Some(b!("_+"))); 800 } 801 } 802