Annotation of freem/mlib/%ulmath.m, revision 1.1

1.1     ! snw         1: %ulmath ; MATH library - version 0.5.0.1
        !             2:  ;
        !             3:  ; Unless otherwise noted, the code below
        !             4:  ; was approved in document X11/95-11
        !             5:  ;
        !             6:  ; CORRECTION INFORMATION
        !             7:  ; Due to the overall routine size this has not been provided
        !             8:  ; It is available from Ed de Moel who provided these functions
        !             9:  ;
        !            10: ABS(X) Quit $Translate(+X,"-")
        !            11:  ;===
        !            12:  ;
        !            13:  ;
        !            14: %ARCCOS(X) ;
        !            15:  ;
        !            16:  New A,N,R,SIGN,XX
        !            17:  If X<-1 Set $Ecode=",M28,"
        !            18:  If X>1 Set $Ecode=",M28,"
        !            19:  Set SIGN=1 Set:X<0 X=-X,SIGN=-1
        !            20:  Set A(0)=1.5707963050,A(1)=-0.2145988016,A(2)=0.0889789874
        !            21:  Set A(3)=-0.0501743046,A(4)=0.0308918810,A(5)=-0.0170881256
        !            22:  Set A(6)=0.0066700901,A(7)=-0.0012624911
        !            23:  Set R=A(0),XX=1 For N=1:1:7 Set XX=XX*X,R=A(N)*XX+R
        !            24:  ;
        !            25:  Set R=$$SQRT(1-X,11)*R
        !            26:  ;;;
        !            27:  ;
        !            28:  Quit R*SIGN
        !            29:  ;===
        !            30:  ;
        !            31:  ;
        !            32: ARCCOS(X,PREC) ;
        !            33:  I '$D(PREC) Q $$%ARCCOS(X)
        !            34:  ;
        !            35:  New L,LIM,K,SIG,SIGS,VALUE
        !            36:  ;;;
        !            37:  ;
        !            38:  If X<-1 Set $Ecode=",M28,"
        !            39:  If X>1 Set $Ecode=",M28,"
        !            40:  Set PREC=$Get(PREC,11)
        !            41:  ;
        !            42:  If $Translate(X,"-")=1 Quit 0
        !            43:  ;;;
        !            44:  ;
        !            45:  Set SIG=$Select(X<0:-1,1:1),VALUE=1-(X*X)
        !            46:  ;
        !            47:  Set X=$$SQRT(VALUE,PREC)
        !            48:  ;;;
        !            49:  ;
        !            50:  If $Translate(X,"-")=1 Do  Quit VALUE
        !            51:  . ;;;
        !            52:  . ;
        !            53:  . Set VALUE=$$PI()/2*X
        !            54:  . Quit
        !            55:  ;
        !            56:  If X>0.9 Do  Quit VALUE
        !            57:  . ;;;
        !            58:  . ;
        !            59:  . Set SIGS=$Select(X<0:-1,1:1)
        !            60:  . Set VALUE=1/(1/X/X-1)
        !            61:  . ;
        !            62:  . Set X=$$SQRT(VALUE,PREC)
        !            63:  . ;;;
        !            64:  . ;
        !            65:  . ;
        !            66:  . Set VALUE=$$ARCTAN(X,PREC)*SIGS
        !            67:  . ;;;
        !            68:  ;
        !            69:  . Quit
        !            70:  Set (VALUE,L)=X
        !            71:  Set LIM=$Select((PREC+3)'>11:PREC+3,1:11),@("LIM=1E-"_LIM)
        !            72:  For K=3:2 Do  Quit:($Translate(L,"-")<LIM)
        !            73:  . Set L=L*X*X*(K-2)/(K-1)*(K-2)/K,VALUE=VALUE+L
        !            74:  . Quit
        !            75:  Quit $Select(SIG<0:$$PI()-VALUE,1:VALUE)
        !            76:  ;===
        !            77:  ;
        !            78:  ;
        !            79: ARCCOSH(X,PREC) ;
        !            80:  If X<1 Set $Ecode=",M28,"
        !            81:  New SQ
        !            82:  ;
        !            83:  Set PREC=$Get(PREC,11)
        !            84:  ;;;
        !            85:  ;
        !            86:  Set SQ=$$SQRT(X*X-1,PREC)
        !            87:  Quit $$LOG(X+SQ,PREC)
        !            88:  ;===
        !            89:  ;
        !            90:  ;
        !            91: ARCCOT(X,PREC) ;
        !            92:  Set PREC=$Get(PREC,11)
        !            93:  Set X=1/X
        !            94:  Quit $$ARCTAN(X,PREC)
        !            95:  ;===
        !            96:  ;
        !            97:  ;
        !            98: ARCCOTH(X,PREC) ;
        !            99:  New L1,L2
        !           100:  ;
        !           101:  Set PREC=$Get(PREC,11)
        !           102:  ;;;
        !           103:  ;
        !           104:  Set L1=$$LOG(X+1,PREC)
        !           105:  Set L2=$$LOG(X-1,PREC)
        !           106:  Quit L1-L2/2
        !           107:  ;===
        !           108:  ;
        !           109:  ;
        !           110: ARCCSC(X,PREC) ;
        !           111:  Set PREC=$Get(PREC,11)
        !           112:  Set X=1/X
        !           113:  Quit $$ARCSIN(X,PREC)
        !           114:  ;===
        !           115:  ;
        !           116:  ;
        !           117: ARCSEC(X,PREC) ;
        !           118:  Set PREC=$Get(PREC,11)
        !           119:  Set X=1/X
        !           120:  Quit $$ARCCOS(X,PREC)
        !           121:  ;===
        !           122:  ;
        !           123:  ;
        !           124: %ARCSIN(X) ;
        !           125:  ;;; ;                                                                 Number ~~
        !           126:  ; Winfried Gerum (8 June 1995)
        !           127:  ;
        !           128:  New A,N,R,SIGN,XX
        !           129:  If X<-1 Set $Ecode=",M28,"
        !           130:  If X>1 Set $Ecode=",M28,"
        !           131:  Set SIGN=1 Set:X<0 X=-X,SIGN=-1
        !           132:  Set A(0)=1.5707963050,A(1)=-0.2145988016,A(2)=0.0889789874
        !           133:  Set A(3)=-0.0501743046,A(4)=0.0308918810,A(5)=-0.0170881256
        !           134:  Set A(6)=0.0066700901,A(7)=-0.0012624911
        !           135:  Set R=A(0),XX=1 For N=1:1:7 Set XX=XX*X,R=A(N)*XX+R
        !           136:  ;
        !           137:  Set R=$$SQRT(1-X,11)*R
        !           138:  ;;;
        !           139:  ;
        !           140:  Set R=$$PI()/2-R
        !           141:  Quit R*SIGN
        !           142:  ;===
        !           143:  ;
        !           144:  ;
        !           145: ARCSIN(X,PREC) ;
        !           146:  I '$D(PREC) Q $$%ARCSIN(X)
        !           147:  New L,LIM,K,SIGS,VALUE
        !           148:  Set PREC=$Get(PREC,11)
        !           149:  ;
        !           150:  If $Translate(X,"-")=1 Do  Quit VALUE
        !           151:  . ;;;
        !           152:  . ;
        !           153:  . Set VALUE=$$PI()/2*X
        !           154:  . Quit
        !           155:  ;
        !           156:  If X>0.99999 Do  Quit VALUE
        !           157:  . ;;;
        !           158:  . ;
        !           159:  . Set SIGS=$Select(X<0:-1,1:1)
        !           160:  . Set VALUE=1/(1/X/X-1)
        !           161:  . ;
        !           162:  . ;;;
        !           163:  . ;
        !           164:  . Set VALUE=$$ARCTAN(X,PREC)*SIGS
        !           165:  . ;;;
        !           166:  . ;
        !           167:  . Quit
        !           168:  Set (VALUE,L)=X
        !           169:  Set LIM=$Select((PREC+3)'>11:PREC+3,1:11),@("LIM=1E-"_LIM)
        !           170:  For K=3:2 Do  Quit:($Translate(L,"-")<LIM)
        !           171:  . Set L=L*X*X*(K-2)/(K-1)*(K-2)/K,VALUE=VALUE+L
        !           172:  . Quit
        !           173:  Quit VALUE
        !           174:  ;===
        !           175:  ;
        !           176:  ;
        !           177: ARCSINH(X,PREC) ;
        !           178:  If X<1 Set $Ecode=",M28,"
        !           179:  New SQ
        !           180:  ;
        !           181:  Set PREC=$Get(PREC,11)
        !           182:  ;;;
        !           183:  ;
        !           184:  Set SQ=$$SQRT(X*X+1,PREC)
        !           185:  Quit $$LOG(X+SQ,PREC)
        !           186:  ;===
        !           187:  ;
        !           188:  ;
        !           189: ARCTAN(X,PREC) ;
        !           190:  New FOLD,HI,L,LIM,LO,K,SIGN,SIGS,SIGT,VALUE
        !           191:  Set PREC=$Get(PREC,11)
        !           192:  Set LO=0.0000000001,HI=9999999999
        !           193:  Set SIGT=$Select(X<0:-1,1:1),X=$Translate(X,"-")
        !           194:  Set X=$Select(X<LO:LO,X>HI:HI,1:X)
        !           195:  ;
        !           196:  Set FOLD=$Select(X'<1:0,1:1)
        !           197:  ;;;
        !           198:  ;
        !           199:  Set X=$Select(FOLD:1/X,1:X)
        !           200:  Set L=X,VALUE=$$PI()/2-(1/X),SIGN=1
        !           201:  ;
        !           202:  If X<1.3 Do  Quit VALUE
        !           203:  . ;;;
        !           204:  . ;
        !           205:  . Set X=$Select(FOLD:1/X,1:X),VALUE=1/((1/X/X)+1)
        !           206:  . ;
        !           207:  . Set X=$$SQRT(VALUE,PREC)
        !           208:  . ;;;
        !           209:  . ;
        !           210:  . If $Translate(X,"-")=1 Do  Quit
        !           211:  . . Set VALUE=$$PI()/2*X
        !           212:  . . Quit
        !           213:  . If X>0.9 Do  Quit
        !           214:  . . Set SIGS=$Select(X<0:-1,1:1)
        !           215:  . . Set VALUE=1/(1/X/X-1)
        !           216:  . . Set X=$$SQRT(VALUE)
        !           217:  . . Set VALUE=$$ARCTAN(X,10)
        !           218:  . . Set VALUE=VALUE*SIGS
        !           219:  . . Quit
        !           220:  . Set (VALUE,L)=X
        !           221:  . Set LIM=$Select((PREC+3)'>11:PREC+3,1:11),@("LIM=1E-"_LIM)
        !           222:  . For K=3:2 Do  Quit:($Translate(L,"-")<LIM)
        !           223:  . . Set L=L*X*X*(K-2)/(K-1)*(K-2)/K,VALUE=VALUE+L
        !           224:  . . Quit
        !           225:  . Set VALUE=$Select(SIGT<1:-VALUE,1:VALUE)
        !           226:  . Quit
        !           227:  Set LIM=$Select((PREC+3)'>11:PREC+3,1:11),@("LIM=1E-"_LIM)
        !           228:  For K=3:2 Do  Quit:($Translate(1/L,"-")<LIM)
        !           229:  . ;
        !           230:  . Set L=L*X*X,VALUE=VALUE+(1/(K*L)*SIGN)
        !           231:  . ;;;
        !           232:  . ;
        !           233:  . Set SIGN=SIGN*-1
        !           234:  . Quit
        !           235:  Set VALUE=$Select(FOLD:$$PI()/2-VALUE,1:VALUE)
        !           236:  Set VALUE=$Select(SIGT<1:-VALUE,1:VALUE)
        !           237:  Quit VALUE
        !           238:  ;===
        !           239:  ;
        !           240:  ;
        !           241: ARCTANH(X,PREC) ;
        !           242:  If X<-1 Set $Ecode=",M28,"
        !           243:  If X>1 Set $Ecode=",M28,"
        !           244:  ;
        !           245:  Set PREC=$Get(PREC,11)
        !           246:  ;;;
        !           247:  ;
        !           248:  Quit $$LOG(1+X/(1-X),PREC)/2
        !           249:  ;===
        !           250:  ;
        !           251:  ;
        !           252: CABS(Z) ;
        !           253:  New ZRE,ZIM
        !           254:  Set ZRE=+Z,ZIM=+$Piece(Z,"%",2)
        !           255:  Quit $$SQRT(ZRE*ZRE+(ZIM*ZIM))
        !           256:  ;===
        !           257:  ;
        !           258:  ;
        !           259: CADD(X,Y) ;
        !           260:  New XRE,XIM,YRE,YIM
        !           261:  Set XRE=+X,XIM=+$Piece(X,"%",2)
        !           262:  Set YRE=+Y,YIM=+$Piece(Y,"%",2)
        !           263:  Quit XRE+YRE_"%"_(XIM+YIM)
        !           264:  ;===
        !           265:  ;
        !           266:  ;
        !           267: CCOS(Z,PREC) ;
        !           268:  New E1,E2,IA
        !           269:  ;
        !           270:  Set PREC=$Get(PREC,11)
        !           271:  ;;;
        !           272:  ;
        !           273:  Set IA=$$CMUL(Z,"0%1")
        !           274:  Set E1=$$CEXP(IA,PREC)
        !           275:  Set IA=-IA_"%"_(-$Piece(IA,"%",2))
        !           276:  Set E2=$$CEXP(IA,PREC)
        !           277:  Set IA=$$CADD(E1,E2)
        !           278:  Quit $$CMUL(IA,"0.5%0")
        !           279:  ;===
        !           280:  ;
        !           281:  ;
        !           282: CDIV(X,Y) ;
        !           283:  New D,IM,RE,XIM,XRE,YIM,YRE
        !           284:  Set XRE=+X,XIM=+$Piece(X,"%",2)
        !           285:  Set YRE=+Y,YIM=+$Piece(Y,"%",2)
        !           286:  Set D=YRE*YRE+(YIM*YIM)
        !           287:  Set RE=XRE*YRE+(XIM*YIM)/D
        !           288:  Set IM=XIM*YRE-(XRE*YIM)/D
        !           289:  Quit RE_"%"_IM
        !           290:  ;===
        !           291:  ;
        !           292:  ;
        !           293: CEXP(Z,PREC) ;
        !           294:  New R,ZIM,ZRE
        !           295:  ;
        !           296:  Set PREC=$Get(PREC,11)
        !           297:  ;;;
        !           298:  ;
        !           299:  Set ZRE=+Z,ZIM=+$Piece(Z,"%",2)
        !           300:  Set R=$$EXP(ZRE,PREC)
        !           301:  Quit R*$$COS(ZIM,PREC)_"%"_(R*$$SIN(ZIM,PREC))
        !           302:  ;===
        !           303:  ;
        !           304:  ;
        !           305: CLOG(Z,PREC) ;
        !           306:  New ABS,ARG,ZIM,ZRE
        !           307:  ;
        !           308:  Set PREC=$Get(PREC,11)
        !           309:  ;;;
        !           310:  ;
        !           311:  Set ABS=$$CABS(Z)
        !           312:  Set ZRE=+Z,ZIM=+$Piece(Z,"%",2)
        !           313:  ;
        !           314:  Set ARG=$$ARCTAN(ZIM/ZRE,PREC)
        !           315:  ;;;
        !           316:  ;
        !           317:  Quit $$LOG(ABS,PREC)_"%"_ARG
        !           318:  ;===
        !           319:  ;
        !           320:  ;
        !           321: CMUL(X,Y) ;
        !           322:  New XIM,XRE,YIM,YRE
        !           323:  Set XRE=+X,XIM=+$Piece(X,"%",2)
        !           324:  Set YRE=+Y,YIM=+$Piece(Y,"%",2)
        !           325:  Quit XRE*YRE-(XIM*YIM)_"%"_(XRE*YIM+(XIM*YRE))
        !           326:  ;===
        !           327:  ;
        !           328:  ;
        !           329: COMPLEX(X) Quit +X_"%0"
        !           330:  ;===
        !           331:  ;
        !           332:  ;
        !           333: CONJUG(Z) ;
        !           334:  New ZIM,ZRE
        !           335:  Set ZRE=+Z,ZIM=+$Piece(Z,"%",2)
        !           336:  Quit ZRE_"%"_(-ZIM)
        !           337:  ;===
        !           338:  ;
        !           339:  ;
        !           340: COS(X,PREC) ;
        !           341:  I '$D(PREC) Q $$%COS(X)
        !           342:  New L,LIM,K,SIGN,VALUE
        !           343:  ;
        !           344:  Set:X[":" X=$$DMSDEC(X)
        !           345:  ;;;
        !           346:  ;
        !           347:  Set PREC=$Get(PREC,11)
        !           348:  Set X=X#(2*$$PI())
        !           349:  Set (VALUE,L)=1,SIGN=-1
        !           350:  Set LIM=$Select((PREC+3)'>11:PREC+3,1:11),@("LIM=1E-"_LIM)
        !           351:  For K=2:2 Do  Quit:($Translate(L,"-")<LIM)  Set SIGN=SIGN*-1
        !           352:  . Set L=L*X*X/(K-1*K),VALUE=VALUE+(SIGN*L)
        !           353:  . Quit
        !           354:  Quit VALUE
        !           355:  ;===
        !           356:  ;
        !           357:  ;
        !           358: %COS(X) ;
        !           359:  ;;; ;                                                                 Number ~~
        !           360:  ; Winfried Gerum (8 June 1995)
        !           361:  ;
        !           362:  New A,N,PI,R,SIGN,XX
        !           363:  ;
        !           364:  ; This approximation only works for 0 <= x <= pi/2
        !           365:  ; so reduce angle to correct quadrant.
        !           366:  ;
        !           367:  Set PI=$$PI(),X=X#(PI*2),SIGN=1
        !           368:  Set:X>PI X=2*PI-X
        !           369:  Set:X*2>PI X=PI-X,SIGN=-1
        !           370:  ;
        !           371:  Set XX=X*X,A(1)=-0.4999999963,A(2)=0.0416666418
        !           372:  Set A(3)=-0.0013888397,A(4)=0.0000247609,A(5)=-0.0000002605
        !           373:  Set (X,R)=1 For N=1:1:5 Set X=X*XX,R=A(N)*X+R
        !           374:  Quit R*SIGN
        !           375:  ;===
        !           376:  ;
        !           377:  ;
        !           378: COSH(X,PREC) ;
        !           379:  ;
        !           380:  New E,F,I,P,R,T,XX
        !           381:  ;;;
        !           382:  ;
        !           383:  Set PREC=$Get(PREC,11)+1
        !           384:  Set @("E=1E-"_PREC)
        !           385:  Set XX=X*X,F=1,(P,R,T)=1,I=1
        !           386:  For  Set T=T*XX,F=I+1*I*F,R=T/F+R,P=P-R/R,I=I+2 If -E<P,P<E Quit
        !           387:  Quit R
        !           388:  ;===
        !           389:  ;
        !           390:  ;
        !           391: COT(X,PREC) ;
        !           392:  New C,L,LIM,K,SIGN,VALUE
        !           393:  Set:X[":" X=$$DMSDEC(X)
        !           394:  ;;;
        !           395:  ;
        !           396:  Set PREC=$Get(PREC,11)
        !           397:  Set (VALUE,L)=1,SIGN=-1
        !           398:  Set LIM=$Select((PREC+3)'>11:PREC+3,1:11),@("LIM=1E-"_LIM)
        !           399:  For K=2:2 Do  Quit:($Translate(L,"-")<LIM)  Set SIGN=SIGN*-1
        !           400:  . Set L=L*X*X/(K-1*K),VALUE=VALUE+(SIGN*L)
        !           401:  . Quit
        !           402:  Set C=VALUE
        !           403:  Set X=X#(2*$$PI())
        !           404:  Set (VALUE,L)=X,SIGN=-1
        !           405:  Set LIM=$Select((PREC+3)'>11:PREC+3,1:11),@("LIM=1E-"_LIM)
        !           406:  For K=3:2 Do  Quit:($Translate(L,"-")<LIM)  Set SIGN=SIGN*-1
        !           407:  . Set L=L/(K-1)*X/K*X,VALUE=VALUE+(SIGN*L)
        !           408:  . Quit
        !           409:  If 'VALUE Quit "INFINITE"
        !           410:  Quit VALUE=C/VALUE
        !           411:  ;===
        !           412:  ;
        !           413:  ;
        !           414: COTH(X,PREC) ;
        !           415:  New SINH
        !           416:  If 'X Quit "INFINITE"
        !           417:  ;
        !           418:  Set PREC=$Get(PREC,11)
        !           419:  ;;;
        !           420:  ;
        !           421:  Set SINH=$$SINH(X,PREC)
        !           422:  If 'SINH Quit "INFINITE"
        !           423:  Quit $$COSH(X,PREC)/SINH
        !           424:  ;===
        !           425:  ;
        !           426:  ;
        !           427: CPOWER(Z,N,PREC) ;
        !           428:  New AR,NIM,NRE,PHI,PI,R,RHO,TH,ZIM,ZRE
        !           429:  ;
        !           430:  Set PREC=$Get(PREC,11)
        !           431:  ;;;
        !           432:  ;
        !           433:  Set ZRE=+Z,ZIM=+$Piece(Z,"%",2)
        !           434:  Set NRE=+N,NIM=+$Piece(N,"%",2)
        !           435:  If 'ZRE,'ZIM,'NRE,'NIM Set $Ecode=",M28,"
        !           436:  ;
        !           437:  If 'ZRE,'ZIM Quit "0%0"
        !           438:  ;;;
        !           439:  ;
        !           440:  Set PI=$$PI()
        !           441:  ;
        !           442:  Set R=$$SQRT(ZRE*ZRE+(ZIM*ZIM),PREC)
        !           443:  ;;;
        !           444:  ;
        !           445:  ;
        !           446:  If ZRE Set TH=$$ARCTAN(ZIM/ZRE,PREC)
        !           447:  ;;;
        !           448:  ;
        !           449:  Else  Set TH=$SELECT(ZIM>0:PI/2,1:-PI/2)
        !           450:  ;;;
        !           451:  ;
        !           452:  Set RHO=$$LOG(R,PREC)
        !           453:  Set AR=$$EXP(RHO*NRE-(TH*NIM),PREC)
        !           454:  Set PHI=RHO*NIM+(NRE*TH)
        !           455:  Quit AR*$$COS(PHI,PREC)_"%"_(AR*$$SIN(PHI,PREC))
        !           456:  ;===
        !           457:  ;
        !           458:  ;
        !           459: CSC(X,PREC) ;
        !           460:  New L,LIM,K,SIGN,VALUE
        !           461:  ;
        !           462:  ; Winfried Gerum (8 June 1995)
        !           463:  Set:X[":" X=$$DMSDEC(X)
        !           464:  ;;;
        !           465:  ;
        !           466:  Set PREC=$Get(PREC,11)
        !           467:  ;;;
        !           468:  ;
        !           469:  Set X=X#(2*$$PI())
        !           470:  Set (VALUE,L)=X,SIGN=-1
        !           471:  Set LIM=$Select((PREC+3)'>11:PREC+3,1:11),@("LIM=1E-"_LIM)
        !           472:  For K=3:2 Do  Quit:($Translate(L,"-")<LIM)  Set SIGN=SIGN*-1
        !           473:  . Set L=L/(K-1)*X/K*X,VALUE=VALUE+(SIGN*L)
        !           474:  . Quit
        !           475:  If 'VALUE Quit "INFINITE"
        !           476:  Quit 1/VALUE
        !           477:  ;===
        !           478:  ;
        !           479:  ;
        !           480:  ;
        !           481: CSCH(X,PREC) 
        !           482:  Quit 1/$$SINH(X,$Get(PREC,11))
        !           483:  ;;;
        !           484:  ;
        !           485:  ;===
        !           486:  ;
        !           487:  ;
        !           488: CSIN(Z,PREC) ;
        !           489:  New IA,E1,E2
        !           490:  ;
        !           491:  Set PREC=$Get(PREC,11)
        !           492:  ;;;
        !           493:  ;
        !           494:  Set IA=$$CMUL(Z,"0%1")
        !           495:  Set E1=$$CEXP(IA,PREC)
        !           496:  Set IA=-IA_"%"_(-$Piece(IA,"%",2))
        !           497:  Set E2=$$CEXP(IA,PREC)
        !           498:  Set IA=$$CSUB(E1,E2)
        !           499:  Set IA=$$CMUL(IA,"0.5%0")
        !           500:  Quit $$CMUL("0%-1",IA)
        !           501:  ;===
        !           502:  ;
        !           503:  ;
        !           504: CSUB(X,Y) ;
        !           505:  New XIM,XRE,YIM,YRE
        !           506:  Set XRE=+X,XIM=+$Piece(X,"%",2)
        !           507:  Set YRE=+Y,YIM=+$Piece(Y,"%",2)
        !           508:  Quit XRE-YRE_"%"_(XIM-YIM)
        !           509:  ;===
        !           510:  ;
        !           511:  ;
        !           512: DECDMS(X,PREC) ;
        !           513:  Set PREC=$Get(PREC,5)
        !           514:  Set X=X#360*3600
        !           515:  Set X=+$Justify(X,0,$Select((PREC-$Length(X\1))'<0:PREC-$Length(X\1),1:0))
        !           516:  Quit X\3600_":"_(X\60#60)_":"_(X#60)
        !           517:  ;===
        !           518:  ;
        !           519:  ;
        !           520: DEGRAD(X) Quit X*3.14159265358979/180
        !           521:  ;===
        !           522:  ;
        !           523:  ;
        !           524: DMSDEC(X) ;
        !           525:  Quit $Piece(X,":")+($Piece(X,":",2)/60)+($Piece(X,":",3)/3600)
        !           526:  ;===
        !           527:  ;
        !           528:  ;
        !           529: E() Quit 2.71828182845905
        !           530:  ;===
        !           531:  ;
        !           532:  ;
        !           533: EXP(X,PREC) ;
        !           534:  New L,LIM,K,VALUE
        !           535:  Set PREC=$Get(PREC,11)
        !           536:  Set L=X,VALUE=X+1
        !           537:  Set LIM=$Select((PREC+3)'>11:PREC+3,1:11),@("LIM=1E-"_LIM)
        !           538:  For K=2:1 Set L=L*X/K,VALUE=VALUE+L Quit:($Translate(L,"-")<LIM)
        !           539:  Quit VALUE
        !           540:  ;===
        !           541:  ;
        !           542:  ;
        !           543: LOG(X,PREC) ;
        !           544:  New L,LIM,M,N,K,VALUE
        !           545:  If X'>0 Set $Ecode=",M28,"
        !           546:  Set PREC=$Get(PREC,11)
        !           547:  Set M=1
        !           548:  ;
        !           549:  For N=0:1 Quit:(X/M)<10  Set M=M*10
        !           550:  ;;;
        !           551:  ;
        !           552:  If X<1 For N=0:-1 Quit:(X/M)>0.1  Set M=M*0.1
        !           553:  Set X=X/M
        !           554:  Set X=(X-1)/(X+1),(VALUE,L)=X
        !           555:  Set LIM=$Select((PREC+3)'>11:PREC+3,1:11),@("LIM=1E-"_LIM)
        !           556:  For K=3:2 Set L=L*X*X,M=L/K,VALUE=M+VALUE Set:M<0 M=-M Quit:M<LIM
        !           557:  Set VALUE=VALUE*2+(N*2.30258509298749)
        !           558:  Quit VALUE
        !           559:  ;===
        !           560:  ;
        !           561:  ;
        !           562: LOG10(X,PREC) ;
        !           563:  New L,LIM,M,N,K,VALUE
        !           564:  If X'>0 Set $Ecode=",M28,"
        !           565:  Set PREC=$Get(PREC,11)
        !           566:  Set M=1
        !           567:  ;
        !           568:  For N=0:1 Quit:(X/M)<10  Set M=M*10
        !           569:  ;;;
        !           570:  ;
        !           571:  If X<1 For N=0:-1 Quit:(X/M)>0.1  Set M=M*0.1
        !           572:  Set X=X/M
        !           573:  Set X=(X-1)/(X+1),(VALUE,L)=X
        !           574:  Set LIM=$Select((PREC+3)'>11:PREC+3,1:11),@("LIM=1E-"_LIM)
        !           575:  For K=3:2 Set L=L*X*X,M=L/K,VALUE=M+VALUE Set:M<0 M=-M Quit:M<LIM
        !           576:  Set VALUE=VALUE*2+(N*2.30258509298749)
        !           577:  Quit VALUE/2.30258509298749
        !           578:  ;===
        !           579:  ;
        !           580:  ;
        !           581: MTXADD(A,B,R,ROWS,COLS) ;
        !           582:  ; Add A[ROWS,COLS] to B[ROWS,COLS],
        !           583:  ; result goes to R[ROWS,COLS]
        !           584:  IF $DATA(A)<10 QUIT 0
        !           585:  IF $DATA(B)<10 QUIT 0
        !           586:  IF $GET(ROWS)<1 QUIT 0
        !           587:  IF $GET(COLS)<1 QUIT 0
        !           588:  ;
        !           589:  NEW ROW,COL,ANY
        !           590:  FOR ROW=1:1:ROWS FOR COL=1:1:COLS DO
        !           591:  . KVALUE R(ROW,COL) SET ANY=0
        !           592:  . SET:$DATA(A(ROW,COL))#2 ANY=1
        !           593:  . SET:$DATA(B(ROW,COL))#2 ANY=1
        !           594:  . SET:ANY R(ROW,COL)=$GET(A(ROW,COL))+$GET(B(ROW,COL))
        !           595:  . QUIT
        !           596:  QUIT 1
        !           597:  ;===
        !           598:  ;
        !           599:  ;
        !           600: MTXCOF(A,I,K,N) ;
        !           601:  ; Compute cofactor for element [i,k]
        !           602:  ; in matrix A[N,N]
        !           603:  NEW T,R,C,RR,CC
        !           604:  SET CC=0 FOR C=1:1:N DO:C'=K
        !           605:  . SET CC=CC+1,RR=0
        !           606:  . FOR R=1:1:N SET:R'=I RR=RR+1,T(RR,CC)=$GET(A(R,C))
        !           607:  . QUIT
        !           608:  QUIT $$MTXDET(.T,N-1)
        !           609:  ;===
        !           610:  ;
        !           611:  ;
        !           612: MTXCOPY(A,R,ROWS,COLS) ;
        !           613:  ; Copy A[ROWS,COLS] to R[ROWS,COLS]
        !           614:  IF $DATA(A)<10 QUIT 0
        !           615:  IF $GET(ROWS)<1 QUIT 0
        !           616:  IF $GET(COLS)<1 QUIT 0
        !           617:  ;
        !           618:  NEW ROW,COL
        !           619:  FOR ROW=1:1:ROWS FOR COL=1:1:COLS DO
        !           620:  . KVALUE R(ROW,COL)
        !           621:  . SET:$DATA(A(ROW,COL))#2 R(ROW,COL)=A(ROW,COL)
        !           622:  . QUIT
        !           623:  QUIT 1
        !           624:  ;===
        !           625:  ;
        !           626:  ;
        !           627: MTXDET(A,N) ;
        !           628:  ; Compute determinant of matrix A[N,N]
        !           629:  IF $DATA(A)<10 QUIT ""
        !           630:  IF N<1 QUIT ""
        !           631:  ;
        !           632:  ; First the simple cases
        !           633:  ;
        !           634:  IF N=1 QUIT $GET(A(1,1))
        !           635:  IF N=2 QUIT $GET(A(1,1))*$GET(A(2,2))-($GET(A(1,2))*$GET(A(2,1)))
        !           636:  ;
        !           637:  NEW DET,I,SIGN
        !           638:  ;
        !           639:  ; Det A = sum (k=1:n) element (i,k) * cofactor [i,k]
        !           640:  ;
        !           641:  SET DET=0,SIGN=1
        !           642:  FOR I=1:1:N DO
        !           643:  . SET DET=$GET(A(1,I))*$$MTXCOF(.A,1,I,N)*SIGN+DET
        !           644:  . SET SIGN=-SIGN
        !           645:  . QUIT
        !           646:  QUIT DET
        !           647:  ;===
        !           648:  ;
        !           649:  ;
        !           650: MTXEQU(A,B,R,N,M) ;
        !           651:  ; Solve matrix equation A [M,M] * R [M,N] = B [M,N]
        !           652:  IF $GET(M)<1 QUIT ""
        !           653:  IF $GET(N)<1 QUIT ""
        !           654:  IF '$$MTXDET(.A) QUIT 0
        !           655:  ;
        !           656:  NEW I,I1,J,J1,J2,K,L,T,T1,T2,TEMP,X
        !           657:  ;
        !           658:  SET X=$$MTXCOPY(.A,.T,N,N)
        !           659:  SET X=$$MTXCOPY(.B,.R,N,M)
        !           660:  ;
        !           661:  ; Reduction of matrix A
        !           662:  ; Steps of reduction are counted by index K
        !           663:  ;
        !           664:  FOR K=1:1:N-1 DO
        !           665:  . ;
        !           666:  . ; Search for largest coefficient of T
        !           667:  . ; (denoted by TEMP)
        !           668:  . ; in first column of reduced system
        !           669:  . ;
        !           670:  . SET TEMP=0,J2=K
        !           671:  . FOR J1=K:1:N DO
        !           672:  . . QUIT:$TRANSLATE($GET(T(J1,K)),"-")>$TRANSLATE(TEMP,"-")
        !           673:  . . SET TEMP=T(J1,K),J2=J1
        !           674:  . . QUIT
        !           675:  . ;
        !           676:  . ; Exchange row number K with row number J2,
        !           677:  . ; if necessary
        !           678:  . ;
        !           679:  . DO:J2'=K
        !           680:  . . ;
        !           681:  . . FOR J=K:1:N DO
        !           682:  . . . SET T1=$GET(T(K,J)),T2=$GET(T(J2,J))
        !           683:  . . . KILL T(K,J),T(J2,J)
        !           684:  . . . IF T1'="" SET T(J2,J)=T1
        !           685:  . . . IF T2'="" SET T(K,J)=T2
        !           686:  . . . QUIT
        !           687:  . . FOR J=1:1:M DO
        !           688:  . . . SET T1=$GET(R(K,J)),T2=$GET(R(J2,J))
        !           689:  . . . KILL R(K,J),R(J2,J)
        !           690:  . . . IF T1'="" SET R(J2,J)=T1
        !           691:  . . . IF T2'="" SET R(K,J)=T2
        !           692:  . . . QUIT
        !           693:  . . QUIT
        !           694:  . ;
        !           695:  . ; Actual reduction
        !           696:  . ;
        !           697:  . FOR I=K+1:1:N DO
        !           698:  . . FOR J=K+1:1:N DO
        !           699:  . . . QUIT:'$GET(T(K,K))
        !           700:  . . . SET T(I,J)=-$GET(T(K,J))*$GET(T(I,K))/T(K,K)+$GET(T(I,J))
        !           701:  . . . QUIT
        !           702:  . . FOR J=1:1:M DO
        !           703:  . . . QUIT:'$GET(T(K,K))
        !           704:  . . . SET R(I,J)=-$GET(R(K,J))*$GET(T(I,K))/T(K,K)+$GET(R(I,J))
        !           705:  . . . QUIT
        !           706:  . . QUIT
        !           707:  . QUIT
        !           708:  ;
        !           709:  ; Backsubstitution
        !           710:  ;
        !           711:  FOR J=1:1:M DO
        !           712:  . IF $GET(T(N,N)) SET R(N,J)=$GET(R(N,J))/T(N,N)
        !           713:  . IF N-1>0 FOR I1=1:1:N-1 DO
        !           714:  . . SET I=N-I1
        !           715:  . . FOR L=I+1:1:N DO
        !           716:  . . . SET R(I,J)=-$GET(T(I,L))*$GET(R(L,J))+$GET(R(I,J))
        !           717:  . . . QUIT
        !           718:  . . IF $GET(T(I,I)) SET R(I,J)=$GET(R(I,J))/$GET(T(I,I))
        !           719:  . . QUIT
        !           720:  . QUIT
        !           721:  QUIT $$MTXDET(.R)
        !           722:  ;===
        !           723:  ;
        !           724:  ;
        !           725: MTXINV(A,R,N) ;
        !           726:  ; Invert A[N,N], result goes to R[N,N]
        !           727:  IF $DATA(A)<10 QUIT 0
        !           728:  IF $GET(N)<1 QUIT 0
        !           729:  ;
        !           730:  NEW T,X
        !           731:  SET X=$$MTXUNIT(.T,N)
        !           732:  QUIT $$MTXEQU(.A,.T,.R,N,N)
        !           733:  ;===
        !           734:  ;
        !           735:  ;
        !           736: MTXMUL(A,B,R,M,L,N) ;
        !           737:  ; Multiply A[M,L] by B[L,N], result goes to R[M,N]
        !           738:  IF $DATA(A)<10 QUIT 0
        !           739:  IF $DATA(B)<10 QUIT 0
        !           740:  IF $GET(L)<1 QUIT 0
        !           741:  IF $GET(M)<1 QUIT 0
        !           742:  IF $GET(N)<1 QUIT 0
        !           743:  ;
        !           744:  NEW I,J,K,SUM,ANY
        !           745:  FOR I=1:1:M FOR J=1:1:N DO
        !           746:  . SET (SUM,ANY)=0
        !           747:  . KVALUE R(I,J)
        !           748:  . FOR K=1:1:L DO
        !           749:  . . SET:$DATA(A(I,K))#2 ANY=1
        !           750:  . . SET:$DATA(B(K,J))#2 ANY=1
        !           751:  . . SET SUM=$GET(A(I,K))*$GET(B(K,J))+SUM
        !           752:  . . QUIT
        !           753:  . SET:ANY R(I,J)=SUM
        !           754:  . QUIT
        !           755:  QUIT 1
        !           756:  ;===
        !           757:  ;
        !           758:  ;
        !           759: MTXSCA(A,R,ROWS,COLS,S) ;
        !           760:  ; Multiply A[ROWS,COLS] with the scalar S,
        !           761:  ; result goes to R[ROWS,COLS]
        !           762:  IF $DATA(A)<10 QUIT 0
        !           763:  IF $GET(ROWS)<1 QUIT 0
        !           764:  IF $GET(COLS)<1 QUIT 0
        !           765:  IF '($DATA(S)#2) QUIT 0
        !           766:  ;
        !           767:  NEW ROW,COL
        !           768:  FOR ROW=1:1:ROWS FOR COL=1:1:COLS DO
        !           769:  . KVALUE R(ROW,COL)
        !           770:  . SET:$DATA(A(ROW,COL))#2 R(ROW,COL)=A(ROW,COL)*S
        !           771:  . QUIT
        !           772:  QUIT 1
        !           773:  ;===
        !           774:  ;
        !           775:  ;
        !           776: MTXSUB(A,B,R,ROWS,COLS) ;
        !           777:  ; Subtract B[ROWS,COLS] from A[ROWS,COLS],
        !           778:  ; result goes to R[ROWS,COLS]
        !           779:  IF $DATA(A)<10 QUIT 0
        !           780:  IF $DATA(B)<10 QUIT 0
        !           781:  IF $GET(ROWS)<1 QUIT 0
        !           782:  IF $GET(COLS)<1 QUIT 0
        !           783:  ;
        !           784:  NEW ROW,COL,ANY
        !           785:  FOR ROW=1:1:ROWS FOR COL=1:1:COLS DO
        !           786:  . KVALUE R(ROW,COL) SET ANY=0
        !           787:  . SET:$DATA(A(ROW,COL))#2 ANY=1
        !           788:  . SET:$DATA(B(ROW,COL))#2 ANY=1
        !           789:  . ;
        !           790:  . SET:ANY R(ROW,COL)=$GET(A(ROW,COL))-$GET(B(ROW,COL))
        !           791:  . ;;;
        !           792:  . ;
        !           793:  . QUIT
        !           794:  QUIT 1
        !           795:  ;===
        !           796:  ;
        !           797:  ;
        !           798: MTXTRP(A,R,M,N) ;
        !           799:  ; Transpose A[M,N], result goes to R[N,M]
        !           800:  IF $DATA(A)<10 QUIT 0
        !           801:  IF $GET(M)<1 QUIT 0
        !           802:  IF $GET(N)<1 QUIT 0
        !           803:  ;
        !           804:  NEW I,J,K,D1,V1,D2,V2
        !           805:  FOR I=1:1:M+N-1 FOR J=1:1:I+1\2 DO
        !           806:  . SET K=I-J+1
        !           807:  . IF K=J DO  QUIT
        !           808:  . . SET V1=$GET(A(J,J)),D1=$DATA(A(J,J))#2
        !           809:  . . IF J'>N,J'>M KVALUE R(J,J) SET:D1 R(J,J)=V1
        !           810:  . . QUIT
        !           811:  . ;
        !           812:  . SET V1=$GET(A(K,J)),D1=$DATA(A(K,J))#2
        !           813:  . SET V2=$GET(A(J,K)),D2=$DATA(A(J,K))#2
        !           814:  . IF K'>M,J'>N KVALUE R(K,J) SET:D2 R(K,J)=V2
        !           815:  . IF J'>M,K'>N KVALUE R(J,K) SET:D1 R(J,K)=V1
        !           816:  . QUIT
        !           817:  QUIT 1
        !           818:  ;===
        !           819:  ;
        !           820:  ;
        !           821: MTXUNIT(R,N,SPARSE) ;
        !           822:  ; Create a unit matrix R[N,N]
        !           823:  IF $GET(N)<1 QUIT 0
        !           824:  ;
        !           825:  NEW ROW,COL
        !           826:  FOR ROW=1:1:N FOR COL=1:1:N DO
        !           827:  . KVALUE R(ROW,COL)
        !           828:  . IF $GET(SPARSE) QUIT:ROW'=COL
        !           829:  . SET R(ROW,COL)=$SELECT(ROW=COL:1,1:0)
        !           830:  . QUIT
        !           831:  QUIT 1
        !           832:  ;===
        !           833:  ;
        !           834:  ;
        !           835: PI() Quit 3.14159265358979
        !           836:  ;===
        !           837:  ;
        !           838:  ;
        !           839: RADDEG(X) Quit X*180/3.14159265358979
        !           840:  ;===
        !           841:  ;
        !           842:  ;
        !           843: SEC(X,PREC) ;
        !           844:  New L,LIM,K,SIGN,VALUE
        !           845:  ;
        !           846:  Set:X[":" X=$$DMSDEC(X)
        !           847:  ;;;
        !           848:  ;
        !           849:  Set PREC=$Get(PREC,11)
        !           850:  Set X=X#(2*$$PI())
        !           851:  Set (VALUE,L)=1,SIGN=-1
        !           852:  Set LIM=$Select((PREC+3)'>11:PREC+3,1:11),@("LIM=1E-"_LIM)
        !           853:  For K=2:2 Do  Quit:($Translate(L,"-")<LIM)  Set SIGN=SIGN*-1
        !           854:  . Set L=L*X*X/(K-1*K),VALUE=VALUE+(SIGN*L)
        !           855:  . Quit
        !           856:  If 'VALUE Quit "INFINITE"
        !           857:  Quit 1/VALUE
        !           858:  ;===
        !           859:  ;
        !           860:  ;
        !           861: SECH(X,PREC) 
        !           862:  Quit 1/$$COSH(X,$Get(PREC,11))
        !           863:  ;;;
        !           864:  ;===
        !           865:  ;
        !           866:  ;
        !           867: SIGN(X) Quit $SELECT(X<0:-1,X>0:1,1:0)
        !           868:  ;===
        !           869:  ;
        !           870:  ;
        !           871: SIN(X,PREC) ;
        !           872:  I '$D(PREC) Q $$%SIN(X)
        !           873:  New L,LIM,K,SIGN,VALUE
        !           874:  ;
        !           875:  Set:X[":" X=$$DMSDEC(X)
        !           876:  ;;;
        !           877:  ;
        !           878:  Set PREC=$Get(PREC,11)
        !           879:  Set X=X#(2*$$PI())
        !           880:  Set (VALUE,L)=X,SIGN=-1
        !           881:  Set LIM=$Select((PREC+3)'>11:PREC+3,1:11),@("LIM=1E-"_LIM)
        !           882:  For K=3:2 Do  Quit:($Translate(L,"-")<LIM)  Set SIGN=SIGN*-1
        !           883:  . Set L=L/(K-1)*X/K*X,VALUE=VALUE+(SIGN*L)
        !           884:  . Quit
        !           885:  Quit VALUE
        !           886:  ;===
        !           887:  ;
        !           888:  ;
        !           889: %SIN(X) ;
        !           890:  ;
        !           891:  New A,N,PI,R,SIGN,XX
        !           892:  ;
        !           893:  ; This approximation only works for 0 <= x <= pi/2
        !           894:  ; so reduce angle to correct quadrant.
        !           895:  ;
        !           896:  Set PI=$$PI(),X=X#(PI*2),SIGN=1
        !           897:  Set:X>PI X=2*PI-X,SIGN=-1
        !           898:  ;
        !           899:  Set:X*2<PI X=PI-X
        !           900:  ;;;
        !           901:  ;
        !           902:  ;
        !           903:  Set XX=X*X,A(1)=-0.4999999963,A(2)=0.0416666418
        !           904:  Set A(3)=-0.0013888397,A(4)=0.0000247609,A(5)=-0.0000002605
        !           905:  Set (X,R)=1 For N=1:1:5 Set X=X*XX,R=A(N)*X+R
        !           906:  Quit R*SIGN
        !           907:  ;===
        !           908:  ;
        !           909:  ;
        !           910: SINH(X,PREC) ;
        !           911:  ;
        !           912:  New E,F,I,P,R,T,XX
        !           913:  ;;;
        !           914:  ;
        !           915:  Set PREC=$Get(PREC,11)+1
        !           916:  Set @("E=1E-"_PREC)
        !           917:  Set XX=X*X,F=1,I=2,(P,R,T)=X
        !           918:  For  Set T=T*XX,F=I+1*I*F,R=T/F+R,P=P-R/R,I=I+2 If -E<P,P<E Quit
        !           919:  Quit R
        !           920:  ;===
        !           921:  ;
        !           922:  ;
        !           923: SQRT(X,PREC) ;
        !           924:  If X<0 Set $Ecode=",M28,"
        !           925:  If X=0 Quit 0
        !           926:  ;
        !           927:  Set PREC=$Get(PREC,11)
        !           928:  ;;;
        !           929:  ;
        !           930:  ;
        !           931:  If X<1 Quit 1/$$SQRT(1/X,PREC)
        !           932:  ;;;
        !           933:  ;
        !           934:  New P,R,E
        !           935:  Set PREC=$Get(PREC,11)+1
        !           936:  ;
        !           937:  Set @("E=1E-"_PREC)
        !           938:  ;;;
        !           939:  ;
        !           940:  Set R=X
        !           941:  For  Set P=R,R=X/R+R/2,P=P-R/R If -E<P,P<E Quit
        !           942:  Quit R
        !           943:  ;===
        !           944:  ;
        !           945:  ;
        !           946: TAN(X,PREC) ;
        !           947:  New L,LIM,K,S,SIGN,VALUE
        !           948:  ;
        !           949:  Set:X[":" X=$$DMSDEC(X)
        !           950:  ;;;
        !           951:  ;
        !           952:  Set PREC=$Get(PREC,11)
        !           953:  Set X=X#(2*$$PI())
        !           954:  Set (VALUE,L)=X,SIGN=-1
        !           955:  Set LIM=$Select((PREC+3)'>11:PREC+3,1:11),@("LIM=1E-"_LIM)
        !           956:  For K=3:2 Do  Quit:($Translate(L,"-")<LIM)  Set SIGN=SIGN*-1
        !           957:  . Set L=L/(K-1)*X/K*X,VALUE=VALUE+(SIGN*L)
        !           958:  . Quit
        !           959:  Set S=VALUE
        !           960:  Set X=X#(2*$$PI())
        !           961:  Set (VALUE,L)=1,SIGN=-1
        !           962:  Set LIM=$Select((PREC+3)'>11:PREC+3,1:11),@("LIM=1E-"_LIM)
        !           963:  For K=2:2 Do  Quit:($Translate(L,"-")<LIM)  Set SIGN=SIGN*-1
        !           964:  . Set L=L*X*X/(K-1*K),VALUE=VALUE+(SIGN*L)
        !           965:  . Quit
        !           966:  If 'VALUE Quit "INFINITE"
        !           967:  Quit S/VALUE
        !           968:  ;===
        !           969:  ;
        !           970:  ;
        !           971: TANH(X,PREC) ;
        !           972:  ;
        !           973:  Set PREC=$Get(PREC,11)
        !           974:  ;;;
        !           975:  ;
        !           976:  Quit $$SINH(X,PREC)/$$COSH(X,PREC)
        !           977:  ;===
        !           978: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>