Ito ang command na PDL::PPp na maaaring patakbuhin sa OnWorks na libreng hosting provider gamit ang isa sa aming maramihang libreng online na workstation gaya ng Ubuntu Online, Fedora Online, Windows online emulator o MAC OS online emulator
PROGRAMA:
NAME
PDL::PP - Bumuo ng mga gawain ng PDL mula sa maigsi na paglalarawan
SINOPSIS
hal
pp_def(
'sumover',
Pars => 'a(n); [o]b();',
Code => q{
dobleng tmp=0;
loop(n) %{
tmp += $a();
%}
$b() = tmp;
},
);
pp_done();
Mga function
Narito ang isang mabilis na listahan ng sanggunian ng mga function na ibinigay ng PDL::PP.
pp_add_boot
Magdagdag ng code sa seksyong BOOT ng nabuong XS file
pp_add_exported
Magdagdag ng mga function sa listahan ng mga na-export na function
pp_add_isa
Magdagdag ng mga entry sa listahan ng @ISA
pp_addbegin
Nagtatakda ng code na idaragdag sa itaas ng generate .pm file
pp_addhdr
Magdagdag ng code at kasama sa seksyong C ng nabuong XS file
pp_addpm
Magdagdag ng code sa nabuong .pm file
pp_addxs
Magdagdag ng karagdagang XS code sa nabuong XS file
pp_beginwrap
Magdagdag ng BEGIN-block wrapping sa code para sa nabuong .pm file
pp_bless
Itinatakda ang package kung saan idinaragdag ang XS code (default ay PDL)
pp_boundscheck
Kontrolin ang estado ng aktibidad ng pagsusuri sa hangganan ng PDL
pp_core_importList
Tukuyin kung ano ang na-import mula sa PDL::Core
pp_def
Tukuyin ang isang bagong PDL function
pp_deprecate_module
Magdagdag ng runtime at mga babala ng POD tungkol sa isang module na hindi na ginagamit
pp_tapos na
Markahan ang dulo ng mga kahulugan ng PDL::PP sa file
pp_export_nothing
I-clear ang listahan ng pag-export para sa iyong nabuong module
pp_line_numbers
Magdagdag ng impormasyon ng numero ng linya upang pasimplehin ang pag-debug ng PDL::PP code
pp_setversion
Itakda ang bersyon para sa .pm at .xs na mga file
PANGKALAHATANG-IDEYA
Bakit kailangan natin ng PP? Maraming dahilan: una, gusto naming makabuo ng subroutine
code para sa bawat isa sa mga PDL datatypes (PDL_Byte, PDL_Short,. etc). AUTOMATIKA. Pangalawa,
kapag tinutukoy ang mga hiwa ng PDL array sa Perl (hal. "$a->slice('0:10:2,:')" o iba pa
bagay tulad ng transposes) ito ay maganda upang magawa ito nang malinaw at magagawa
upang gawin itong 'in-place' - ibig sabihin, hindi na kailangang gumawa ng memory copy ng seksyon. humahawak ng PP
lahat ng kinakailangang elemento at offset arithmetic para sa iyo. Mayroon ding mga paniwala ng
threading (paulit-ulit na pagtawag ng parehong gawain para sa maraming hiwa, tingnan ang PDL::Indexing)
at dataflow (tingnan ang PDL::Dataflow) na pinapayagan ng paggamit ng PP.
Sa karamihan ng mga sumusunod ay ipapalagay natin ang pagiging pamilyar ng mambabasa sa mga konsepto ng
implicit at tahasang threading at index manipulations sa loob ng PDL. Kung wala ka pa
narinig ang tungkol sa mga konseptong ito o hindi masyadong komportable sa kanila oras na upang suriin
PDL::Pag-i-index.
Bilang maaari mong pahalagahan mula sa pangalan nito PDL::PP ay isang Pre-Processor, ibig sabihin, pinapalawak nito ang code sa pamamagitan ng
mga pagpapalit upang makagawa ng totoong C-code. Sa teknikal, ang output ay XS code (tingnan perlxs) ngunit
na malapit sa C.
Kaya paano mo ginagamit ang PP? Well para sa karamihan ng bahagi mo lamang magsulat ng ordinaryong C code maliban sa
mga espesyal na konstruksyon ng PP na may anyo:
$something(something else)
o:
PPfunction %{
%}
Ang pinakamahalagang konstruksyon ng PP ay ang form na "$array()". Isaalang-alang ang napakasimpleng PP
function upang isama ang mga elemento ng isang 1D vector (sa katunayan ito ay halos kapareho sa aktwal
code na ginamit ng 'sumover'):
pp_def('sumit',
Pars => 'a(n); [o]b();',
Code => q{
dobleng tmp;
tmp = 0;
loop(n) %{
tmp += $a();
%}
$b() = tmp;
}
);
Ano ang nangyayari? Ang linyang "Pars =>" ay napakahalaga para sa PP - tinutukoy nito ang lahat ng
mga argumento at ang kanilang sukat. Tinatawag namin itong lagda ng PP function (ihambing
gayundin ang mga paliwanag sa PDL::Indexing). Sa kasong ito ang routine ay tumatagal ng isang 1-D function bilang
input at nagbabalik ng 0-D scalar bilang output. Ang "$a()" PP construct ay ginagamit upang ma-access
mga elemento ng array a(n) para sa iyo - pinupunan ng PP ang lahat ng kinakailangang C code.
Mapapansin mo na ginagamit namin ang "q{}" single-quote operator. Ito ay hindi isang
aksidente. Karaniwang nais mong gumamit ng mga solong panipi upang tukuyin ang iyong mga seksyon ng PP Code. PDL::PP
gumagamit ng "$var()" para sa pag-parse nito at kung hindi ka gagamit ng mga solong panipi, susubukan ni Perl
interpolate "$var()". Gayundin, ang paggamit ng solong quote na "q" na operator na may mga kulot na braces ay ginagawa ito
mukhang gumagawa ka ng block ng code, na What You Mean. (Si Perl ay sapat na matalino upang
maghanap ng mga nested curly braces at huwag isara ang quote hanggang sa makita nito ang katugmang kulot
brace, kaya ligtas na magkaroon ng mga nested block.) Sa iba pang mga pangyayari, gaya ng kapag ikaw ay
pagsasama-sama ng isang bloke ng Code gamit ang mga string concatenation, madalas itong pinakamadaling gamitin
totoong single quotes bilang
Code => 'something'.$interpolatable.'somethingelse;'
Sa simpleng kaso dito kung saan ang lahat ng mga elemento ay na-access ang PP construct "loop(n) %{ ...
%}" ay ginagamit upang i-loop ang lahat ng elemento sa dimensyon na "n". Tandaan ang tampok na ito ng PP: LAHAT
ANG MGA DIMENSYON AY ITINAKDA NG PANGALAN.
Ito ay magiging mas malinaw kung iiwasan natin ang PP loop () buuin at isulat ang loop nang tahasan
gamit ang conventional C:
pp_def('sumit',
Pars => 'a(n); [o]b();',
Code => q{
int i,n_size;
dobleng tmp;
n_size = $SIZE(n);
tmp = 0;
para sa(i=0; i
tmp += $a(n=>i);
}
$b() = tmp;
},
);
na katulad ng dati, ngunit mas matagal. Maaari mong makita upang makakuha ng elementong "i" ng
a() sinasabi namin ang "$a(n =>i)" - tinutukoy namin ang dimensyon sa pamamagitan ng pangalang "n". Sa 2D maaari nating sabihin:
Pars => 'a(m,n);',
...
tmp += $a(m=>i,n=>j);
...
Ang syntax na "m=>i" ay humiram mula sa Perl hash, na sa katunayan ay ginagamit sa pagpapatupad
ng PP. Maaari ding sabihin ng isa ang "$a(n=>j,m=>i)" dahil hindi mahalaga ang order.
Maaari mo ring makita sa halimbawa sa itaas ang paggamit ng isa pang konstruksyon ng PP - $SIZE(n) upang makuha
ang haba ng dimensyon na "n".
Gayunpaman, dapat itong tandaan na hindi ka dapat magsulat ng isang tahasang C-loop kung magagawa mo
gumamit ng PP "loop" construct dahil awtomatikong sinusuri ng PDL::PP ang mga limitasyon ng loop para sa
ikaw, ang paggamit ng "loop" ay ginagawang mas maigsi ang code, atbp. Ngunit may mga tiyak na sitwasyon
kung saan kailangan mo ng tahasang kontrol ng loop at ngayon alam mo na kung paano ito gawin;).
Upang muling bisitahin ang 'Bakit PP?' - ang code sa itaas para sa summit() bubuo para sa bawat uri ng data. Ito
ay gagana sa mga hiwa ng arrays 'in-place'. Awtomatikong mag-thread ito - hal kung isang 2D
array ay ibinigay ito ay tatawagin nang paulit-ulit para sa bawat 1D row (muli suriin ang PDL::Indexing para sa
ang mga detalye ng threading). At pagkatapos ay ang b() ay magiging isang 1D na hanay ng mga kabuuan ng bawat hilera. kaya namin
tawagan ito ng $a->xchg(0,1) upang isama ang mga column sa halip. At ang Dataflow tracing atbp. ay magiging
magagamit.
Maaari mong makitang iniligtas ng PP ang programmer mula sa pagsusulat ng maraming paulit-ulit na C-code --
sa aming opinyon ito ay isa sa mga pinakamahusay na tampok ng paggawa ng PDL sa pagsulat ng mga bagong C subroutine
para sa PDL isang kamangha-manghang maigsi na ehersisyo. Ang pangalawang dahilan ay ang kakayahang palawakin ang PP
ang iyong maigsi na mga kahulugan ng code sa iba't ibang C code batay sa mga pangangailangan ng computer
arkitektura na pinag-uusapan. Isipin na halimbawa ikaw ay mapalad na magkaroon ng isang supercomputer sa
iyong mga kamay; sa kasong iyon gusto mong PDL::PP tiyak na bumuo ng code na sinasamantala
ng mga feature ng vectorising/parallel computing ng iyong makina (ito ay isang proyekto para sa
kinabukasan). Sa anumang kaso, ang pangunahing punto ay dapat pa ring lumawak ang iyong hindi nabagong code
gumagana ang XS code kahit na nagbago ang internals ng PDL.
Gayundin, dahil bumubuo ka ng code sa isang aktwal na Perl script, maraming masaya
mga bagay na kaya mong gawin. Sabihin nating kailangan mong isulat ang parehong sumit (tulad ng nasa itaas) at multit.
Sa kaunting pagkamalikhain, magagawa natin
para sa({Pangalan => 'sumit', Init => '0', Op => '+='},
{Pangalan => 'multit', Init => '1', Op => '*='}) {
pp_def($_->{Pangalan},
Pars => 'a(n); [o]b();',
Code => '
dobleng tmp;
tmp = '.$_->{Init}.';
loop(n) %{
tmp '.$_->{Op}.' $a();
%}
$b() = tmp;
');
}
na tumutukoy sa parehong mga pag-andar nang madali. Ngayon, kung kailangan mong baguhin sa ibang pagkakataon ang lagda o
dimensionality o anuman, kailangan mo lang baguhin ang isang lugar sa iyong code. Oo, sigurado,
ang iyong editor ay mayroong 'cut and paste' at 'search and replace' ngunit mas kaunti pa rin ito
nakakainis at siguradong mas mahirap kalimutan ang isang lugar lang at may kakaibang mga bug
creep in. Gayundin, ang pagdaragdag ng 'orit' (bitwise o) mamaya ay isang one-liner.
At tandaan, nasa iyo talaga ang buong kakayahan ni Perl - napakadali mong basahin
anumang input file at gumawa ng mga gawain mula sa impormasyon sa file na iyon. Para sa mga simpleng kaso tulad ng
sa itaas, kasalukuyang pinapaboran ng may-akda (Tjl) ang hash syntax tulad ng nasa itaas - hindi ito masyadong
mas maraming character kaysa sa kaukulang array syntax ngunit mas madaling maunawaan at
baguhin.
Dapat din nating banggitin dito ang kakayahang makuha ang pointer sa simula ng data
memorya - isang kinakailangan para sa interfacing ng PDL sa ilang mga aklatan. Ito ay hinahawakan gamit ang
"$P(var)" na direktiba, tingnan sa ibaba.
Kapag nagsimulang magtrabaho sa isang bagong pp_def'ined function, kung magkamali ka, karaniwan mong gagawin
maghanap ng isang tumpok ng mga error sa compiler na nagpapahiwatig ng mga numero ng linya sa nabuong XS file. kung ikaw
alam kung paano magbasa ng mga XS file (o kung gusto mong matutunan ang mahirap na paraan), maaari mong buksan ang
nakabuo ng XS file at hanapin ang numero ng linya na may error. Gayunpaman, isang kamakailang
karagdagan sa PDL::PP ay tumutulong sa pag-uulat ng tamang numero ng linya ng iyong mga error:
"pp_line_numbers". Paggawa gamit ang orihinal na halimbawa ng summit, kung mayroon kang maling spelling ng
tmp sa iyong code, maaari mong baguhin ang (erroneos) code sa isang bagay na tulad nito at ang
ang compiler ay magbibigay sa iyo ng mas kapaki-pakinabang na impormasyon:
pp_def('sumit',
Pars => 'a(n); [o]b();',
Code => pp_line_numbers(__LINE__, q{
dobleng tmp;
tmp = 0;
loop(n) %{
tmp += $a();
%}
$b() = rmp;
})
);
Para sa sitwasyon sa itaas, ang aking compiler ay nagsasabi sa akin:
...
test.pd:15: error: 'rmp' undeclared (unang paggamit sa function na ito)
...
Sa aking halimbawang script (tinatawag na test.pd), ang linya 15 ay eksaktong linya kung saan ko ginawa ang aking
typo: "rmp" sa halip na "tmp".
Kaya, pagkatapos ng mabilis na pangkalahatang-ideya ng pangkalahatang lasa ng programming PDL routines gamit
PDL::PP ibubuod natin kung aling mga pangyayari ang dapat mo talagang gamitin ito
preprocessor/precompiler. Dapat mong gamitin ang PDL::PP kung gusto mo
· interface ng PDL sa ilang panlabas na library
· magsulat ng ilang algorithm na magiging mabagal kung naka-code sa Perl (ito ay hindi kasingdalas mo
isipin; tingnan muna ang threading at dataflow).
· maging isang developer ng PDL (at kahit na hindi ito obligado)
BABALA
Dahil sa arkitektura nito, ang PDL::PP ay maaaring maging parehong flexible at madaling gamitin sa isang banda,
pa exuberantly kumplikado sa parehong oras. Sa kasalukuyan, bahagi ng problema ang error na iyon
ang mga mensahe ay hindi masyadong nagbibigay-kaalaman at kung may nangyaring mali, mas mabuting malaman mo kung ano ka
ginagawa at nagagawa mong i-hack ang iyong paraan sa pamamagitan ng mga internals (o magagawang malaman sa pamamagitan ng
trial and error kung ano ang mali sa iyong args sa "pp_def"). Kahit na ang trabaho ay ginagawa sa
gumawa ng mas mahusay na mga babala, huwag matakot na ipadala ang iyong mga katanungan sa mailing list kung
nagkakaproblema ka.
DESCRIPTION
Ngayon na mayroon kang ilang ideya kung paano gamitin ang "pp_def" upang tukuyin ang mga bagong function ng PDL oras na upang
ipaliwanag ang pangkalahatang syntax ng "pp_def". Kinukuha ng "pp_def" bilang argumento muna ang pangalan ng
function na iyong tinutukoy at pagkatapos ay isang listahan ng hash na maaaring maglaman ng iba't ibang mga key.
Batay sa mga key na ito, bumubuo ang PP ng XS code at isang .pm na file. Ang function na "pp_done" (tingnan
halimbawa sa SYNOPSIS) ay ginagamit upang sabihin sa PDL::PP na wala nang mga kahulugan sa
ang file na ito at oras na para buuin ang .xs at
.pm file.
Bilang resulta, maaaring mayroong ilan pp_def() mga tawag sa loob ng isang file (sa pamamagitan ng mga convention file
na may PP code ay may extension na .pd o .pp) ngunit sa pangkalahatan ay isa lamang pp_done().
Mayroong dalawang pangunahing iba't ibang uri ng paggamit ng pp_def(), ang 'data operation' at 'slice
mga prototype ng operasyon.
Ang 'data operation' ay ginagamit upang kumuha ng ilang data, mangle ito at maglabas ng ilang iba pang data; ito
kasama halimbawa ang '+' operation, matrix inverse, sumover etc at lahat ng mga halimbawa
napag-usapan na natin sa dokumentong ito sa ngayon. Implicit at tahasang threading at ang
Ang paglikha ng resulta ay awtomatikong inaalagaan sa mga operasyong iyon. Kaya mo rin
gawin ang dataflow na may "sumit", "sumover", atbp (huwag madismaya kung hindi mo naiintindihan ang
konsepto ng dataflow sa PDL napakahusay pa; ito ay napaka-eksperimento pa rin).
Ang 'slice operation' ay ibang uri ng operasyon: sa isang slice operation, hindi ka
binabago ang anumang data, tinutukoy mo ang mga pagsusulatan sa pagitan ng magkaibang elemento ng dalawa
piddles (kasama sa mga halimbawa ang index manipulation/slicing function na mga kahulugan sa file
hiwa.pd iyon ay bahagi ng pamamahagi ng PDL; ngunit mag-ingat, ito ay hindi panimulang antas
bagay-bagay).
Kung pinagsama-sama ang PDL na may suporta para sa mga masamang halaga (ibig sabihin, "WITH_BADVAL => 1"), pagkatapos ay karagdagang
kailangan ang mga key para sa "pp_def", gaya ng ipinaliwanag sa ibaba.
Kung interesado ka lang sa pakikipag-ugnayan sa ilang panlabas na aklatan (halimbawa ang ilan
linear algebra/matrix library), karaniwan mong gugustuhin ang 'data operation' kaya pupunta tayo
para pag-usapan muna yan.
data operasyon
A simple halimbawa
Sa pagpapatakbo ng data, dapat mong malaman kung anong mga sukat ng data ang kailangan mo. Una, isang halimbawa
na may mga scalar:
pp_def('add',
Pars => 'a(); b(); [o]c();',
Code => '$c() = $a() + $b();'
);
Medyo kakaiba iyon pero hiwa-hiwalayin natin. Ang unang linya ay madali: tinutukoy namin ang a
routine na may pangalang 'add'. Ang pangalawang linya ay nagdedeklara lamang ng aming mga parameter at ang
ang mga panaklong ay nangangahulugan na sila ay mga scalar. Tinatawag namin ang string na tumutukoy sa aming mga parameter at
kanilang dimensionality ang lagda ng function na iyon. Para sa kaugnayan nito patungkol sa
threading at index manipulations tingnan ang PDL::Indexing man page.
Ang ikatlong linya ay ang aktwal na operasyon. Kailangan mong gamitin ang mga dollar sign at panaklong
upang sumangguni sa iyong mga parameter (malamang na magbabago ito sa isang punto sa hinaharap, kapag a
magandang syntax ay natagpuan).
Ang mga linyang ito ay ang lahat na kinakailangan upang aktwal na tukuyin ang function para sa PDL (well,
sa totoo lang ay hindi; kailangan mo ring magsulat ng Makefile.PL (tingnan sa ibaba) at buuin ang
module (tulad ng 'perl Makefile.PL; make'); ngunit huwag nating pansinin iyon pansamantala).
Kaya ngayon magagawa mo na
gamitin ang MyModule;
$a = pdl 2,3,4;
$b = pdl 5;
$c = add($a,$b);
# o
add($a,$b,($c=null)); # Alternatibong anyo, kapaki-pakinabang kung naging $c
# preset sa isang bagay na malaki, hindi kapaki-pakinabang dito.
at magkaroon ng threading gumana nang tama (ang resulta ay $c == [7 8 9]).
Ang Tigilan seksyon: ang lagda of a PP tungkulin
Kapag nakikita mo ang halimbawang code sa itaas, malamang na itatanong mo: ano itong kakaibang "$c=null"
syntax sa pangalawang tawag sa aming bagong function na "add"? Kung titingnan mo muli ang
kahulugan ng "idagdag" mapapansin mo na ang ikatlong argumentong "c" ay na-flag ng
qualifier "[o]" na nagsasabi sa PDL::PP na ito ay isang output argument. Kaya tawag sa itaas sa
Ang ibig sabihin ng add ay 'lumikha ng bagong $c mula sa simula na may mga tamang sukat' - ang "null" ay isang espesyal
token para sa 'empty piddle' (maaaring itanong mo kung bakit hindi namin ginamit ang value na "undef" para i-flag ito
sa halip na ang tiyak na PDL na "null"; kasalukuyan naming pinag-iisipan ito ;).
[Dapat ipaliwanag din ito sa ibang seksyon ng manwal!!] Ang dahilan para sa
Ang pagkakaroon ng syntax na ito bilang isang alternatibo ay kung mayroon kang napakalaking piddles, magagawa mo
$c = PDL->null;
para sa(ilang mahabang loop) {
# munge a,b
add($a,$b,$c);
# munge c, ibalik ang isang bagay sa a,b
}
at iwasang maglaan at magdeallocating ng $c sa bawat pagkakataon. Ito ay inilalaan nang isang beses sa una
magdagdag () at pagkatapos ay mananatili ang memorya hanggang sa masira ang $c.
Kung sasabihin mo lang
$c = add($a,$b);
ang code na nabuo ng PP ay awtomatikong pupunan ang "$c=null" at ibabalik ang resulta. Kung
gusto mong matuto nang higit pa tungkol sa mga dahilan kung bakit sinusuportahan ng PDL::PP ang istilong ito kung saan ang output
ang mga argumento ay ibinibigay bilang mga huling argumento na suriin ang PDL::Indexing man page.
Ang "[o]" ay hindi lamang ang qualifier na maaaring magkaroon ng pdl argument sa lagda. Isa pa
Ang mahalagang qualifier ay ang "[t]" na opsyon na nagba-flag ng pdl bilang pansamantala. Anong ginagawa niyan
ibig sabihin? Sabihin mo sa PDL::PP na ang pdl na ito ay ginagamit lamang para sa mga pansamantalang resulta sa kurso ng
ang pagkalkula at hindi ka interesado sa halaga nito pagkatapos ng pagkalkula
nakumpleto. Ngunit bakit kailangan munang malaman ng PDL::PP ang tungkol dito? Ang dahilan
ay malapit na nauugnay sa mga konsepto ng pdl auto creation (narinig mo ang tungkol sa itaas) at
implicit threading. Kung gagamit ka ng implicit threading ang dimensionality ng awtomatikong
ang ginawang pdls ay talagang mas malaki kaysa sa tinukoy sa lagda. Na may "[o]" na na-flag
Ang mga pdls ay gagawin upang magkaroon sila ng mga karagdagang dimensyon ayon sa kinakailangan ng numero
ng mga implicit na sukat ng thread. Kapag lumilikha ng isang pansamantalang pdl, gayunpaman, ito ay palaging lamang
gawing sapat na malaki upang mahawakan nito ang resulta para sa isang pag-ulit sa isang thread loop, ibig sabihin
kasing laki ng hinihingi ng lagda. Kaya mas kaunting memorya ang nasayang kapag nag-flag ka ng isang pdl bilang
pansamantala. Pangalawa, maaari mong gamitin ang output auto creation na may pansamantalang pdls kahit na ikaw
ay gumagamit ng tahasang threading na ipinagbabawal para sa mga normal na output pdls na na-flag ng "[o]"
(tingnan ang PDL::Indexing).
Narito ang isang halimbawa kung saan ginagamit namin ang [t] qualifier. Tinukoy namin ang function na "callf" na
tinatawag ang isang C routine na "f" na nangangailangan ng pansamantalang hanay ng parehong laki at uri ng array
"a" (paumanhin tungkol sa forward reference para sa $P; ito ay isang pointer access, tingnan sa ibaba):
pp_def('callf',
Pars => 'a(n); [t] tmp(n); [o] b()',
Code => 'int ns = $SIZE(n);
f($P(a),$P(b),$P(tmp),ns);
'
);
Argumento sukat at ang lagda
Ngayon lang natin napag-usapan ang mga sukat ng pdls at ang lagda. Paano sila magkakaugnay?
Sabihin nating gusto nating magdagdag ng scalar + ang index number sa isang vector:
pp_def('add2',
Pars => 'a(n); b(); [o]c(n);',
Code => 'loop(n) %{
$c() = $a() + $b() + n;
%}'
);
Mayroong ilang mga puntong dapat pansinin dito: una, ang argumentong "Pars" ay naglalaman na ngayon ng n
mga argumento upang ipakita na mayroon tayong iisang dimensyon a at c. Mahalagang tandaan
na ang mga dimensyon ay mga aktwal na entity na naa-access sa pamamagitan ng pangalan kaya ito idineklara a at c sa
magkaroon ng pareho unang sukat. Sa karamihan ng mga kahulugan ng PP ang laki ng mga pinangalanang dimensyon ay
itakda mula sa kani-kanilang dimensyon ng mga di-output na pdls (mga walang "[o]" na bandila) ngunit
minsan baka gusto mong itakda ang laki ng isang pinangalanang dimensyon nang tahasan sa pamamagitan ng isang
integer na parameter. Tingnan sa ibaba sa paglalarawan ng seksyong "OtherPars" kung paano iyon gumagana.
Patuloy argumento sukat in ang lagda
Ipagpalagay na gusto mong awtomatikong malikha ang isang output piddle at alam mo iyon sa bawat
tawagan ang dimensyon nito ay magkakaroon ng parehong sukat (sabihin ang 9) anuman ang mga sukat ng
input piddles. Sa kasong ito, ginagamit mo ang sumusunod na syntax sa seksyong Pars upang tukuyin
laki ng sukat:
' [o] y(n=9); '
Tulad ng inaasahan, ang mga karagdagang sukat na kinakailangan sa pamamagitan ng pag-thread ay gagawin kung kinakailangan. kung ikaw
kailangang magtalaga ng pinangalanang dimensyon ayon sa isang mas kumplikadong formula (kaysa sa pare-pareho)
dapat mong gamitin ang key na "RedoDimsCode" na inilarawan sa ibaba.
uri mga conversion at ang lagda
Tinutukoy din ng lagda ang uri ng mga conversion na isasagawa kapag ang isang PP
function ay hinihingi. Kaya ano ang mangyayari kapag tinawag namin ang isa sa aming naunang tinukoy
mga function na may iba't ibang uri ng pdls, hal
add2($a,$b,($ret=null));
kung saan ang $a ay may uri na "PDL_Float" at $b na may uri na "PDL_Short"? Gamit ang lagda tulad ng ipinapakita sa
ang kahulugan ng "add2" sa itaas ng datatype ng operasyon (tulad ng tinutukoy sa runtime) ay
na sa pdl na may 'pinakamataas' na uri (ang pagkakasunud-sunod ay byte < short < ushort < long < float
< doble). Sa add2 halimbawa ang datatype ng operasyon ay float ($a ay mayroon na
uri ng datos). Ang lahat ng mga pdl argument ay pagkatapos ay uri na na-convert sa datatype na iyon (hindi sila
na-convert sa lugar ngunit isang kopya na may tamang uri ay nilikha kung ang isang pdl argument ay walang
ang uri ng operasyon). Ang mga null pdls ay hindi nag-aambag ng isang uri sa pagpapasiya ng
uri ng operasyon. Gayunpaman, malilikha ang mga ito gamit ang datatype ng operasyon;
dito, halimbawa, $ret ay magiging ng uri ng float. Dapat mong malaman ang mga patakarang ito kung kailan
pagtawag sa mga function ng PP na may mga pdls ng iba't ibang uri upang kunin ang karagdagang imbakan at
isinasaalang-alang ang mga kinakailangan sa runtime.
Ang mga uri ng conversion na ito ay tama para sa karamihan ng mga function na karaniwan mong tinutukoy gamit ang "pp_def".
Gayunpaman, may ilang partikular na kaso kung saan ang bahagyang binagong uri ng pag-uugali ng conversion
ninanais. Para sa mga kasong ito, maaaring gamitin ang mga karagdagang kwalipikasyon sa lagda upang tukuyin ang
ninanais na mga katangian patungkol sa uri ng conversion. Ang mga kwalipikadong ito ay maaaring pagsamahin sa
ang mga nakatagpo na natin (ang paglikha mga kwalipikasyon "[o]" at "[t]"). Tara na
sa pamamagitan ng listahan ng mga qualifier na nagbabago ng uri ng pag-uugali ng conversion.
Ang pinakamahalaga ay ang "int" qualifier na madaling gamitin kapag may pdl argument
kumakatawan sa mga indeks sa isa pang pdl. Tingnan natin ang isang halimbawa mula sa "PDL::Ufunc":
pp_def('maximum_ind',
Pars => 'a(n); int [o] b()',
Code => '$GENERIC() cur;
int curind;
loop(n) %{
kung (!n || $a() > cur) {cur = $a(); curind = n;}
%}
$b() = curind;',
);
Hinahanap ng function na "maximum_ind" ang index ng pinakamalaking elemento ng isang vector. Kung titingnan mo
sa lagda napansin mo na ang output argument na "b" ay idineklara kasama ang
karagdagang "int" qualifier. Ito ay may mga sumusunod na kahihinatnan para sa mga uri ng conversion:
anuman ang uri ng input pdl "a" ang output pdl "b" ay magiging type "PDL_Long"
na may katuturan dahil ang "b" ay kakatawan ng isang index sa "a". Higit pa rito, kung tatawagan mo ang
function na may umiiral na output pdl "b" ang uri nito ay hindi makakaimpluwensya sa datatype ng
operasyon (tingnan sa itaas). Samakatuwid, kahit na ang "a" ay isang mas maliit na uri kaysa sa "b" hindi ito magiging
na-convert upang tumugma sa uri ng "b" ngunit nananatiling hindi nagalaw, na nakakatipid ng memorya at mga cycle ng CPU
at ang tamang gawin kapag ang "b" ay kumakatawan sa mga indeks. Tandaan din na maaari mong gamitin ang
'int' qualifier kasama ng iba pang qualifier (ang "[o]" at "[t]" qualifiers). Ang order ay
makabuluhan -- nauuna ang mga uri ng kwalipikasyon sa mga kwalipikasyon sa paggawa ("[o]" at "[t]").
Ang halimbawa sa itaas ay nagpapakita rin ng karaniwang paggamit ng "$GENERIC()" na macro. Lumalawak ito
sa kasalukuyang uri sa tinatawag na generic loop. Ano ang isang generic na loop? Tulad mo na
narinig ang isang PP function na may runtime datatype na tinutukoy ng uri ng pdl arguments
ito ay na-invoke sa. Ang PP na nabuong XS code para sa function na ito ay naglalaman ng a
lumipat tulad ng "switch (type) {case PDL_Byte: ... case PDL_Double: ...}" na pumipili ng case
batay sa runtime datatype ng function (ito ay tinatawag na isang uri ``loop'' dahil doon
ay isang loop sa PP code na bumubuo ng mga kaso). Sa anumang kaso ang iyong code ay ipinasok nang isang beses
para sa bawat uri ng PDL sa pahayag ng switch na ito. Ang "$GENERIC()" macro ay lumalawak lamang sa
kani-kanilang uri sa bawat kopya ng iyong na-parse na code sa "switch" na pahayag na ito, hal, sa
Ang "case PDL_Byte" na seksyong "cur" ay lalawak sa "PDL_Byte" at iba pa para sa ibang case
mga pahayag. Sa palagay ko napagtanto mo na ito ay isang kapaki-pakinabang na macro upang magkaroon ng mga halaga ng pdls sa ilan
code.
Mayroong ilang iba pang mga qualifier na may katulad na mga epekto bilang "int". Para sa iyong
kaginhawaan doon ay ang "float" at "double" qualifiers na may kahalintulad na mga kahihinatnan sa
i-type ang mga conversion bilang "int". Ipagpalagay natin na mayroon kang isang napaka malaking hanay kung saan mo nais
kalkulahin ang mga kabuuan ng row at column na may katumbas ng function na "sumover". Gayunpaman, kasama
ang normal na kahulugan ng "sumover" na maaari kang magkaroon ng mga problema kapag ang iyong data ay, hal ng
uri ng maikli. Isang tawag na parang
sumover($large_pdl,($sums = null));
ay magreresulta sa $sums na uri ng maikli at samakatuwid ay madaling kapitan ng mga error sa overflow kung
Ang $large_pdl ay isang napakalaking array. Sa kabilang banda tumatawag
@dims = $large_pdl->dims; shift @dims;
sumover($large_pdl,($sums = zeroes(double,@dims)));
ay hindi rin magandang alternatibo. Ngayon wala kaming mga overflow na problema sa $sums ngunit sa
ang gastos ng isang uri ng conversion ng $large_pdl sa doble, isang bagay na masama kung ito talaga
isang malaking pdl. Na kung saan ang "doble" ay madaling gamitin:
pp_def('sumoverd',
Pars => 'a(n); doble [o] b()',
Code => 'double tmp=0;
loop(n) %{ tmp += a(); %}
$b() = tmp;',
);
Ito ay nakakakuha sa amin sa paligid ng uri ng conversion at mga problema sa overflow. Muli, kahalintulad sa
Ang "int" qualifier na "double" ay nagreresulta sa "b" na palaging may uri na doble anuman ang uri
ng "a" nang hindi humahantong sa isang uri ng conversion ng "a" bilang side effect.
Sa wakas, mayroong mga "type+" na mga qualifier kung saan ang uri ay isa sa "int" o "float". Ano
ibig sabihin ba nito. Ilarawan natin ang qualifier na "int+" na may aktwal na kahulugan ng
sumover:
pp_def('sumover',
Pars => 'a(n); int+ [o] b()',
Code => '$GENERIC(b) tmp=0;
loop(n) %{ tmp += a(); %}
$b() = tmp;',
);
Gaya ng nakita na natin para sa mga kwalipikasyong "int", "float" at "double", isang pdl na minarkahan ng
"type+" qualifier ay hindi nakakaimpluwensya sa datatype ng pdl operation. Ang kahulugan nito ay
"gawin itong pdl kahit man lang sa uri ng "uri" o mas mataas, ayon sa kinakailangan ng uri ng
operation". Sa halimbawa ng sumover, nangangahulugan ito na kapag tinawag mo ang function na may "a"
ng uri PDL_Short ang output pdl ay magiging uri ng PDL_Long (tulad ng magiging
kaso na may "int" qualifier). Muli nitong sinusubukan na maiwasan ang mga problema sa pag-apaw kapag ginagamit
maliliit na datatypes (eg byte images). Gayunpaman, kapag ang datatype ng operasyon ay mas mataas
kaysa sa uri na tinukoy sa "type+" qualifier na "b" ay gagawin gamit ang datatype ng
ang operasyon, hal. kapag ang "a" ay may uri ng doble, ang "b" ay magiging doble rin. Umaasa kami
sumasang-ayon ka na ito ay makatwirang pag-uugali para sa "sumover". Ito ay dapat na malinaw kung paano ang
Gumagana ang qualifier na "float+" ayon sa pagkakatulad. Maaaring kailanganin upang matukoy ang isang set
ng mga alternatibong uri para sa mga parameter. Gayunpaman, malamang na hindi ito maipapatupad
hanggang sa may makaisip ng makatwirang paggamit nito.
Tandaan na kailangan na nating tukuyin ang $GENERIC macro na may pangalan ng pdl upang makuha ang
type mula sa argument na iyon. Bakit ganon? Kung maingat mong sinunod ang aming mga paliwanag ay gagawin mo
napagtanto na sa ilang mga kaso ang "b" ay magkakaroon ng ibang uri kaysa sa uri ng
operasyon. Ang pagtawag sa '$GENERIC' na macro na may "b" bilang argument ay tinitiyak na ang uri
ay palaging kapareho ng sa "b" sa bahaging iyon ng generic na loop.
Ito ay tungkol sa lahat ng masasabi tungkol sa seksyong "Pars" sa isang "pp_def" na tawag. Dapat mo
tandaan na ang seksyong ito ay tumutukoy sa lagda ng isang tinukoy na function ng PP, maaari mong gamitin
ilang mga pagpipilian upang maging kwalipikado ang ilang mga argumento bilang output at pansamantalang args at lahat
ang mga sukat na maaari mong i-refer sa ibang pagkakataon sa seksyong "Code" ay tinutukoy ng pangalan.
Mahalagang maunawaan mo ang kahulugan ng lagda dahil sa pinakabagong PDL
mga bersyon na magagamit mo ito upang tukuyin ang mga sinulid na function mula sa loob ng Perl, ibig sabihin, kung ano ang tinatawag namin
Perl antas sinulid. Pakisuri ang PDL::Indexing para sa mga detalye.
Ang kodigo seksyon
Ang seksyong "Code" ay naglalaman ng aktwal na XS code na nasa pinakaloob na bahagi ng a
thread loop (kung hindi mo alam kung ano ang thread loop ay hindi mo pa rin nabasa
PDL::Pag-index; gawin ito ngayon ;) pagkatapos ng anumang PP macros (tulad ng $GENERIC) at PP function na
pinalawak (tulad ng "loop" function na ipapaliwanag namin sa susunod).
Mabilis nating ulitin ang halimbawa ng "sumover":
pp_def('sumover',
Pars => 'a(n); int+ [o] b()',
Code => '$GENERIC(b) tmp=0;
loop(n) %{ tmp += a(); %}
$b() = tmp;',
);
Ang "loop" construct sa seksyong "Code" ay tumutukoy din sa pangalan ng dimensyon kaya hindi mo gagawin
kailangang tukuyin ang anumang mga limitasyon: ang loop ay tama ang laki at lahat ay ginagawa para sa iyo,
muli.
Susunod, mayroong nakakagulat na katotohanang ginagawa ng "$a()" at "$b()". hindi naglalaman ng index. Ito
ay hindi kailangan dahil kami ay umiikot n at alam ng parehong mga variable kung aling mga sukat
mayroon sila kaya awtomatiko nilang alam na nilo-loop sila.
Ang feature na ito ay napakadaling gamitin sa maraming lugar at gumagawa ng mas maikling code. Ng
siyempre, may mga pagkakataon na gusto mong iwasan ito; narito ang isang function na gumagawa ng a
matrix symmetric at nagsisilbing halimbawa kung paano mag-code ng tahasang pag-loop:
pp_def('symm',
Pars => 'a(n,n); [o]c(n,n);',
Code => 'loop(n) %{
int n2;
para sa(n2=n; n2<$SIZE(n); n2++) {
$c(n0 => n, n1 => n2) =
$c(n0 => n2, n1 => n) =
$a(n0 => n, n1 => n2);
}
%}
'
);
I-dissect natin ang mga nangyayari. Una, ano ang dapat gawin ng pagpapaandar na ito? Mula nito
signature na nakikita mo na nangangailangan ng 2D matrix na may pantay na bilang ng mga column at row at
naglalabas ng matrix na may parehong laki. Mula sa isang ibinigay na input matrix $a ito ay nag-compute ng simetriko
output matrix $c (symmetric sa matrix sense na A^T = A kung saan ang ^T ay nangangahulugang matrix
transpose, o sa PDL parlance $c == $c->xchg(0,1)). Ginagawa ito sa pamamagitan lamang ng paggamit ng mga halaga
sa at sa ibaba ng dayagonal ng $a. Sa output matrix $c lahat ng mga halaga sa at sa ibaba ng
ang dayagonal ay kapareho ng nasa $a habang ang nasa itaas ng dayagonal ay isang salamin na imahe ng
ang mga nasa ibaba ng dayagonal (sa itaas at ibaba ay binibigyang-kahulugan dito sa paraan ng pagpi-print ng PDL
2D pdls). Kung medyo kakaiba pa rin ang paliwanag na ito, sige lang, gumawa ng kaunting file
kung saan mo isusulat ang kahulugang ito, buuin ang bagong extension ng PDL (tingnan ang seksyon sa
Makefiles para sa PP code) at subukan ito gamit ang ilang mga halimbawa.
Ang pagkakaroon ng ipinaliwanag kung ano ang function ay dapat na gawin mayroong isang pares ng mga puntos na nagkakahalaga
pagpuna mula sa syntactical point of view. Una, nakuha namin ang laki ng dimensyon na pinangalanan
"n" muli sa pamamagitan ng paggamit ng $SIZE macro. Pangalawa, biglang may mga nakakatawang "n0" at "n1"
mga pangalan ng index sa code kahit na ang lagda ay tumutukoy lamang sa dimensyon na "n". Bakit ito? Ang
nagiging malinaw ang dahilan kapag napansin mong pareho ang una at pangalawang dimensyon ng $a at $b
ay pinangalanang "n" sa pirma ng "symm". Ito ay nagsasabi sa PDL::PP na ang una at pangalawa
ang sukat ng mga argumentong ito ay dapat na may parehong laki. Kung hindi ang nabuong function
magtataas ng runtime error. Gayunpaman, ngayon ay nasa isang access sa $a at $c PDL::PP ay hindi maaaring malaman
out kung aling index ang "n" ay tumutukoy sa anumang higit pa mula sa pangalan ng index. Samakatuwid, ang
ang mga indeks na may parehong mga pangalan ng dimensyon ay binibilang mula kaliwa hanggang kanan simula sa 0, hal
ang halimbawa sa itaas na "n0" ay tumutukoy sa unang dimensyon ng $a at $c, "n1" sa pangalawa at
iba pa.
Sa lahat ng mga halimbawa sa ngayon, ginamit lang namin ang mga miyembro ng "Pars" at "Code" ng hash na iyon
naipasa sa "pp_def". Mayroong tiyak na iba pang mga susi na kinikilala ng PDL::PP at
maririnig natin ang tungkol sa ilan sa kanila sa kurso ng dokumentong ito. Maghanap ng isang (hindi kumpleto)
listahan ng mga key sa Appendix A. Isang listahan ng mga macro at PPfunctions (na-encounter lang namin
ilan sa mga nasa mga halimbawa sa itaas pa) na pinalawak sa mga halaga ng hash argument
sa "pp_def" ay buod sa Appendix B.
Sa puntong ito, maaaring angkop na banggitin na ang PDL::PP ay hindi isang ganap na static,
mahusay na dinisenyo na hanay ng mga gawain (tulad ng sinabi ni Tuomas: "itigil ang pag-iisip ng PP bilang isang set ng
mga gawaing inukit sa bato") ngunit sa halip ay isang koleksyon ng mga bagay na ang PDL::PP may-akda
Itinuturing ni (Tuomas J. Lukka) na kailangan niyang magsulat ng madalas sa kanyang mga nakagawiang extension ng PDL.
Sinisikap ng PP na maging napapalawak upang sa hinaharap, kapag lumitaw ang mga bagong pangangailangan, magagawa ang bagong karaniwang code
i-abstract pabalik dito. Kung gusto mong matuto nang higit pa kung bakit mo gustong magbago
PDL::PP at kung paano ito gawin tingnan ang seksyon sa PDL::PP internals.
Pag-asikaso masama halaga
Kung wala kang masamang halaga na suporta na naipon sa PDL maaari mong balewalain ang seksyong ito at ang
mga kaugnay na key: "BadCode", "HandleBad", ... (subukang i-print ang halaga ng
$PDL::Bad::Status - kung katumbas ito ng 0 pagkatapos ay dumiretso).
Mayroong ilang mga key at macro na ginagamit kapag nagsusulat ng code upang pangasiwaan ang mga masasamang halaga. Ang una
ang isa ay ang "HandleBad" key:
HandleBad => 0
Nagba-flag ito ng pp-routine bilang HINDI paghawak ng masasamang halaga. Kung ang gawaing ito ay pinadalhan ng piddles
gamit ang kanilang "badflag" set, pagkatapos ay isang babala na mensahe ay naka-print sa STDOUT at ang piddles
ay pinoproseso na parang valid na numero ang value na ginamit para kumatawan sa masamang value. Ang
Ang halaga ng "badflag" ay hindi itinataguyod sa mga piddle ng output.
Ang isang halimbawa kung kailan ito ginagamit ay para sa mga nakagawiang FFT, na sa pangkalahatan ay walang paraan
ng pagbalewala sa bahagi ng data.
HandleBad => 1
Nagiging sanhi ito ng PDL::PP na magsulat ng karagdagang code na nagsisigurong ginagamit ang seksyong BadCode, at
na gumagana ang "$ISBAD()" macro (at ang mga kapatid nito).
Hindi ibinigay ang HandleBad
Kung ang alinman sa mga input piddles ay may kanilang "badflag" set, pagkatapos ay ang output piddles ay
itakda ang kanilang "badflag", ngunit ang anumang ibinigay na BadCode ay binabalewala.
Ang halaga ng "HandleBad" ay ginagamit upang tukuyin ang mga nilalaman ng "BadDoc" key, kung ito ay hindi
binigay
Upang mahawakan ang masasamang halaga, dapat na medyo naiiba ang pagkakasulat ng code; halimbawa,
$c() = $a() + $b();
nagiging parang
kung ($a() != BADVAL && $b() != BADVAL ) {
$c() = $a() + $b();
} Iba pa {
$c() = BADVAL;
}
Gayunpaman, gusto lang namin ang pangalawang bersyon kung may masasamang halaga sa mga input piddle
(at ang suportang may masamang halaga ay gusto!) - kung hindi, gusto talaga namin ang orihinal na code.
Dito pumapasok ang "BadCode" key; ginagamit mo ito upang tukuyin ang code na isasagawa kung masama
maaaring naroroon ang mga halaga, at ginagamit ito ng PP at ang seksyong "Code" upang lumikha ng isang bagay
gaya ng:
kung (naroroon_ang_masamang_halaga) {
fancy_threadloop_stuff {
BadCode
}
} Iba pa {
fancy_threadloop_stuff {
kodigo
}
}
Nangangahulugan ang diskarte na ito na halos walang overhead kapag walang masamang halaga
(ibig sabihin ang badflag routine ay nagbabalik ng 0).
Ang seksyong BadCode ay maaaring gumamit ng parehong mga macro at looping construct bilang seksyon ng Code.
Gayunpaman, hindi ito gaanong magagamit kung wala ang mga sumusunod na karagdagang macro:
$ISBAD(var)
Upang suriin kung ang halaga ng piddle ay masama, gamitin ang $ISBAD macro:
if ($ISBAD(a()) ) { printf("a() is bad\n"); }
Maaari mo ring i-access ang mga ibinigay na elemento ng piddle:
if ($ISBAD(a(n=>l)) ) { printf("element %d of a() is bad\n", l); }
$ISGOOD(var)
Ito ang kabaligtaran ng $ISBAD macro.
$SETBAD(var)
Para kapag gusto mong magtakda ng isang elemento ng isang piddle masama.
$ISBADVAR(c_var,pdl)
Kung na-cache mo ang halaga ng piddle "$a()" sa isang c-variable ("foo" say), pagkatapos ay sa
suriin kung ito ay masama, gamitin ang "$ISBADVAR(foo,a)".
$ISGOODVAR(c_var,pdl)
Tulad ng nasa itaas, ngunit sa pagkakataong ito ay tinitingnan kung hindi masama ang naka-cache na halaga.
$SETBADVAR(c_var,pdl)
Upang kopyahin ang masamang halaga para sa isang piddle sa ac variable, gamitin ang "$SETBADVAR(foo,a)".
GAGAWIN: banggitin ang "$PPISBAD()" atbp mga macro.
Gamit ang mga macro na ito, maaaring tukuyin ang code sa itaas bilang:
Code => '$c() = $a() + $b();',
BadCode => '
kung ($ISBAD(a()) || $ISBAD(b()) ) {
$SETBAD(c());
} Iba pa {
$c() = $a() + $b();
}',
Dahil ito ay Perl, TMTOWTDI, kaya maaari mo ring isulat:
BadCode => '
kung ($ISGOOD(a()) && $ISGOOD(b()) ) {
$c() = $a() + $b();
} Iba pa {
$SETBAD(c());
}',
Kung gusto mo ng access sa halaga ng badflag para sa isang naibigay na piddle, maaari mong gamitin ang
Mga macro na "$PDLSTATExxxx()":
$PDLSTATEISBAD(pdl)
$PDLSTATEISGOOD(pdl)
$PDLSTATESETBAD(pdl)
$PDLSTATESETGOOD(pdl)
GAGAWIN: banggitin ang mga opsyon na "FindBadStatusCode" at "CopyBadStatusCode" sa "pp_def", pati na rin
bilang "BadDoc" key.
interfacing iyong sariling/aklatan function paggamit PP
Ngayon, isaalang-alang ang sumusunod: mayroon kang sariling C function (na maaaring sa katunayan ay bahagi ng
ilang library na gusto mong i-interface sa PDL) na tumatagal bilang mga argumento ng dalawang pointer
mga vector ng doble:
void myfunc(int n,doble *v1,doble *v2);
Ang tamang paraan ng pagtukoy sa PDL function ay
pp_def('myfunc',
Pars => 'a(n); [o]b(n);',
GenericTypes => ['D'],
Code => 'myfunc($SIZE(n),$P(a),$P(b));'
);
Ang "$P("pagkakapantayAng ")" syntax ay nagbabalik ng isang pointer sa unang elemento at ang iba pang mga elemento ay
garantisadong magsisinungaling pagkatapos nito.
Pansinin na dito posible na gumawa ng maraming pagkakamali. Una, dapat gamitin ang $SIZE(n).
sa halip na "n". Pangalawa, hindi ka dapat maglagay ng anumang mga loop sa code na ito. Pangatlo, dito tayo magkaharap
isang bagong hash key na kinikilala ng PDL::PP : ang deklarasyon ng "GenericTypes" ay nagsasabi sa PDL::PP na
BUMUO LAMANG ANG TYPELOOP FOP ANG LISTAHAN NG MGA URI NA ITINUKAD. Sa kasong ito, "doble". Ito
ay may dalawang pakinabang. Una ang laki ng pinagsama-samang code ay nabawasan nang malaki, pangalawa kung
Ang mga hindi dobleng argumento ay ipinapasa sa "myfunc()" Awtomatikong iko-convert ng PDL ang mga ito sa
doble bago ipasa sa panlabas na C routine at i-convert ang mga ito pabalik pagkatapos.
Maaari ding gamitin ng isa ang "Pars" para maging kwalipikado ang mga uri ng indibidwal na argumento. Kaya maaari rin ang isa
isulat ito bilang:
pp_def('myfunc',
Pars => 'doble a(n); doble [o]b(n);',
Code => 'myfunc($SIZE(n),$P(a),$P(b));'
);
Ang uri ng pagtutukoy sa "Pars" ay hindi nagbubukod sa argumento mula sa pagkakaiba-iba sa typeloop -
sa halip ito ay awtomatikong na-convert din at mula sa uri na tinukoy. Ito ay malinaw naman
kapaki-pakinabang sa isang mas pangkalahatang halimbawa, hal:
void myfunc(int n,float *v1,long *v2);
pp_def('myfunc',
Pars => 'float a(n); mahaba [o]b(n);',
GenericTypes => ['F'],
Code => 'myfunc($SIZE(n),$P(a),$P(b));'
);
Tandaan na ginagamit pa rin namin ang "GenericTypes" upang bawasan ang laki ng uri ng loop, malinaw naman na magagawa ng PP
sa prinsipyo, makita ito at awtomatikong gawin ito kahit na ang code ay hindi pa nakakamit iyon
antas ng pagiging sopistikado!
Panghuli tandaan kapag ang mga uri ay awtomatikong na-convert DAPAT gamitin ang "[o]" qualifier para sa
output variable o mahirap ang isang pagbabago ay ma-optimize ng PP!
Kung nag-interface ka sa isang malaking library maaari mong i-automate ang interfacing nang higit pa. Kaya ni Perl
tulungan kang muli(!) sa paggawa nito. Sa maraming mga aklatan mayroon kang ilang mga convention sa pagtawag.
Ito ay maaaring pagsamantalahan. Sa madaling salita, maaari kang magsulat ng isang maliit na parser (na talagang hindi
mahirap sa Perl) na bubuo ng mga tawag sa "pp_def" mula sa mga na-parse na paglalarawan ng
ang mga function sa library na iyon. Para sa isang halimbawa, mangyaring suriin ang Slatec interface sa
"Lib" tree ng pamamahagi ng PDL. Kung gusto mong suriin (sa panahon ng pag-debug) kung saan tumatawag
Pinapaandar ng PP ang iyong Perl code na nakabuo ng isang maliit na helper package ay madaling gamitin
pinapalitan ang mga function ng PP sa pamamagitan ng magkaparehong pinangalanang mga na nagtatapon ng kanilang mga argumento sa stdout.
Sabihin mo lang
perl -MPDL::PP::Dump myfile.pd
upang makita ang mga tawag sa "pp_def" at mga kaibigan. Subukan ito sa ops.pd at slatec.pd. Kung ikaw ay
interesado (o gustong pagandahin ito), ang source ay nasa Basic/Gen/PP/Dump.pm
iba macros at function in ang kodigo seksyon
Macros: Sa ngayon ay nakatagpo na tayo ng $SIZE, $GENERIC at $P na mga macro. Ngayon kami ay pupunta sa
mabilis na ipaliwanag ang iba pang mga macro na pinalawak sa seksyong "Code" ng PDL::PP kasama
na may mga halimbawa ng kanilang paggamit.
$T Ang $T macro ay ginagamit para sa mga switch ng uri. Ito ay lubhang kapaki-pakinabang kapag kailangan mong gamitin
iba't ibang panlabas (hal. library) na mga function depende sa uri ng input ng mga argumento.
Ang pangkalahatang syntax ay
$Ttypeletters(type_alternatives)
kung saan ang "typeletters" ay isang permutation ng isang subset ng mga titik na "BSULFD" na nakatayo
para sa Byte, Short, Ushort, atbp. at "type_alternatives" ay ang mga pagpapalawak kapag ang uri
ng operasyon ng PP ay katumbas ng ipinahiwatig ng kaukulang titik. tayo
ilarawan ang hindi maintindihang paglalarawan na ito sa pamamagitan ng isang halimbawa. Ipagpalagay na mayroon kang dalawang C
mga function na may mga prototype
void float_func(float *in, float *out);
void double_func(double *in, double *out);
na karaniwang ginagawa ang parehong bagay ngunit ang isa ay tumatanggap ng float at ang iba pang double pointer.
Maaari mong i-interface ang mga ito sa PDL sa pamamagitan ng pagtukoy sa isang generic na function na "foofunc" (na kung saan ay
tawagan ang tamang function depende sa uri ng pagbabago):
pp_def('foofunc',
Pars => ' a(n); [o] b();',
Code => ' $TFD(float_func,double_func) ($P(a),$P(b));'
GenericTypes => [qw(FD)],
);
Pakitandaan na hindi mo masasabi
Code => ' $TFD(float,double)_func ($P(a),$P(b));'
dahil ang $T macro ay lumalawak na may mga trailing space, kahalintulad sa C preprocessor macros.
Ang bahagyang mas mahabang anyo na inilarawan sa itaas ay tama. Kung gusto mo talaga ng maikli, ikaw
pwede syempre
'$TBSULFD('.(sumali sa ',',mapa {"long_identifier_name_$_"}
qw/byt short unseigned lounge flotte dubble/).');'
$PP
Ang $PP macro ay ginagamit para sa isang tinatawag na Physical puntero daan. ang Physical ay tumutukoy sa
ilang mga panloob na pag-optimize ng PDL (para sa mga pamilyar sa PDL core tayo
pinag-uusapan ang tungkol sa mga pag-optimize ng vaffine). Ang macro na ito ay pangunahing para sa panloob na paggamit at ikaw
hindi dapat kailanganing gamitin ito sa alinman sa iyong normal na code.
$COMP (at ang seksyong "OtherPars")
Ang $COMP macro ay ginagamit upang ma-access ang mga hindi pdl na halaga sa seksyon ng code. Ang pangalan nito ay
hango sa pagpapatupad ng mga pagbabago sa PDL. Ang mga variable na maaari mong i-refer
sa paggamit ng $COMP ay mga miyembro ng ``compiled'' structure na kumakatawan sa PDL
pagbabagong pinag-uusapan ngunit hindi pa naglalaman ng anumang impormasyon tungkol sa mga sukat
(para sa karagdagang detalye tingnan ang PDL::Internals). Gayunpaman, maaari mong ituring ang $COMP bilang isang
itim na kahon nang walang alam tungkol sa pagpapatupad ng mga pagbabago sa PDL.
Kaya kailan mo gagamitin ang macro na ito? Ang pangunahing paggamit nito ay upang ma-access ang mga halaga ng mga argumento na
ay idineklara sa seksyong "OtherPars" ng isang "pp_def" na kahulugan. Ngunit pagkatapos ay wala ka pa
narinig mo pa ang tungkol sa "OtherPars" key?! Magkaroon tayo ng isa pang halimbawa na naglalarawan
karaniwang paggamit ng parehong mga bagong tampok:
pp_def('pnmout',
Pars => 'a(m)',
OtherPars => "char* fd",
GenericTypes => [qw(BUSL)],
Code => 'PerlIO *fp;
IO *io;
io = GvIO(gv_fetchpv ($COMP(fd),FALSE,SVt_PVIO));
kung (!io || !(fp = IoIFP(io)))
croak("Hindi malaman ang FP");
kung (PerlIO_write(fp,$P(a),len) != len)
croak("Error sa pagsulat ng pnm file");
');
Ang function na ito ay ginagamit upang magsulat ng data mula sa isang pdl sa isang file. Ang file descriptor ay naipasa
bilang isang string sa function na ito. Ang parameter na ito ay hindi napupunta sa seksyong "Mga Par."
dahil hindi ito maaaring maging kapaki-pakinabang na tratuhin tulad ng isang pdl kundi sa angkop na pinangalanan
"OtherPars" na seksyon. Ang mga parameter sa seksyong "OtherPars" ay sumusunod sa mga nasa "Pars"
seksyon kapag invoking ang function, ibig sabihin
buksan ang FILE,">out.dat" o mamatay "hindi mabuksan out.dat";
pnmout($pdl,'FILE');
Kapag nais mong ma-access ang parameter na ito sa loob ng seksyon ng code kailangan mong sabihin sa PP sa pamamagitan ng
gamit ang $COMP macro, ibig sabihin, isulat mo ang "$COMP(fd)" tulad ng sa halimbawa. Kung hindi PP
hindi malalaman na ang "fd" na iyong tinutukoy ay kapareho ng tinukoy sa
"OtherPars" na seksyon.
Ang isa pang gamit para sa seksyong "OtherPars" ay ang magtakda ng pinangalanang dimensyon sa lagda.
Magkaroon tayo ng isang halimbawa kung paano ito ginagawa:
pp_def('setdim',
Pars => '[o] a(n)',
OtherPars => 'int ns => n',
Code => 'loop(n) %{ $a() = n; %}',
);
Sinasabi nito na ang pinangalanang dimensyon na "n" ay pasisimulan mula sa halaga ng iba
parametro "ns" na may uri ng integer (hulaan ko napagtanto mo na ginagamit namin ang
"CType From => named_dim" syntax). Ngayon ay maaari mong tawagan ang function na ito sa karaniwang paraan:
setdim(($a=null),5);
i-print ang $a;
[ 0 1 2 3 4 ]
Tinatanggap na ang function na ito ay hindi masyadong kapaki-pakinabang ngunit ito ay nagpapakita kung paano ito gumagana. kung ikaw
tawagan ang function na may umiiral na pdl at hindi mo kailangang tahasang tukuyin ang
laki ng "n" dahil maaaring malaman ito ng PDL::PP mula sa mga sukat ng hindi null na pdl. Sa
kaso binigay mo lang ang parameter ng dimensyon bilang "-1":
$a = kasaysayan($b);
setdim($a,-1);
Iyon ay dapat gawin ito.
Ang tanging PP function na ginamit namin sa mga halimbawa sa ngayon ay "loop". Bukod pa rito,
may kasalukuyang dalawang iba pang function na kinikilala sa seksyong "Code":
threadloop
Tulad ng narinig namin sa itaas, ang lagda ng isang tinukoy na function ng PP ay tumutukoy sa mga sukat ng lahat
ang mga argumentong pdl na kasangkot sa a kauna-unahan operasyon. Gayunpaman, madalas kang tumawag sa
mga function na tinukoy mo sa PP na may mga pdls na may mas maraming dimensyon kaysa doon
tinukoy sa lagda. Sa kasong ito, ang primitive na operasyon ay ginagawa sa lahat
subslices ng naaangkop na dimensionality sa tinatawag na a sinulid silo (Tingnan din
pangkalahatang-ideya sa itaas at PDL::Indexing). Ipagpalagay na mayroon kang ilang mga paniwala ng konseptong ito ikaw
malamang na pahalagahan na ang operasyon na tinukoy sa seksyon ng code ay dapat na
na-optimize dahil ito ang pinakamahigpit na loop sa loob ng thread loop. Gayunpaman, kung muli mong bisitahin
ang halimbawa kung saan tinukoy namin ang function na "pnmout", mabilis mong mapagtanto na naghahanap
up ang "IO" file descriptor sa panloob na thread loop ay hindi masyadong mahusay kapag nagsusulat
isang pdl na may maraming hilera. Ang isang mas mahusay na diskarte ay upang hanapin ang "IO" descriptor nang isang beses
sa labas ng thread loop at gamitin ang halaga nito pagkatapos ay sa loob ng pinakamahigpit na thread loop. Ito ay
eksakto kung saan magagamit ang function na "threadloop". Narito ang isang pinahusay na kahulugan
ng "pnmout" na gumagamit ng function na ito:
pp_def('pnmout',
Pars => 'a(m)',
OtherPars => "char* fd",
GenericTypes => [qw(BUSL)],
Code => 'PerlIO *fp;
IO *io;
int len;
io = GvIO(gv_fetchpv ($COMP(fd),FALSE,SVt_PVIO));
kung (!io || !(fp = IoIFP(io)))
croak("Hindi malaman ang FP");
len = $SIZE(m) * sizeof($GENERIC());
threadloop %{
kung (PerlIO_write(fp,$P(a),len) != len)
croak("Error sa pagsulat ng pnm file");
%}
');
Gumagana ito bilang mga sumusunod. Karaniwan ang C code na iyong isinusulat sa loob ng seksyong "Code" ay inilalagay
sa loob ng thread loop (ibig sabihin, ang PP ay bumubuo ng naaangkop na pambalot na XS code sa paligid nito).
Gayunpaman, kapag tahasan mong ginamit ang function na "threadloop", kinikilala ito ng PDL::PP at
hindi binabalot ang iyong code ng karagdagang thread loop. Ito ay may epekto na nagko-code sa iyo
magsulat sa labas ng thread loop ay isasagawa lamang ng isang beses sa bawat pagbabago at ang code lamang
kasama sa nakapalibot na "%{ ... %}" na pares ay inilalagay sa loob ng pinakamahigpit na thread loop. Ito
Magagamit din kapag gusto mong magsagawa ng desisyon (o anumang iba pang code, lalo na
CPU intensive code) isang beses lamang bawat thread, ibig sabihin
pp_addhdr('
#define RAW 0
#define ASCII 1
');
pp_def('do_raworascii',
Pars => 'a(); b(); [o]c()',
OtherPars => 'int mode',
Code => ' switch ($COMP(mode)) {
kaso RAW:
threadloop %{
/* gumawa ng hilaw na bagay */
%}
masira;
kaso ASCII:
threadloop %{
/* gawin ang mga bagay na ASCII */
%}
masira;
default:
croak("hindi kilalang mode");
}'
);
Mga uri
Gumagana ang mga uri ng function na katulad ng $T macro. Gayunpaman, kasama ang "mga uri" na pag-andar ang
code sa sumusunod na block (tinatanggalan ng "%{" at "%}" gaya ng dati) ay isinasagawa para sa lahat
mga kaso kung saan ang datatype ng operasyon ay anumang of ang mga uri na kinakatawan ng
ang mga titik sa argumento sa "type", hal
Code => '...
mga uri(BSUL) %{
/* gawin ang integer type na operasyon */
%}
mga uri(FD) %{
/* gawin ang floating point operation */
%}
... '
Ang RedoDimsCode seksyon
Ang "RedoDimsCode" na key ay isang opsyonal na key na ginagamit upang kalkulahin ang mga sukat ng piddles sa
runtime kung sakaling ang mga karaniwang tuntunin para sa pag-compute ng mga dimensyon mula sa lagda ay hindi
sapat. Ang mga nilalaman ng entry na "RedoDimsCode" ay binibigyang-kahulugan sa parehong paraan na iyon
ang seksyon ng Code ay binibigyang kahulugan-- ibig sabihin, ang mga PP macro ay pinalawak at ang resulta ay
binibigyang kahulugan bilang C code. Ang layunin ng code ay itakda ang laki ng ilang dimensyon na iyon
makikita sa pirma. Ang paglalaan ng imbakan at mga threadloop at iba pa ay ise-set up bilang
kung ang nakalkulang dimensyon ay lumitaw sa lagda. Sa iyong code, mag-compute ka muna
ang nais na laki ng isang pinangalanang dimensyon sa lagda ayon sa iyong mga pangangailangan at pagkatapos
italaga ang halagang iyon dito sa pamamagitan ng $SIZE() macro.
Bilang halimbawa, isaalang-alang ang sumusunod na sitwasyon. Nakikipag-interface ka sa isang panlabas na library
routine na nangangailangan ng pansamantalang array para maipasa ang workspace bilang argumento. Dalawa
input data arrays na naipasa ay p(m) at x(n). Ang output data array ay y(n). Ang
Ang routine ay nangangailangan ng workspace array na may haba na n+m*m, at gusto mo ang storage
awtomatikong nilikha tulad ng para sa anumang piddle na na-flag ng [t] o [o]. Ano
gusto mo ay sabihin ang isang bagay tulad ng
pp_def("myexternalfunc",
Pars => " p(m); x(n); [o] y; [t] trabaho(n+m*m); ",...
ngunit hindi iyon gagana, dahil hindi ma-interpret ng PP ang mga expression na may arithmetic sa
lagda. Sa halip magsulat ka
pp_def("myexternalfunc",
Pars => " p(m); x(n); [o] y; [t] trabaho(wn); ",
RedoDimsCode => "
int im = $PDL(p)->dims[0];
int in = $PDL(x)->dims[0];
int min = sa + im * im;
int inw = $PDL(work)->dims[0];
$SIZE(wn) = inw >= min ? inw: min; ",
Code => "
externalfunc($P(p),$P(x),$SIZE(m),$SIZE(n),$P(trabaho));
";)
Gumagana ang code na ito bilang mga sumusunod: Ang macro $PDL(p) ay lumalawak sa isang pointer sa pdl struct para sa
ang piddle p. Hindi mo gusto ang isang pointer sa data ( ie $P ) sa kasong ito, dahil ikaw
nais na ma-access ang mga pamamaraan para sa piddle sa antas ng C. Makukuha mo ang unang dimensyon ng
bawat isa sa mga piddles at itabi ang mga ito sa integer. Pagkatapos ay kalkulahin mo ang pinakamababang haba ng
work array ay maaaring. Kung nagpadala ang user ng piddle "work" na may sapat na storage, pagkatapos ay iwanan ito
mag-isa. Kung nagpadala ang user, sabihin ang isang null pdl, o walang pdl sa lahat, ang laki ng wn ay magiging
zero at i-reset mo ito sa pinakamababang halaga. Bago ang code sa seksyon ng Code ay
ang executed PP ay lilikha ng wastong imbakan para sa "trabaho" kung wala ito. Tandaan na ikaw
Kinuha lang ang unang dimensyon ng "p" at "x" dahil maaaring nagpadala ng piddles ang user
dagdag na sukat ng threading. Siyempre, ang pansamantalang piddle ay "gumana" (tandaan ang [t] flag)
hindi dapat bigyan ng anumang mga sukat ng thread.
Maaari mo ring gamitin ang "RedoDimsCode" para itakda ang dimensyon ng piddle na na-flag ng [o]. Dito sa
kaso itinakda mo ang mga sukat para sa pinangalanang dimensyon sa lagda gamit ang $SIZE() tulad ng sa
ang naunang halimbawa. Gayunpaman, dahil ang piddle ay na-flag ng [o] sa halip na [t],
ang mga sukat ng threading ay idaragdag kung kinakailangan na parang ang laki ng dimensyon
kinalkula mula sa lagda ayon sa karaniwang mga tuntunin. Narito ang isang halimbawa mula sa
PDL::Math
pp_def("polyroots",
Pars => 'cr(n); ci(n); [o]rr(m); [o]ri(m);',
RedoDimsCode => 'int sn = $PDL(cr)->dims[0]; $SIZE(m) = sn-1;',
Ang input piddles ay ang tunay at haka-haka na mga bahagi ng mga kumplikadong coefficient ng a
polinomyal. Ang output piddles ay tunay at haka-haka na mga bahagi ng mga ugat. may "n"
nag-ugat sa isang "n"th order polynomial at ang naturang polynomial ay may "n+1" coefficients (ang
zeoreth sa pamamagitan ng "n"th). Sa halimbawang ito, gagana nang tama ang threading. Ibig sabihin, ang
unang dimensyon ng output piddle na may sukat nito nababagay, ngunit iba pang mga threading
itatalaga ang mga sukat na parang walang "RedoDimsCode".
Typemap pag-asikaso in ang "Ibang Pars" seksyon
Ang seksyong "OtherPars" na tinalakay sa itaas ay kadalasang talagang napakahalaga kapag ikaw
interface ng mga panlabas na aklatan na may PDL. Gayunpaman sa maraming mga kaso ang mga panlabas na aklatan alinman
gumamit ng mga hinango na uri o pointer ng iba't ibang uri.
Ang karaniwang paraan upang mahawakan ito sa Perl ay ang paggamit ng "typemap" na file. Ito ay tinalakay sa
ilang detalye sa perlx sa karaniwang dokumentasyon ng Perl. Sa PP ang pag-andar ay napaka
katulad, para makagawa ka ng "typemap" na file sa direktoryo kung saan naninirahan ang iyong PP file
at kapag ito ay binuo ito ay awtomatikong binabasa upang malaman ang naaangkop na pagsasalin
sa pagitan ng uri ng C at ng built-in na uri ng Perl.
Iyon ay sinabi, mayroong ilang mahahalagang pagkakaiba mula sa pangkalahatang paghawak ng mga uri
sa XS. Ang una, at marahil ang pinakamahalaga, ay ang mga pointer sa mga uri sa ngayon
hindi pinapayagan sa seksyong "OtherPars." Upang malampasan ang limitasyong ito dapat mong gamitin ang
Uri ng "IV" (salamat kay Judd Taylor sa pagturo na ito ay kinakailangan para sa portability).
Malamang na pinakamahusay na ilarawan ito sa ilang mga code-snippet:
Halimbawa, ang function na "gsl_spline_init" ay may sumusunod na deklarasyon ng C:
int gsl_spline_init(gsl_spline * spline,
const double xa[], const double ya[], size_t size);
Malinaw na ang mga array na "xa" at "ya" ay mga kandidato para maipasa bilang piddles at ang
"Size" argument ay ang haba lang ng mga piddles na ito para mahawakan ng mga
"$SIZE()" macro sa PP. Ang problema ay ang pointer sa uri ng "gsl_spline". Ang likas na
Ang solusyon ay ang pagsulat ng isang "OtherPars" na deklarasyon ng form
OtherPars => 'gsl_spline *spl'
at sumulat ng isang maikling "typemap" na file na humawak sa ganitong uri. Hindi ito gumagana sa kasalukuyan
gayunpaman! Kaya ang kailangan mong gawin ay talakayin nang bahagya ang problema (at sa ilang paraan
mas madali din ito!):
Ang solusyon ay ang magdeklara ng "spline" sa seksyong "OtherPars" gamit ang isang "Integer Value",
"IV". Itinatago nito ang likas na katangian ng variable mula sa PP at pagkatapos ay kailangan mong (mabuti upang maiwasan
mga babala ng compiler!) magsagawa ng uri ng cast kapag ginamit mo ang variable sa iyong code.
Kaya ang "OtherPars" ay dapat kumuha ng form:
OtherPars => 'IV spl'
at kapag ginamit mo ito sa code ay isusulat mo
INT2PTR(gsl_spline *, $COMP(spl))
kung saan ang Perl API macro na "INT2PTR" ay ginamit upang mahawakan ang pointer cast upang maiwasan
mga babala ng compiler at mga problema para sa mga makina na may pinaghalong 32bit at 64bit na Perl
mga pagsasaayos. Ang pagsasama-sama nito tulad ng ginawa ni Andres Jordan (kasama ang pagbabago
gamit ang "IV" ni Judd Taylor) sa "gsl_interp.pd" sa pinagmumulan ng pamamahagi na makukuha mo:
pp_def('init_meat',
Pars => 'dobleng x(n); dobleng y(n);',
OtherPars => 'IV spl',
Code =>'
gsl_spline_init,( INT2PTR(gsl_spline *, $COMP(spl)), $P(x),$P(y),$SIZE(n)));'
);
kung saan inalis ko ang isang tawag sa macro wrapper, ngunit ikukubli nito ang talakayan.
Ang iba pang maliit na pagkakaiba kumpara sa karaniwang paghawak ng typemap sa Perl, ay iyon
hindi maaaring tukuyin ng user ang hindi karaniwang mga lokasyon ng typemap o mga filename ng typemap gamit ang
"TYPEMAPS" na opsyon sa MakeMaker... Kaya maaari ka lamang gumamit ng file na tinatawag na "typemap" at/o ang
"IV" trick sa itaas.
iba kapaki-pakinabang PP mga susi in data operasyon mga kahulugan
Narinig mo na ang tungkol sa "OtherPars" key. Sa kasalukuyan, walang maraming iba pang mga susi
para sa isang operasyon ng data na magiging kapaki-pakinabang sa normal (anuman iyon) PP programming. Sa
sa katunayan, magiging kawili-wiling marinig ang tungkol sa isang kaso kung saan sa tingin mo ay kailangan mo ng higit sa kung ano
ay ibinigay sa ngayon. Mangyaring magsalita sa isa sa mga mailing list ng PDL. Karamihan sa iba
Ang mga key na kinikilala ng "pp_def" ay talagang kapaki-pakinabang para sa tinatawag namin pagpira-pirasuhin pagpapatakbo (Tingnan ang
din sa itaas).
Ang isang bagay na mahigpit na pinaplano ay ang variable na bilang ng mga argumento, na magiging a
medyo nakakalito.
Isang hindi kumpletong listahan ng mga available na key:
Sa lugar
Ang pagtatakda ng key na ito ay nagmamarka sa nakagawiang bilang gumagana sa lugar - ie ang input at output
pareho ang piddles. Ang isang halimbawa ay "$a->inplace->sqrt()" (o "sqrt(inplace($a))").
Inplace => 1
Gamitin kapag ang routine ay unary function, gaya ng "sqrt".
Inplace => ['a']
Kung mayroong higit sa isang input piddles, tukuyin ang pangalan ng isa na maaaring
binago ang inplace gamit ang isang array reference.
Inplace => ['a','b']
Kung mayroong higit sa isang output piddle, tukuyin ang pangalan ng input piddle at
output piddle sa isang 2-element array reference. Ito ay malamang na hindi kailangan, ngunit iniwan
sa para sa pagkakumpleto.
Kung ang mga masamang halaga ay ginagamit, ang pangangalaga ay dapat gawin upang matiyak ang pagpapalaganap ng
badflag kapag inplace ay ginagamit; isaalang-alang ang sipi na ito mula sa Basic/Bad/bad.pd:
pp_def('replacebad',HandleBad => 1,
Pars => 'a(); [o]b();',
OtherPars => 'double newval',
Inplace => 1,
CopyBadStatusCode =>
'/* isulong ang badflag kung nasa lugar AT ito ay nagbago */
kung ( a == b && $ISPDLSTATEBAD(a) )
PDL->propogate_badflag( b, 0 );
/* laging siguraduhin na ang output ay "maganda" */
$SETPDLSATEGOOD(b);
',
...
Dahil ang routine na ito ay nag-aalis ng lahat ng masamang value, kung gayon ang output piddle ay nagkaroon ng masamang flag
nalinis. Kung tumakbo sa lugar (kaya "a == b"), pagkatapos ay kailangan nating sabihin sa lahat ng mga anak ng "a"
na ang masamang bandila ay nabura na (upang makatipid ng oras, siguraduhing tumatawag kami
"PDL->propogate_badgflag" lang kung ang input piddle ay may masamang flag set).
TANDAAN: ang isang ideya ay ang dokumentasyon para sa gawain ay maaaring awtomatiko
na-flag upang ipahiwatig na maaari itong isagawa sa lugar, ibig sabihin, isang bagay na katulad ng kung paano
Ang "HandleBad" ay nagtatakda ng "BadDoc" kung hindi ito ibinibigay (ito ay hindi isang perpektong solusyon).
iba PDL::PP function sa suportahan maigsi pakete depinisyon
Sa ngayon, inilarawan namin ang mga function na "pp_def" at "pp_done". PDL:: Nag-export ang PP ng ilan
iba pang mga pag-andar upang tulungan ka sa pagsulat ng maigsi na mga kahulugan ng pakete ng extension ng PDL.
pp_addhdr
Kadalasan kapag nag-interface ka sa mga function ng library tulad ng sa halimbawa sa itaas kailangan mong isama
karagdagang C kasama ang mga file. Dahil ang XS file ay nabuo ng PP kailangan namin ng ilang paraan upang
gawin PP ipasok ang naaangkop na isama ang mga direktiba sa tamang lugar sa nabuong XS
file. Sa layuning ito mayroong "pp_addhdr" function. Ito rin ang function na gagamitin
kapag gusto mong tukuyin ang ilang C function para sa panloob na paggamit ng ilan sa mga XS function
(na karamihan ay mga function na tinukoy ng "pp_def"). Sa pamamagitan ng pagsasama ng mga function na ito dito mo
siguraduhing ilalagay ng PDL::PP ang iyong code bago ang punto kung saan ang aktwal na XS module
magsisimula ang seksyon at samakatuwid ay iiwang hindi ginagalaw ng xsubpp (cf. perlxs at perlxstut
mga pahina ng tao).
Ang isang karaniwang tawag ay magiging
pp_addhdr('
#isama /* kailangan namin ng defs ng XXXX */
#include "libprotos.h" /* mga prototype ng mga function ng library */
#include "mylocaldecs.h" /* Local decs */
static void do_the real_work(PDL_Byte * in, PDL_Byte * out, int n)
{
/* gumawa ng ilang kalkulasyon gamit ang data */
}
');
Tinitiyak nito na ang lahat ng mga constant at prototype na kailangan mo ay maisasama nang maayos at
na maaari mong gamitin ang mga panloob na function na tinukoy dito sa "pp_def", hal:
pp_def('barfoo',
Pars => ' a(n); [o] b(n)',
GenericTypes => ['B'],
Code => ' int ns = $SIZE(n);
do_the_real_work($P(a),$P(b),ns);
',
);
pp_addpm
Sa maraming kaso, ang aktwal na PP code (ibig sabihin ang mga argumento sa "pp_def" na mga tawag) ay bahagi lamang ng
ang pakete na kasalukuyan mong ipinapatupad. Kadalasan mayroong karagdagang Perl code at XS
code na karaniwan mong isusulat sa pm at XS na mga file na awtomatiko na ngayon
nabuo ng PP. Kaya paano maipasok ang mga bagay na ito sa mga dynamic na nabuong file?
Sa kabutihang palad, mayroong ilang mga function, karaniwang tinatawag na "pp_addXXX" na tumutulong sa iyo
sa paggawa nito.
Ipagpalagay natin na mayroon kang karagdagang Perl code na dapat mapunta sa nabuo pm-file. Ito
ay madaling makamit gamit ang "pp_addpm" na utos:
pp_addpm(<<'EOD');
=head1 PANGALAN
PDL::Lib::Mylib -- isang PDL interface sa Mylib library
=head1 DESCRIPTION
Ang package na ito ay nagpapatupad ng isang interface sa Mylib package na may buo
threading at suporta sa pag-index (tingnan ang L ).
= gupitin
gumamit ng PGPLOT;
=head2 use_myfunc
inilalapat ng function na ito ang myfunc operation sa lahat ng
mga elemento ng input pdl anuman ang mga sukat
at ibinabalik ang kabuuan ng resulta
= gupitin
sub use_myfunc {
aking $pdl = shift;
myfunc($pdl->clump(-1),($res=null));
ibalik ang $res->sum;
}
DOE
pp_add_exported
Marahil ay nakuha mo na ang ideya. Sa ilang mga kaso gusto mo ring i-export ang iyong karagdagang
mga function. Para maiwasang magkaproblema sa PP na nakakagulo din sa @EXPORT
array na sasabihin mo lang sa PP na idagdag ang iyong mga function sa listahan ng mga na-export na function:
pp_add_exported('use_myfunc gethynx');
pp_add_isa
Gumagana ang command na "pp_add_isa" tulad ng function na "pp_add_exported". Ang mga argumento sa
Ang "pp_add_isa" ay idinagdag sa listahan ng @ISA, hal
pp_add_isa(' Some::Other::Class ');
pp_bless
Kung ang iyong pp_def routines ay gagamitin bilang object method gamitin ang "pp_bless" upang tukuyin ang
package (ie klase) kung saan ang iyong pp_defed pamamaraan ay idadagdag. Halimbawa,
"pp_bless('PDL::MyClass')". Ang default ay "PDL" kung ito ay aalisin.
pp_addxs
Minsan gusto mong magdagdag ng dagdag na XS code ng iyong sarili (na sa pangkalahatan ay hindi kasangkot sa
anumang mga isyu sa threading/indexing ngunit nagbibigay ng ilang iba pang pag-andar na gusto mong i-access
mula sa Perl side) hanggang sa nabuong XS file, halimbawa
pp_addxs('','
# Tukuyin ang endianness ng makina
int
isbigendian()
CODE:
unsigned short i;
PDL_Byte *b;
i = 42; b = (PDL_Byte*) (walang bisa*) &i;
kung (*b == 42)
RETVAL = 0;
else if (*(b+1) == 42)
RETVAL = 1;
iba
croak("Imposible - ang makina ay hindi malaki o maliit na endian!!\n");
OUTPUT:
RETVAL
');
Lalo na ang "pp_add_exported" at "pp_addxs" ay dapat gamitin nang may pag-iingat. Ginagamit ng PP
PDL::Exporter, kaya't ang pagpapahintulot sa PP na i-export ang iyong function ay nangangahulugan na sila ay idinagdag sa
karaniwang listahan ng function na na-export bilang default (ang listahan na tinukoy ng export tag
``:Func''). Kung gumagamit ka ng "pp_addxs" hindi mo dapat subukang gumawa ng anumang bagay na may kinalaman sa threading
o direktang pag-index. Ang PP ay mas mahusay sa pagbuo ng naaangkop na code mula sa iyong
mga kahulugan.
pp_add_boot
Sa wakas, maaaring gusto mong magdagdag ng ilang code sa seksyong BOOT ng XS file (kung hindi mo gagawin
alam kung ano ang check perlxs). Madali itong gawin gamit ang command na "pp_add_boot":
pp_add_boot(<
descript = mylib_initialize(KEEP_OPEN);
kung (ilarawan == NULL)
croak("Hindi masimulan ang library");
GlobalStruc->descrip = paglalarawan;
GlobalStruc->maxfiles = 200;
EOB
pp_export_nothing
Bilang default, inilalagay ng PP.pm ang lahat ng subs na tinukoy gamit ang pp_def function sa output na .pm
listahan ng EXPORT ng file. Maaari itong lumikha ng mga problema kung gumagawa ka ng subclassed object kung saan
hindi mo gustong ma-export ang anumang pamamaraan. (ibig sabihin, ang mga pamamaraan ay tatawagin lamang gamit ang
$object->method syntax).
Para sa mga kasong ito maaari kang tumawag pp_export_nothing() upang i-clear ang listahan ng pag-export. Halimbawa (Sa
dulo ng .pd file):
pp_export_nothing();
pp_done();
pp_core_importList
Bilang default, inilalagay ng PP.pm ang 'use Core;' linya sa output .pm file. Nag-import ito ng Core's
na-export na mga pangalan sa kasalukuyang namespace, na maaaring lumikha ng mga problema kung ikaw ay sobra-
pagsakay sa isa sa mga pamamaraan ng Core sa kasalukuyang file. Makakatanggap ka ng mga mensahe tulad ng
"Babala: muling tinukoy ang sub sumover sa file subclass.pm" kapag pinapatakbo ang program.
Para sa mga kasong ito ang pp_core_importList ay maaaring gamitin upang baguhin kung saan ito na-import
Core.pm. Halimbawa:
pp_core_importList('()')
Magreresulta ito sa
gumamit ng Core();
na nabuo sa output .pm file. Magreresulta ito sa walang mga pangalan na na-import mula sa
Core.pm. Katulad nito, ang pagtawag
pp_core_importList(' qw/ barf /')
magreresulta sa
gumamit ng Core qw/ barf/;
na nabuo sa output .pm file. Magreresulta ito sa pag-import lamang ng 'barf'
mula sa Core.pm.
pp_setversion
Sigurado ako na pinapayagan ka nitong itakda nang sabay-sabay ang .pm at .xs na mga file'
mga bersyon, kaya iniiwasan ang hindi kinakailangang bersyon-skew sa pagitan ng dalawa. Upang gamitin ito, mayroon lamang
ang sumusunod na linya sa isang punto sa iyong .pd file:
pp_setversion('0.0.3');
Gayunpaman, huwag gamitin ito kung gagamit ka ng Module::Build::PDL. Tingnan ang dokumentasyon ng module na iyon para sa
mga detalye.
pp_deprecate_module
Kung ang isang partikular na module ay itinuring na hindi na ginagamit, ang function na ito ay maaaring gamitin upang markahan ito bilang
hindi na ginagamit. Ito ay may epekto ng paglalabas ng babala kapag sinubukan ng isang user na "gamitin" ang
modyul. Ang nabuong POD para sa modyul na ito ay nagdadala din ng abiso sa paghinto sa paggamit. Ang
Ang kapalit na module ay maaaring maipasa bilang isang argumento tulad nito:
pp_deprecate_module( infavor => "PDL::NewNonDeprecatedModule" );
Tandaan na nakakaapekto ang function lamang ang babala ng runtime at ang POD.
Paggawa iyong PP tungkulin "pribado"
Sabihin nating mayroon kang function sa iyong module na tinatawag na PDL::foo na gumagamit ng PP
function na "bar_pp" upang gawin ang mabigat na pagbubuhat. Ngunit hindi mo gustong i-advertise ang "bar_pp" na iyon
umiiral. Upang gawin ito, dapat mong ilipat ang iyong PP function sa tuktok ng iyong module file, pagkatapos
tawag
pp_export_nothing()
upang i-clear ang listahan ng "EXPORT". Upang matiyak na walang dokumentasyon (kahit ang default na PP docs) ay
nabuo, itinakda
Doc => undef
at upang maiwasan ang pag-andar na maidagdag sa talahanayan ng simbolo, itakda
PMFunc => ''
sa iyong pp_def deklarasyon (tingnan ang Image2D.pd para sa isang halimbawa). Ito ay epektibong makakagawa
iyong PP function na "pribado." Gayunpaman, ito ay palagi naa-access sa pamamagitan ng PDL::bar_pp dahil sa Perl's
disenyo ng module. Ngunit ang paggawa nitong pribado ay magdudulot ng napakalayo ng user sa kanya
paraan upang gamitin ito, kaya siya ang bahala sa mga kahihinatnan!
Hiwa operasyon
Ang seksyon ng slice operation ng manwal na ito ay ibinigay gamit ang dataflow at lazy evaluation:
kapag kailangan mo, hilingin kay Tjl na isulat ito. isang paghahatid sa loob ng isang linggo mula nang matanggap ko ang email
ay 95% malamang at dalawang linggong paghahatid ay 99% malamang.
At gayon pa man, ang mga operasyon ng paghiwa ay nangangailangan ng isang mas kilalang-kilala na kaalaman sa mga panloob na PDL
kaysa sa mga operasyon ng data. Higit pa rito, ang pagiging kumplikado ng mga isyu na kasangkot ay
mas mataas kaysa sa average na operasyon ng data. Kung gusto mong kumbinsihin
iyong sarili ng katotohanang ito tingnan ang Basic/Slices/Slices.pd file sa PDL
pamamahagi :-). Gayunpaman, ang mga function na nabuo gamit ang slice operations ay nasa
puso ng index manipulation at dataflow na kakayahan ng PDL.
Gayundin, maraming maruruming isyu sa mga virtual na piddle at vaffines na gagawin natin
ganap na laktawan dito.
Mga hiwa at masama halaga
Ang mga operasyon ng hiwa ay kailangang mahawakan ang mga masamang halaga (kung ang suporta ay pinagsama-sama sa PDL).
Ang pinakamadaling gawin ay tumingin Basic/Slices/Slices.pd upang makita kung paano ito gumagana.
Kasama ng "BadCode", mayroon ding "BadBackCode" at "BadRedoDimsCode" key para sa
"pp_def". Gayunpaman, ang anumang "EquivCPOffsCode" ay dapat hindi kailangan baguhin, dahil ang anumang mga pagbabago ay
hinihigop sa kahulugan ng "$EQUIVCPOFFS()" na macro (ibig sabihin, ito ay pinangangasiwaan
awtomatikong sa pamamagitan ng PDL::PP>.
A ilan mga tala on pagsulat a pagpipiraso routine...
Ang mga sumusunod na ilang talata ay naglalarawan ng pagsulat ng isang bagong gawain sa paghiwa ('saklaw'); anuman
ang mga error ay sa CED. (--CED 26-Ago-2002)
Pag-asikaso of "balaan" at "barf" in PP kodigo
Para sa pag-print ng mga mensahe ng babala o pagpapalaglag/pagkamatay, maaari kang tumawag sa "babala" o "barf" mula sa PP
code. Gayunpaman, dapat mong malaman na ang mga tawag na ito ay muling tinukoy gamit ang C
preprocessor macros sa "PDL->barf" at "PDL->warn". Ang mga redefinition na ito ay nakalagay sa
pigilan ka sa hindi sinasadyang pagtawag sa "babala" o "barf" ni perl nang direkta, na maaaring magdulot ng
segfault sa panahon ng pthreading (ibig sabihin, processor multi-threading).
Ang sariling bersyon ng "barf" at "warning" ng PDL ay mag-queue-up ng mga babala o mga mensahe ng barf hanggang pagkatapos
nakumpleto ang pthreading, at pagkatapos ay tawagan ang mga perl na bersyon ng mga gawaing ito.
Tingnan ang PDL::ParallelCPU para sa higit pang impormasyon sa pthreading.
MAHALAGA MGA RUTIN
Ang istraktura ng "Core" ng PDL, na tinukoy sa Basic/Core/pdlcore.h.PL, ay naglalaman ng mga pointer sa a
bilang ng mga gawain na maaaring maging kapaki-pakinabang sa iyo. Ang karamihan sa mga nakagawiang ito ay nakikitungo
pagmamanipula ng mga piddles, ngunit ang ilan ay mas pangkalahatan:
PDL->qsort_B( PDL_Byte *xx, int a, int b )
Pagbukud-bukurin ang array "xx" sa pagitan ng mga indeks na "a" at "b". Mayroon ding mga bersyon para sa
ibang PDL datatypes, na may postfix na "_S", "_U", "_L", "_F", at "_D". Anumang module na gumagamit
dapat nitong tiyakin na ang "PDL::Ufunc" ay na-load.
PDL->qsort_ind_B( PDL_Byte *xx, int *ix, int a, int b )
Tulad ng para sa "PDL->qsort_B", ngunit sa pagkakataong ito ay pinagbubukod-bukod ang mga indeks kaysa sa data.
Ang nakagawiang "med2d" sa Lib/Image2D/image2d.pd nagpapakita kung paano ginagamit ang mga ganitong gawain.
MAKEFILES PARA SA PP MGA FILE
Kung bubuo ka ng isang pakete mula sa iyong PP file (karaniwang mga extension ng file ay
".pd" o ".pp" para sa mga file na naglalaman ng PP code) ito ay pinakamadali at pinakaligtas na umalis
pagbuo ng naaangkop na mga utos sa Makefile. Sa mga sumusunod ay magbabalangkas tayo
ang karaniwang format ng isang Perl Makefile kung saan awtomatikong buuin at mai-install ang iyong package mula sa
isang paglalarawan sa isang PP file. Karamihan sa mga panuntunan sa pagbuo ng xs, pm at iba pang kinakailangang mga file
mula sa PP file ay na-predefine na sa PDL::Core::Dev package. Kailangan lang natin
sabihin sa MakeMaker na gamitin ito.
Sa karamihan ng mga kaso maaari mong tukuyin ang iyong Makefile tulad ng
# Makefile.PL para sa isang package na tinukoy ng PP code.
gumamit ng PDL::Core::Dev; # Kunin ang mga kagamitan sa pagpapaunlad
gumamit ng ExtUtils::MakeMaker;
$package = ["mylib.pd",Mylib,PDL::Lib::Mylib];
%hash = pdlpp_stdargs($package);
$hash{OBJECT} .= ' additional_Ccode$(OBJ_EXT) ';
$hash{clean}->{FILES} .= ' todelete_Ccode$(OBJ_EXT) ';
$hash{'VERSION_FROM'} = 'mylib.pd';
WriteMakefile(%hash);
sub MY::postamble { pdlpp_postamble($package); }
Dito, ang listahan sa $package ay: una: PP source file name, pagkatapos ay ang prefix para sa
gumawa ng mga file at sa wakas ang buong pangalan ng package. Maaari mong baguhin ang hash sa anuman
sa paraang gusto mo ngunit makatuwirang manatili sa loob ng ilang limitasyon upang ang iyong package
ay patuloy na gagana sa mga susunod na bersyon ng PDL.
Kung ayaw mong gumamit ng mga naka-prepack na argumento, narito ang generic Makefile.PL na kaya mo
iakma para sa iyong sariling mga pangangailangan:
# Makefile.PL para sa isang package na tinukoy ng PP code.
gumamit ng PDL::Core::Dev; # Kunin ang mga kagamitan sa pagpapaunlad
gumamit ng ExtUtils::MakeMaker;
WriteMakefile(
'NAME' => 'PDL::Lib::Mylib',
'VERSION_FROM' => 'mylib.pd',
'TYPEMAPS' => [&PDL_TYPEMAP()],
'OBJECT' => 'mylib$(OBJ_EXT) additional_Ccode$(OBJ_EXT)',
'PM' => { 'Mylib.pm' => '$(INST_LIBDIR)/Mylib.pm'},
'INC' => &PDL_INCLUDE(), # add isama ang mga dirs ayon sa kinakailangan ng iyong lib
'LIBS' => [''], # magdagdag ng mga direktiba ng link kung kinakailangan
'clean' => {'FILES' =>
'Mylib.pm Mylib.xs Mylib$(OBJ_EXT)
additional_Ccode$(OBJ_EXT)'},
);
# Magdagdag ng panuntunan ng genpp; i-invoke nito ang PDL::PP sa aming PP file
# ang argument ay isang sanggunian ng array kung saan ang array ay may tatlong elemento ng string:
# arg1: pangalan ng source file na naglalaman ng PP code
# arg2: basename ng xs at pm file na bubuuin
# arg3: pangalan ng package na bubuuin
sub MY::postamble { pdlpp_postamble(["mylib.pd",Mylib,PDL::Lib::Mylib]); }
Upang gawing mas madali ang buhay PDL::Core::Dev ay tumutukoy sa function na "pdlpp_stdargs" na nagbabalik
isang hash na may mga default na halaga na maaaring maipasa (direkta man o pagkatapos ng naaangkop
pagbabago) sa isang tawag sa WriteMakefile. Sa kasalukuyan, ang "pdlpp_stdargs" ay nagbabalik ng hash kung saan
ang mga susi ay pinupunan tulad ng sumusunod:
(
'NAME' => $mod,
'TYPEMAPS' => [&PDL_TYPEMAP()],
'OBJECT' => "$pref\$(OBJ_EXT)",
PM => {"$pref.pm" => "\$(INST_LIBDIR)/$pref.pm"},
MAN3PODS => {"$src" => "\$(INST_MAN3DIR)/$mod.\$(MAN3EXT)"},
'INC' => &PDL_INCLUDE(),
'LIBS' => [''],
'clean' => {'FILES' => "$pref.xs $pref.pm $pref\$(OBJ_EXT)"},
)
Dito, ang $src ay ang pangalan ng source file na may PP code, $pref ang prefix para sa nabuo
.pm at .xs na mga file at $mod ang pangalan ng extension na module na bubuo.
MGA INTERNAL
Ang mga panloob ng kasalukuyang bersyon ay binubuo ng isang malaking talahanayan na nagbibigay ng mga patakaran
ayon sa kung aling mga bagay ang isinasalin at ang mga subs na nagpapatupad ng mga panuntunang ito.
Sa paglaon, mainam na gawing nababago ng gumagamit ang talahanayan upang maiba
maaaring subukan ang mga bagay.
[Meta comment: dito sana ay mas marami pa sa hinaharap; sa kasalukuyan, ang iyong pinakamahusay na mapagpipilian ay
para basahin ang source code :-( o magtanong sa listahan (subukan muna ang huli) ]
Apendiks A: ilan mga susi kinikilala by PDL::PP
Maliban kung tinukoy, ang mga argumento ay mga string. Ang mga susi na may markang (masama) ay lamang
ginagamit kung ang suporta sa masamang halaga ay pinagsama-sama sa PDL.
Tigilan
tukuyin ang lagda ng iyong function
Iba Par
mga argumento na hindi pdls. Default: wala. Ito ay isang semi-colon na pinaghiwalay na listahan ng
mga argumento, hal, "OtherPars => 'int k; dobleng halaga; char* fd'". Tingnan ang $COMP(x) at gayundin
ang parehong entry sa Appendix B.
kodigo
ang aktwal na code na nagpapatupad ng functionality; ilang PP macro at PP function
ay kinikilala sa halaga ng string
HandleBad (masama)
Kung nakatakda sa 1, ang routine ay ipinapalagay na sumusuporta sa masasamang halaga at ang code sa BadCode
ginagamit ang susi kung mayroong masasamang halaga; itinatakda din nito ang mga bagay upang ang "$ISBAD()"
etc macros ay maaaring gamitin. Kung nakatakda sa 0, maging sanhi ng nakagawiang mag-print ng babala kung mayroon man
ang input piddles ay may kanilang masamang flag set.
BadCode (masama)
Ibigay ang code na gagamitin kung maaaring may masasamang halaga sa mga input piddle. Ginamit lang
kung "HandleBad => 1".
Mga GenericTypes
Isang array reference. Ang array ay maaaring maglaman ng anumang subset ng isang-character na string na `B',
`S', `U', `L', `Q', `F' at `D', na tumutukoy kung aling mga uri ang tatanggapin ng iyong operasyon.
Ang kahulugan ng bawat uri ay:
B - signed byte (ibig sabihin, signed char)
S - naka-sign maikli (two-byte integer)
U - unsigned short
L - naka-sign mahaba (four-byte integer, int sa 32 bit system)
Q - nilagdaan ang mahabang haba (walong byte integer)
F - lumutang
D - doble
Ito ay lubhang kapaki-pakinabang (at mahalaga!) kapag nakikipag-ugnay sa isang panlabas na aklatan. Default:
[qw/BSULQFD/]
Sa lugar
Markahan ang isang function bilang magagawang magtrabaho sa lugar.
Inplace => 1 kung Pars => 'a(); [o]b();'
Inplace => ['a'] if Pars => 'a(); b(); [o]c();'
Inplace => ['a','b'] if Pars => 'a(); b(); [o]c(); [o]d();'
Kung ang mga masamang halaga ay ginagamit, ang pangangalaga ay dapat gawin upang matiyak ang pagpapalaganap ng
badflag kapag inplace ay ginagamit; halimbawa tingnan ang code para sa "replacebad" sa
Basic/Bad/bad.pd.
Doc Ginagamit upang tumukoy ng string ng dokumentasyon sa Pod na format. Tingnan ang PDL::Doc para sa impormasyon sa
Mga kumbensyon sa dokumentasyon ng PDL. Tandaan: sa espesyal na kaso kung saan ang PP 'Doc' string ay
isang linya ito ay tahasang ginagamit para sa mabilisang sanggunian AT ang dokumentasyon!
Kung ang patlang ng Doc ay tinanggal, ang PP ay bubuo ng default na dokumentasyon (pagkatapos ng lahat ng alam nito
tungkol sa Lagda).
Kung talagang gusto mo ang function na HINDI maidokumento sa anumang paraan sa puntong ito (hal
para sa isang panloob na gawain, o dahil ginagawa mo ito sa ibang lugar sa code) nang tahasan
tukuyin ang "Doc => undef".
BadDoc (masama)
Naglalaman ng text na ibinalik ng "badinfo" na command (sa "perldl") o ang "-b" switch
sa "pdldoc" shell script. Sa maraming mga kaso, hindi mo kailangang tukuyin ito, dahil
ang impormasyon ay maaaring awtomatikong malikha ng PDL::PP. Gayunpaman, tulad ng nararapat sa computer-
nabuong teksto, ito ay medyo stilted; maaaring mas mahusay na gawin ito sa iyong sarili!
WalangPthread
Opsyonal na flag upang ipahiwatig ang PDL function ay dapat hindi gumamit ng mga thread ng processor (hal
pthreads o POSIX thread) upang hatiin ang trabaho sa maraming mga core ng CPU. Ang pagpipiliang ito ay
karaniwang nakatakda sa 1 kung hindi threadsafe ang pinagbabatayan na function ng PDL. Kung ang pagpipiliang ito
ay hindi naroroon, kung gayon ang function ay ipinapalagay na threadsafe. Nalalapat lang ang opsyong ito
kung ang PDL ay pinagsama-sama sa mga POSIX thread na pinagana.
PMCode
Nagbibigay-daan sa iyo ang mga function ng PDL na ipasa sa isang piddle kung saan mo gustong i-save ang output. Ito
ay madaling gamitin dahil maaari kang maglaan ng isang output piddle nang isang beses at muling gamitin ito ng maraming beses; ang
Ang alternatibo ay para sa PDL na lumikha ng isang bagong piddle sa bawat oras, na maaaring mag-aaksaya ng pag-compute
cycle o, mas malamang, RAM. Ang karagdagang flexibility na ito ay may halaga ng higit pa
pagiging kumplikado: Ang PDL::PP ay kailangang magsulat ng mga function na sapat na matalino upang mabilang ang
ang mga argumento ay ipinasa dito at lumikha ng mga bagong piddles sa mabilisang, ngunit kung gusto mo lamang ang mga ito.
PDL::Si PP ay sapat na matalino upang gawin iyon, ngunit may mga paghihigpit sa pagkakasunud-sunod ng argumento at
ang katulad. Kung gusto mo ng mas nababaluktot na function, maaari mong isulat ang iyong sariling Perl-side
wrapper at tukuyin ito sa PMCode key. Ang string na ibinibigay mo ay dapat (dapat)
tukuyin ang isang Perl function na may pangalan na tumutugma sa ibinigay mo sa pp_def sa una
lugar. Kapag nais mong i-invoke ang PP-generated function, kakailanganin mong gawin
ibigay ang lahat ng piddles sa eksaktong pagkakasunud-sunod na tinukoy sa lagda: output piddles ay
hindi opsyonal, at ang PP-generated na function ay hindi magbabalik ng anuman. Ang obfuscated
pangalan na tatawagin mo ay _ _int.
Naniniwala ako na ang dokumentasyong ito ay nangangailangan ng karagdagang paglilinaw, ngunit ito ay kailangang gawin.
:-(
PMUnc
Kapag ang pp_def ay bumubuo ng mga function, kadalasang tinutukoy nito ang mga ito sa PDL package. pagkatapos,
sa .pm file na binubuo nito para sa iyong module, karaniwan itong nagdaragdag ng linyang iyon
mahalagang mga kopya na gumagana sa iyong kasalukuyang talahanayan ng simbolo ng package na may code
ganito ang hitsura:
*func_name = \&PDL::func_name;
Ito ay medyo mas matalino kaysa doon (alam nito kung kailan ibalot ang ganoong uri ng bagay sa isang
BEGIN block, halimbawa, at kung may tinukoy kang kakaiba para sa pp_bless), ngunit
yan ang buod nito. Kung wala kang pakialam na i-import ang function sa iyong kasalukuyang
simbolo ng talahanayan ng package, maaari mong tukuyin
PMFunc => '',
Walang ibang side-effects ang PMFunc, kaya magagamit mo ito para magpasok ng arbitrary na Perl code
sa iyong module kung gusto mo. Gayunpaman, dapat mong gamitin ang pp_addpm kung gusto mong magdagdag ng Perl
code sa iyong module.
Apendiks B: PP macros at function
Macros
Ang mga macro na may label na (masamang) ay ginagamit lamang kung ang suporta sa masamang halaga ay pinagsama-sama sa PDL.
$variablename_from_sig()
i-access ang isang pdl (sa pangalan nito) na tinukoy sa lagda
$COMP(x)
i-access ang isang halaga sa istruktura ng pribadong data ng pagbabagong ito (pangunahing ginagamit sa
gumamit ng argumento na tinukoy sa seksyong "OtherPars")
$SIZE(n)
pinalitan sa runtime ng aktwal na laki ng a pinangalanan dimensyon (tulad ng tinukoy sa
lagda)
$GENERIC()
pinalitan ng uri ng C na katumbas ng uri ng runtime ng operasyon
$P(a) isang pointer na access sa PDL na pinangalanang "a" sa lagda. Kapaki-pakinabang para sa interfacing sa C
function
$PP(a) isang pisikal na pointer na access sa pdl "a"; higit sa lahat para sa panloob na paggamit
$TXXX(Alternatibong, Alternatibo)
mga alternatibo sa pagpapalawak ayon sa uri ng pagpapatakbo ng runtime, kung saan ang XXX ay ilan
string na tumutugma sa "/[BSULFD+]/".
$PDL(a)
ibalik ang isang pointer sa pdl data structure (pdl *) ng piddle "a"
$ISBAD(a()) (masama)
nagbabalik ng true kung ang value na nakaimbak sa "a()" ay katumbas ng masamang value para sa piddle na ito.
Nangangailangan ng "HandleBad" na itakda sa 1.
$ISGOOD(a()) (masama)
nagbabalik ng totoo kung ang halaga na nakaimbak sa "a()" ay hindi katumbas ng masamang halaga para dito
piddle. Nangangailangan ng "HandleBad" na itakda sa 1.
$SETBAD(a()) (masama)
Itinatakda ang "a()" na katumbas ng masamang halaga para sa piddle na ito. Nangangailangan ng "HandleBad" na itakda
sa 1.
function
"loop(DIMS) %{ ... %}"
loop sa pinangalanang mga sukat; Ang mga limitasyon ay awtomatikong nabuo ng PP
"threadloop %{ ... %}"
ilakip ang sumusunod na code sa isang thread loop
"mga uri(TYPES) %{ ... %}"
isagawa ang sumusunod na code kung ang uri ng operasyon ay alinman sa "TYPES"
Apendiks C: Pag-andar angkat by PDL::PP
Ang ilang mga function ay na-import kapag "gumamit ka ng PDL::PP". Kabilang dito ang mga function na
kontrolin ang nabuong C o XS code, mga function na kumokontrol sa nabuong Perl code, at
mga function na nagmamanipula sa mga pakete at mga talahanayan ng simbolo kung saan nilikha ang code.
Bumubuo C at XS kodigo
PDL::Ang pangunahing layunin ng PP ay gawing madali para sa iyo na balutin ang threading engine sa paligid mo
sariling C code, ngunit maaari mo ring gawin ang ilang iba pang mga bagay.
pp_def
Ginagamit upang balutin ang threading engine sa paligid ng iyong C code. Halos lahat ng dokumentong ito
tinatalakay ang paggamit ng pp_def.
pp_tapos na
Isinasaad na tapos ka na sa PDL::PP at dapat itong bumuo ng mga .xs at .pm na file nito
batay sa iba pang pp_* function na iyong tinawag. Ang function na ito ay tumatagal ng no
argumento.
pp_addxs
Hinahayaan ka nitong magdagdag ng XS code sa iyong .xs file. Ito ay kapaki-pakinabang kung nais mong lumikha ng Perl-
naa-access na mga function na humihiling ng C code ngunit hindi maaaring o hindi dapat mag-invoke ng threading
makina. Ang XS ay ang karaniwang paraan kung saan mo binabalot ang Perl-accessible C code. Kaya mo
matuto pa sa perlxs.
pp_add_boot
Ang function na ito ay nagdaragdag ng anumang string na ipapasa mo sa XS BOOT na seksyon. Ang seksyon ng BOOT
ay C code na tatawagin ng Perl kapag na-load ang iyong module at kapaki-pakinabang para sa
awtomatikong pagsisimula. Maaari kang matuto nang higit pa tungkol sa XS at sa seksyong BOOT sa perlxs.
pp_addhdr
Nagdaragdag ng pure-C code sa iyong XS file. Ang mga XS na file ay nakabalangkas na ang purong C code ay dapat
mauna sa mga detalye ng XS. Pinapayagan ka nitong tukuyin ang naturang C code.
pp_boundscheck
Karaniwang sinusuri ng PDL ang mga hangganan ng iyong mga pag-access bago gawin ang mga ito. Maaari mong i-on iyon
on o off sa runtime sa pamamagitan ng pagtatakda ng MyPackage::set_boundscheck. Pinapayagan ka ng function na ito
upang alisin ang flexibility ng runtime na iyon at hindi kailanman gumawa ng bounds checking. Ibinabalik din nito ang
kasalukuyang boundschecking status kung tawagin nang walang anumang argumento.
TANDAAN: Wala akong nakitang anuman tungkol sa pagsuri ng mga hangganan sa ibang dokumentasyon. yun
kailangang matugunan.
Bumubuo Perl kodigo
Maraming mga function na na-import kapag gumamit ka ng PDL::PP ay nagpapahintulot sa iyo na baguhin ang mga nilalaman ng
nabuong .pm na file. Bilang karagdagan sa pp_def at pp_done, ang tungkulin ng mga function na ito ay
pangunahin upang magdagdag ng code sa iba't ibang bahagi ng iyong nabuong .pm file.
pp_addpm
Nagdaragdag ng Perl code sa nabuong .pm file. Talagang sinusubaybayan ng PDL::PP ang tatlo
iba't ibang seksyon ng nabuong code: ang Itaas, ang Gitna, at ang Ibaba. Pwede kang magdagdag
Perl code sa Middle section gamit ang one-argument form, kung saan ang argument ay ang
Perl code na gusto mong ibigay. Sa dalawang-argumentong anyo, ang unang argumento ay isang
anonymous hash na may isang susi lamang na tumutukoy kung saan ilalagay ang pangalawang argumento,
alin ang string na gusto mong idagdag sa .pm file. Ang hash ay isa sa mga ito
tatlo:
{Sa => 'Itaas'}
{Sa => 'Gitna'}
{Sa => 'Bot'}
Halimbawa:
pp_addpm({Sa => 'Bot'}, <
=head1 Ilang dokumentasyon
Alam kong tina-type ko ito sa gitna ng aking file, ngunit mapupunta ito sa
ang ilalim.
= gupitin
Supot ng buto
Babala: Kung, sa gitna ng iyong .pd file, naglagay ka ng dokumentasyong para sa
ilalim ng iyong pod, lubusan mong malito ang CPAN. Sa kabilang banda, kung sa
gitna ng iyong .pd fil, magdagdag ka ng ilang Perl code na nakalaan para sa ibaba o itaas ng iyong
.pm file, sarili mo lang ang kailangan mong lituhin. :-)
pp_beginwrap
Nagdaragdag ng BEGIN-block wrapping. Ang ilang mga deklarasyon ay maaaring balot sa mga bloke ng BEGIN, bagaman
ang default na pag-uugali ay ang walang ganoong pambalot.
pp_addbegin
Nagtatakda ng code na idaragdag sa itaas ng iyong .pm file, kahit na sa itaas ng code na iyong tinukoy
na may "pp_addpm({Sa => 'Itaas'}, ...)". Hindi tulad ng pp_addpm, ang pagtawag dito ay na-overwrite ang anuman
nandoon dati. Sa pangkalahatan, malamang na hindi mo ito dapat gamitin.
Pagsubaybay Linya Numero
Kapag nakakuha ka ng mga error sa pag-compile, mula sa iyong C-like na code o sa iyong Perl code, makakatulong ito
upang maibalik ang mga error na iyon sa mga numero ng linya sa source file kung saan ang error
naganap.
pp_line_numbers
Kumuha ng numero ng linya at isang (karaniwang mahaba) na string ng code. Ang numero ng linya ay dapat
ipahiwatig ang linya kung saan nagsisimula ang quote. Ito ay karaniwang "__LINE__" ni Perl
literal, maliban kung gumagamit ka ng heredocs, kung saan ito ay "__LINE__ + 1". Ang
ang ibinalik na string ay may mga #line na mga direktiba na pinagsalitan upang matulungan ang compiler na mag-ulat ng mga error
sa tamang linya.
Pagbabago ang Icon mesa at I-export Pag-uugali
Karaniwang ini-export ng PDL::PP ang lahat ng mga function na nabuo gamit ang pp_def, at karaniwang ini-install ang mga ito
sa talahanayan ng simbolo ng PDL. Gayunpaman, maaari mong baguhin ang gawi na ito gamit ang mga function na ito.
pp_bless
Itinatakda ang package (talahanayan ng simbolo) kung saan idinaragdag ang XS code. Ang default ay PDL,
na sa pangkalahatan ay kung ano ang gusto mo. Kung gagamitin mo ang default na pagpapala at lumikha ka ng a
function myfunc, pagkatapos ay maaari mong gawin ang sumusunod:
$piddle->myfunc( );
PDL::myfunc($piddle, );
Sa kabilang banda, kung pinagpapala mo ang iyong mga function sa isa pang package, hindi ka makakapag-invoke
ang mga ito bilang mga pamamaraan ng PDL, at dapat gamitin ang mga ito bilang:
MyPackage::myfunc($piddle, );
Siyempre, maaari mong palaging gamitin ang PMFunc key upang idagdag ang iyong function sa simbolo ng PDL
mesa, ngunit bakit gagawin iyon?
pp_add_isa
Nagdaragdag sa listahan ng mga module kung saan ang iyong module namamana. Ang default na listahan ay
qw(PDL::Exporter DynaLoader)
pp_core_importlist
Sa itaas ng iyong nabuong .pm file ay isang linya na ganito ang hitsura:
gumamit ng PDL::Core;
Maaari mong baguhin iyon sa pamamagitan ng pagtukoy ng isang string sa pp_core_importlist. Halimbawa,
pp_core_importlist('::Blarg');
ay magreresulta sa
gumamit ng PDL::Core::Blarg;
Magagamit mo ito, halimbawa, upang magdagdag ng listahan ng mga simbolo na ii-import mula sa PDL::Core. Para sa
halimbawa:
pp_core_importlist(" ':Internal'");
ay hahantong sa sumusunod na pahayag ng paggamit:
gamitin ang PDL::Core ':Internal';
pp_setversion
Itinatakda ang bersyon ng iyong module. Dapat pare-pareho ang bersyon sa pagitan ng .xs at .pm
file, at ginagamit upang matiyak na ang iyong mga aklatan ng Perl ay hindi nagdurusa sa bersyon
hilig.
pp_add_exported
Idinaragdag sa listahan ng pag-export ang anumang pangalan na ibibigay mo dito. Mga function na ginawa gamit ang pp_def
ay awtomatikong idinaragdag sa listahan. Ang function na ito ay kapaki-pakinabang kung tutukuyin mo ang anumang Perl
mga function gamit ang pp_addpm o pp_addxs na gusto mo ring i-export.
pp_export_nothing
Nire-reset nito ang listahan ng mga na-export na simbolo sa wala. Ito ay malamang na mas mahusay na tawagan
"pp_export_clear", dahil maaari kang magdagdag ng mga na-export na simbolo pagkatapos tumawag
"pp_export_nothing". Kapag tinawag bago tumawag sa pp_done, tinitiyak nito na ang iyong
module ay hindi nag-e-export ng kahit ano, halimbawa, kung gusto mo lang gamitin ng mga programmer ang iyong
gumaganap bilang mga pamamaraan.
Gamitin ang PDL::PPp online gamit ang mga serbisyo ng onworks.net