105 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Factor
		
	
	
		
		
			
		
	
	
			105 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Factor
		
	
	
| 
								 | 
							
								! Copyright (C) 2004, 2007 Slava Pestov.
							 | 
						||
| 
								 | 
							
								! See http://factorcode.org/license.txt for BSD license.
							 | 
						||
| 
								 | 
							
								USING: kernel math.private namespaces sequences strings arrays
							 | 
						||
| 
								 | 
							
								combinators splitting math ;
							 | 
						||
| 
								 | 
							
								IN: math.parser
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								DEFER: base>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: string>ratio ( str radix -- a/b )
							 | 
						||
| 
								 | 
							
								    >r "/" split1 r> tuck base> >r base> r>
							 | 
						||
| 
								 | 
							
								    2dup and [ / ] [ 2drop f ] if ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: digit> ( ch -- n )
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        { [ dup digit?  ] [ CHAR: 0 - ] }
							 | 
						||
| 
								 | 
							
								        { [ dup letter? ] [ CHAR: a - 10 + ] }
							 | 
						||
| 
								 | 
							
								        { [ dup LETTER? ] [ CHAR: A - 10 + ] }
							 | 
						||
| 
								 | 
							
								        { [ t ] [ drop f ] }
							 | 
						||
| 
								 | 
							
								    } cond ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: digits>integer ( radix seq -- n )
							 | 
						||
| 
								 | 
							
								    0 rot [ swapd * + ] curry reduce ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: valid-digits? ( radix seq -- ? )
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        { [ dup empty? ] [ 2drop f ] }
							 | 
						||
| 
								 | 
							
								        { [ f over memq? ] [ 2drop f ] }
							 | 
						||
| 
								 | 
							
								        { [ t ] [ swap [ < ] curry all? ] }
							 | 
						||
| 
								 | 
							
								    } cond ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: string>digits ( str -- digits )
							 | 
						||
| 
								 | 
							
								    [ digit> ] { } map-as ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: string>integer ( str radix -- n/f )
							 | 
						||
| 
								 | 
							
								    swap "-" ?head >r
							 | 
						||
| 
								 | 
							
								    string>digits 2dup valid-digits?
							 | 
						||
| 
								 | 
							
								    [ digits>integer r> [ neg ] when ] [ r> 3drop f ] if ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: base> ( str radix -- n/f )
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        { [ CHAR: / pick member? ] [ string>ratio ] }
							 | 
						||
| 
								 | 
							
								        { [ CHAR: . pick member? ] [ drop string>float ] }
							 | 
						||
| 
								 | 
							
								        { [ t ] [ string>integer ] }
							 | 
						||
| 
								 | 
							
								    } cond ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: 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 ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: integer, ( num radix -- )
							 | 
						||
| 
								 | 
							
								    dup 1 <= [ "Invalid radix" throw ] when
							 | 
						||
| 
								 | 
							
								    dup >r /mod >digit , dup 0 >
							 | 
						||
| 
								 | 
							
								    [ r> integer, ] [ r> 2drop ] if ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								GENERIC# >base 1 ( n radix -- str )
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: integer >base
							 | 
						||
| 
								 | 
							
								    [
							 | 
						||
| 
								 | 
							
								        over 0 < [
							 | 
						||
| 
								 | 
							
								            swap neg swap integer, CHAR: - ,
							 | 
						||
| 
								 | 
							
								        ] [
							 | 
						||
| 
								 | 
							
								            integer,
							 | 
						||
| 
								 | 
							
								        ] if
							 | 
						||
| 
								 | 
							
								    ] "" make reverse ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: ratio >base
							 | 
						||
| 
								 | 
							
								    [
							 | 
						||
| 
								 | 
							
								        over numerator over >base %
							 | 
						||
| 
								 | 
							
								        CHAR: / ,
							 | 
						||
| 
								 | 
							
								        swap denominator swap >base %
							 | 
						||
| 
								 | 
							
								    ] "" make ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								: fix-float ( str -- newstr )
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            [ CHAR: e over member? ]
							 | 
						||
| 
								 | 
							
								            [ "e" split1 >r fix-float "e" r> 3append ]
							 | 
						||
| 
								 | 
							
								        } {
							 | 
						||
| 
								 | 
							
								            [ CHAR: . over member? ]
							 | 
						||
| 
								 | 
							
								            [ ]
							 | 
						||
| 
								 | 
							
								        } {
							 | 
						||
| 
								 | 
							
								            [ t ]
							 | 
						||
| 
								 | 
							
								            [ ".0" append ]
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    } cond ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								M: float >base
							 | 
						||
| 
								 | 
							
								    drop {
							 | 
						||
| 
								 | 
							
								        { [ dup 1.0/0.0 = ] [ drop "1.0/0.0" ] }
							 | 
						||
| 
								 | 
							
								        { [ dup -1.0/0.0 = ] [ drop "-1.0/0.0" ] }
							 | 
						||
| 
								 | 
							
								        { [ dup fp-nan? ] [ drop "0.0/0.0" ] }
							 | 
						||
| 
								 | 
							
								        { [ t ] [ float>string fix-float ] }
							 | 
						||
| 
								 | 
							
								    } 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 % ;
							 |