%%HP: T(3)A(R)F(.); \<< DUP TYPE IF DUP 28. == THEN DROP I\->R IF DUPDUP 1. < SWAP 3999. > OR THEN "Bad Range: " SWAP \->STR + DOERR END 0. ELSE CASE DUP 2. == THEN END DUP 6. == THEN SWAP \->STR DUP SIZE 1. - 2. SWAP SUB SWAP END DROP "Bad Argument: " SWAP + DOERR END END "IVXLCDM" \-> sromt \<< IF THEN { 1. 5. 10. 50. 100. 500. 1000. } { } \-> svalt result \<< DO DUP HEAD sromt SWAP POS DUP IF NOT THEN DROP "Unknown Digit: " SWAP + DOERR END svalt SWAP GET \-> cval \<< 'result' cval STO+ result 1. \<< ABS cval < \>> DOLIST 0. + \GSLIST DUP IF 2. \>= THEN DROP "Unexpected Digit: " SWAP + DOERR END IF THEN 'result' result SIZE 1. - DUP2 GET NEG PUT END \>> UNTIL TAIL DUP SIZE NOT END DROP result 0. + \GSLIST R\->I \>> ELSE 1000. sromt SIZE "" \-> divisor sidx result \<< DO DUP divisor / IP DUP UNROT divisor * - SWAP IF DUPDUP 4. == SWAP 9. == OR THEN 'result' sromt sidx DUP SUB STO+ 'result' sromt ROT 9. == 1. + sidx + DUP SUB STO+ ELSE WHILE DUP REPEAT sidx OVER IF 5. \>= THEN 1. + SWAP 4. - SWAP END DUP sromt UNROT SUB 'result' SWAP STO+ 1. - END DROP END 'sidx' 2. STO- UNTIL divisor 10. / IP DUP 'divisor' STO NOT END DROP result \>> END \>> \>>