• No results found

2.10. H¨ arledda typer i Fortran 90

N/A
N/A
Protected

Academic year: 2021

Share "2.10. H¨ arledda typer i Fortran 90"

Copied!
22
0
0

Loading.... (view fulltext now)

Full text

(1)

2.10. H¨ arledda typer i Fortran 90

En sammanst¨allning av v¨arden, som inte n¨odv¨andigtvis ¨ar av samma typ, brukar kallas f¨or en struktur.

Objekten som ing˚ar i en s˚adan struktur brukar kallas komponenter. Strukturkomponenter ges s¨arskilda namn i Fortran, i motsats till vektorkomponenter, som anges med nummer.

Antag att vi vill spara p˚a datorn adressuppgifter f¨or personer som ing˚ar i en adressbok. Vi kan d˚a behandla uppgifterna f¨or en person som en struktur med t.ex. fyra komponenter: namn, adress, telefon, kommentar.

Strukturen kan vi kalla person. Om vi vill, kan vi g˚a ett steg vidare och uppfatta t.ex. adress som en struktur med komponenterna gatnummer, gatnamn, stad, postnummer.

Adressen f¨or en person Kalle kan man d˚a h¨anvisa till med uttrycket Kalle%adress, som i sin tur ¨ar en struktur. Staden d¨ar Kalle bor skulle man t.ex. kunna h¨anvisa till med Kalle%adress%stad. F¨or att deklarera Kalle som en struktur m˚aste man f¨orst definera en ny typ, t.ex. person, och sedan deklarera Kalle som en variabel av denna typ.

Detta ¨ar m¨ojligt i Fortran 90, d¨ar man kan deklarera egna typer f¨orutom de n¨amnda inbyggda typerna.

S˚adana datatyper h¨arleds fr˚an existerande inbyggda eller tidigare definierade datatyper och kallas d¨arf¨or ocks˚a f¨or h¨arledda typer. En h¨arledd datatyp deklareras genom en f¨oljd av satser av formen (ett dubbelkolon kan ins¨attas efter TYPE):

(2)

TYPE nytyp

(deklarationer) ...

END TYPE nytyp

Som ett exempel skall vi t¨anka oss att vi vill s¨atta upp en databas f¨or en f¨orening som inneh˚aller medlems- adresser. Det ¨ar d˚a praktiskt att definiera en ny datatyp, som t.ex. kallas medlem:

TYPE medlem

CHARACTER(LEN=20) :: titel,f_namn,t_namn CHARACTER(LEN=20) :: adress, ort*10

INTEGER :: postnr END TYPE medlem

Variabler av en h¨arledd datatyp kan deklareras p˚a samma s¨att som tidigare behandlade variabler, med undantag av att typnamnet skrivs inom parentes, och f¨oreg˚as av ordet TYPE:

TYPE(medlem) :: kalle, lisa

(3)

Ett v¨arde av en h¨arledd typ skrivs som en lista av konstanter, som svarar mot de variabeltyper, som ing˚ar i den h¨arledda typens definition. Listan omges av en parentes, och f¨oreg˚as av typnamnet:

kalle = medlem("stud","Karl","Fridolfsson","Stugv. 17 A 21","K:stad",1234) lisa = medlem("stud","Elisabet", "Fridolin","˚Asv. 21 A 17","K:stad",1234)

F¨or att h¨anvisa till en komponent av en h¨arledd datatyp, skriver man datatypens namn, efterf¨oljt av ett procenttecken och komponentens namn, t.ex. lisa%t_namn = "Fridolin". I definitionen f¨or en ny datatyp kan givetvis ocks˚a ing˚a en tidigare deklarerad h¨arledd typ.

Som ett exempel p˚a hur man i praktiken kan anv¨anda h¨arledda typer i Fortran skall vi skriva ett program som l¨aser in koordinaterna f¨or tv˚a punkter i planet och d¨arp˚a ber¨aknar ekvationen f¨or en r¨at linje som passerar dem.

Vi kan g¨ora detta genom att definiera tv˚a datatyper, av vilka den ena anger en punkt med hj¨alp av tv˚a koordinater (x, y) och den andra beskriver linjens ekvation ax + by + c = 0 med hj¨alp av koefficienterna a, b, c.

