On Monday, March 27, 2017 at 11:33:50 PM UTC-7, lehs wrote:
> Den tisdag 28 mars 2017 kl. 01:44:40 UTC+2 skrev Albert van der Horst:
> > Get rid of the u. They are numbers.
> > When was the last time that you had a number between
> > 18446744073709551615 and half of that?
>
> No, I focus on unsigned integers.
>
> \ Unsigned integer number theory basicsinglext.4th
> \
> \ isprime \ u -- flag
> \ nextprime \ u -- p
> \ primefactors \ u -- q1 q2 ... qn n
> \ radical \ n -- r
> \ totients \ n -- t
> \ mobius \ n -- m
> \ bigomega \ n -- b
> \ smallomega \ n -- s
> \ legendre \ a p -- i
> \ tau \ u -- n The number of divisors of u
> \ sigma \ u -- s The sum of all divisors of u
> \ choose \ n k -- nCk
> \ sqrtf \ u -- floor
> \ log~ \ n -- 1+log n
> \ umin \ u1 u2 -- u
> \ umax \ u1 u2 -- u
> \ umod \ u q -- u(mod q)
> \ ugcd \ u1 u2 -- u
> \ u*mod \ u1 u2 u3 -- u1*u2(mod u3)
> \ u**mod \ b a m -- b^a(mod m)
>
>
https://github.com/Lehs/ANS-Forth-libraries
I have double-precision GCD etc. in the novice-package.
I have CF.4TH in the novice-package that calculates continued fractions. This was written by Nathaniel Grosman in a "Forth Dimensions" article for 16-bit Forth-83 --- I upgraded it slightly to work under 32-bit ANS-Forth.
Porting this to ANS-Forth was one of my very first ANS-Forth efforts. Elizabeth Rather told me that I can never be a Forth programmer because I complained about the lack of double-precision division in ANS-Forth.
Here is the first half of the CF.4TH code:
-------------------------------------------------------------------------
\ ******
\ ****** This is the first section, which provides UD/MOD.
\ ******
: LPswap ( d1 d2 d3 d4 -- d3 d4 d1 d2 )
>r >r 2swap >r >r 2swap r> r> r> r> 2swap
>r >r 2swap r> r> ;
: LPdup ( d1 d2 -- d1 d2 d1 d2 )
2dup >r >r 2over r> r> ;
: LPover ( d1 d2 d3 d4 -- d1 d2 d3 d4 d1 d2 )
>r >r >r >r LPdup r> r> r> r> LPswap ;
: LProt ( d1 d2 d3 d4 d5 d6 -- d3 d4 d5 d6 d1 d2 )
>r >r >r >r LPswap r> r> r> r> LPswap ;
: LPdrop ( d1 d2 -- )
drop drop drop drop ;
: um/ ( ud un -- un ) \ divide UD by UN and drop remainder
um/mod swap drop ;
: u*/ ( Umultiplier Udividend Udivisor -- Uquotient )
>r um* r> um/mod nip ;
: t* ( ud un -- ut )
dup rot um* >r >r
um*
0 r> r> d+ ;
: t/ ( ut un -- ud )
>r r@ um/mod swap
rot 0 r@ um/mod swap
rot r> um/mod swap drop
0 2swap swap d+ ;
: ut*/ ( ud un un -- ud ) \ this was called U*/ in Grossman's article, but I'm already using that name
>r t* r> t/ ;
: d- ( d1 d2 -- d1-d2 )
dnegate d+ ;
: narrow-ud/mod ( UDividend UNdivisor -- UDremainder UDquotient )
drop >r 2dup r@ \ shuck high cell of divisor
1 swap ut*/ \ -- UDquotient
2swap 2over r> 1 ut*/ d- 2swap ; \ -- UDrem UDquot
variable numH
variable denH
variable denL
variable denscale
2variable num
2variable den
0 1 2constant superbase \ this was 65536. in Grossman's article
: us>d \ convert unsigned single-cell to double-cell
0 ;
: ud/mod-tuck ( ud ud -- ) \ save parts of num and den
2dup den 2! denH ! denL !
2dup num 2! numH ! drop ;
: ud/mod-denscale ( -- un ) \ for scaling-up den
superbase denH @ 1+ um/
denscale ! ;
: scale-den ( -- ) \ multiply denominator by scale factor
den 2@ denscale @ 1 ut*/
denH ! denL ! ;
: wide-quot ( -- ud ) \ if divisor needs more than one cell
num 2@ numH @ us>d
denL @ denH @ ut*/ d-
denscale @ denH @ ut*/ swap drop ;
: ?narrow-divisor ( d -- ? ) \ is divisor < superbase?
dup 0= ;
: wide-rem ( -- ud ) \ remainder in wide division
dup num 2@ rot den 2@
rot 1 ut*/ d- rot us>d ;
: wide-ud/mod ( UDdividend UDdivisor -- UDremainder UDquotient )
ud/mod-tuck
ud/mod-denscale
scale-den
wide-quot
wide-rem ;
: ud/mod ( UDdividend UDdivisor -- UDremainder UDquotient )
?narrow-divisor if narrow-ud/mod
else wide-ud/mod then ;
: udmod ( UDdividend UDdivisor -- UDremainder )
ud/mod 2drop ;
: ud/ ( UDdividend UDdivisor -- UDquotient )
ud/mod 2swap 2drop ;