Skip to main content

strtod2/
lib.rs

1// Translated from
2// - http://mxr.mozilla.org/mozilla-central/source/js/src/dtoa.c
3
4#![allow(non_upper_case_globals)]
5#![allow(non_snake_case)]
6
7use std::mem::transmute;
8use std::num::Wrapping;
9
10const DBL_DIG : u32 = 15;
11const DBL_MAX_10_EXP : i32 = 308;
12const DBL_MAX_EXP : u32 = 1024;
13const FLT_RADIX : u32 = 2;
14const Exp_shift : u32 = 20;
15const Exp_msk1 : u32 = 0x100000;
16const Exp_mask : u32 = 0x7ff00000;
17const P : u32 = 53;
18const Bias : i32 = 1023;
19const Emin : i32 = (-1022);
20const Exp_1 : u32 = 0x3ff00000;
21const Ebits : u32 = 11;
22const Frac_mask : u32 = 0xfffff;
23const Frac_mask1 : u32 = 0xfffff;
24const Ten_pmax : i32 = 22;
25const Bndry_mask : u32 = 0xfffff;
26const Bndry_mask1 : u32 = 0xfffff;
27const LSB : u32 = 1;
28const Log2P : i32 = 1;
29const Tiny1 : u32 = 1;
30const Flt_Rounds : u32 = 1;
31const Big0 : u32 = Frac_mask1 | Exp_msk1 * (DBL_MAX_EXP + Bias as u32 - 1);
32const Big1 : u32 = 0xffffffff;
33const n_bigtens : u32 = 5;
34const Scale_Bit : i32 = 0x10;
35
36const CTAB : u32 = 9;
37const CNL : u32 = 10;
38const CVT : u32 = 11;
39const CFF : u32 = 12;
40const CCR : u32 = 13;
41const CSP : u32 = 32;
42const CPLUS : u32 = 43;
43const CMIN : u32 = 45;
44const CDOT : u32 = 46;
45const C0 : u32 = 48;
46const C9 : u32 = 57;
47const CE : u32 = 69;
48const Ce : u32 = 101;
49
50static tens : [f64; 23] = [
51	1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
52	1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
53	1e20, 1e21, 1e22
54];
55static bigtens : [f64; 5] = [ 1e16, 1e32, 1e64, 1e128, 1e256 ];
56static tinytens : [f64; 5] = [
57	1e-16, 1e-32, 1e-64, 1e-128,
58	9007199254740992_f64 * 9007199254740992e-256_f64
59];
60
61/// Parses a 64-bit floating point number.
62///
63/// Leading whitspace and trailing characters are ignored. If the input
64/// string does not contain a valid floating point number (where e.g.
65/// `"."` is seen as a valid floating point number), `None` is returned.
66/// Otherwise the parsed floating point number is returned.
67///
68/// This implementation is a translation from
69/// http://mxr.mozilla.org/mozilla-central/source/js/src/dtoa.c.
70pub fn strtod(input: &str) -> Option<f64> {
71	let mut parser = Parser {
72		sign: false,
73		rv: U { d: 0_f64 }
74	};
75	
76	parser.parse(input.as_bytes())
77}
78
79#[derive(Copy, Clone)]
80struct Chars<'a> {
81	bytes: &'a [u8],
82	offset: usize
83}
84
85impl<'a> Chars<'a> {
86	fn peek(&self) -> u32 {
87		if self.offset == self.bytes.len() {
88			0
89		} else if self.offset < self.bytes.len() {
90			self.bytes[self.offset] as u32
91		} else {
92			panic!();
93		}
94	}
95	
96	fn bump(&mut self) {
97		self.offset += 1;
98	}
99}
100
101struct Parser {
102	sign: bool,
103	rv: U
104}
105
106impl Parser {
107	fn parse(&mut self, input: &[u8]) -> Option<f64> {
108		if !self.parse_impl(Chars { bytes: input, offset: 0 }) {
109			None
110		} else {
111			Some(if self.sign { -self.rv.d } else { self.rv.d })
112		}
113	}
114	
115	fn parse_impl(&mut self, mut s: Chars) -> bool {
116		let mut nz0 = 0;
117		let mut nz = 0;
118		
119		loop {
120			match s.peek() {
121				0 => return false,
122				CPLUS | CMIN => {
123					if s.peek() == CMIN {
124						self.sign = true;
125					}
126					s.bump();
127					if s.peek() == 0 {
128						return false;
129					}
130					break;
131				}
132				CTAB | CNL | CVT | CFF | CCR | CSP => {},
133				_ => break
134			}
135			
136			s.bump();
137		}
138		
139		let start = s;
140		
141		if s.peek() == C0 {
142			nz0 = 1;
143			
144			s.bump();
145			while s.peek() == C0 {
146				s.bump();
147			}
148			
149			if s.peek() == 0 {
150				return true;
151			}
152		}
153		
154		let mut s0 = s;
155		let mut y = 0;
156		let mut z = 0;
157		
158		let mut nd = 0;
159		let mut nf = 0;
160		let mut c;
161		
162		loop {
163			c = s.peek();
164			if c < C0 || c > C9 {
165				break;
166			}
167			
168			if nd < 9 {
169				y = 10 * y + c - C0;
170			} else if nd < 16 {
171				z = 10 * z + c - C0;
172			}
173			
174			nd += 1;
175			s.bump();
176		}
177		
178		let mut nd0 = nd;
179		
180		if c == CDOT {
181			s.bump();
182			c = s.peek();
183			
184			if nd == 0 {
185				while c == C0 {
186					s.bump();
187					c = s.peek();
188					nz += 1;
189				}
190				
191				if c > C0 && c <= C9 {
192					s0 = s;
193					nf += nz;
194					nz = 0;
195				}
196			}
197			
198			while c >= C0 && c <= C9 {
199				nz += 1;
200				
201				if c > C0 {
202					nf += nz;
203					
204					for _ in 1..nz {
205						if nd < 9 {
206							y *= 10;
207						} else if nd < DBL_DIG + 1 {
208							z *= 10;
209						}
210						nd += 1;
211					}
212					if nd < 9 {
213						y = 10 * y + c - C0;
214					} else if nd < DBL_DIG + 1 {
215						z = 10 * z + c - C0;
216					}
217					nd += 1;
218					nz = 0;
219				}
220				
221				s.bump();
222				c = s.peek();
223			}
224		}
225		
226		let mut e = 0_i32;
227		if c == Ce || c == CE {
228			if nd == 0 && nz == 0 && nz0 == 0 {
229				self.sign = false;
230				return true;
231			}
232			
233			let mut esign = false;
234			
235			s.bump();
236			c = s.peek();
237			
238			match c {
239				CPLUS | CMIN => {
240					if c == CMIN {
241						esign = true;
242					}
243					s.bump();
244					c = s.peek();
245				}
246				_ => {}
247			}
248			
249			if c >= C0 && c <= C9 {
250				while c == C0 {
251					s.bump();
252					c = s.peek();
253				}
254				
255				if c > C0 && c <= C9 {
256					let mut L = c - C0;
257					let s1 = s;
258					
259					s.bump();
260					c = s.peek();
261					
262					while c >= C0 && c <= C9 {
263						L = u32::wrapping_sub(u32::wrapping_add(u32::wrapping_mul(L, 10), c), C0);
264						
265						s.bump();
266						c = s.peek();
267					}
268					
269					if s.offset - s1.offset > 8 || L > 19999 {
270						// Avoid confusion from exponents
271					    // so large that e might overflow.
272					    
273					    e = 19999; // safe for 16 bit ints
274					} else {
275						e = L as i32;
276					}
277					
278					if esign {
279						e = -e;
280					}
281				} else {
282					e = 0;
283				}
284			}
285		}
286		
287		if nd == 0 {
288			if nz == 0 && nz0 == 0 {
289				self.sign = false;
290			}
291			return s.offset > start.offset;
292		}
293		
294		e -= nf;
295		let mut e1 = e;
296		
297		// Now we have nd0 digits, starting at s0, followed by a
298	 	// decimal point, followed by nd-nd0 digits.  The number we're
299	 	// after is the integer represented by those digits times
300	 	// 10**e
301	 	
302	 	if nd0 == 0 {
303	 		nd0 = nd;
304	 	}
305	 	
306	 	let k = if nd < DBL_DIG + 1 { nd } else { DBL_DIG + 1 };
307	 	self.rv.d = y as f64;
308	 	if k > 9 {
309	 		self.rv.d = tens[k as usize - 9] * self.rv.d + z as f64;
310	 	}
311	 	if nd <= DBL_DIG && Flt_Rounds == 1 {
312	 		if e == 0 {
313	 			return true;
314	 		}
315	 		if e > 0 {
316	 			if e <= Ten_pmax {
317	 				self.rv.d *= tens[e as usize];
318	 				return true;
319	 			}
320	 			
321	 			let i = DBL_DIG - nd;
322	 			if e <= Ten_pmax + i as i32 {
323	 				// A fancier test would sometimes let us do
324				 	// this for larger i values.
325				 	e -= i as i32;
326				 	self.rv.d *= tens[i as usize];
327				 	self.rv.d *= tens[e as usize];
328				 	return true;
329	 			}
330	 		} else if e >= -Ten_pmax {
331	 			self.rv.d /= tens[-e as usize];
332	 			return true;
333	 		}
334	 	}
335	 	
336	 	e1 += (nd - k) as i32;
337	 	
338	 	let mut scale = 0_i32;
339	 	
340	 	// Get starting approximation = rv * 10**e1
341	 	
342	 	if e1 > 0 {
343	 		let i = e1 & 15;
344	 		if i != 0 {
345	 			self.rv.d *= tens[i as usize];
346	 		}
347	 		e1 &= !15;
348	 		if e1 != 0 {
349	 			if e1 > DBL_MAX_10_EXP {
350	 				self.overflow();
351	 				return true;
352	 			}
353	 			
354	 			e1 >>= 4;
355	 			
356	 			let mut j = 0;
357	 			
358	 			while e1 > 1 {
359	 				if e1 & 1 != 0 {
360	 					self.rv.d *= bigtens[j];
361	 				}
362	 				
363	 				j += 1;
364	 				e1 >>= 1;
365	 			}
366	 			
367	 			// The last multiplication could overflow.
368	 			let w = self.rv.word0() - P * Exp_msk1;
369	 			self.rv.set_word0(w);
370	 			self.rv.d *= bigtens[j];
371	 			
372	 			let z = self.rv.word0() & Exp_mask;
373	 			if z > Exp_msk1 * (DBL_MAX_EXP + Bias as u32 - P) {
374	 				self.overflow();
375	 				return true;
376	 			}
377	 			
378	 			if z > Exp_msk1 * (DBL_MAX_EXP + Bias as u32 - 1 - P) {
379	 				self.rv.set_word0(Big0);
380	 				self.rv.set_word1(Big1);
381	 			} else {
382	 				let w = self.rv.word0() + P * Exp_msk1;
383	 				self.rv.set_word0(w);
384	 			}
385	 		}
386	 	} else if e1 < 0 {
387	 		e1 = -e1;
388	 		let i = e1 & 15;
389	 		if i != 0 {
390	 			self.rv.d /= tens[i as usize];
391	 		}
392	 		e1 >>= 4;
393	 		if e1 != 0 {
394	 			if e1 >= 1 << n_bigtens {
395	 				self.rv.d = 0_f64;
396	 				return true;
397	 			}
398	 			
399	 			if e1 & Scale_Bit != 0 {
400	 				scale = (2 * P) as i32;
401	 			}
402	 			
403	 			let mut j = 0;
404	 			while e1 > 0 {
405	 				if e1 & 1 != 0 {
406	 					self.rv.d *= tinytens[j];
407	 				}
408	 				
409	 				j += 1;
410	 				e1 >>= 1;
411	 			}
412	 			
413	 			if scale != 0 {
414	 				let j = 2 * P as i32 + 1 - ((self.rv.word0() & Exp_mask) >> Exp_shift) as i32;
415	 				if j > 0 {
416	 					// scaled rv is denormal; zap j low bits
417	 					if j >= 32 {
418	 						self.rv.set_word1(0);
419	 						if j >= 53 {
420	 							self.rv.set_word0((P + 2) * Exp_msk1);
421	 						} else {
422	 							let w = self.rv.word0() & 0xffffffff << (j - 32);
423	 							self.rv.set_word0(w);
424	 						}
425	 					} else {
426	 						let w = self.rv.word1() & 0xffffffff << j;
427	 						self.rv.set_word1(w);
428	 					}
429	 					
430	 					if self.rv.d == 0_f64 {
431	 						return true;
432	 					}
433	 				}
434	 			}
435	 		}
436	 	}
437	 	
438	 	// Now the hard part -- adjusting rv to the correct value.
439	 	
440	 	// Put digits into bd: true value = bd * 10^e
441	 	
442	 	let bd0 = s2b(s0, nd0, nd, y);
443	 	
444	 	loop {
445	 		let mut bd = bd0.clone();
446	 		let (mut bb, bbe, bbbits) = d2b(self.rv); // rv = bb * 2^bbe
447	 		let mut bs = i2b(1);
448	 		
449	 		let (mut bb2, bb5, mut bd2, bd5) = if e >= 0 {
450	 			(0_i32, 0_i32, e, e)
451	 		} else {
452	 			(-e, -e, 0_i32, 0_i32)
453	 		};
454	 		
455	 		if bbe >= 0 {
456	 			bb2 += bbe;
457	 		} else {
458	 			bd2 -= bbe;
459	 		}
460	 		
461	 		let mut bs2 = bb2;
462	 		
463	 		let mut j = bbe - scale;
464	 		let i = j + bbbits as i32 - 1; // logb(rv)
465	 		if i < Emin {
466	 			j += P as i32 - Emin;
467	 		} else {
468	 			j = (P + 1 - bbbits) as i32;
469	 		}
470	 		bb2 += j;
471	 		bd2 += j;
472	 		bd2 += scale;
473	 		let mut i = if bb2 < bd2 { bb2 } else { bd2 };
474	 		if i > bs2 {
475	 			i = bs2;
476	 		}
477	 		if i > 0 {
478	 			bb2 -= i;
479	 			bd2 -= i;
480	 			bs2 -= i;
481	 		}
482	 		
483	 		if bb5 > 0 {
484	 			bs = pow5mult(bs, bb5);
485	 			bb = mult(&bs, &bb);
486	 		}
487	 		if bb2 > 0 {
488	 			bb = lshift(&bb, bb2);
489	 		}
490	 		if bd5 > 0 {
491	 			bd = pow5mult(bd, bd5);
492	 		}
493	 		if bd2 > 0 {
494	 			bd = lshift(&bd, bd2);
495	 		}
496	 		if bs2 > 0 {
497	 			bs = lshift(&bs, bs2);
498	 		}
499	 		
500	 		let mut delta = diff(&bb, &bd);
501	 		let dsign = delta.sign;
502	 		delta.sign = false;
503	 		
504	 		let i = cmp(&delta, &bs);
505	 		if i < 0 {
506	 			// Error is less than half an ulp -- check for
507	 			// special case of mantissa a power of two.
508	 			
509	 			if
510	 				dsign ||
511	 				self.rv.word1() != 0 ||
512	 				self.rv.word0() & Bndry_mask != 0 ||
513	 				(self.rv.word0() & Exp_mask) <= (2 * P + 1) * Exp_msk1
514 				{
515 					break;
516 				}
517 				
518 				if delta.x[0] == 0 && delta.x.len() <= 1 {
519 					// exact result
520 					break;
521 				}
522 				
523 				delta = lshift(&delta, Log2P);
524 				if cmp(&delta, &bs) > 0 {
525 					if self.drop_down(scale) {
526 						return true;
527 					}
528 				}
529 				break;
530	 		}
531	 		if i == 0 {
532	 			// exactly half-way between
533	 			if dsign {
534	 				if (self.rv.word0() & Bndry_mask1) == Bndry_mask1 {
535	 					let y = self.rv.word0() & Exp_mask;
536	 					if
537	 						self.rv.word1() == (
538								if scale != 0 && y <= 2 * P * Exp_msk1 {
539									0xffffffff & (0xffffffff << ( 2 * P + 1 - (y >> Exp_shift)))
540								} else {
541									0xffffffff
542								}
543							)
544						{
545							// boundary case -- increment exponent
546							let w = (self.rv.word0() & Exp_mask) + Exp_msk1;
547							self.rv.set_word0(w);
548							self.rv.set_word1(0);
549							break;
550						}
551					}
552	 			} else if self.rv.word0() & Bndry_mask == 0 && self.rv.word1() == 0 {
553	 				if self.drop_down(scale) {
554	 					return true;
555	 				}
556	 				break;
557	 			}
558	 			
559	 			if self.rv.word1() & LSB == 0 {
560	 				break;
561	 			}
562	 			
563	 			if dsign {
564	 				self.rv.d += ulp(self.rv);
565	 			} else {
566	 				self.rv.d -= ulp(self.rv);
567	 				if self.rv.d == 0_f64 {
568	 					return true;
569	 				}
570	 			}
571	 			
572	 			break;
573	 		}
574	 		
575	 		let mut aadj = ratio(&delta, &bs);
576	 		let mut aadj1 = U { d: 0_f64 };
577	 		if aadj <= 2_f64 {
578	 			if dsign {
579	 				aadj = 1_f64;
580	 				aadj1.d = 1_f64;
581	 			} else if self.rv.word1() != 0 || self.rv.word0() & Bndry_mask != 0 {
582	 				if self.rv.word1() == Tiny1 && self.rv.word0() == 0 {
583	 					self.rv.d = 0_f64;
584	 					return true;
585	 				}
586	 				
587	 				aadj = 1_f64;
588	 				aadj1.d = -1_f64;
589	 			} else {
590	 				// special case -- power of FLT_RADIX to be
591	 				// rounded down...
592	 				
593	 				if aadj < 2_f64 / FLT_RADIX as f64 {
594	 					aadj = 1_f64 / FLT_RADIX as f64;
595	 				} else {
596	 					aadj *= 0.5_f64;
597	 				}
598	 				aadj1.d = -aadj;
599	 			}
600	 		} else {
601	 			aadj *= 0.5_f64;
602	 			aadj1.d = if dsign { aadj } else { -aadj };
603	 			if Flt_Rounds == 0 {
604	 				aadj1.d += 0.5_f64;
605	 			}
606	 		}
607	 		
608	 		let y = self.rv.word0() & Exp_mask;
609	 		
610	 		// Check for overflow
611	 		
612	 		if y == Exp_msk1 * (DBL_MAX_EXP + Bias as u32 - 1) {
613	 			let rv0 = self.rv;
614	 			let w = self.rv.word0() - P * Exp_msk1;
615	 			self.rv.set_word0(w);
616	 			let adj = aadj1.d * ulp(self.rv);
617	 			self.rv.d += adj;
618	 			if (self.rv.word0() & Exp_mask) >= Exp_msk1 * (DBL_MAX_EXP + Bias as u32 - P) {
619	 				if rv0.word0() == Big0 && rv0.word1() == Big1 {
620	 					self.overflow();
621	 					return true;
622	 				}
623	 				self.rv.set_word0(Big0);
624	 				self.rv.set_word1(Big1);
625	 				
626	 				continue;
627	 			} else {
628	 				let w = self.rv.word0() + P * Exp_msk1;
629	 				self.rv.set_word0(w);
630	 			}
631	 		} else {
632	 			if scale != 0 && y <= 2 * P * Exp_msk1 {
633	 				if aadj <= 0x7fffffff as f64 {
634	 					let mut z = aadj as u32;
635	 					if z <= 0 {
636	 						z = 1;
637	 					}
638	 					aadj = z as f64;
639	 					aadj1.d = if dsign { aadj } else { -aadj };
640	 				}
641	 				let w = aadj1.word0() + (2 * P + 1) * Exp_msk1 - y;
642	 				aadj1.set_word0(w);
643	 			}
644	 			let adj = aadj1.d * ulp(self.rv);
645	 			self.rv.d += adj;
646	 		}
647	 		
648	 		let z = self.rv.word0() & Exp_mask;
649	 		if scale == 0 {
650	 			if y == z {
651	 				// Can we stop now?
652	 				let L = aadj as i32;
653	 				aadj -= L as f64;
654	 				// The tolerances below are conservative.
655	 				if dsign || self.rv.word1() != 0 || self.rv.word0() & Bndry_mask != 0 {
656	 					if aadj < 0.4999999_f64 || aadj > 0.5000001_f64 {
657	 						break;
658	 					}
659	 				} else if aadj < 0.4999999_f64 / FLT_RADIX as f64 {
660	 					break;
661	 				}
662	 			}
663	 		}
664 		}
665 		
666 		if scale != 0 {
667 			let mut rv0 = U { d: 0_f64 };
668 			rv0.set_word0(Exp_1 - 2 * P * Exp_msk1);
669 			rv0.set_word1(0);
670 			self.rv.d *= rv0.d;
671 		}
672 		
673 		true
674	}
675	
676	fn overflow(&mut self) {
677		self.rv.set_word0(Exp_mask);
678		self.rv.set_word1(0);
679	}
680	
681	fn drop_down(&mut self, scale: i32) -> bool {
682		// boundary case -- decrement exponent
683		if scale != 0 {
684			let L = self.rv.word0() & Exp_mask;
685			if L <= (2 * P + 1) & Exp_msk1 {
686				if L > (P + 2) * Exp_msk1 {
687					// round even ==>
688					// accept rv
689					return false;
690				}
691				// rv = smallest denormal
692				self.rv.d = 0_f64;
693				return true;
694			}
695		}
696		
697		let L = (self.rv.word0() & Exp_mask) - Exp_msk1;
698		
699		self.rv.set_word0(L | Bndry_mask1);
700		self.rv.set_word1(0xffffffff);
701		
702		false
703	}
704}
705
706#[derive(Copy, Clone)]
707struct U {
708	d: f64
709}
710
711impl U {
712	fn word0(&self) -> u32 {
713		let words = unsafe { transmute::<_, [u32; 2]>(self.d) };
714		
715		if cfg!(target_endian = "little") {
716			words[1]
717		} else {
718			words[0]
719		}
720	}
721	
722	fn set_word0(&mut self, word: u32) {
723		let mut words = unsafe { transmute::<_, [u32; 2]>(self.d) };
724		
725		if cfg!(target_endian = "little") {
726			words[1] = word;
727		} else {
728			words[0] = word;
729		}
730		
731		self.d = unsafe { transmute(words) };
732	}
733	
734	fn word1(&self) -> u32 {
735		let words = unsafe { transmute::<_, [u32; 2]>(self.d) };
736		
737		if cfg!(target_endian = "little") {
738			words[0]
739		} else {
740			words[1]
741		}
742	}
743	
744	fn set_word1(&mut self, word: u32) {
745		let mut words = unsafe { transmute::<_, [u32; 2]>(self.d) };
746		
747		if cfg!(target_endian = "little") {
748			words[0] = word;
749		} else {
750			words[1] = word;
751		}
752		
753		self.d = unsafe { transmute(words) };
754	}
755}
756
757#[derive(Clone)]
758struct BigInt {
759	sign: bool,
760	x: Vec<u32>
761}
762
763impl BigInt {
764	fn new() -> BigInt {
765		BigInt {
766			sign: false,
767			x: Vec::new()
768		}
769	}
770	
771	fn trim(&mut self) {
772		while self.x.len() > 1 {
773			if self.x[self.x.len() - 1] == 0 {
774				self.x.pop();
775			} else {
776				break;
777			}
778		}
779	}
780}
781
782fn ulp(x: U) -> f64 {
783	let L = (x.word0() & Exp_mask) - (P - 1) * Exp_msk1;
784	let mut a = U { d: 0_f64 };
785	a.set_word0(L);
786	a.set_word1(0);
787	a.d
788}
789
790fn ratio(a: &BigInt, b: &BigInt) -> f64 {
791	let (da, ka) = b2d(a);
792	let mut da = U { d: da };
793	let (db, kb) = b2d(b);
794	let mut db = U { d: db };
795	
796	let mut k = ka - kb + 32 * (a.x.len() - b.x.len()) as i32;
797	
798	if k > 0 {
799		let w = da.word0() + k as u32 * Exp_msk1;
800		da.set_word0(w);
801	} else {
802		k = -k;
803		let w = db.word0() + k as u32 * Exp_msk1;
804		db.set_word0(w);
805	}
806	
807	da.d / db.d
808}
809
810fn b2d(a: &BigInt) -> (f64, i32) {
811	let xa0 = 0;
812	let mut xa = xa0 + a.x.len() - 1;
813	let mut y = a.x[xa];
814	let mut k = hi0bits(y);
815	let e = 32 - k as i32;
816	
817	let mut d = U { d: 0_f64 };
818	
819	if k < Ebits {
820		d.set_word0(Exp_1 | y >> (Ebits - k));
821		let w = if xa > xa0 {
822			xa -= 1;
823			a.x[xa]
824		} else {
825			0
826		};
827		d.set_word1(y << ((32-Ebits) + k) | w >> (Ebits - k));
828		return (d.d, e);
829	}
830	
831	let z = if xa > xa0 {
832		xa -= 1;
833		a.x[xa]
834	} else {
835		0
836	};
837	
838	k -= Ebits;
839	if k != 0 {
840		d.set_word0(Exp_1 | y << k | z >> (32 - k));
841		y = if xa > xa0 {
842			xa -= 1;
843			a.x[xa]
844		} else {
845			0
846		};
847		d.set_word1(z << k | y >> (32 - k));
848	} else {
849		d.set_word0(Exp_1 | y);
850		d.set_word1(z);
851	}
852
853	(d.d, e)
854}
855
856fn hi0bits(mut x: u32) -> u32 {
857	let mut k = 0;
858
859	if x & 0xffff0000 == 0 {
860		k = 16;
861		x <<= 16;
862	}
863	if x & 0xff000000 == 0 {
864		k += 8;
865		x <<= 8;
866	}
867	if x & 0xf0000000 == 0 {
868		k += 4;
869		x <<= 4;
870	}
871	if x & 0xc0000000 == 0 {
872		k += 2;
873		x <<= 2;
874	}
875	if x & 0x80000000 == 0 {
876		k += 1;
877		if x & 0x40000000 == 0 {
878			return 32;
879		}
880	}
881	return k;
882}
883
884fn s2b(mut s: Chars, nd0: u32, nd: u32, y9: u32) -> BigInt {
885	let mut b = BigInt::new();
886	b.x.push(y9);
887
888	let mut i = 9;
889	if 9 < nd0 {
890		s.offset += 9;
891		
892		loop {
893			let c = s.peek();
894			s.bump();
895			
896			multadd(&mut b, 10, c - C0);
897			
898			i += 1;
899			if i >= nd0 {
900				break;
901			}
902		}
903		
904		s.bump();
905	} else {
906		s.offset += 10;
907	}
908	
909	while i < nd {
910		let c = s.peek();
911		s.bump();
912		
913		multadd(&mut b, 10, c - C0);
914		i += 1;
915	}
916	
917	b
918}
919
920fn multadd(b: &mut BigInt, m: i32, a: u32) { // multiply by m and add a
921	let mut carry = a;
922	
923	for x in 0..b.x.len() {
924		let y = b.x[x] as u64 * m as u64 + carry as u64;
925		carry = (y >> 32) as u32;
926		b.x[x] = y as u32 & 0xffffffff;
927	}
928	
929	if carry != 0 {
930		b.x.push(carry as u32);
931	}
932}
933
934fn d2b(mut d: U) -> (BigInt, i32, u32) {
935	let mut b = BigInt::new();
936
937	let mut z = d.word0() & Frac_mask;
938	let w = d.word0() & 0x7fffffff;
939	d.set_word0(w); // clear sign bit, which we ignore
940	let de = d.word0() >> Exp_shift;
941	if de != 0 {
942		z |= Exp_msk1;
943	}
944	
945	let mut y = d.word1();
946	let mut k;
947	
948	if y != 0 {
949		k = lo0bits(&mut y);
950		if k != 0 {
951			b.x.push(y | z << (32 - k));
952			z >>= k;
953		} else {
954			b.x.push(y);
955		}
956		if z != 0 {
957			b.x.push(z);
958		}
959	} else {
960		k = lo0bits(&mut z);
961		b.x.push(z);
962		k += 32;
963	}
964	
965	let e;
966	let bits;
967	
968	if de != 0 {
969		e = de as i32 - Bias - (P - 1) as i32 + k as i32;
970		bits = P - k;
971	} else {
972		e = de as i32 - Bias - (P - 1) as i32 + 1 + k as i32;
973		bits = 32 * b.x.len() as u32 - hi0bits(b.x[b.x.len() - 1]);
974	}
975	
976	(b, e, bits)
977}
978
979fn lo0bits(y: &mut u32) -> u32 {
980	let mut x = *y;
981
982	if x & 7 != 0 {
983		if x & 1 != 0 {
984			return 0;
985		}
986		if x & 2 != 0 {
987			*y = x >> 1;
988			return 1;
989		}
990		*y = x >> 2;
991		return 2;
992	}
993	let mut k = 0;
994	if x & 0xffff == 0 {
995		k = 16;
996		x >>= 16;
997	}
998	if x & 0xff == 0 {
999		k += 8;
1000		x >>= 8;
1001	}
1002	if x & 0xf == 0 {
1003		k += 4;
1004		x >>= 4;
1005	}
1006	if x & 0x3 == 0 {
1007		k += 2;
1008		x >>= 2;
1009	}
1010	if x & 1 == 0 {
1011		k += 1;
1012		x >>= 1;
1013		if x == 0 {
1014			return 32;
1015		}
1016	}
1017	
1018	*y = x;
1019	
1020	k
1021}
1022
1023fn i2b(i: u32) -> BigInt {
1024	let mut b = BigInt::new();
1025	b.x.push(i);
1026	b
1027}
1028
1029static p05 : [u32; 3] = [ 5, 25, 125 ];
1030
1031fn pow5mult(mut b: BigInt, mut k: i32) -> BigInt {
1032	let i = k & 3;
1033	if i != 0 {
1034		multadd(&mut b, p05[i as usize - 1] as i32, 0);
1035	}
1036	
1037	k >>= 2;
1038	if k == 0 {
1039		return b;
1040	}
1041	
1042	let mut p5 = i2b(625);
1043	
1044	loop {
1045		if k & 1 != 0 {
1046			b = mult(&b, &p5);
1047		}
1048		k >>= 1;
1049		if k == 0 {
1050			break;
1051		}
1052		
1053		p5 = mult(&p5, &p5);
1054	}
1055	
1056	b
1057}
1058
1059fn mult<'a>(mut a: &'a BigInt, mut b: &'a BigInt) -> BigInt {
1060	if a.x.len() < b.x.len() {
1061		let c = a;
1062		a = b;
1063		b = c;
1064	}
1065	
1066	let wa = a.x.len();
1067	let wb = b.x.len();
1068	let wc = wa + wb;
1069	let mut c = BigInt::new();
1070	for _ in 0..wc {
1071		c.x.push(0);
1072	}
1073	let xa = 0;
1074	let xae = wa;
1075	let mut xb = 0;
1076	let xbe = wb;
1077	let mut xc0 = 0;
1078	
1079	while xb < xbe {
1080		let y = b.x[xb];
1081		xb += 1;
1082		if y != 0 {
1083			let mut x = xa;
1084			let mut xc = xc0;
1085			let mut carry = 0;
1086			
1087			loop {
1088				let z = a.x[x] as u64 * y as u64 + c.x[xc] as u64 + carry;
1089				x += 1;
1090				carry = z >> 32;
1091				c.x[xc] = z as u32 & 0xffffffff;
1092				xc += 1;
1093				
1094				if x >= xae {
1095					break;
1096				}
1097			}
1098			
1099			c.x[xc] = carry as u32;
1100		}
1101		
1102		xc0 += 1;
1103	}
1104	
1105	c.trim();
1106	
1107	c
1108}
1109
1110fn lshift(b: &BigInt, k: i32) -> BigInt {
1111	let mut b1 = BigInt::new();
1112	for _ in 0..(k >> 5) {
1113		b1.x.push(0);
1114	}
1115	
1116	let k = k & 0x1f;
1117	
1118	if k != 0 {
1119		let k1 = 32 - k;
1120		let mut z = 0;
1121		
1122		for x in 0..b.x.len() {
1123			b1.x.push(b.x[x] << k | z);
1124			z = b.x[x] >> k1;
1125		}
1126		
1127		b1.x.push(z);
1128	} else {
1129		for x in 0..b.x.len() {
1130			b1.x.push(b.x[x]);
1131		}
1132	}
1133	
1134	b1.trim();
1135	
1136	b1
1137}
1138
1139fn diff<'a>(mut a: &'a BigInt, mut b: &'a BigInt) -> BigInt {
1140	let mut i = cmp(a, b);
1141	if i == 0 {
1142		let mut c = BigInt::new();
1143		c.x.push(0);
1144		return c;
1145	}
1146	
1147	if i < 0 {
1148		let c = a;
1149		a = b;
1150		b = c;
1151		i = 1;
1152	} else {
1153		i = 0;
1154	}
1155	
1156	let mut c = BigInt::new();
1157	c.sign = i != 0;
1158	let mut borrow = 0;
1159	let mut xa = 0;
1160	
1161	for xb in 0..b.x.len() {
1162		let y = Wrapping(a.x[xa] as u64) - Wrapping(b.x[xb] as u64) - Wrapping(borrow as u64);
1163		xa += 1;
1164		
1165		borrow = (y.0 >> 32) as u32 & 1;
1166		c.x.push((y.0 & 0xffffffff) as u32);
1167	}
1168	
1169	for xa in xa..a.x.len() {
1170		let y = Wrapping(a.x[xa] as u64) - Wrapping(borrow as u64);
1171		borrow = (y.0 >> 32) as u32 & 1;
1172		c.x.push(y.0 as u32 & 0xffffffff);
1173	}
1174	
1175	c.trim();
1176	
1177	c
1178}
1179
1180fn cmp<'a>(a: &'a BigInt, b: &'a BigInt) -> i32 {
1181	let mut i = a.x.len() as i32;
1182	let j = b.x.len() as i32;
1183	i -= j;
1184	if i != 0 {
1185		return i;
1186	}
1187	
1188	for x in (0..j as usize).rev() {
1189		if a.x[x] != b.x[x] {
1190			return if a.x[x] < b.x[x] { -1 } else { 1 };
1191		}
1192	}
1193	
1194	0
1195}
1196
1197#[cfg(test)]
1198mod test {
1199	#![allow(overflowing_literals)]
1200	
1201	use super::strtod;
1202	use std::f64;
1203	
1204	#[test]
1205	pub fn tests() {
1206	    test("12.345", Some(12.345));
1207		test("12.345e19", Some(12.345e19));
1208		test("-.1e+9", Some(-0.1e+9));
1209		test(".125", Some(0.125));
1210		test("1e20", Some(1e20));
1211		test("0e-19", Some(0.0));
1212		test("4\00012", Some(4.0));
1213		test("5.9e-76", Some(5.9e-76));
1214		test("Inf", None);
1215		test("-Inf", None);
1216		test("+InFiNiTy", None);
1217		test("1e-324", Some(0.0));
1218		test("+1.000000000116415321826934814453125", Some(1.000000000116415321826934814453125));
1219		test("42.0000000000000000001", Some(42.0000000000000000001));
1220		test("42.00000000000000000001", Some(42.00000000000000000001));
1221		test("42.000000000000000000001", Some(42.000000000000000000001));
1222		test("179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368", Some(179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000));
1223		test(".y", Some(0.0));
1224		test("0.y", Some(0.0));
1225		test(".0y", Some(0.0));
1226		test("000,,,e1", Some(0.0));
1227		test("000e1", Some(0.0));
1228		test("000,1e1", Some(0.0));
1229		test("0", Some(0.0));
1230		test("000", Some(0.0));
1231		test("-0", Some(-0.0));
1232		test("-000", Some(-0.0));
1233		test("0,", Some(0.0));
1234		test("-0,", Some(-0.0));
1235		test("0,0", Some(0.0));
1236		test("-0,0", Some(-0.0));
1237		test("0e-10", Some(0.0));
1238		test("-0e-10", Some(-0.0));
1239		test("0,e-10", Some(0.0));
1240		test("-0,e-10", Some(-0.0));
1241		test("0,0e-10", Some(0.0));
1242		test("-0,0e-10", Some(-0.0));
1243		test("0e-1000000", Some(0.0));
1244		test("-0e-1000000", Some(-0.0));
1245		test("0,0e-1000000", Some(0.0));
1246		test("-0,0e-1000000", Some(-0.0));
1247		test("0", Some(0.0));
1248		test("000", Some(0.0));
1249		test("-0", Some(-0.0));
1250		test("-000", Some(-0.0));
1251		test("0e-10", Some(0.0));
1252		test("-0e-10", Some(-0.0));
1253		test("0e-1000000", Some(0.0));
1254		test("-0e-1000000", Some(-0.0));
1255		test("1", Some(1_f64));
1256		test("1.1", Some(1.1));
1257		test("1.1e1", Some(1.1e1));
1258		test("1234.1234", Some(1234.1234));
1259		test("1234.12345678", Some(1234.12345678));
1260		test("1234.123456789012", Some(1234.123456789012));
1261		test("1.797693134862315708145274237317e+10", Some(1.797693134862315708145274237317e+10));
1262		test("1.797693134862315708145274237317e+308", Some(1.797693134862315708145274237317e+308_f64));
1263		test("000000000e123", Some(0.0));
1264		test("0000000010000e-329", Some(0.0));
1265		test("000000001e-325", Some(0.0));
1266		test("0000000020000e-328", Some(0.0));
1267		test("0000000090000e-329", Some(0.0));
1268		test("0e+999", Some(0.0));
1269		test("0e1", Some(0.0));
1270		test("0e12345", Some(0.0));
1271		test("0e2", Some(0.0));
1272		test("0e-2", Some(0.0));
1273		test("0e-999", Some(0.0));
1274		test("10000e-329", Some(0.0));
1275		test("1e-325", Some(0.0));
1276		test("20000e-328", Some(0.0));
1277		test("2e-324", Some(0.0));
1278		test("90000e-329", Some(0.0));
1279		test("e1324", Some(0.0));
1280		test("1e0", Some(1.0));
1281		test("17976931348623157e292", Some(1.7976931348623157E+308));
1282		test("17976931348623158e292", Some(1.7976931348623158E+308));
1283		test("1e1", Some(10.0));
1284		test("1e2", Some(100.0));
1285		test("10141204801825834086073718800384e0", Some(10141204801825834086073718800384.0));
1286		test("1014120480182583464902367222169599999e-5", Some(10141204801825834086073718800384.0));
1287		test("1014120480182583464902367222169600001e-5", Some(10141204801825835211973625643008.0));
1288		test("10141204801825834649023672221696e0", Some(10141204801825835211973625643008.0));
1289		test("10141204801825835211973625643008e0", Some(10141204801825835211973625643008.0));
1290		test("104110013277974872254e-225", Some(104110013277974872254e-225));
1291		test("12345e0", Some(12345.0));
1292		test("12345e1", Some(123450.0));
1293		test("12345e2", Some(1234500.0));
1294		test("12345678901234e0", Some(12345678901234.0));
1295		test("12345678901234e1", Some(123456789012340.0));
1296		test("12345678901234e2", Some(1234567890123400.0));
1297		test("123456789012345e0", Some(123456789012345.0));
1298		test("123456789012345e1", Some(1234567890123450.0));
1299		test("123456789012345e2", Some(12345678901234500.0));
1300		test("1234567890123456789012345e108", Some(1234567890123456789012345e108));
1301		test("1234567890123456789012345e109", Some(1234567890123456789012345e109));
1302		test("1234567890123456789012345e110", Some(1234567890123456789012345e110));
1303		test("1234567890123456789012345e111", Some(1234567890123456789012345e111));
1304		test("1234567890123456789012345e112", Some(1234567890123456789012345e112));
1305		test("1234567890123456789012345e113", Some(1234567890123456789012345e113));
1306		test("1234567890123456789012345e114", Some(1234567890123456789012345e114));
1307		test("1234567890123456789012345e115", Some(1234567890123456789012345e115));
1308		test("1234567890123456789052345e108", Some(1234567890123456789052345e108));
1309		test("1234567890123456789052345e109", Some(1234567890123456789052345e109));
1310		test("1234567890123456789052345e110", Some(1234567890123456789052345e110));
1311		test("1234567890123456789052345e111", Some(1234567890123456789052345e111));
1312		test("1234567890123456789052345e112", Some(1234567890123456789052345e112));
1313		test("1234567890123456789052345e113", Some(1234567890123456789052345e113));
1314		test("1234567890123456789052345e114", Some(1234567890123456789052345e114));
1315		test("1234567890123456789052345e115", Some(1234567890123456789052345e115));
1316		test("123456789012345e-1", Some(123456789012345e-1));
1317		test("123456789012345e-2", Some(123456789012345e-2));
1318		test("123456789012345e20", Some(123456789012345e20));
1319		test("123456789012345e-20", Some(123456789012345e-20));
1320		test("123456789012345e22", Some(123456789012345e22));
1321		test("123456789012345e-22", Some(123456789012345e-22));
1322		test("123456789012345e23", Some(123456789012345e23));
1323		test("123456789012345e-23", Some(123456789012345e-23));
1324		test("123456789012345e-25", Some(123456789012345e-25));
1325		test("123456789012345e35", Some(123456789012345e35));
1326		test("123456789012345e36", Some(123456789012345e36));
1327		test("123456789012345e37", Some(123456789012345e37));
1328		test("123456789012345e39", Some(123456789012345e39));
1329		test("123456789012345e-39", Some(123456789012345e-39));
1330		test("123456789012345e-5", Some(123456789012345e-5));
1331		test("12345678901234e-1", Some(12345678901234e-1));
1332		test("12345678901234e-2", Some(12345678901234e-2));
1333		test("12345678901234e20", Some(12345678901234e20));
1334		test("12345678901234e-20", Some(12345678901234e-20));
1335		test("12345678901234e22", Some(12345678901234e22));
1336		test("12345678901234e-22", Some(12345678901234e-22));
1337		test("12345678901234e23", Some(12345678901234e23));
1338		test("12345678901234e-23", Some(12345678901234e-23));
1339		test("12345678901234e-25", Some(12345678901234e-25));
1340		test("12345678901234e30", Some(12345678901234e30));
1341		test("12345678901234e31", Some(12345678901234e31));
1342		test("12345678901234e32", Some(12345678901234e32));
1343		test("12345678901234e35", Some(12345678901234e35));
1344		test("12345678901234e36", Some(12345678901234e36));
1345		test("12345678901234e37", Some(12345678901234e37));
1346		test("12345678901234e-39", Some(12345678901234e-39));
1347		test("12345678901234e-5", Some(12345678901234e-5));
1348		test("123456789e108", Some(123456789e108));
1349		test("123456789e109", Some(123456789e109));
1350		test("123456789e110", Some(123456789e110));
1351		test("123456789e111", Some(123456789e111));
1352		test("123456789e112", Some(123456789e112));
1353		test("123456789e113", Some(123456789e113));
1354		test("123456789e114", Some(123456789e114));
1355		test("123456789e115", Some(123456789e115));
1356		test("12345e-1", Some(12345e-1));
1357		test("12345e-2", Some(12345e-2));
1358		test("12345e20", Some(12345e20));
1359		test("12345e-20", Some(12345e-20));
1360		test("12345e22", Some(12345e22));
1361		test("12345e-22", Some(12345e-22));
1362		test("12345e23", Some(12345e23));
1363		test("12345e-23", Some(12345e-23));
1364		test("12345e-25", Some(12345e-25));
1365		test("12345e30", Some(12345e30));
1366		test("12345e31", Some(12345e31));
1367		test("12345e32", Some(12345e32));
1368		test("12345e35", Some(12345e35));
1369		test("12345e36", Some(12345e36));
1370		test("12345e37", Some(12345e37));
1371		test("12345e-39", Some(12345e-39));
1372		test("12345e-5", Some(12345e-5));
1373		test("000000001234e304", Some(1234e304));
1374		test("0000000123400000e299", Some(1234e304));
1375		test("123400000e299", Some(1234e304));
1376		test("1234e304", Some(1234e304));
1377		test("00000000123400000e300", Some(1234e305));
1378		test("00000001234e305", Some(1234e305));
1379		test("123400000e300", Some(1234e305));
1380		test("1234e305", Some(1234e305));
1381		test("00000000170000000e300", Some(17e307));
1382		test("0000000017e307", Some(17e307));
1383		test("170000000e300", Some(17e307));
1384		test("17e307", Some(17e307));
1385		test("1e-1", Some(1e-1));
1386		test("1e-2", Some(1e-2));
1387		test("1e20", Some(1e20));
1388		test("1e-20", Some(1e-20));
1389		test("1e22", Some(1e22));
1390		test("1e-22", Some(1e-22));
1391		test("1e23", Some(1e23));
1392		test("1e-23", Some(1e-23));
1393		test("1e-25", Some(1e-25));
1394		test("000000000000100000e303", Some(1e308));
1395		test("00000001e308", Some(1e308));
1396		test("100000e303", Some(1e308));
1397		test("1e308", Some(1e308));
1398		test("1e35", Some(1e35));
1399		test("1e36", Some(1e36));
1400		test("1e37", Some(1e37));
1401		test("1e-39", Some(1e-39));
1402		test("1e-5", Some(1e-5));
1403		test("2e0", Some(2.0));
1404		test("22250738585072011e-324", Some(2.225073858507201e-308));
1405		test("2e1", Some(20.0));
1406		test("2e2", Some(200.0));
1407		test("2e-1", Some(2e-1));
1408		test("2e-2", Some(2e-2));
1409		test("2e20", Some(2e20));
1410		test("2e-20", Some(2e-20));
1411		test("2e22", Some(2e22));
1412		test("2e-22", Some(2e-22));
1413		test("2e23", Some(2e23));
1414		test("2e-23", Some(2e-23));
1415		test("2e-25", Some(2e-25));
1416		test("2e35", Some(2e35));
1417		test("2e36", Some(2e36));
1418		test("2e37", Some(2e37));
1419		test("2e-39", Some(2e-39));
1420		test("2e-5", Some(2e-5));
1421		test("358416272e-33", Some(358416272e-33));
1422		test("00000030000e-328", Some(40000e-328));
1423		test("30000e-328", Some(40000e-328));
1424		test("3e-324", Some(4e-324));
1425		test("5445618932859895362967233318697132813618813095743952975439298223406969961560047552942717636670910728746893019786283454139917900193169748259349067524939840552682198095012176093045431437495773903922425632551857520884625114624126588173520906670968542074438852601438992904761759703022688483745081090292688986958251711580854575674815074162979705098246243690189880319928315307816832576838178256307401454285988871020923752587330172447966674453785790265533466496640456213871241930958703059911787722565044368663670643970181259143319016472430928902201239474588139233890135329130660705762320235358869874608541509790266400643191187286648422874774910682648288516244021893172769161449825765517353755844373640588822904791244190695299838293263075467057383813882521706545084301049855505888186560731e-1035", Some(5.445618932859895e-255));
1426		test("5708990770823838890407843763683279797179383808e0", Some(5708990770823838890407843763683279797179383808.0));
1427		test("5708990770823839207320493820740630171355185151999e-3", Some(5708990770823838890407843763683279797179383808.0));
1428		test("5708990770823839207320493820740630171355185152001e-3", Some(5708990770823839524233143877797980545530986496.0));
1429		test("5708990770823839207320493820740630171355185152e0", Some(5708990770823839524233143877797980545530986496.0));
1430		test("5708990770823839524233143877797980545530986496e0", Some(5708990770823839524233143877797980545530986496.0));
1431		test("72057594037927928e0", Some(72057594037927928.0));
1432		test("7205759403792793199999e-5", Some(72057594037927928.0));
1433		test("7205759403792793200001e-5", Some(72057594037927936.0));
1434		test("72057594037927932e0", Some(72057594037927936.0));
1435		test("72057594037927936e0", Some(72057594037927936.0));
1436		test("89255e-22", Some(89255e-22));
1437		test("9e0", Some(9.0));
1438		test("9e1", Some(90.0));
1439		test("9e2", Some(900.0));
1440		test("9223372036854774784e0", Some(9223372036854774784.0));
1441		test("922337203685477529599999e-5", Some(9223372036854774784.0));
1442		test("922337203685477529600001e-5", Some(9223372036854775808.0));
1443		test("9223372036854775296e0", Some(9223372036854775808.0));
1444		test("9223372036854775808e0", Some(9223372036854775808.0));
1445		test("9e-1", Some(9e-1));
1446		test("9e-2", Some(9e-2));
1447		test("9e20", Some(9e20));
1448		test("9e-20", Some(9e-20));
1449		test("9e22", Some(9e22));
1450		test("9e-22", Some(9e-22));
1451		test("9e23", Some(9e23));
1452		test("9e-23", Some(9e-23));
1453		test("9e-25", Some(9e-25));
1454		test("9e35", Some(9e35));
1455		test("9e36", Some(9e36));
1456		test("9e37", Some(9e37));
1457		test("9e-39", Some(9e-39));
1458		test("9e-5", Some(9e-5));
1459		test("00000000180000000e300", Some(f64::INFINITY));
1460		test("0000000018e307", Some(f64::INFINITY));
1461		test("00000001000000e303", Some(f64::INFINITY));
1462		test("0000001e309", Some(f64::INFINITY));
1463		test("1000000e303", Some(f64::INFINITY));
1464		test("17976931348623159e292", Some(f64::INFINITY));
1465		test("180000000e300", Some(f64::INFINITY));
1466		test("18e307", Some(f64::INFINITY));
1467		test("1e309", Some(f64::INFINITY));
1468	}
1469	
1470	fn test(input: &str, val: Option<f64>) {
1471		let result = strtod(input);
1472		assert_eq!(result, val);
1473		if result.is_some() {
1474			assert_eq!(result.unwrap().is_sign_positive(), val.unwrap().is_sign_positive());
1475		}
1476	}
1477}