Om de tv˚a punkterna inte sammanfaller och har koordinaterna (x1, y1) och (x2, y2) s˚a ¨ar linjens vinkelko- efficient k = (y2− y1)/(x2− x1), och ekvationen f¨or en r¨at linje som g˚ar genom punkterna kan skrivas y = k(x − x1) + y1 (enpunktsformeln). Genom j¨amf¨orelse med normalformen finner man d˚a koefficien- terna a = y2 − y1, b = x1 − x2 och c = x2y1 − x1y2.

(4)

Ett program som ber¨aknar linjens ekvation skulle d˚a kunna skrivas p˚a f¨oljande s¨att:

PROGRAM ekvation IMPLICIT NONE

! Typdefinitioner:

TYPE punkt ! kartesiska koordinater f¨or en punkt REAL :: x,y

END TYPE punkt

TYPE linje ! koefficienter f¨or linjens ekvation REAL :: a,b,c

END TYPE linje

TYPE(punkt) :: p1, p2 TYPE(linje) :: p1p2

! L¨as datapunkter

PRINT *, "Ange koordinaterna f¨or f¨orsta punkten"

READ *,p1

PRINT *, "Ange koordinaterna f¨or andra punkten"

READ *,p2

! Ber¨akna koefficienterna i ekvationen p1p2%a = p2%y - p1%y

p1p2%b = p1%x - p2%x

p1p2%c = p2%x*p1%y - p1%x*p2%y

! Skriv ut resultat

PRINT *, "Ekvationen f¨or linjen genom de tv˚a punkterna ¨ar"

PRINT *, "ax + by + c = 0"

PRINT *, "d¨ar a = ", p1p2%a PRINT *, " b = ", p1p2%b PRINT *, " c = ", p1p2%c END PROGRAM ekvation

(5)

Programmet kan g¨oras betydligt elegantare om man anv¨ander en modul f¨or att definera de nya typerna.

Vi skall se p˚a ett enkelt exempel, d¨ar koordinater definieras i ett tredimensionellt rum med en h¨arledd typ, som initialiseras med en funktion av samma typ:

MODULE tredim IMPLICIT NONE TYPE koord

REAL :: x,y,z END TYPE koord CONTAINS

TYPE(koord) FUNCTION InitKoord(x,y,z) REAL, INTENT(IN), OPTIONAL :: x,y,z

! Nollst¨all koordinaterna

InitKoord = koord(0.0, 0.0, 0.0) IF (PRESENT(x)) InitKoord%x = x IF (PRESENT(y)) InitKoord%y = y IF (PRESENT(z)) InitKoord%z = z END FUNCTION InitKoord

END MODULE tredim

H¨ar har vi anv¨ant den inbyggda funktionen PRESENT f¨or att ta reda p˚a om ett verkligt argument ¨ar associerat med den invariabel, som har attributet OPTIONAL. Om inget argument anges, blir koordinaterna nollst¨allda. Modulen kan testas med f¨oljande program:

(6)

PROGRAM test3dim USE tredim

IMPLICIT NONE

TYPE (koord) :: p1, p2, p3 p1 = InitKoord()

p2 = InitKoord(1.0,-1.0) p3 = InitKoord(z=3.0) PRINT *, "P1: ",p1 PRINT *, "P2: ",p2 PRINT *, "P3: ",p3 END PROGRAM test3dim

Vi skall nu till¨ampa en liknande metod p˚a programmet som ber¨aknar den r¨ata linjens ekvation.

F¨orst s¨atter vi in de nya typerna i en modul, och skriver en subrutin f¨or att ber¨akna koefficienterna, som inkapslas i en annan modul:

(7)

MODULE linjedata IMPLICIT NONE SAVE

! Typdefinitioner:

TYPE punkt ! kartesiska koordinater f¨or en punkt REAL :: x,y

END TYPE punkt

TYPE linje ! koefficienter f¨or linjens ekvation REAL :: a,b,c

END TYPE linje

END MODULE linjedata MODULE geometri

USE linjedata IMPLICIT NONE CONTAINS

SUBROUTINE ekvation(linje1,punkt1,punkt2) IMPLICIT NONE

TYPE(linje), INTENT(OUT) :: linje1 ! utdata TYPE(punkt), INTENT(IN) :: punkt1, punkt2 ! indata

! Ber¨akna linjens koefficienter linje1%a = punkt2%y - punkt1%y linje1%b = punkt1%x - punkt2%x

linje1%c = punkt2%x*punkt1%y - punkt1%x*punkt2%y END SUBROUTINE ekvation

