米空軍のボーイング F-22 ステルス戦闘機パイロット訓練ソフトウェア開発者が募集されているようです。
C, C++, Ada, Fortran, OpenGL programming languages. Qt user interface framework, Perl, GLStudio
なお応募には米国市民権wと軍機を守れる安全審査許可が必要なようです。
J.Borwein & K.Devlin 著 『数学を生み出す魔法のるつぼ』二章にある Spigot algorithm を使って e を1桁づつ求める計算をしてみます。
Spigot algorithm は直訳すれば、「蛇口算法」となりますが、邦訳では「こつこつアルゴリズム」になっています。しまりの悪い蛇口からポタポタと水滴が垂れるイメージでしょうか?
(邦訳はアマゾンのレビューでもクソミソに書かれているように機械翻訳のような訳文で、用語の誤りや何を言ってるのか意味不明なところが多数あります。)
クラスを使って OO 風にしましたが、冗長になってしまいました。1桁づつ数字が求まることを強調するため、1桁毎に出力しています。advance ='no' にすると改行は避けられますが、buffering されてしまうので、flush で強制出力しています。
なお4バイト整数の配列を使っているので、一回に1桁ではなく、8桁まで求められるんじゃないかと思います。
Intel Fortran compiler のバグで parameterized derived type のサイズが正しく取れないために、associate で配列をポインタで別名化することが出来ませんでした。
module m_e implicit none private public :: t_e type :: t_e(n) private integer, len:: n integer :: m(n + 1) contains procedure, public :: next, init end type t_e contains subroutine init(this) class(t_e(*)), intent(in out) :: this this%m = 1 end subroutine init impure subroutine next(this, k) class(t_e(*)), intent(in out) :: this integer, intent(in out) :: k integer :: i, l associate (n => this%n, m=> this%m) ! m => this%m: bug this%m = this%m * 10 do i = n + 1, 1, -1 l = mod(this%m(i) + k , i + 1) k = (this%m(i) + k) / (i + 1) this%m(i) = l end do end associate end subroutine next end module m_e program Console16 use m_e implicit none integer :: i, n = 10000, k = 0 type(t_e(:)), allocatable :: e allocate(t_e(n)::e) call e%init() write(6, '(a)', advance='no') '2.' flush(6) do i = 1, n - 1 call e%next(k) write(6, '(i1)', advance='no') k flush(6) end do print * stop end program Console16
一万桁求めてみました。千桁目までは他の結果と比較して確かめました。
2.718281828459045235360287471352662497757247093699959574966967627724076630353547594571382178525166427427466391932003059921817413596629043572900334295260595630738132328627943490763233829880753195251019011573834187930702154089149934884167509244761460668082264800168477411853742345442437107539077744992069551702761838606261331384583000752044933826560297606737113200709328709127443747047230696977209310141692836819025515108657463772111252389784425056953696770785449969967946864454905987931636889230098793127736178215424999229576351482208269895193668033182528869398496465105820939239829488793320362509443117301238197068416140397019837679320683282376464804295311802328782509819455815301756717361332069811250996181881593041690351598888519345807273866738589422879228499892086805825749279610484198444363463244968487560233624827041978623209002160990235304369941849146314093431738143640546253152096183690888707016768396424378140592714563549061303107208510383750510115747704171898610687396965521267154688957035035402123407849819334321068170121005627880235193033224745015853904730419957777093503660416997329725088687696640355570716226844716256079882651787134195124665201030592123667719432527867539855894489697096409754591856956380236370162112047742722836489613422516445078182442352948636372141740238893441247963574370263755294448337998016125492278509257782562092622648326277933386566481627725164019105900491644998289315056604725802778631864155195653244258698294695930801915298721172556347546396447910145904090586298496791287406870504895858671747985466775757320568128845920541334053922000113786300945560688166740016984205580403363795376452030402432256613527836951177883863874439662532249850654995886234281899707733276171783928034946501434558897071942586398772754710962953741521115136835062752602326484728703920764310059584116612054529703023647254929666938115137322753645098889031360205724817658511806303644281231496550704751025446501172721155519486685080036853228183152196003735625279449515828418829478761085263981395599006737648292244375287184624578036192981971399147564488262603903381441823262515097482798777996437308997038886778227138360577297882412561190717663946507063304527954661855096666185664709711344474016070462621568071748187784437143698821855967095910259686200235371858874856965220005031173439207321139080329363447972735595527734907178379342163701205005451326383544000186323991490705479778056697853358048966906295119432473099587655236812859041383241160722602998330535370876138939639177957454016137223618789365260538155841587186925538606164779834025435128439612946035291332594279490433729908573158029095863138268329147711639633709240031689458636060645845925126994655724839186564209752685082307544254599376917041977780085362730941710163434907696423722294352366125572508814779223151974778060569672538017180776360346245927877846585065605078084421152969752189087401966090665180351650179250461950136658543663271254963990854914420001457476081930221206602433009641270489439039717719518069908699860663658323227870937650226014929101151717763594460202324930028040186772391028809786660565118326004368850881715723866984224220102495055188169480322100251542649463981287367765892768816359831247788652014117411091360116499507662907794364600585194199856016264790761532103872755712699251827568798930276176114616254935649590379804583818232336861201624373656984670378585330527583333793990752166069238053369887956513728559388349989470741618155012539706464817194670834819721448889879067650379590366967249499254527903372963616265897603949857674139735944102374432970935547798262961459144293645142861715858733974679189757121195618738578364475844842355558105002561149239151889309946342841393608038309166281881150371528496705974162562823609216807515017772538740256425347087908913729172282861151591568372524163077225440633787593105982676094420326192428531701878177296023541306067213604600038966109364709514141718577701418060644363681546444005331608778314317444081194942297559931401188868331483280270655383300469329011574414756313999722170380461709289457909627166226074071874997535921275608441473782330327033016823719364800217328573493594756433412994302485023573221459784328264142168487872167336701061509424345698440187331281010794512722373788612605816566805371439612788873252737389039289050686532413806279602593038772769778379286840932536588073398845721874602100531148335132385004782716937621800490479559795929059165547050577751430817511269898518840871856402603530558373783242292418562564425502267215598027401261797192804713960068916382866527700975276706977703643926022437284184088325184877047263844037953016690546593746161932384036389313136432713768884102681121989127522305625675625470172508634976536728860596675274086862740791285657699631378975303466061666980421826772456053066077389962421834085988207186468262321508028828635974683965435885668550377313129658797581050121491620765676995065971534476347032085321560367482860837865680307306265763346977429563464371670939719306087696349532884683361303882943104080029687386911706666614680001512114344225602387447432525076938707777519329994213727721125884360871583483562696166198057252661220679754062106208064988291845439530152998209250300549825704339055357016865312052649561485724925738620691740369521353373253166634546658859728665945113644137033139367211856955395210845840724432383558606310680696492485123263269951460359603729725319836842336390463213671011619282171115028280160448805880238203198149309636959673583274202498824568494127386056649135252670604623445054922758115170931492187959271800194096886698683703730220047531433818109270803001720593553052070070607223399946399057131158709963577735902719628506114651483752620956534671329002599439766311454590268589897911583709341937044115512192011716488056694593813118384376562062784631049034629395002945834116482411496975832601180073169943739350696629571241027323913874175492307186245454322203955273529524024590380574450289224688628533654221381572213116328811205214648980518009202471939171055539011394331668151582884368760696110250517100739276238555338627255353883096067164466237092264680967125406186950214317621166814009759528149390722260111268115310838731761732323526360583817315103459573653822353499293582283685100781088463434998351840445170427018938199424341009057537625776757111809008816418331920196262341628816652137471732547772778348877436651882875215668571950637193656539038944936642176400312152787022236646363575550356557694888654950027085392361710550213114741374410613444554419210133617299628569489919336918472947858072915608851039678195942983318648075608367955149663644896559294818785178403877332624705194505041984774201418394773120281588684570729054405751060128525805659470304683634459265255213700806875200959345360731622611872817392807462309468536782310609792159936001994623799343421068781349734695924646975250624695861690917857397659519939299399556754271465491045686070209901260681870498417807917392407194599632306025470790177452751318680998228473086076653686685551646770291133682756310722334672611370549079536583453863719623585631261838715677411873852772292259474337378569553845624680101390572787101651296663676445187246565373040244368414081448873295784734849000301947788802046032466084287535184836495919508288832320652212810419044804724794929134228495197002260131043006241071797150279343326340799596053144605323048852897291765987601666781193793237245385720960758227717848336161358261289622611812945592746276713779448758675365754486140761193112595851265575973457301533364263076798544338576171533346232527057200530398828949903425956623297578248873502925916682589445689465599265845476269452878051650172067478541788798227680653665064191097343452887833862172615626958265447820567298775642632532159429441803994321700009054265076309558846589517170914760743713689331946909098190450129030709956622662030318264936573369841955577696378762491885286568660760056602560544571133728684020557441603083705231224258722343885412317948138855007568938112493538631863528708379984569261998179452336408742959118074745341955142035172618420084550917084568236820089773945584267921427347756087964427920270831215015640634134161716644806981548376449157390012121704154787259199894382536495051477137939914720521952907939613762110723849429061635760459623125350606853765142311534966568371511660422079639446662116325515772907097847315627827759878813649195125748332879377157145909106484164267830994972367442017586226940215940792448054125536043131799269673915754241929660731239376354213923061787675395871143610408940996608947141834069836299367536262154524729846421375289107988438130609555262272083751862983706678722443019579379378607210725427728907173285487437435578196651171661833088112912024520404868220007234403502544820283425418788465360259150644527165770004452109773558589762265548494162171498953238342160011406295071849042778925855274303522139683567901807640604213830730877446017084268827226117718084266433365178000217190344923426426629226145600433738386833555534345300426481847398921562708609565062934040526494324426144566592129122564889356965500915430642613425266847259491431423939884543248632746184284665598533231221046625989014171210344608427161661900125719587079321756969854401339762209674945418540711844643394699016269835160784892451405894094639526780735457970030705116368251948770118976400282764841416058720618418529718915401968825328930914966534575357142731848201638464483249903788606900807270932767312758196656394114896171683298045513972950668760474091542042842999354102582911350224169076943166857424252250902693903481485645130306992519959043638402842926741257342244776558417788617173726546208549829449894678735092958165263207225899236876845701782303809656788311228930580914057261086588484587310165815116753332767488701482916741970151255978257270740643180860142814902414678047232759768426963393577354293018673943971638861176420900406866339885684168100387238921448317607011668450388721236436704331409115573328018297798873659091665961240202177855885487617616198937079438005666336488436508914480557103976521469602766258359905198704230017946553678 続行するには何かキーを押してください . . .
複素数 a+bi を2つの実数(a,b)の組と考えて、その加減乗除の演算規則が適当に与えられている代数系を考えることが出来ます。ここで、a,b に実数じゃなくて複素数を突っ込んだらどうなるかと考えると、うまく適当な演算規則をあたえると、矛盾なく定義が出来て超複素数というべきもの(四元数)が作れることが知られています。この作り方はケーリー=ディクソン構成と言われるものです。
ケーリー=ディクソン構成 積 :(a,b)(c,d):=(ac-~db, da+b~c) 共役:~(a,b):=(~a,-b)
四元数は単なる空想の産物ではなく、自然界では量子力学のスピンのところでパウリのスピン行列として登場してきます。四元数は行列表現があることから推察できるように、交換則が成り立ちません。
調子に乗って進むともう一段階進むと、八元数というものも定義出来て加減乗除の演算規則が作れます。しかし、八元数では結合則も成立せず、だんだんと手足を切り取られてダルマさんになってしまい、この先は加減乗除可能な16元数というものは作れなくなってしまいます。
ここで、それぞれの数のノルムを考えると、実数ベクトルのノルムを保存するのは回転群、複素数のベクトルのノルムを保存するのはユニタリー群、四元数ベクトルのノルムを保存するのは斜交群(シンプレクティック群)、八元数のノルムを保存するのは例外群(特にG2)とリー群の分類と関係しています。
交換則からの逸脱具合は、commutator(交換子積) [A,B]=AB-BA、結合則からの逸脱具合は、associator [X,Y,Z]=(XY)Z-X(YZ) で表現されます。 associator は三項演算子になっています。ところで交換子積は非結合積なので、[X,Y,Z]=[[X,Y],Z]-[X,[Y,Z]]となりますが、Jacobiの恒等式によりこの値は[Y,[X,Z]]と分かります。これが交換子積の非結合具合となります。
八元数では、前述のとおり一般には結合則は満たさないのですが、部分的に二つの元の演算では結合則が成り立ちます。すなわち[x,x,y]=[x,y,x]=[y,x,x]=0 となります。
ケーリー=ディクソン構成は、実数からはじまって同じアルゴリズムが三回反復されて、複素数・四元数・八元数が作られます。Fortran90/95 の場合、派生型を使って下から組み上げていく形で順々に定義してゆき、最後に演算子オーバーロードで二項演算子などを定義する形が素直だと思いますが、ほぼ同じ内容の繰り返しが必要となります。これに対し、Fortran2003/08では無制限ポインタを使って、上側から下側の実数に向かってゆく再帰的な定義で反復なしに1回の記述で定義することが出来ます。(ただし無制限多態ポインタ使用のため見苦しいプログラムになります。)
以下に両方式のプログラムを示します。ここで簡単のため、加減乗除のうち加算と乗算のみを定義しいます。減算と除算は、加算と乗算から定義されるのでここでは省きました。
(533.0000,0.0000000E+00) 533.0000 0.0000000E+00 cc 533.0000 0.0000000E+00 0.0000000E+00 0.0000000E+00 -6.000000 13.00000 32.00000 1.000000 50.00000 -1.000000 -12.00000 67.00000 204.0000 0.0000000E+00 0.0000000E+00 0.0000000E+00 0.0000000E+00 0.0000000E+00 0.0000000E+00 0.0000000E+00 続行するには何かキーを押してください . . .
module m_comp implicit none interface operator(+) procedure :: plus_r, plus_c, plus_h, plus_o end interface interface operator(*) procedure :: prod_r, prod_c, prod_h, prod_o end interface interface operator(-) procedure :: minus_r, minus_c, minus_h, minus_o end interface interface operator(.cc.) procedure :: conj_r, conj_c, conj_h, conj_o end interface interface conj procedure :: conj_r, conj_c, conj_h, conj_o end interface type :: t_r real :: r end type t_r type :: t_c type(t_r) :: re, im end type t_c type :: t_h type(t_c) :: re, im end type t_h type :: t_o type(t_h) :: re, im end type t_o contains type(t_r) function conj_r(a) result(c) type(t_r), intent(in) :: a c%r = a%r end function conj_r type(t_r) function minus_r(a) result(c) type(t_r), intent(in) :: a c%r = -a%r end function minus_r type(t_r) function plus_r(a, b) result(c) type(t_r), intent(in) :: a, b c%r = a%r + b%r end function plus_r type(t_r) function prod_r(a, b) result(c) type (t_r), intent(in) :: a, b c%r = a%r * b%r end function prod_r type(t_c) function conj_c(a) result(c) type(t_c), intent(in) :: a c%re = a%re c%im = -a%im end function conj_c type(t_c) function minus_c(a) result(c) type(t_c), intent(in) :: a c%re = -a%re c%im = -a%im end function minus_c type(t_c) function plus_c(a, b) result(c) type (t_c), intent(in) :: a, b c%re = a%re + b%re c%im = a%im + b%im end function plus_c type(t_c) function prod_c(a, b) result(c) type (t_c), intent(in) :: a, b c%re = a%re * b%re + (-b%im * a%im) c%im = b%im * a%re + a%im * b%re end function prod_c type(t_c) function to_c(r0, r1) real, intent(in) :: r0, r1 to_c = t_c(t_r(r0), t_r(r1)) end function to_c type(t_h) function conj_h(a) result(c) type(t_h), intent(in) :: a c%re = .cc.a%re c%im = -a%im end function conj_h type(t_h) function minus_h(a) result(c) type(t_h), intent(in) :: a c%re = -a%re c%im = -a%im end function minus_h type(t_h) function plus_h(a, b) result(c) type (t_h), intent(in) :: a, b c%re = a%re + b%re c%im = a%im + b%im end function plus_h type(t_h) function prod_h(a, b) result(c) type (t_h), intent(in) :: a, b c%re = a%re * b%re + (-(.cc.b%im) * a%im) c%im = b%im * a%re + a%im * (.cc.b%re) end function prod_h type(t_h) function to_h(r0, r1, r2, r3) real, intent(in) :: r0, r1, r2, r3 to_h = t_h(to_c(r0, r1), to_c(r2, r3)) end function to_h type(t_o) function conj_o(a) result(c) type(t_o), intent(in) :: a c%re = .cc.a%re c%im = -a%im end function conj_o type(t_o) function minus_o(a) result(c) type(t_o), intent(in) :: a c%re = -a%re c%im = -a%im end function minus_o type(t_o) function plus_o(a, b) result(c) type (t_o), intent(in) :: a, b c%re = a%re + b%re c%im = a%im + b%im end function plus_o type(t_o) function prod_o(a, b) result(c) type (t_o), intent(in) :: a, b c%re = a%re * b%re + (-(.cc.b%im) * a%im) c%im = b%im * a%re + a%im * (.cc.b%re) end function prod_o type(t_o) function to_o(r0, r1, r2, r3, r4, r5, r6, r7) real, intent(in) :: r0, r1, r2, r3, r4, r5, r6, r7 to_o = t_o(to_h(r0, r1, r2, r3), to_h(r4, r5, r6, r7)) end function to_o end module m_comp program supercomplex use m_comp implicit none complex :: a, b, c type(t_r) :: ra, rb, rc type(t_c) :: ca, cb, cc type(t_h) :: ha, hb, hc type(t_o) :: oa, ob, oc ra = t_r(2.0) rb = t_r(3.0) a = (2.0, 3.0) b = (4.0, 5.0) c = a * b ca = to_c(2.0, 3.0) cb = to_c(4.0, 5.0) cc = ca * cb print *, conjg(c) * c print *, (.cc.cc) * cc, 'cc' ha = t_h(ca, to_c(0.0, 0.0)) hb = t_h(cb, to_c(0.0, 0.0)) hc = ha * hb print *, (.cc. hc) * hc hc = to_h(0.0, 0.0, 0.0, 0.0) oa = to_o(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0) ob = t_o(hb, hc) oc = oa * ob print *, oc print * print *, (.cc. oa) * oa end program supercomplex
ケーリー=ディクソン構成を再帰的に実現しますが、再帰の出発値に当たるのは、組を作る数の型として intrinsic な real 型が現れた時になります。 intrinsic な real 型は継承できないなので、real 型を他の派生型と同等に扱うには、無制限多態ポインタ class(*) を使う必要があります。しかし class(*) は代入するにも出力するにも何するにも select type で型を確定する必要があるので厄介です。このため出力用のユーザー定義ルーチンも用意しておきました。(楽な抜け道があるのかもしれませんが、私の今の知識ではこれで精一杯)
-3.000000 -5.000000 10.00000 (-5.000000,10.00000) -60.00000 12.00000 30.00000 24.00000 -60.00000 -12.00000 -30.00000 -24.00000 -1000.000 -1200.000 -1400.000 -1600.000 608.0000 400.0000 600.0000 800.0000 -1000.000 -1200.000 -1400.000 -1600.000 608.0000 400.0000 600.0000 800.0000 -1000.000 1264.000 1488.000 1712.000 -104.0000 -288.0000 -472.0000 -656.0000 -1000.000 1264.000 1488.000 1712.000 -104.0000 -288.0000 -472.0000 -656.0000 -1000.000 -1184.000 -1368.000 -1552.000 -104.0000 528.0000 752.0000 976.0000 -1000.000 -1184.000 -1368.000 -1552.000 -104.0000 528.0000 752.0000 976.0000 8489664. 0.0000000E+00 0.0000000E+00 0.0000000E+00 0.0000000E+00 0.0000000E+00 0.0000000E+00 0.0000000E+00 350.0000 -390.0000 -198.0000 -186.0000 218.0000 -254.0000 -222.0000 -270.0000 350.0000 -42.00000 -158.0000 -470.0000 218.0000 -206.0000 -190.0000 -294.0000 続行するには何かキーを押してください . . .
ここではノルムが実部のみになること、また八元数の非結合性や部分結合性等を確認しています。
module m_sc implicit none type :: t_sc class(*), allocatable :: re, im contains generic :: assignment(=) => assign_sc generic :: operator(-) => minus generic :: operator(.cc.) => conj generic :: operator(+) => plus generic :: operator(*) => prod procedure :: minus, plus, conj, prod generic :: write(formatted) => pr_sc procedure :: assign_sc, pr_sc end type t_sc contains recursive function minus(a) result(c) class(t_sc), intent(in) :: a class(t_sc), allocatable:: c allocate(t_sc::c) select type (re => a%re) type is (real) c%re = -re class is (t_sc) allocate(c%re, source = -re) select type (im => a%im) class is (t_sc) allocate(c%im, source = -im) end select end select end function minus recursive function conj(a) result(c) class(t_sc), intent(in) :: a class(t_sc), allocatable:: c allocate(t_sc::c) select type (re => a%re) type is (real) c%re = re class is (t_sc) allocate(c%re, source = conj(re)) select type (im => a%im) class is (t_sc) allocate(c%im, source = -im) end select end select end function conj recursive function plus(a, b) result(c) class(t_sc), intent(in) :: a, b class(t_sc), allocatable:: c allocate(t_sc::c) select type (ar => a%re) type is (real) select type (br => b%re) type is (real) c%re = ar + br end select class is (t_sc) select type (br => b%re) class is (t_sc) allocate(c%re, source = ar + br) end select select type (ai => a%im) class is (t_sc) select type (bi => b%im) class is (t_sc) allocate(c%im, source = ai + bi) end select end select end select end function plus recursive function prod(a, b) result(c) class(t_sc), intent(in) :: a, b class(t_sc), allocatable:: c allocate(t_sc::c) select type (ar => a%re) type is (real) select type (br => b%re) type is (real) c%re = ar * br end select class is (t_sc) select type (br => b%re) class is (t_sc) select type (ai => a%im) class is (t_sc) select type (bi => b%im) class is (t_sc) allocate(c%re, source = ar * br + conj(-bi) * ai) allocate(c%im, source = bi * ar + ai * conj(br) ) end select end select end select end select end function prod subroutine assign_sc(c, a) class(t_sc), intent(out) :: c real, intent(in) :: a(:) allocate(t_sc::c%re) allocate(t_sc::c%im) select case (size(a)) case (1) ! R allocate(c%re, source = a(1)) case (2) ! C select type (cr => c%re) type is (t_sc) cr = a(1:1) end select select type (ci => c%im) type is (t_sc) ci = a(2:2) end select case (4) ! H select type (cr => c%re) type is (t_sc) cr = a(1:2) end select select type (ci => c%im) type is (t_sc) ci = a(3:4) end select case (8) ! O select type (cr => c%re) type is (t_sc) cr = a(1:4) end select select type (ci => c%im) type is (t_sc) ci = a(5:8) end select case default stop 'assign_c: error!' end select end subroutine assign_sc recursive subroutine pr_sc(dtv, unit, iotype, vlist, iostat, iomsg) class(t_sc), intent(in) :: dtv integer, intent(in) :: unit character (len = *), intent(in) :: iotype integer, intent(in) :: vlist(:) integer, intent(out) :: iostat character (len = *), intent(in out) :: iomsg select type (re => dtv%re) type is (real) write(unit, *, iostat = iostat) re type is (t_sc) call re%pr_sc(unit, iotype, vlist, iostat, iomsg) select type (im => dtv%im) type is (t_sc) call im%pr_sc(unit, iotype, vlist, iostat, iomsg) end select end select end subroutine pr_sc end module m_sc program hello use m_sc implicit none class(t_sc), allocatable :: ra, rb, rc, ca, cb, cc class(t_sc), allocatable :: ha, hb, hc, oa, ob, oc, od allocate(ra, rb) ra = [1.0] rb = [2.0] rc = -ra + (-rb) print *, rc allocate(ca, cb) ca = [1.0, 2.0] cb = [3.0, 4.0] cc = ca * cb print *, cc print *, (1.0, 2.0) * (3.0, 4.0) ! print *, conj(cc) allocate(ha, hb, oa, ob) ha = [1.0, 2.0, 3.0, 4.0] hb = [5.0, 6.0, 7.0, 8.0] hc = ha * hb print *, hc print *, conj(hc) oa = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0] ob = [5.0, 6.0, 7.0, 8.0, -1.0, -2.0, -3.0, -4.0] oc = (oa * oa) * ob od = oa * (oa * ob) print *, oc print *, od print * oc = (oa * ob) * oa od = oa * (ob * oa) print *, oc print *, od print * oc = (ob * oa) * oa od = ob * (oa * oa) print *, oc print *, od print * print *, conj(od) * od print * oa = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0] ob = [5.0, 6.0, 7.0, 8.0, -1.0, -2.0, -3.0, -4.0] oc = [1.0, 1.0, 1.0, 1.0, -2.0, -2.0, -1.0, -1.0] print *, (oa * ob) * oc print *, oa * (ob * oc) end program Hello
配列の全配列操作を記述するとき、スカラーと配列を明示的に区別するために、配列名のあとに (:) をつけることが推奨されることがありますが、文脈によって微妙に意味が違う場合もあり、また副プログラム呼び出しの引数にしたときの挙動など、コンパイラの実装にも依存するので、時には注意が必要かと思います。
特に Fortran 2003 で、allocatable 属性の配列に代入するときの挙動がそれまでのものと変わって、自動再割り付けが行われたりするので危険です。
Cray が 2005 年に出した、Fortran 2003 and Beyond という Fortran 2003 規格と Fortran 2008 規格案を紹介した文書に、いい実例が出ていたので少し変えて紹介します。
(:) があるとたとえ全部分を指定していても部分配列となり、自動再割り付けは行われません。(文字列の場合も同様です)
program Console6 implicit none block character(len = :), allocatable :: string allocate(character(16)::string) string = '0123456789abcdef' ! print *, len(string), ':', string, ':' ! length = 16 string(:) = 'pad' print *, len(string), ':', string, ':' ! length = 16 string = 'short' print *, len(string), ':', string, ':' ! lenght = 5 end block ! print * ! block real, allocatable :: a(:), b(:), c(:) allocate(a(10), b(20)) a = 1.10 b = 1.20 c = a print *, size(c) ! size(c) = 10 c = b print *, size(c) ! size(c) = 20 c(:) = a(:) ! error size-mismatch end block end program Console6
16 :0123456789abcdef: 16 :pad : 5 :short: 10 20 forrtl: severe (408): fort: (2): Subscript #1 of the array A has value 11 which is greater than the upper bound of 10 Image PC Routine Line Source libifcoremdd.dll 5A1B4138 Unknown Unknown Unknown Console6.exe 00C323AF _MAIN__ 26 Console6.f90 Console6.exe 00C327DF Unknown Unknown Unknown Console6.exe 00C3521E Unknown Unknown Unknown Console6.exe 00C35100 Unknown Unknown Unknown Console6.exe 00C34FAD Unknown Unknown Unknown Console6.exe 00C35238 Unknown Unknown Unknown KERNEL32.DLL 73F68744 Unknown Unknown Unknown ntdll.dll 774C587D Unknown Unknown Unknown ntdll.dll 774C584D Unknown Unknown Unknown 続行するには何かキーを押してください . . .