int main(int argc, char *argv[]) { int i; int rval, ll; struct text *kk; init(); /* Initialize everything */ signal(SIGINT, trapdel); if (argc > 1) { /* Restore file specified */ /* Restart is label 8305 (Fortran) */ i = restore(argv[1]); /* See what we've got */ switch (i) { case 0: /* The restore worked fine */ yea = Start(); k = null; unlink(argv[1]);/* Don't re-use the save */ goto l8; /* Get where we're going */ case 1: /* Couldn't open it */ errx(1, "can't open file"); /* So give up */ case 2: /* Oops -- file was altered */ rspeak(202); /* You dissolve */ exit(2); /* File could be non-adventure */ } /* So don't unlink it. */ } startup(); /* prepare for a user */ for (;;) { /* main command loop (label 2) */ if (newloc < 9 && newloc != 0 && closng) { rspeak(130); /* if closing leave only by */ newloc = loc; /* main office */ if (!panic) clock2 = 15; panic = TRUE; } rval = fdwarf(); /* dwarf stuff */ if (rval == 99) die(99); l2000: if (loc == 0) die(99); /* label 2000 */ kk = &stext[loc]; if ((abb[loc] % abbnum) ==0 || kk->seekadr == 0) kk = <ext[loc]; if (!forced(loc) && dark()) { if (wzdark && pct(35)) { die(90); goto l2000; } kk = &rtext[16]; } l2001: if (toting(bear)) rspeak(141); /* 2001 */ speak(kk); k = 1; if (forced(loc)) goto l8; if (loc == 33 && pct(25) && !closng) rspeak(8); if (!dark()) { abb[loc]++; for (i = atloc[loc]; i != 0; i = linkx[i]) { /*2004*/ obj = i; if (obj > 100) obj -= 100; if (obj == steps && toting(nugget)) continue; if (prop[obj] < 0) { if (closed) continue; prop[obj] = 0; if (obj == rug || obj == chain) prop[obj] = 1; tally--; if (tally == tally2 && tally != 0) if (limit > 35) limit = 35; } ll = prop[obj]; /* 2006 */ if (obj == steps && loc == fixed[steps]) ll = 1; pspeak(obj, ll); } /* 2008 */ goto l2012; l2009: k = 54; /* 2009 */ l2010: spk = k; l2011: rspeak(spk); } l2012: verb = 0; /* 2012 */ obj = 0; l2600: checkhints(); /* to 2600-2602 */ if (closed) { if (prop[oyster] < 0 && toting(oyster)) pspeak(oyster, 1); for (i = 1; i < 100; i++) if (toting(i) && prop[i] < 0) /* 2604 */ prop[i] = -1 - prop[i]; } wzdark = dark(); /* 2605 */ if (knfloc > 0 && knfloc != loc) knfloc = 1; getin(wd1, sizeof(wd1), wd2, sizeof(wd2)); if (delhit) { /* user typed a DEL */ delhit = 0; /* reset counter */ /* pretend he's quitting */ strlcpy(wd1, "quit", sizeof(wd1)); wd2[0] = 0; } l2608: if ((foobar = -foobar) > 0) foobar = 0; /* 2608 */ /* should check here for "magic mode" */ turns++; if (demo && turns >= SHORT) done(1); /* to 13000 */ if (verb == say && wd2[0] != 0) verb = 0; if (verb == say) goto l4090; if (tally == 0 && loc >= 15 && loc != 33) clock1--; if (clock1 == 0) { closing(); /* to 10000 */ goto l19999; } if (clock1 < 0) clock2--; if (clock2 == 0) { caveclose(); /* to 11000 */ continue; /* back to 2 */ } if (prop[lamp] == 1) limit--; if (limit <= 30 && here(batter) && prop[batter] == 0 && here(lamp)) { rspeak(188); /* 12000 */ prop[batter] = 1; if (toting(batter)) drop(batter, loc); limit += 2500; lmwarn = FALSE; goto l19999; } if (limit == 0) { limit = -1; /* 12400 */ prop[lamp] = 0; rspeak(184); goto l19999; } if (limit < 0 && loc <= 8) { rspeak(185); /* 12600 */ gaveup = TRUE; done(2); /* to 20000 */ } if (limit <= 30) { if (lmwarn || !here(lamp)) goto l19999; /*12200*/ lmwarn = TRUE; spk = 187; if (place[batter] == 0) spk = 183; if (prop[batter] == 1) spk = 189; rspeak(spk); } l19999: k = 43; if (liqloc(loc) == water) k = 70; if (weq(wd1, "enter") && (weq(wd2, "strea") || weq(wd2, "water"))) goto l2010; if (weq(wd1, "enter") && *wd2 != 0) goto l2800; if ((!weq(wd1, "water") && !weq(wd1, "oil")) || (!weq(wd2, "plant") && !weq(wd2, "door"))) goto l2610; if (at(vocab(wd2, 1, 0))) strlcpy(wd2, "pour", sizeof(wd2)); l2610: if (weq(wd1, "west")) if (++iwest == 10) rspeak(17); l2630: i = vocab(wd1, -1, 0); if (i== -1) { spk = 60; /* 3000 */ if (pct(20)) spk = 61; if (pct(20)) spk = 13; rspeak(spk); goto l2600; } k = i % 1000; kq = i / 1000 + 1; switch (kq) { case 1: goto l8; case 2: goto l5000; case 3: goto l4000; case 4: goto l2010; default: bug(22); } l8: switch (march()) { case 2: continue; /* i.e. goto l2 */ case 99: die(99); goto l2000; default: bug(110); } l2800: strlcpy(wd1, wd2, sizeof(wd1)); wd2[0] = 0; goto l2610; l4000: verb = k; spk = actspk[verb]; if (wd2[0] != 0 && verb != say) goto l2800; if (verb == say) obj = wd2[0]; if (obj != 0) goto l4090; l4080: switch (verb) { case 1: /* take = 8010 */ if (atloc[loc] == 0 || linkx[atloc[loc]] != 0) goto l8000; for (i = 1; i <= 5; i++) if (dloc[i] == loc && dflag >= 2) goto l8000; obj = atloc[loc]; goto l9010; case 2: case 3: case 9: /* 8000 : drop, say, wave */ case 10: case 16: case 17: /* calm, rub, toss */ case 19: case 21: case 28: /* find, feed, break */ case 29: /* wake */ l8000: printf("%s what?\n", wd1); obj = 0; goto l2600; case 4: case 6: /* 8040 open, lock */ spk = 28; if (here(clam)) obj = clam; if (here(oyster)) obj = oyster; if (at(door)) obj = door; if (at(grate)) obj = grate; if (obj != 0 && here(chain)) goto l8000; if (here(chain)) obj = chain; if (obj == 0) goto l2011; goto l9040; case 5: goto l2009; /* nothing */ case 7: goto l9070; /* on */ case 8: goto l9080; /* off */ case 11: goto l8000; /* walk */ case 12: goto l9120; /* kill */ case 13: goto l9130; /* pour */ case 14: /* eat: 8140 */ if (!here(food)) goto l8000; l8142: dstroy(food); spk = 72; goto l2011; case 15: goto l9150; /* drink */ case 18: /* quit: 8180 */ gaveup = yes(22, 54, 54); if (gaveup) done(2); /* 8185 */ goto l2012; case 20: /* invent = 8200 */ spk = 98; for (i = 1; i <= 100; i++) { if (i != bear && toting(i)) { if (spk == 98) rspeak(99); blklin = FALSE; pspeak(i, -1); blklin = TRUE; spk = 0; } } if (toting(bear)) spk = 141; goto l2011; case 22: goto l9220; /* fill */ case 23: goto l9230; /* blast */ case 24: /* score: 8240 */ scorng = TRUE; printf("If you were to quit now, you would score"); printf(" %d out of a possible ", score()); printf("%d.", mxscor); scorng = FALSE; gaveup = yes(143, 54, 54); if (gaveup) done(2); goto l2012; case 25: /* foo: 8250 */ k = vocab(wd1, 3, 0); spk = 42; if (foobar == 1 - k) goto l8252; if (foobar != 0) spk = 151; goto l2011; l8252: foobar = k; if (k != 4) goto l2009; foobar = 0; if (place[eggs] == plac[eggs] || (toting(eggs) && loc == plac[eggs])) goto l2011; if (place[eggs] == 0 && place[troll] == 0 && prop[troll] == 0) prop[troll] = 1; k = 2; if (here(eggs)) k = 1; if (loc == plac[eggs]) k = 0; move(eggs, plac[eggs]); pspeak(eggs, k); goto l2012; case 26: /* brief = 8260 */ spk = 156; abbnum = 10000; detail = 3; goto l2011; case 27: /* read = 8270 */ if (here(magzin)) obj = magzin; if (here(tablet)) obj = obj * 100 + tablet; if (here(messag)) obj = obj * 100 + messag; if (closed && toting(oyster)) obj = oyster; if (obj > 100 || obj == 0 || dark()) goto l8000; goto l9270; case 30: /* suspend = 8300 */ spk = 201; if (demo) goto l2011; printf("I can suspend your adventure for you so"); printf(" you can resume later, but\n"); printf("you will have to wait at least"); printf(" %d minutes before continuing.", latncy); if (!yes(200, 54, 54)) goto l2012; time(&savet); ciao(); /* Do we quit? */ continue; /* Maybe not */ case 31: /* hours = 8310 */ printf("Colossal cave is closed 9am-5pm Mon "); printf("through Fri except holidays.\n"); goto l2012; default: bug(23); } l4090: switch (verb) { case 1: /* take = 9010 */ l9010: switch (trtake()) { case 2011: goto l2011; case 9220: goto l9220; case 2009: goto l2009; case 2012: goto l2012; default: bug(102); } l9020: case 2: /* drop = 9020 */ switch (trdrop()) { case 2011: goto l2011; case 19000: done(3); case 2012: goto l2012; default: bug(105); } l9030: case 3: switch (trsay()) { case 2012: goto l2012; case 2630: goto l2630; default: bug(107); } l9040: case 4: case 6: /* open, close */ switch (tropen()) { case 2011: goto l2011; case 2010: goto l2010; default: bug(106); } case 5: goto l2009; /* nothing */ case 7: /* on 9070 */ l9070: if (!here(lamp)) goto l2011; spk = 184; if (limit < 0) goto l2011; prop[lamp] = 1; rspeak(39); if (wzdark) goto l2000; goto l2012; case 8: /* off */ l9080: if (!here(lamp)) goto l2011; prop[lamp] = 0; rspeak(40); if (dark()) rspeak(16); goto l2012; case 9: /* wave */ if ((!toting(obj)) && (obj != rod || !toting(rod2))) spk = 29; if (obj != rod || !at(fissur)||!toting(obj) || closng) goto l2011; prop[fissur] = 1-prop[fissur]; pspeak(fissur, 2-prop[fissur]); goto l2012; case 10: case 11: case 18: /* calm, walk, quit */ case 24: case 25: case 26: /* score, foo, brief */ case 30: case 31: /* suspend, hours */ goto l2011; l9120: case 12: /* kill */ switch (trkill()) { case 8000: goto l8000; case 8: goto l8; case 2011: goto l2011; case 2608: goto l2608; case 19000: done(3); default: bug(112); } l9130: case 13: /* pour */ if (obj == bottle || obj == 0) obj = liq(); if (obj == 0) goto l8000; if (!toting(obj)) goto l2011; spk = 78; if (obj != oil && obj != water) goto l2011; prop[bottle] = 1; place[obj] = 0; spk = 77; if (!(at(plant) || at(door))) goto l2011; if (at(door)) { prop[door] = 0; /* 9132 */ if (obj == oil) prop[door] = 1; spk = 113 + prop[door]; goto l2011; } spk = 112; if (obj != water) goto l2011; pspeak(plant, prop[plant] + 1); prop[plant] = (prop[plant] + 2) % 6; prop[plant2] = prop[plant] / 2; k = null; goto l8; case 14: /* 9140 - eat */ if (obj == food) goto l8142; if (obj == bird || obj == snake || obj == clam || obj == oyster || obj == dwarf || obj == dragon || obj == troll || obj == bear) spk = 71; goto l2011; l9150: case 15: /* 9150 - drink */ if (obj == 0 && liqloc(loc) != water && (liq() != water || !here(bottle))) goto l8000; if (obj != 0 && obj != water) spk = 110; if (spk == 110 || liq() != water || !here(bottle)) goto l2011; prop[bottle] = 1; place[water] = 0; spk = 74; goto l2011; case 16: /* 9160: rub */ if (obj != lamp) spk = 76; goto l2011; case 17: /* 9170: throw */ switch (trtoss()) { case 2011: goto l2011; case 9020: goto l9020; case 9120: goto l9120; case 8: goto l8; case 9210: goto l9210; default: bug(113); } case 19: case 20: /* 9190: find, invent */ if (at(obj) || (liq() == obj && at(bottle)) || k == liqloc(loc)) spk = 94; for (i = 1; i <= 5; i++) if (dloc[i] == loc && dflag >= 2 && obj == dwarf) spk = 94; if (closed) spk = 138; if (toting(obj)) spk = 24; goto l2011; l9210: case 21: /* feed */ switch (trfeed()) { case 2011: goto l2011; default: bug(114); } l9220: case 22: /* fill */ switch (trfill()) { case 2011: goto l2011; case 8000: goto l8000; case 9020: goto l9020; default: bug(115); } l9230: case 23: /* blast */ if (prop[rod2] < 0 || !closed) goto l2011; bonus = 133; if (loc == 115) bonus = 134; if (here(rod2)) bonus = 135; rspeak(bonus); done(2); l9270: case 27: /* read */ if (dark()) goto l5190; if (obj == magzin) spk = 190; if (obj == tablet) spk = 196; if (obj == messag) spk = 191; if (obj == oyster && hinted[2] && toting(oyster)) spk = 194; if (obj != oyster || hinted[2] || !toting(oyster) || !closed) goto l2011; hinted[2] = yes(192, 193, 54); goto l2012; l9280: case 28: /* break */ if (obj == mirror) spk = 148; if (obj == vase && prop[vase] == 0) { spk = 198; if (toting(vase)) drop(vase, loc); prop[vase] = 2; fixed[vase] = -1; goto l2011; } if (obj != mirror||!closed) goto l2011; rspeak(197); done(3); l9290: case 29: /* wake */ if (obj != dwarf||!closed) goto l2011; rspeak(199); done(3); default: bug(24); } l5000: obj = k; if (fixed[k] != loc && !here(k)) goto l5100; l5010: if (wd2[0] != 0) goto l2800; if (verb != 0) goto l4090; printf("What do you want to do with the %s?\n", wd1); goto l2600; l5100: if (k != grate) goto l5110; if (loc == 1 || loc == 4 || loc == 7) k = dprssn; if (loc > 9 && loc < 15) k = entrnc; if (k != grate) goto l8; l5110: if (k != dwarf) goto l5120; for (i = 1; i <= 5; i++) if (dloc[i] == loc && dflag >= 2) goto l5010; l5120: if ((liq() == k && here(bottle)) || k == liqloc(loc)) goto l5010; if (obj != plant || !at(plant2) || prop[plant2] == 0) goto l5130; obj = plant2; goto l5010; l5130: if (obj != knife || knfloc != loc) goto l5140; knfloc = -1; spk = 116; goto l2011; l5140: if (obj != rod || !here(rod2)) goto l5190; obj = rod2; goto l5010; l5190: if ((verb == find || verb == invent) && wd2[0] == 0) goto l5010; printf("I see no %s here\n", wd1); goto l2012; } }
/*.BE*/ int spline /* nichtparametrischer kubischer Polynomspline .......*/ /*.BA*/ /*.IX{spline}*/ /*.BE*/ ( int m, /* Anzahl der Stuetzstellen ............*/ REAL x[], /* Stuetzstellen .......................*/ REAL y[], /* Stuetzwerte .........................*/ int marg_cond, /* Art der Randbedingung ...............*/ REAL marg_0, /* linke Randbedingung .................*/ REAL marg_n, /* rechte Randbedingung ................*/ int save, /* dynamische Hilfsfelder sichern? .....*/ REAL b[], /* Splinekoeffizienten von (x-x[i]) ....*/ REAL c[], /* Splinekoeffizienten von (x-x[i])^2 ..*/ REAL d[] /* Splinekoeffizienten von (x-x[i])^3 ..*/ ) /* Fehlercode ..........................*/ /*.BA*/ /*********************************************************************** * zu den vorgegebenen Wertepaaren * * (x[i], y[i]), i = 0(1)m-1 * * die Koeffizienten eines nichtparametrischen interpolierenden * * kubischen Polynomplines berechnen. * .BE*) * Die Art der Randbedingung wird durch den Parameter marg_cond * * festgelegt. Die x[i] muessen streng monoton wachsen. * * Bei wiederholten Aufrufen mit gleichen Stuetzstellen, aber verschie- * * denen Stuetzwerten besteht die Moeglichkeit, die erneute Aufstellung * * und Zerlegung der Matrix des Gleichungssystems zu vermeiden, indem * * man den Parameter save von Null verschieden waehlt und so die Be- * * schreibung der Zerlegungsmatrizen fuer den naechsten Aufruf rettet. * * Wichtig: Damit der Speicher fuer die Hilfsfelder wieder frei wird * * -------- und bei weiteren Aufrufen nicht mit falschen Zerlegungs- * * matrizen gearbeitet wird, muss der letzte Aufruf einer * * zusammengehoerigen Aufruffolge mit save = 0 statt mit * * save = 1 ausgefuehrt werden! * * * * Eingabeparameter: * * ================= * * m: Anzahl der Stuetzstellen (mindestens 3) * * x: [0..m-1]-Vektor mit den x-Koordinaten der Wertepaare * * (wird nicht benoetigt, falls der vorige Aufruf mit * * save != 0 stattfand) * * y: [0..m-1]-Vektor mit den y-Koordinaten der Wertepaare * * marg_cond: = 0: not-a-knot-Bedingung (=> marg_0, marg_n ohne * * Bedeutung) * * = 1: marg_0, marg_n sind 1. Ableitungen. * * = 2: marg_0, marg_n sind 2. Ableitungen. * * (Fuer marg_0 = marg_n = 0 erhaelt man einen * * natuerlichen Spline.) * * = 3: marg_0, marg_n sind 3. Ableitungen. * * = 4: periodischer Spline (=> marg_0, marg_n ohne * * Bedeutung) * * marg_0: Randbedingung in x[0] * * marg_n: Randbedingung in x[m-1] * * save: Flagge, die anzeigt, ob der Speicher fuer die Hilfsfel- * * der mit den Zerlegungsmatrizen fuer den naechsten Aufruf * * aufbewahrt werden soll. Im Normalfall ist save = 0 zu * * setzen. Wenn man mehrere Splinefunktionen mit denselben * * Stuetzstellen x[i], aber anderen y[i] berechnen will * * (z. B. bei parametrischen Splines), kann man ab dem * * zweiten Aufruf Rechenzeit sparen, indem man beim ersten * * Aufruf save = 1 setzt. Dann wird naemlich die neuerliche * * Aufstellung und Zerlegung der Tridiagonalmatrix umgangen * * (=> ca. 4*m Punktoperationen weniger). * * Im letzten Aufruf muss man save = 0 waehlen, damit der * * von den Hilfsfeldern beanspruchte dynamische Speicher * * fuer andere Programmteile wieder verfuegbar wird. * * * * Ausgabeparameter: * * ================= * * b: \ [0..m-2]-Vektoren mit den Splinekoeffizienten nach dem Ansatz * * c: > s(x) = a[i] + b[i] * (x - x[i]) + c[i] * (x - x[i]) ^ 2 * * d: / + d[i] * (x - x[i]) ^ 3. * * a entspricht y, * * c hat (wie a) noch ein zusaetzliches Element c[m-1]. * * * * Funktionswert: * * ============== * * = 0: kein Fehler * * = -i: Monotoniefehler: x[i-1] >= x[i] * * = 1: falscher Wert fuer marg_cond * * = 2: m < 3 * * = 3: nicht genuegend Heapspeicher fuer die Hilfsfelder * * = 4: marg_cond = 4: Eingabedaten nichtperiodisch * * > 4: Fehler in trdiag() oder tzdiag() * * Im Fehlerfall sind die Werte der Ausgabeparameter unbestimmt, und * * der Speicher fuer die Hilfsfelder wird freigegeben. * * * * benutzte globale Namen: * * ======================= * * REAL, vminit, vmalloc, vmcomplete, vmfree, VEKTOR, trdiag, tzdiag, * * NULL, ZERO, THREE, HALF, TWO * .BA*) ***********************************************************************/ /*.BE*/ { #define ciao(fehler) /* dafuer sorgen, dass vor dem Beenden */\ { \ /* von spline() aufgeraeumt wird */\ vmfree(vmblock); /* Speicherplatz fuer die Hilfsfelder freigeben */\ vmblock = NULL; /* und dies auch anzeigen */\ return fehler; /* den Fehlercode an den Aufrufer weiterreichen */\ } static void *vmblock = NULL; /* Liste der dynamisch vereinbarten Vek- */ /* toren. Der Wert NULL zeigt an, dass */ /* noch keine Hilfsvektoren aus eventu- */ /* ellen frueheren Aufrufen existieren, */ /* dass dies also der erste Aufruf einer */ /* zusammengehoerenden Folge mit glei- */ /* chen Stuetzstellen ist. */ static REAL *h, /* [0..m-2]-Vektor mit den Laengen der Stuetz- */ /* stellenintervalle */ *lower, /* [0..m-2]-Vektor mit der unteren Nebendiago- */ /* nale der Matrix, spaeter Zerlegungsmatrix */ /* von trdiag() bzw. tzdiag() */ *diag, /* [0..m-2]-Vektor mit der Hauptdiagonale der */ /* Matrix, spaeter Zerlegungsmatrix von */ /* trdiag() bzw. tzdiag() */ *upper, /* [0..m-2]-Vektor mit der oberen Nebendiago- */ /* nale der Matrix, spaeter Zerlegungsmatrix */ /* von trdiag() bzw. tzdiag() */ *lowrow, /* [0..m-4]-Vektor mit der unteren Zeile der */ /* Matrix, spaeter Zerlegungsmatrix von tzdiag() */ *ricol; /* [0..m-4]-Vektor mit der rechten Spalte der */ /* Matrix, spaeter Zerlegungsmatrix von tzdiag() */ int n, /* m - 1, Index der letzten Stuetzstelle */ fehler, /* Fehlercode von trdiag() bzw. tzdiag() */ i, /* Laufvariable */ erster_aufruf; /* Flagge, die anzeigt, dass gerade der */ /* erste Aufruf einer Folge stattfindet */ n = m - 1; if (n < 2) /* zu kleinen Wert fuer n abfangen */ ciao(2); if (marg_cond < 0 || marg_cond > 4) /* falsches marg_cond abfangen */ ciao(1); if (marg_cond == 4) /* periodischer Spline? */ if (y[n] != y[0]) /* Periodizitaet ueberpruefen */ ciao(4); /* 1. Aufruf: Speicher fuer die Hilfsfelder anfordern: 4 [0..n-1]- */ /* Vektoren (im periodischen Fall noch 2 [0..n-3]-Vektoren) */ if (vmblock == NULL) /* erster Aufruf einer Folge? */ { erster_aufruf = 1; #define MYALLOC(l) (REAL *)vmalloc(vmblock, VEKTOR, (l), 0) vmblock = vminit(); /* Speicherblock initialisieren */ h = MYALLOC(n); /* Speicher fuer die */ lower = MYALLOC(n); /* Hilfsvektoren anfordern */ diag = MYALLOC(n); upper = MYALLOC(n); if (marg_cond == 4) /* periodischer Spline mit */ if (n > 2) /* genuegend Stuetzstellen? */ lowrow = MYALLOC(n - 2), /* auch die zusaetzlichen */ ricol = MYALLOC(n - 2); /* Vektoren versorgen */ #undef MYALLOC } else erster_aufruf = 0; if (! vmcomplete(vmblock)) /* Ging eine der Speicheranforderungen */ ciao(3); /* fuer den Block schief? */ if (erster_aufruf) for (i = 0; i < n; i++) /* Schrittweiten berechnen und dabei die */ { /* Stuetzstellen auf Monotonie pruefen */ h[i] = x[i + 1] - x[i]; /* Schrittweiten berechnen */ if (h[i] <= ZERO) /* Stuetzstellen nicht monoton wachsend? */ ciao(-(i + 1)); } for (i = 0; i < n - 1; i++) /* das Gleichungssystem aufstellen */ { /* rechte Seite */ c[i] = THREE * ((y[i + 2] - y[i + 1]) / h[i + 1] - (y[i + 1] - y[i]) / h[i]); if (erster_aufruf) diag[i] = TWO * (h[i] + h[i + 1]), /* Hauptdiagonale */ lower[i + 1] = upper[i] = h[i + 1]; /* untere und obere */ } /* Nebendiagonale */ switch (marg_cond) /* je nach Randbedingung einige Koeffizienten */ { /* des Gleichungssystems korrigieren */ case 0: /* not-a-knot-Bedingung? */ if (n == 2) /* nur drei Stuetzstellen? */ { /* Da in diesem Fall das Gleichungssystem */ /* unterbestimmt ist, wird nur ein Polynom */ /* 2. Grades berechnet. */ c[0] /= THREE; /* rechte Seite */ if (erster_aufruf) diag[0] *= HALF; /* auch die Matrix */ } else /* mehr als drei Stuetzstellen? */ { /* rechte */ c[0] *= h[1] / (h[0] + h[1]); /* Seite */ c[n - 2] *= h[n - 2] / (h[n - 1] + h[n - 2]); if (erster_aufruf) diag[0] -= h[0], /* auch die */ diag[n - 2] -= h[n - 1], /* Matrix */ upper[0] -= h[0], lower[n - 2] -= h[n - 1]; } break; case 1: /* erste Randableitungen vorgegeben? */ c[0] -= (REAL)1.5 * ((y[1] - y[0]) / h[0] - marg_0); c[n - 2] -= (REAL)1.5 * (marg_n - (y[n] - y[n - 1]) / h[n - 1]); if (erster_aufruf) diag[0] -= HALF * h[0], /* auch die Matrix */ diag[n - 2] -= HALF * h[n - 1]; /* vorbesetzen */ break; case 2: /* zweite Randableitungen vorgegeben? */ c[0] -= h[0] * HALF * marg_0; c[n - 2] -= h[n - 1] * HALF * marg_n; break; case 3: /* dritte Randableitungen vorgegeben? */ c[0] += HALF * marg_0 * h[0] * h[0]; c[n - 2] -= HALF * marg_n * h[n - 1] * h[n - 1]; if (erster_aufruf) diag[0] += h[0], /* auch die Matrix */ diag[n - 2] += h[n - 1]; /* vorbesetzen */ break; case 4: /* periodischer Spline? */ c[n - 1] = THREE * ((y[1] - y[0]) / h[0] - (y[n] - y[n - 1]) / h[n - 1]); if (erster_aufruf) if (n > 2) diag[n - 1] = TWO * (h[0] + h[n - 1]), ricol[0] = lowrow[0] = h[0]; } switch (n) /* das Gleichungssystem loesen und damit */ { /* die Splinekoeffizienten c[i] berechnen */ case 2: /* nur drei Stuetzstellen => */ /* => Loesung direkt berechnen */ if (marg_cond == 4) /* periodischer Spline? */ c[1] = THREE * (y[0] - y[1]) / (x[2] - x[1]) / (x[1] - x[0]), c[2] = - c[1]; else c[1] = c[0] / diag[0]; break; default: /* mehr als drei Stuetzstellen? */ if (marg_cond == 4) /* periodischer Spline? */ fehler = tzdiag(n, lower, diag, upper, lowrow, ricol, c, !erster_aufruf); else /* nichtperiodischer Spline? */ fehler = trdiag(n - 1, lower, diag, upper, c, !erster_aufruf); if (fehler != 0) /* Fehler in tzdiag() oder in trdiag()? */ ciao(fehler + 4); for (i = n; i != 0; i--) /* die Elemente des Loesungsvektors */ c[i] = c[i - 1]; /* eine Position nach rechts schieben */ } switch (marg_cond) /* in Abhaengigkeit von der Randbedingung den */ { /* ersten und letzten Wert von c korrigieren */ case 0: /* not-a-knot-Bedingung? */ if (n == 2) /* nur drei Stuetzstellen? */ c[0] = c[2] = c[1]; else /* mehr als drei Stuetzstellen? */ c[0] = c[1] + h[0] * (c[1] - c[2]) / h[1], c[n] = c[n - 1] + h[n - 1] * (c[n - 1] - c[n - 2]) / h[n - 2]; break; case 1: /* erste Randableitungen vorgegeben? */ c[0] = (REAL)1.5 * ((y[1] - y[0]) / h[0] - marg_0); c[0] = (c[0] - c[1] * h[0] * HALF) / h[0]; c[n] = (REAL)-1.5 * ((y[n] - y[n - 1]) / h[n - 1] - marg_n); c[n] = (c[n] - c[n - 1] * h[n - 1] * HALF) / h[n - 1]; break; case 2: /* zweite Randableitungen vorgegeben? */ c[0] = marg_0 * HALF; c[n] = marg_n * HALF; break; case 3: /* dritte Randableitungen vorgegeben? */ c[0] = c[1] - marg_0 * HALF * h[0]; c[n] = c[n - 1] + marg_n * HALF * h[n - 1]; break; case 4: /* periodischer Spline? */ c[0] = c[n]; } for (i = 0; i < n; i++) /* die restlichen */ b[i] = (y[i + 1] - y[i]) / h[i] - h[i] * /* Splinekoeffizienten */ (c[i + 1] + TWO * c[i]) / THREE, /* b[i] und d[i] */ d[i] = (c[i + 1] - c[i]) / (THREE * h[i]);/* berechnen */ if (!save) /* Hilfsfelder nicht aufbewahren */ ciao(0); /* (letzter Aufruf einer Folge)? */ return 0; #undef ciao }