| 
									
										
										
										
											2009-04-11 21:30:51 -04:00
										 |  |  | ! Copyright (C) 2004, 2009 Slava Pestov. | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | ! See http://factorcode.org/license.txt for BSD license. | 
					
						
							| 
									
										
										
										
											2009-04-11 21:30:51 -04:00
										 |  |  | USING: kernel math.private namespaces sequences sequences.private | 
					
						
							| 
									
										
										
										
											2009-05-02 14:45:38 -04:00
										 |  |  | strings arrays combinators splitting math assocs byte-arrays make ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | IN: math.parser | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : digit> ( ch -- n )
 | 
					
						
							| 
									
										
										
										
											2008-02-01 00:00:08 -05:00
										 |  |  |     H{ | 
					
						
							|  |  |  |         { CHAR: 0 0 } | 
					
						
							|  |  |  |         { CHAR: 1 1 } | 
					
						
							|  |  |  |         { CHAR: 2 2 } | 
					
						
							|  |  |  |         { CHAR: 3 3 } | 
					
						
							|  |  |  |         { CHAR: 4 4 } | 
					
						
							|  |  |  |         { CHAR: 5 5 } | 
					
						
							|  |  |  |         { CHAR: 6 6 } | 
					
						
							|  |  |  |         { CHAR: 7 7 } | 
					
						
							|  |  |  |         { CHAR: 8 8 } | 
					
						
							|  |  |  |         { CHAR: 9 9 } | 
					
						
							|  |  |  |         { CHAR: A 10 } | 
					
						
							|  |  |  |         { CHAR: B 11 } | 
					
						
							|  |  |  |         { CHAR: C 12 } | 
					
						
							|  |  |  |         { CHAR: D 13 } | 
					
						
							|  |  |  |         { CHAR: E 14 } | 
					
						
							|  |  |  |         { CHAR: F 15 } | 
					
						
							|  |  |  |         { CHAR: a 10 } | 
					
						
							|  |  |  |         { CHAR: b 11 } | 
					
						
							|  |  |  |         { CHAR: c 12 } | 
					
						
							|  |  |  |         { CHAR: d 13 } | 
					
						
							|  |  |  |         { CHAR: e 14 } | 
					
						
							|  |  |  |         { CHAR: f 15 } | 
					
						
							| 
									
										
										
										
											2009-04-11 21:30:51 -04:00
										 |  |  |     } at 255 or ; inline
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-02-06 21:05:03 -05:00
										 |  |  | : string>digits ( str -- digits )
 | 
					
						
							| 
									
										
										
										
											2009-04-11 21:30:51 -04:00
										 |  |  |     [ digit> ] B{ } map-as ; inline
 | 
					
						
							| 
									
										
										
										
											2008-02-06 21:05:03 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-11 21:30:51 -04:00
										 |  |  | : (digits>integer) ( valid? accum digit radix -- valid? accum )
 | 
					
						
							|  |  |  |     2dup < [ swapd * + ] [ 2drop 2drop f 0 ] if ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : each-digit ( seq radix quot -- n/f )
 | 
					
						
							|  |  |  |     [ t 0 ] 3dip curry each swap [ drop f ] unless ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : digits>integer ( seq radix -- n/f )
 | 
					
						
							|  |  |  |     [ (digits>integer) ] each-digit ; inline
 | 
					
						
							| 
									
										
										
										
											2008-02-06 22:15:47 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-02-06 21:05:03 -05:00
										 |  |  | DEFER: base> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <PRIVATE
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SYMBOL: radix | 
					
						
							| 
									
										
										
										
											2008-02-10 02:40:17 -05:00
										 |  |  | SYMBOL: negative? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-11 21:30:51 -04:00
										 |  |  | : string>natural ( seq radix -- n/f )
 | 
					
						
							| 
									
										
										
										
											2009-04-13 21:25:55 -04:00
										 |  |  |     over empty? [ 2drop f ] [ | 
					
						
							|  |  |  |         [ [ digit> ] dip (digits>integer) ] each-digit | 
					
						
							|  |  |  |     ] if ; inline
 | 
					
						
							| 
									
										
										
										
											2009-04-11 21:30:51 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-08 16:32:55 -04:00
										 |  |  | : sign ( -- str ) negative? get "-" "+" ? ;
 | 
					
						
							| 
									
										
										
										
											2008-02-06 21:05:03 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | : with-radix ( radix quot -- )
 | 
					
						
							|  |  |  |     radix swap with-variable ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : (base>) ( str -- n ) radix get base> ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : whole-part ( str -- m n )
 | 
					
						
							| 
									
										
										
										
											2008-11-23 03:44:56 -05:00
										 |  |  |     sign split1 [ (base>) ] dip
 | 
					
						
							| 
									
										
										
										
											2008-02-06 21:05:03 -05:00
										 |  |  |     dup [ (base>) ] [ drop 0 swap ] if ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-11 21:30:51 -04:00
										 |  |  | : string>ratio ( str radix -- a/b )
 | 
					
						
							|  |  |  |     [ | 
					
						
							|  |  |  |         "-" ?head dup negative? set swap
 | 
					
						
							|  |  |  |         "/" split1 (base>) [ whole-part ] dip
 | 
					
						
							|  |  |  |         3dup and and [ / + swap [ neg ] when ] [ 2drop 2drop f ] if
 | 
					
						
							|  |  |  |     ] with-radix ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-11 21:30:51 -04:00
										 |  |  | : string>integer ( str radix -- n/f )
 | 
					
						
							|  |  |  |     over first-unsafe CHAR: - = [ | 
					
						
							|  |  |  |         [ rest-slice ] dip string>natural dup [ neg ] when
 | 
					
						
							|  |  |  |     ] [ | 
					
						
							|  |  |  |         string>natural | 
					
						
							|  |  |  |     ] if ; inline
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-02 14:45:38 -04:00
										 |  |  | : string>float ( str -- n/f )
 | 
					
						
							|  |  |  |     >byte-array 0 suffix (string>float) ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-02-06 21:05:03 -05:00
										 |  |  | PRIVATE>
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : base> ( str radix -- n/f )
 | 
					
						
							| 
									
										
										
										
											2009-04-11 21:30:51 -04:00
										 |  |  |     over empty? [ 2drop f ] [ | 
					
						
							|  |  |  |         over [ "/." member? ] find nip { | 
					
						
							|  |  |  |             { CHAR: / [ string>ratio ] } | 
					
						
							|  |  |  |             { CHAR: . [ drop string>float ] } | 
					
						
							|  |  |  |             [ drop string>integer ] | 
					
						
							|  |  |  |         } case
 | 
					
						
							|  |  |  |     ] if ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : string>number ( str -- n/f ) 10 base> ;
 | 
					
						
							|  |  |  | : bin> ( str -- n/f ) 2 base> ;
 | 
					
						
							|  |  |  | : oct> ( str -- n/f ) 8 base> ;
 | 
					
						
							|  |  |  | : hex> ( str -- n/f ) 16 base> ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : >digit ( n -- ch )
 | 
					
						
							|  |  |  |     dup 10 < [ CHAR: 0 + ] [ 10 - CHAR: a + ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-27 18:54:44 -04:00
										 |  |  | : positive>base ( num radix -- str )
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  |     dup 1 <= [ "Invalid radix" throw ] when
 | 
					
						
							| 
									
										
										
										
											2009-02-28 16:31:34 -05:00
										 |  |  |     [ dup 0 > ] swap [ /mod >digit ] curry "" produce-as nip
 | 
					
						
							| 
									
										
										
										
											2008-09-27 18:54:44 -04:00
										 |  |  |     dup reverse-here ; inline
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-02-06 21:05:03 -05:00
										 |  |  | PRIVATE>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | GENERIC# >base 1 ( n radix -- str )
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-02-06 21:05:03 -05:00
										 |  |  | <PRIVATE
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-30 19:28:11 -04:00
										 |  |  | : (>base) ( n -- str ) radix get positive>base ;
 | 
					
						
							| 
									
										
										
										
											2008-02-06 21:05:03 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | PRIVATE>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | M: integer >base | 
					
						
							| 
									
										
										
										
											2008-09-27 18:54:44 -04:00
										 |  |  |     over 0 = [ | 
					
						
							|  |  |  |         2drop "0" | 
					
						
							|  |  |  |     ] [ | 
					
						
							|  |  |  |         over 0 > [ | 
					
						
							|  |  |  |             positive>base | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  |         ] [ | 
					
						
							| 
									
										
										
										
											2008-09-27 18:54:44 -04:00
										 |  |  |             [ neg ] dip positive>base CHAR: - prefix
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  |         ] if
 | 
					
						
							| 
									
										
										
										
											2008-09-27 18:54:44 -04:00
										 |  |  |     ] if ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: ratio >base | 
					
						
							|  |  |  |     [ | 
					
						
							| 
									
										
										
										
											2008-09-27 18:54:44 -04:00
										 |  |  |         dup 0 < negative? set
 | 
					
						
							| 
									
										
										
										
											2008-09-30 19:28:11 -04:00
										 |  |  |         abs 1 /mod
 | 
					
						
							| 
									
										
										
										
											2008-09-27 18:54:44 -04:00
										 |  |  |         [ dup zero? [ drop "" ] [ (>base) sign append ] if ] | 
					
						
							| 
									
										
										
										
											2008-02-06 21:05:03 -05:00
										 |  |  |         [ | 
					
						
							| 
									
										
										
										
											2008-09-27 18:54:44 -04:00
										 |  |  |             [ numerator (>base) ] | 
					
						
							|  |  |  |             [ denominator (>base) ] bi
 | 
					
						
							| 
									
										
										
										
											2008-12-03 20:12:48 -05:00
										 |  |  |             "/" glue
 | 
					
						
							| 
									
										
										
										
											2008-09-27 18:54:44 -04:00
										 |  |  |         ] bi* append
 | 
					
						
							|  |  |  |         negative? get [ CHAR: - prefix ] when
 | 
					
						
							| 
									
										
										
										
											2008-02-06 21:05:03 -05:00
										 |  |  |     ] with-radix ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : fix-float ( str -- newstr )
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             [ CHAR: e over member? ] | 
					
						
							| 
									
										
										
										
											2008-11-23 03:44:56 -05:00
										 |  |  |             [ "e" split1 [ fix-float "e" ] dip 3append ] | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  |         } { | 
					
						
							|  |  |  |             [ CHAR: . over member? ] | 
					
						
							|  |  |  |             [ ] | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2008-04-11 13:53:22 -04:00
										 |  |  |         [ ".0" append ] | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  |     } cond ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 14:10:56 -04:00
										 |  |  | : float>string ( n -- str )
 | 
					
						
							| 
									
										
										
										
											2009-05-02 14:45:38 -04:00
										 |  |  |     (float>string) | 
					
						
							|  |  |  |     [ 0 = ] trim-tail >string
 | 
					
						
							|  |  |  |     fix-float ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | M: float >base | 
					
						
							|  |  |  |     drop { | 
					
						
							| 
									
										
										
										
											2009-04-11 21:30:51 -04:00
										 |  |  |         { [ dup fp-nan? ] [ drop "0/0." ] } | 
					
						
							|  |  |  |         { [ dup 1/0. = ] [ drop "1/0." ] } | 
					
						
							|  |  |  |         { [ dup -1/0. = ] [ drop "-1/0." ] } | 
					
						
							| 
									
										
										
										
											2008-08-22 01:32:37 -04:00
										 |  |  |         { [ dup double>bits HEX: 8000000000000000 = ] [ drop "-0.0" ] } | 
					
						
							| 
									
										
										
										
											2009-05-02 14:45:38 -04:00
										 |  |  |         [ float>string ] | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  |     } cond ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : number>string ( n -- str ) 10 >base ;
 | 
					
						
							|  |  |  | : >bin ( n -- str ) 2 >base ;
 | 
					
						
							|  |  |  | : >oct ( n -- str ) 8 >base ;
 | 
					
						
							|  |  |  | : >hex ( n -- str ) 16 >base ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : # ( n -- ) number>string % ;
 |