(8)

END MODULE geometri PROGRAM testgeom

USE geometri IMPLICIT NONE

! Variabeldeklarationer:

TYPE(punkt) :: p1, p2 TYPE(linje) :: p1p2

! L¨as datapunkter

PRINT *, "Ange koordinaterna f¨or f¨orsta punkten"

READ *,p1

PRINT *, "Ange koordinaterna f¨or andra punkten"

READ *,p2

! Anropa subrutinen ekvation CALL ekvation(p1p2,p1,p2)

! Skriv ut resultat

PRINT *, "Ekvationen f¨or linjen genom de tv˚a punkterna ¨ar"

PRINT *, "ax + by + c = 0"

PRINT *, "d¨ar a = ", p1p2%a PRINT *, " b = ", p1p2%b PRINT *, " c = ", p1p2%c END PROGRAM testgeom

Observera h¨ar, att man inte beh¨over s¨atta in USE linjedata i subrutinen ekvation eftersom denna sats redan ing˚ar i modulen. I testprogrammet r¨acker det likas˚a att s¨atta USE geometri.

(9)

Som ett annat exempel p˚a anv¨andningen av datatyper, skall vi g¨ora ett program som ber¨aknar summan och produkten av tv˚a komplexa tal. Som bekant kan ett komplext tal z uttryckas som z = x + iy, d¨ar i betecknar den imagin¨ara enheten.

Summan av tv˚a komplexa tal z1 = x1 + iy1 och z2 = x2 + iy2 kan skrivas z1 + z2 = (x1 + x2) + i(y1 + y2)

och deras produkt ¨ar

z1z2 = (x1x2 − y1y2) + i(x1y2 + x2y1).

Vi skall b¨orja med att definiera en s¨arskild datatyp f¨or de komplexa talen, l¨aser sedan tv˚a komplexa tal, ber¨aknar d¨arp˚a deras summa och produkt, och skriver till sist ut resultatet:

PROGRAM komplex IMPLICIT NONE

! Deklarationer:

TYPE :: komplext_tal

REAL :: reell_del, imaginar_del END TYPE komplext_tal

TYPE(komplext_tal) :: z1, z2, summa, produkt

(10)

! L¨as in talen:

PRINT *, "Skriv tv˚a komplexa tal , uttryckta som tv˚a tal "

PRINT *, "som representerar den reella och imagin¨ara delen:"

READ *, z1, z2

! Ber¨akna summan och produkten:

summa%reell_del = z1%reell_del + z2%reell_del

summa%imaginar_del = z1%imaginar_del + z2%imaginar_del produkt%reell_del = z1%reell_del*z2%reell_del - &

z1%imaginar_del*z2%imaginar_del produkt%imaginar_del = z1%reell_del*z2%imaginar_del + &

z1%imaginar_del*z2%reell_del

! Skriv ut resultat:

PRINT *, "Summan av talen ¨ar ", summa

PRINT *, "och deras produkt ¨ar ", produkt STOP

END PROGRAM komplex

Ocks˚a h¨ar kan vi anv¨anda oss av en modul f¨or att definiera de komplexa talen, samt en annan modul, som definierar tv˚a funktionsrutiner, som ber¨aknar summan, resp. produkten av tv˚a komplexa tal:

(11)

MODULE kompl_tal IMPLICIT NONE

TYPE :: komplext_tal

REAL :: reell_del, imaginar_del END TYPE komplext_tal

END MODULE kompl_tal MODULE functions CONTAINS

FUNCTION kompl_add(z1,z2) USE kompl_tal

IMPLICIT NONE

! Deklarationer

TYPE(komplext_tal) :: kompl_add

TYPE(komplext_tal) , INTENT(IN) :: z1, z2

! R¨akna ut resultatet

kompl_add%reell_del = z1%reell_del + z2%reell_del kompl_add%imaginar_del = z1%imaginar_del + &

z2%imaginar_del RETURN

END FUNCTION kompl_add FUNCTION kompl_mult(z1,z2)

USE kompl_tal USE functions

(12)

IMPLICIT NONE

! Deklarationer

TYPE(komplext_tal) :: kompl_mult

TYPE(komplext_tal) , INTENT(IN) :: z1, z2

! R¨akna ut resultatet

kompl_mult%reell_del = z1%reell_del*z2%reell_del-&

z1%imaginar_del*z2%imaginar_del kompl_mult%imaginar_del= &

z1%reell_del*z2%imaginar_del+ &

z1%imaginar_del*z2%reell_del RETURN

END FUNCTION kompl_mult END MODULE functions PROGRAM komplex_test

USE kompl_tal USE functions IMPLICIT NONE

! Deklarera funktionerna, och de komplexa talen

TYPE(komplext_tal) , EXTERNAL :: kompl_add, kompl_mult TYPE(komplext_tal) :: a,b

! L¨as in talen:

PRINT *, "Skriv tv˚a komplexa tal , uttryckta som tv˚a tal "

PRINT *, "som representerar den reella och imagin¨ara delen:"

READ *, a,b

(13)

! Skriv ut resultat:

PRINT *, "Summan av talen ¨ar ", kompl_add(a,b) PRINT *, "och deras produkt ¨ar ", kompl_mult(a,b) STOP

END PROGRAM komplex_test

Matriser och vektorer kan ofta anv¨andas f¨or att underl¨atta programmeringen. S˚alunda kan vektorer anv¨an- das i kombination med h¨arledda typer, om antalet komponenter blir stort. Ett enkelt exempel ¨ar en h¨arledd typ som definierar en cirkel. Cirkeln kan anges med hj¨alp av medelpunktens koordinater och radien:

TYPE cirkel

REAL, DIMENSION(3) :: medelpunkt REAL :: radie

END TYPE cirkel

Till medelpunktens x–koordinat kan man d˚a h¨anvisa med cirkel%medelpunkt(1).

Ett annat exempel utg¨ors av en f¨orenings adresslista:

(14)

PROGRAM adresser IMPLICIT NONE TYPE medlem

CHARACTER(LEN=20) :: fnamn, tnamn CHARACTER(LEN=30) :: adress

CHARACTER(LEN=15) :: stad INTEGER :: postnr

END TYPE medlem

INTEGER, PARAMETER :: max_medl INTEGER :: i

TYPE(medlem), DIMENSION(max_medl) :: fmedl ...

DO i=1,max_medl READ *, fmedl(i)

IF (fmedl(i)%fnamn = "END") EXIT ! END betyder slut p˚a data END DO

...

END PROGRAM adresser

(15)

2.11. Avancerade moduler och procedurer i Fortran 90

Vi har redan tidigare anv¨ant oss av procedurer, som definierats i en modul (¨aven kallade modulprocedurer).

Moduler, som inneh˚aller procedurdefinitioner k¨anns igen p˚a satsen CONTAINS, som f¨oreg˚ar procedurerna:

MODULE (namn)

(deklarationer ...) ...

CONTAINS

(modulprocedur 1) (modulprocedur 2) ...

END MODULE (namn)

Anv¨ander man modulprocedurer, s˚a beh¨ovs inte explicita gr¨anssnitt, eftersom procedurer som definieras i en modul har tillg˚ang till alla data och typdeklarationer i modulen, och deras gr¨anssnitt ¨ar sinsemellan explicita.

(16)

I fysik och matematik kombinerar man ofta flera likartade variabler med varandra till stora enheter, s˚asom t.ex. komplexa tal, vektorer och matriser. Vi har redan tidigare visat hur man kan definiera en komplex typ i Fortran 90, fast¨an det inte ¨ar n¨odv¨andigt, eftersom som det finns en inbyggd typ COMPLEX. Emellertid kan man framst¨alla ett komplext tal p˚a tv˚a olika s¨att, antingen i kartesisk form z(x, y) = x + iy, eller pol¨ar form z(r, φ) = r(cos φ + i sin φ). B˚ada dessa framst¨allningar kan, som vi ser, h¨arledas ur tv˚a reella tal.

Detta kan leda till problem, ifall man har skrivit modulen, som deklarerar en typ komplex f¨or ett komplext tal p˚a basen av den pol¨ara formen. En okritisk anv¨andare skulle d˚a l¨att kunna g¨ora tillordningen z = komplex(1, pi), i tron att den betyder detsamma som z = 1 + iπ, d˚a den i sj¨alva verket betyder z = −1!. Det ¨ar d¨arf¨or b¨attre om man kan kontrollera anv¨andningen av komponenterna av en h¨arledd typ i programmet, s˚a att de antingen ¨ar fritt tillg¨angliga i hela programmet (PUBLIC), eller endast tillg¨angliga i den modul, d¨ar den h¨arledda typen deklareras (PRIVATE).

Komponenterna av en h¨arledd typ g¨ors privata genom att man ins¨atter ordet PRIVATE framf¨or den f¨orsta deklarationen:

TYPE komplex PRIVATE

REAL :: r, phi END TYPE komplex

(17)

I detta exempel kommer komponenterna av komplex att vara fritt tillg¨angliga inom hela modulen, men otillg¨angliga utanf¨or den.

Som ett exempel skall vi studera en modul, som inneh˚aller en deklaration f¨or en h¨arledd typ kallad vektor och en procedur som bildar skal¨arprodukten av tv˚a vektorer.

Till en b¨orjan skall vi deklarera en h¨arledd typ som beskriver en vektor. En vektor uppfattas som en r¨acka reella tal, vilkas antal best¨ammer vektorns dimension. En vektor har allts˚a tv˚a komponenter, den reella talr¨ackan, som vi kallar vektorns element, och dess dimension. En vektortyp kan d¨arf¨or definieras p˚a f¨oljande s¨att:

TYPE vektor PRIVATE

INTEGER :: dim

REAL, DIMENSION(max_dim) :: element END TYPE vektor

Observera anv¨andningen av PRIVATE, som har till f¨oljd att elementen av en vektortyp inte ¨ar tillg¨angliga utanf¨or den modul, d¨ar den ¨ar definierad. Via USE kan man dock komma ˚at en vektortyp i sin helhet.

Konstanten max_dim anger h¨ar vektorns st¨orsta till˚atna dimension. Denna konstant deklareras i modulen.

Om man m˚aste ¨andra dimensionen, beh¨over man endast g¨ora denna f¨or¨andring i modulen.

(18)

F¨or att kunna anv¨anda vektorer som deklarerats p˚a detta s¨att, m˚aste man f¨orst skriva en funktionsrutin, som alstrar en vektor fr˚an en talr¨acka. Denna rutin ¨ar i sj¨alva verket r¨att s˚a enkel, eftersom den f¨orst bara kontrollerar att antalet element inte ¨overskrider max_dim, varp˚a den anger vektorns dimension, och dess element. D¨arp˚a skriver man en enkel funktionsrutin som ber¨aknar dimensionen av en s˚adan vektor, och en annan rutin som skriver ut elementen av en vektor som en talr¨acka. Till sist skriver man en rutin som ber¨aknar skal¨arprodukten av tv˚a vektorer, som definierats p˚a ovan angivna s¨att. Hela modulen ser ut p˚a f¨oljande s¨att:

MODULE vektorer IMPLICIT NONE

! Ange vektorernas maximidimension:

INTEGER, PARAMETER :: max_dim = 50

! H¨arled en vektortyp:

TYPE :: vektor PRIVATE

INTEGER :: dim

REAL, DIMENSION(max_dim) :: element END TYPE vektor

CONTAINS

FUNCTION alstra_vektor(a,n) IMPLICIT NONE

! Denna funktionsrutin alstrar en vektor ur n element

! av r¨ackan a

! Deklarera argumenten

TYPE (vektor) :: alstra_vektor INTEGER, INTENT(IN) :: n

(19)

REAL, DIMENSION(:), INTENT(IN) :: a

! Kontrollera dimensionen IF (n > max_dim) THEN

! Dimensionen ¨ar f¨or stor

PRINT ’(1X,A,I4,A,I3)’, "Vektorns l¨angd ¨ar ",n, &

" - st¨orsta till˚atna l¨angd ¨ar ",max_dim alstra_vektor%dim = 0

ELSE

! kopiera n element i r¨ackan till en vektor alstra_vektor%dim = n

alstra_vektor%element(1:n) = a(1:n) END IF

RETURN

END FUNCTION alstra_vektor FUNCTION vektor_dim(x) IMPLICIT NONE

! Funktionen ber¨aknar en vektors dimension INTEGER :: vektor_dim

TYPE(vektor), INTENT(IN) :: x vektor_dim = x%dim

RETURN

END FUNCTION vektor_dim FUNCTION vektor_racka(x) IMPLICIT NONE

! Funktionen ger ut vektorelementen som en talr¨acka TYPE(vektor), INTENT(IN) :: x

REAL, DIMENSION(x%dim) :: vektor_racka vektor_racka(1:x%dim) = x%element(1:x%dim) RETURN

(20)

END FUNCTION vektor_racka REAL FUNCTION skal_prod(x,y) IMPLICIT NONE

! Funktionen ger ut skal¨arprodukten av tv˚a vektorer TYPE(vektor), INTENT(IN) :: x,y

! Lokala variabler REAL :: prod = 0.0 INTEGER :: i

! Kontrollera, att vektorerna har samma dimension IF (x%dim /= y%dim) THEN

! vektorerna ¨ar olika l˚anga

PRINT ’(A,I4,A,I4/,A)’, " Vektorerna har inte samma l¨angd: ", &

x%dim," och ",y%dim," Resultatet ¨ar noll!"

skal_prod = 0.0 ELSE

! ber¨akna skal¨arprodukten DO i=1,x%dim

prod = prod + x%element(i)*y%element(i) END DO

skal_prod = prod END IF

RETURN

END FUNCTION skal_prod END MODULE vektorer

Vi skall ocks˚a skriva ett program f¨or att testa modulen:

(21)

PROGRAM vektor_test USE vektorer IMPLICIT NONE INTEGER :: i

REAL, DIMENSION(5) :: a REAL, DIMENSION(60) :: b REAL :: z

TYPE(vektor) :: x,y

! Konstruera talr¨ackor och konvertera till vektorer a = (/(REAL(i), i=1,5)/)

b = (/(REAL(2*i), i=1,10),(0.0, i=11,60)/) x = alstra_vektor(a,5)

y = alstra_vektor(b,5)

! Skriv ut vektorerna:

PRINT 100, "L¨angden av vektorn x ¨ar ",vektor_dim(x), &

" och dess element ¨ar (", vektor_racka(x),")"

PRINT 100, "L¨angden av vektorn y ¨ar ",vektor_dim(y), &

" och dess element ¨ar (", vektor_racka(y),")"

! R¨akna ut deras skal¨arprodukt:

PRINT ’(A,F6.1)’, " Deras skal¨arprodukt ¨ar ",skal_prod(x,y)

! Testa felutskrifter:

y = alstra_vektor(b,60) y = alstra_vektor(b,8) z = skal_prod(x,y)

100 FORMAT (T2,A,I3/,A,4(F4.1,","),F4.1,A) STOP

END PROGRAM vektor_test

(22)

Programmet ger ocks˚a exempel p˚a formaterad utskrift. Utskriften fr˚an programmet ser ut p˚a f¨oljande s¨att:

angden av vektorn x ¨ar 5

och dess element ¨ar ( 1.0, 2.0, 3.0, 4.0, 5.0) angden av vektorn y ¨ar 5

och dess element ¨ar ( 2.0, 4.0, 6.0, 8.0,10.0) Deras skal¨arprodukt ¨ar 110.0

Vektorns l¨angd ¨ar 60 - st¨orsta till˚atna l¨angd ¨ar 50 Vektorerna har inte samma l¨angd: 5 och 8

Resultatet ¨ar noll!

References

Related documents

• Idag jobbar vi för bättre arbetsmiljö och villkor, mer i lön, fler jobbmöjligheter för unga och att alla ska kunna utvecklas på sin

Öppet vattenområde där bro får uppföras med en segelfri höjd på minst 2 meter inom en farledsbredd av minst 3 meter.. Öppet vattenområde där bro, bryggor och

Kortfattad och relevant sjukhistoria för att skapa en gemensam helhets- bild av patientens tillstånd fram tills nu..

Inom socialförvaltningen i Kiruna finns en Relationsfridsgrupp som arbetar för att hjälpa – stödja Kvinnor – Män – Barn som på något sätt har blivit utsatta för

Att Thurc kom att valia lagmastarcns yrke blcv av dcn stё rsta bctydelse fё r hans entomologiska studier Han ick tillbringa en stor dcl av sin tid i skog och mark med talrika

Till exempel fick jag inte med n˚ agot Ljus- och Optikland i f¨ orsta f¨ ors¨ oket, och pilen mot Kosmologi, som ligger utanf¨ or den h¨ ar kartan, borde peka mer upp˚ at,

Det kändes bårdt för Tanja att mista sina fäders slott, men hvad betydde väl denna sorg i jemförelse med det skoningslösa öde, som dref henne och den hon älskade till det fjerran

Det ¨ ar en mots¨ agelse till att vi f˚ ar stryka alla gemensamma faktorer och d¨ arf¨ or ¨ ar x irrationellt.. (a) Skissa grafen av den trigonometriska