Dit is de opdracht PDL::BadValuesp die kan worden uitgevoerd in de gratis hostingprovider van OnWorks met behulp van een van onze meerdere gratis online werkstations zoals Ubuntu Online, Fedora Online, Windows online emulator of MAC OS online emulator
PROGRAMMA:
NAAM
PDL::BadValues - Bespreking van ondersteuning voor slechte waarden in PDL
PRODUCTBESCHRIJVING
Wat zijn slecht waarden en Waarom moet I dwars zitten met hen?
Soms is het handig om te kunnen specificeren dat een bepaalde waarde 'slecht' of 'ontbreekt' is; voor
CCD's die in de astronomie worden gebruikt, produceren bijvoorbeeld 2D-beelden die in bepaalde gebieden niet perfect zijn
ongeldige gegevens bevatten vanwege onvolkomenheden in de detector. Terwijl de krachtige index van PDL
routines en alle ingewikkelde zaken met gegevensstromen, segmenten, enz. betekenen dat deze
regio's kunnen bij de verwerking worden genegeerd, het is lastig om te doen. Het zou veel gemakkelijker zijn om dat te zijn
in staat om "$c = $a + $b" te zeggen en al het gedoe aan de computer over te laten.
Als u hier niet in geïnteresseerd bent, kunt u zich (terecht) zorgen maken over de manier waarop dit gebeurt
beïnvloedt de snelheid van PDL, aangezien de overhead van het controleren op een slechte waarde bij elke bewerking
kan groot zijn. Daarom is de code zo snel mogelijk geschreven -
vooral bij het werken met piddles die geen slechte waarden bevatten. Sterker nog, jij
zou in wezen geen snelheidsverschil moeten merken bij het werken met piddles die dat niet doen
slechte waarden bevatten.
Als u echter geen slechte waarden wilt, gebruik dan de configuratieoptie "WITH_BADVAL" van PDL
komt te hulp; indien ingesteld op 0 of undef, wordt de ondersteuning voor slechte waarden genegeerd. Over de
de enige keer dat ik denk dat je dit nodig hebt - ik geef toe, ik ben bevooroordeeld;) - is als je dat hebt gedaan
beperkte schijf- of geheugenruimte, omdat de code groter wordt (zie hieronder).
Je kunt ook vragen 'nou, mijn computer ondersteunt IEEE NaN, dus ik heb dit al'. Wel, ja
en nee - veel routines, zoals "y=sin(x)", zullen NaN's doorgeven zonder dat de gebruiker
om anders te coderen, maar routines zoals "qsort", of het vinden van de mediaan van een array, hebben dit nodig
opnieuw worden gecodeerd om slechte waarden te verwerken. Voor gegevenstypen met drijvende komma zijn "NaN" en "Inf" dat wel
gebruikt om slechte waarden te markeren IF de optie "BADVAL_USENAN" is ingesteld op 1 in uw configuratiebestand.
Anders worden speciale waarden gebruikt (standaard slechte waarden). Ik heb daar geen benchmarks voor
kijk welke optie sneller is.
Er is een experimentele functie "BADVAL_PER_PDL" die u, indien ingesteld, kunt gebruiken
verschillende slechte waarden voor afzonderlijke piddles van hetzelfde type. Dit werkt momenteel niet
met de optie "BADVAL_USENAN"; als beide zijn ingesteld, negeert PDL de "BADVAL_USENAN"
waarde.
Code toename twee naar slecht waarden
De volgende vergelijking is verouderd!
Op een i386-machine met Linux en Perl 5.005_03 heb ik de volgende maten gemeten (de
Slatec-code is gecompileerd, maar geen van de andere opties: bijvoorbeeld FFTW, GSL en TriD
waren):
MET_BADVAL = 0
Grootte van de blib-map na een succesvolle make = 4963 kb: blib/arch = 2485 kb en
blib/lib = 1587 kb.
MET_BADVAL = 1
Grootte van de blib-map na een succesvolle make = 5723 kb: blib/arch = 3178 kb en
blib/lib = 1613 kb.
De totale stijging is dus gelijk Slechts 15% - niet veel om te betalen voor alle wonderen die slechte waarden met zich meebrengen
biedt ;)
De broncode die voor deze test werd gebruikt, bevatte de overgrote meerderheid van de kernroutines (bijvoorbeeld die in
Basic/) omgezet om slechte waarden te gebruiken, terwijl zeer weinig van de 'externe' routines (bijv
al het andere in de PDL-distributie) was gewijzigd.
A rápido overzicht
pdl> p $PDL::Slechte::Status
1
pdl> $a = reeks(4,3);
pdl> p $a
[
[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]
]
pdl> $a = $a->setbadif( $a % 3 == 2 )
pdl> p $a
[
[ 0 1 SLECHT 3]
[ 4 SLECHT 6 7]
[SLECHT 9 10 SLECHT]
]
pdl> $a *= 3
pdl> p $a
[
[ 0 3 SLECHT 9]
[ 12 SLECHT 18 21]
[SLECHT 27 30 SLECHT]
]
pdl> p $a->som
120
"demo bad" en "demo bad2" binnen perldl of pdl2 geeft een demonstratie van enkele van de
dingen mogelijk met slechte waarden. Deze zijn ook beschikbaar op de website van PDL, op
http://pdl.perl.org/demos/. Zie PDL::Bad voor nuttige routines voor het werken met slechte waarden
en t/slecht.t om ze in actie te zien.
De bedoeling is om:
· heeft geen significante invloed op de PDL voor gebruikers die geen slechte ondersteuning nodig hebben
· wees zo snel mogelijk als ondersteuning voor slechte waarde is geïnstalleerd
Als u nooit ondersteuning voor slechte waarden wilt, stelt u 'WITH_BADVAL' in op 0 inch perldl.conf; PDL
dan is er geen slechte waarde-ondersteuning gecompileerd, dus het zal net zo snel zijn als vroeger.
In de meeste gevallen heeft de slechte waarde-ondersteuning echter een verwaarloosbaar effect op de snelheid, dus jij
moet "WITH_CONFIG" op 1 zetten! Een uitzondering is als u weinig geheugen heeft, aangezien het bedrag
van de geproduceerde code is groter (maar slechts met ongeveer 15% - zie "Codetoename vanwege slecht
waarden").
Als u wilt weten of PDL is gecompileerd met ondersteuning voor slechte waarden, bekijkt u de waarden van beide
$PDL::Config{WITH_BADVAL} of $PDL::Bad::Status - indien waar, dan is dit het geval.
Om erachter te komen of een routine slechte waarden ondersteunt, gebruikt u het commando "badinfo" in perldl of pdl2
of de "-b" optie voor pdldoc. Deze faciliteit is momenteel een 'proof of concept' (of meer
realistisch gezien een snelle hack), dus verwacht dat het ruw is aan de randen.
Elke piddle bevat een vlag - toegankelijk via "$pdl->badflag" - om aan te geven of er een is
slechte gegevens aanwezig:
· Indien onwaar/0, wat betekent dat er hier geen slechte gegevens zijn, de code die wordt geleverd door de "Code"
optie "pp_def()" wordt uitgevoerd. Dit betekent dat de snelheid heel dichtbij moet zijn
die verkregen met "WITH_BADVAL=0", aangezien de enige overhead verschillende toegangen tot a
bit in de statusvariabele piddles.
· Indien waar/1, dan staat dit daar MEI slechte gegevens in de piddle zijn, dus gebruik de code in de
"BadCode" optie (ervan uitgaande dat de "pp_def()" voor deze routine is bijgewerkt naar
een BadCode-sleutel hebt). U krijgt alle voordelen van draadsnijden, zoals bij de "Code"
optie, maar het zal langzamer werken omdat u te maken krijgt met de aanwezigheid van
slechte waarden.
Als u een piddle maakt, wordt de vlag voor slechte waarde ervan ingesteld op 0. Om dit te wijzigen gebruikt u
"$pdl->badflag($new_bad_status)", waarbij $new_bad_status 0 of 1 kan zijn. Wanneer een routine
een piddle creëert, zal de vlag met slechte waarde afhangen van de invoerpiddles: tenzij deze wordt overschreven
(zie de optie "CopyBadStatusCode" voor "pp_def"), de vlag voor slechte waarde wordt waar ingesteld als
elk van de invoerpiddles bevat slechte waarden. Om te controleren of een plas echt slecht bevat
gegevens, gebruik dan de "check_badflag"-methode.
NOTITIE: verspreiding van de slechte vlag
Als je de slechte vlag van een piddle verandert, wordt deze verandering doorgegeven aan alle kinderen een
pimpel, dus
pdl> $a = nullen(20,30);
pdl> $b = $a->plak('0:10,0:10');
pdl> $c = $b->slice(',(2)');
pdl> print ">>c: ", $c->badflag, "\n";
>>c: 0
pdl> $a->slechte vlag(1);
pdl> print ">>c: ", $c->badflag, "\n";
>>c: 1
Nee er wordt verandering aangebracht aan de ouders van een piddle, dus
pdl> print ">>a: ", $a->badflag, "\n";
>>een: 1
pdl> $c->slechte vlag(0);
pdl> print ">>a: ", $a->badflag, "\n";
>>een: 1
gedachten:
· de badflag kan ALLEEN worden gewist ALS een piddle GEEN ouders heeft, en deze verandering zal dat wel doen
verspreiden onder alle kinderen van die plas. Ik heb er niet zoveel zin meer in (ook
onhandig om te coderen, bijvoorbeeld).
· "$a->slechte vlag(1)" zou de slechte vlag moeten verspreiden naar zowel ouders als kinderen.
Dit zou niet moeilijk moeten zijn om te implementeren (hoewel een eerste poging mislukte!). Maakt het
toch zin? Er is ook de vraag wat er gebeurt als je de slechte waarde van a verandert
piddle - moeten deze zich verspreiden naar kinderen/ouders (ja) of zou dat alleen moeten gebeuren
in staat om de slechte waarde op het 'top'-niveau te veranderen - dwz die piddles die dat niet hebben
ouders.
De methode "orig_badvalue()" retourneert de waarde tijdens het compileren voor een bepaald gegevenstype. Het werkt
op piddles, PDL::Type-objecten en getallen - bijv
$pdl->orig_badvalue(), byte->orig_badvalue(), en orig_badvalue(4).
Het heeft ook een vreselijke naam...
Om de huidige slechte waarde te krijgen, gebruikt u de methode "badvalue()" - deze heeft dezelfde syntaxis als
"orig_badvalue()".
Om de huidige slechte waarde te wijzigen, geeft u het nieuwe getal op bij slechtewaarde - bijv
$pdl->slechtewaarde(2.3), byte->slechte waarde(2), slechtewaarde(5,-3e34).
Note: de waarde wordt stil geconverteerd naar het juiste C-type en geretourneerd - dwz
"byte->badvalue(-26)" retourneert 230 op mijn Linux-machine. Het is ook een "nop" voor zwevend-
punttypen wanneer "BADVAL_USENAN" waar is.
Houd er rekening mee dat wijzigingen in de slechte waarde dat wel zijn NIET gepropageerd naar eerder gemaakte piddles - zij
zal nog steeds de slechte waarde hebben, maar plotseling zullen de elementen die slecht waren, dat worden
'goed', maar met de oude slechte waarde. Zie discussie hieronder. Het is geen probleem voor
typen met drijvende komma die NaN gebruiken, omdat u hun slechte waarde niet kunt wijzigen.
slecht waarden en boolean exploitanten
Voor de Booleaanse operatoren in PDL::Ops retourneert evaluatie van een slechte waarde de slechte waarde.
Terwijl dit dat betekent
$mask = $img > $thresh;
correct slechte waarden propageert, it wil problemen veroorzaken bij controles zoals
do_something() indien aanwezig( $img > $thresh );
die herschreven moeten worden als zoiets als
do_something() indien aanwezig( setbadtoval( ($img > $thresh), 0 ) );
Bij gebruik van een van de 'projectie'-functies in PDL::Ufunc - zoals orover - slechte waarden
worden overgeslagen (zie de documentatie van deze functies voor de huidige (slechte) afhandeling
van het geval waarin alle elementen slecht zijn).
A slecht waarde voor elk plasje, en verwant problemen
An experimenteel optie "BADVAL_PER_PDL" is toegevoegd perldl.conf per piddle toestaan
slechte waarden. De documentatie is niet bijgewerkt om rekening te houden met deze wijziging.
Het volgende is alleen relevant voor typen met gehele getallen, en voor typen met drijvende komma if
"BADVAL_USENAN" was niet ingesteld toen PDL werd gebouwd.
Momenteel is er één slechte waarde voor elk gegevenstype. De code is zo geschreven dat we dat konden
een aparte slechte waarde hebben voor elke piddle (opgeslagen in de pdl-structuur) - dit zou dan gebeuren
verwijder het huidige probleem van:
pdl> $a = byte( 1, 2, byte->slechtewaarde, 4, 5);
pdl> p $a;
[1 2 255 4 5]
pdl> $a->slechte vlag(1)
pdl> p $a;
[1 2 SLECHT 4 5]
pdl> byte->slechte waarde(0);
pdl> p $a;
[1 2 255 4 5]
dwz de slechte waarde in $a heeft zijn waarde verloren slecht status met behulp van de huidige implementatie. Het zou
vrijwel zeker elders problemen veroorzaken!
IMPLEMENTATIE DETAILS
Tijdens een "perl Makefile.PL" wordt het bestand Basis/Core/badsupport.p is gecreëerd; dit bestand
bevat de waarden van de variabelen "WITH_BADVAL", "BADVAL_USENAN" en "BADVAL_PER_PDL",
en moet worden gebruikt door code die wordt uitgevoerd vóór de PDL::Config bestand wordt aangemaakt (bijv
Basic/Core/pdlcore.c.PL. De meeste PDL-code heeft echter alleen toegang nodig tot de %PDL::Config
array (bijv Basis/Slecht/slecht.pd) om erachter te komen of er ondersteuning met een slechte waarde nodig is.
Er is een nieuwe vlag toegevoegd aan de status van een piddle: "PDL_BADVAL". Indien niet ingesteld, dan wordt de
piddle bevat geen slechte waarden, en dus kan alle ondersteuningscode worden genegeerd. Indien ingesteld, is het
garandeert niet dat er slechte waarden aanwezig zijn, maar alleen dat hierop gecontroleerd moet worden.
Dankzij Christian, "badflag()" - die deze vlag instelt/wist (zie Basis/Slecht/slecht.pd) -
wordt bijgewerkt ALLE de kinderen/kleinkinderen/enz. van een piddle als de toestand ervan verandert (zie
"slechte vlag" in Basis/Slecht/slecht.pd en "propagate_badflag" in Basic/Core/Core.xs.PL). Het is niet
duidelijk wat ik met ouders moet doen: ik zie de reden voor het propageren van een 'set badflag'
verzoek aan ouders, maar ik vind dat een kind NIET de badflag van a. moet kunnen wissen
ouder. Er is ook de vraag wat er gebeurt als je de slechte waarde voor a verandert
plasje.
De "pdl_trans"-structuur is uitgebreid met een gehele waarde, "bvalflag", die
fungeert als een schakelaar om de code te vertellen of er met slechte waarden moet worden omgegaan of niet. Deze waarde is ingesteld
als voor een van de invoerpiddles de vlag "PDL_BADVAL" is ingesteld (hoewel deze code dat wel kan zijn
vervangen door de instelling "FindBadStateCode" in pp_def). De logica van de controle gaat krijgen
een beetje ingewikkelder als ik routines toesta terug te vallen op het gebruik van de sectie "Code".
typen met drijvende komma (dat wil zeggen die routines met "NoBadifNaN => 1" wanneer "BADVAL_USENAN" is
WAAR).
De slechte waarden voor de integer-typen worden nu opgeslagen in een structuur binnen de Core PDL
structuur - "PDL.bvals" (bijv Basic/Core/pdlcore.h.PL); zie ook "typedef badvals" in
Basis/Core/pdl.h.PL en de BOOT-code van Basic/Core/Core.xs.PL waar de waarden staan
geïnitialiseerd op (hopelijk) verstandige waarden. Zien PDL/Slecht/slecht.pd voor lees-/schrijfroutines naar
de waarden.
De toevoeging van de optie "BADVAL_PER_PDL" heeft geresulteerd in aanvullende wijzigingen in het
binnenkant van plassen. Deze wijzigingen zijn nog niet gedocumenteerd.
Waarom niet maken a PDL subklasse?
De ondersteuning voor slechte waarden had als een PDL-subklasse kunnen worden uitgevoerd. Het voordeel hiervan
De aanpak zou zijn dat je de code alleen laadt om slechte waarden af te handelen als je dat echt wilt
om ze te gebruiken. Het nadeel is dat de code dan wordt gescheiden: elke bug
reparaties/verbeteringen moeten in twee verschillende bestanden aan de code worden aangebracht. Met het heden
benadering van de code bevindt zich in dezelfde "pp_def" -functie (hoewel er nog steeds het probleem is
dat zowel de secties 'Code' als 'BadCode' moeten worden bijgewerkt).
Standaard slecht waarden
De standaard/oorspronkelijke slechte waarden zijn ingesteld op (overgenomen van de Starlink-distributie):
#erbij betrekken
PDL_Byte == UCHAR_MAX
PDL_Short == SHRT_MIN
PDL_Ushort == USHRT_MAX
PDL_Lang == INT_MIN
Als "BADVAL_USENAN == 0", dan hebben we dat ook
PDL_Float == -FLT_MAX
PDL_Double == -DBL_MAX
anders worden alle "NaN", "+Inf" en "-Inf" als slecht beschouwd voor typen met drijvende komma.
In dit geval kan de slechte waarde niet worden gewijzigd, in tegenstelling tot de integer-typen.
Hoe do I verandering a routine naar handvat slecht waarden?
Voorbeelden zijn te vinden in de meeste van de *.pd bestanden Basis/ (en hopelijk nog veel meer plaatsen
spoedig!). Een deel van de logica lijkt misschien een beetje onduidelijk - dat is waarschijnlijk omdat het zo is!
Opmerkingen worden gewaardeerd.
Alle routines zouden de slechte statusvlag automatisch moeten doorgeven aan uitvoerpiddles, tenzij
u verklaart anders.
Als een routine expliciet met slechte waarden omgaat, moet u deze optie aan pp_def opgeven:
HandvatSlecht => 1
Dit zorgt ervoor dat de juiste variabelen worden geïnitialiseerd voor de macro's $ISBAD etc. Het is
wordt ook gebruikt door de automatische documentaanmaakroutines om standaardinformatie over te verstrekken
de slechte waarde-ondersteuning van een routine zonder dat de gebruiker deze zelf hoeft te typen (dit is
in een vroeg stadium).
Om een routine te markeren omdat deze GEEN slechte waarden verwerkt, gebruikt u
HandvatSlecht => 0
Deze moet zorg ervoor dat de routine een waarschuwing afdrukt als er problemen met het kwaad worden verzonden
vlag ingesteld. Primitive's "intover" heeft deze set gehad - omdat het lastig zou zijn om te converteren -
maar ik heb het nog niet uitgeprobeerd om te kijken of het werkt.
Als u slechte waarden wilt afhandelen maar niet de status van alle uitvoerpiddles wilt instellen, of if
het is maar één invoerpiddle die belangrijk is, kijk dan naar de PP-regels
"NewXSFindBadStatus" en "NewXSCopyBadStatus" en de bijbehorende "pp_def" opties:
VindBadStatusCode
Standaard creëert "FindBadStatusCode" code die "$PRIV(bvalflag)" instelt, afhankelijk van
de status van de slechte vlag van de invoerpiddles: zie "findbadstatus" in
Basis/Gen/PP.pm. Door de gebruiker gedefinieerde code moet ook de waarde van "bvalflag" opslaan in de
Variabele "$BADFLAGCACHE()".
KopieerBadStatusCode
De standaardcode is hier iets eenvoudiger dan voor "FindBadStatusCode": de slechte vlag van
de uitvoerpiddles worden ingesteld als "$BADFLAGCACHE()" waar is nadat de code is uitgevoerd
geëvalueerd. Soms is "CopyBadStatusCode" ingesteld op een lege tekenreeks, met de
verantwoordelijkheid voor het instellen van de slechte vlag van de uitvoerpiddle die is overgelaten aan de "BadCode"
sectie (bijvoorbeeld de "xxxover"-routines in Basis/Primitief/primitief.pd).
Vóór PDL 2.4.3 gebruikten we "$PRIV(bvalflag)" in plaats van "$BADFLAGCACHE()". Dit is
gevaarlijk omdat het op dit moment niet gegarandeerd is dat de structuur "$PRIV()" geldig is
de code.
Als je een routine hebt die je ter plaatse wilt kunnen gebruiken, kijk dan naar de routines in
slecht.pd (of ops.pd) die de optie "in-place" gebruiken om te zien hoe de slechte vlag wordt verspreid
voor kinderen die de "xxxBadStatusCode"-opties gebruiken. Ik heb besloten dit niet als regels te automatiseren
zou een beetje ingewikkeld zijn, omdat niet elke lokale operatie de slechte vlag hoeft te verspreiden
(bijvoorbeeld unaire functies).
Als de optie
HandvatSlecht => 1
wordt gegeven, dan gebeuren er veel dingen. Voor integer-typen wordt de readdata-code automatisch uitgevoerd
creëert een variabele met de naam " _badval", die de slechte waarde daarvoor bevat
piddle (zie "get_xsdatapdecl()" in Basis/Gen/PP/PdlParObjs.pm). Voer echter geen harde code uit
deze naam in uw code! Gebruik in plaats daarvan macro's (met dank aan Tuomas voor de suggestie):
'$ISBAD(a(n=>1))' wordt uitgebreid naar '$a(n=>1) == a_badval'
'$ISGOOD(a())' '$a() != a_badval'
'$SETBAD(bob())' '$bob() = bob_badval'
Nou, de "$a(...)" is ook uitgebreid. U kunt ook een "$" vóór de pdl-naam gebruiken, if
je wilt het, maar het begint op lijnruis te lijken - bijvoorbeeld "$ISGOOD($a())".
Als u een piddle-waarde in een variabele in de cache plaatst, bijvoorbeeld "index" in plakjes.pd -- het volgende
routines zijn nuttig:
'$ISBADVAR(c_var,pdl)' 'c_var == pdl_badval'
'$ISGOODVAR(c_var,pdl)' 'c_var != pdl_badval'
'$SETBADVAR(c_var,pdl)' 'c_var = pdl_badval'
Het volgende is geïntroduceerd. Mogelijk moeten ze ermee spelen om hun prestaties te verbeteren
gebruikt.
'$PPISBAD(CHILD,[i]) 'CHILD_physdatap[i] == CHILD_badval'
'$PPISGOOD(CHILD,[i]) 'CHILD_physdatap[i] != CHILD_badval'
'$PPSETBAD(CHILD,[i]) 'CHILD_physdatap[i] = CHILD_badval'
Als "BADVAL_USENAN" is ingesteld, dan is het een beetje anders voor "float" en "double", waarbij we
beschouw "NaN", "+Inf" en "-Inf" allemaal als slecht. In dit geval:
ISBAD wordt eindig(piddle) == 0
ISGOOD eindig(piddle) != 0
SETBAD piddle = NaN
waar de waarde voor NaN hieronder wordt besproken in Omgaan met NaN-waarden.
Dit betekent allemaal dat je kunt veranderen
Code => '$a() = $b() + $c();'
naar
BadCode => 'if ( $ISBAD(b()) || $ISBAD(c()) ) {
$SETBAD(a());
} Else {
$a() = $b() + $c();
}'
Code laten zoals het is. PP::PDLCode zal dan een lus creëren die er ongeveer zo uitziet
if ( __trans->bvalflag ) {
threadloop over BadCode
} Else {
draadlus over code
}
(het is waarschijnlijk gemakkelijker om gewoon naar de .xs bestand om te zien wat er gebeurt).
Going Verder the Code sectie
Net als bij "BadCode" zijn er "BadBackCode" en "BadRedoDimsCode".
Het omgaan met "EquivCPOffsCode" is een beetje anders: in de veronderstelling dat de enige toegang
naar gegevens gaat via de macro "$EQUIVCPOFFS(i,j)", dan kunnen we automatisch de 'slechte' creëren
versie ervan; zie de regels "[EquivCPOffsCode]" en "[Code]" in PDL::PP.
Macro toegang naar the slecht vlag of a plasje
Er zijn macro's beschikbaar om toegang te geven tot de slechte vlagstatus van een pdl:
'$PDLSTATEISBAD(a)' -> '($PDL(a)->status & PDL_BADVAL) > 0'
'$PDLSTATEISGOOD(a)' '($PDL(a)->status & PDL_BADVAL) == 0'
'$PDLSTATESETBAD(a)' '$PDL(a)->status |= PDL_BADVAL'
'$PDLSTATESETGOOD(a)' '$PDL(a)->status &= ~PDL_BADVAL'
Voor gebruik in "xxxxBadStatusCode" (+ andere dingen die in de INIT: sectie gaan) zijn er:
'$SETPDLSTATEBAD(a)' -> 'a->status |= PDL_BADVAL'
'$SETPDLSTATEGOOD(a)' -> 'a->staat &= ~PDL_BADVAL'
'$ISPDLSTATEBAD(a)' -> '((a->status & PDL_BADVAL) > 0)'
'$ISPDLSTATEGOOD(a)' -> '((a->status & PDL_BADVAL) == 0)'
In PDL 2.4.3 is de macro "$BADFLAGCACHE()" geïntroduceerd voor gebruik in "FindBadStatusCode" en
"Kopieer SlechteStatusCode".
Behandeling NaN waarden
Er zijn twee problemen:
NaN als de slechte waarde
wat gedaan is. Om te selecteren, stelt u "BADVAL_USENAN" in op 1 in perldl.conf; een waarde van 0 valt
terug naar het op dezelfde manier behandelen van de drijvende-kommatypen als de gehele getallen. Ik moet wat doen
benchmarks om te zien welke sneller is, en of het afhankelijk is van machines (Linux lijkt
om veel meer te vertragen dan mijn Sparc-machine in een aantal zeer eenvoudige tests die ik deed).
Negeren van BadCode-secties
dat niet.
Voor simpel routines die drijvende-kommagetallen verwerken, moeten we de computer laten verwerken
de slechte waarden (dat wil zeggen "NaN" en "Inf" waarden) in plaats van de code in de "BadCode" te gebruiken
sectie. Veel van dergelijke routines zijn gelabeld met "NoBadifNaN => 1"; hoe dit ook is
momenteel genegeerd door PDL::PP.
Voor deze routines willen we de sectie "Code" gebruiken als
de piddle heeft geen slechte vlag ingesteld
het datatype is float of double
anders gebruiken we de sectie "BadCode". Dit is NIET GEÏMPLEMENTEERD, zoals het zal vereisen
redelijk hacken van PP::PDLCode!
Er is ook het probleem van hoe we omgaan met 'uitzonderingen' - aangezien "$a = pdl(2) / pdl(0) "
produceert een slechte waarde, maar werkt de badflag-waarde van de piddle niet bij. Kunnen we een
exception, of moeten we hiervoor traplopen (zoek bijvoorbeeld naar "exception" in
Basic/Ops/ops.pd)?
Het controleren op "Nan" en "Inf" wordt gedaan met behulp van de systeemaanroep "finite()". Als je wilt
Als u een waarde instelt op de "NaN"-waarde, kan het volgende stukje code worden gebruikt (dit kunt u vinden
in beide Basic/Core/Core.xs.PL en Basis/Slecht/slecht.pd):
/* voor big-endian-machines */
statische unie {niet-ondertekende char __c[4]; zweven __d; }
__pdl_nan = { { 0x7f, 0xc0, 0, 0 } };
/* voor Little Endian-machines */
statische unie {niet-ondertekende char __c[4]; zweven __d; }
__pdl_nan = { { 0, 0, 0xc0, 0x7f } };
Deze aanpak zou waarschijnlijk moeten worden vervangen door bibliotheekroutines zoals "nan("")" of
"atof("NaN")".
Gebruik de routine om erachter te komen of een bepaalde machine big endian is
"PDL::Core::Dev::isbigendian()".
WAT OVER ONS DOCUMENTATIE?
Een van de sterke punten van PDL is de online documentatie. Het doel is om dit systeem te gebruiken
geef informatie over hoe/of een routine slechte waarden ondersteunt: in veel gevallen "pp_def()"
bevat sowieso alle informatie, zodat de functieschrijver niets hoeft te doen
alle! Voor de gevallen waarin dit niet voldoende is, is er de optie "BadDoc". Voor code
geschreven op Perl-niveau - dwz in een .pm-bestand - gebruik de "=for bad" pod-richtlijn.
Deze informatie zal beschikbaar zijn via man/pod2man/html documentatie. Het is ook
toegankelijk vanaf de "perldl" of "pdl2" shells - met behulp van het "badinfo" commando - en de
"pdldoc" shell-opdracht - met behulp van de "-b" optie.
Deze steun bevindt zich in een zeer vroeg stadium, dat wil zeggen dat er nog niet veel over is nagedacht: commentaar
zijn welkom; verbeteringen aan de code hebben de voorkeur ;) Een lastig probleem is voor *.p.m code:
je moet een schrijven *.pm.PL bestand dat alleen de instructie "=for bad" (+ tekst) invoegt als
ondersteuning voor slechte waarden is ingebouwd. In feite is dit lastig bij het omgaan met slechte waarden op de
Perl, in plaats van PDL::PP, niveau: misschien moet ik gewoon de optie "WITH_BADVAL" schrappen...
ACTUEEL KWESTIES
Er zijn een aantal gebieden die werk, gebruikersinvoer of beide nodig hebben! Ze worden genoemd
elders in dit document, maar dit is alleen om er zeker van te zijn dat ze niet verloren gaan.
Trapping ongeldig wiskundig operaties
Moeten we uitzonderingen toevoegen aan de functies in "PDL::Ops" om de uitvoer slecht in te stellen voor out-of-
bereik invoerwaarden?
pdl> plog10(pdl(10,100,-1))
Ik zou graag willen dat het bovenstaande "[1 2 BAD]" oplevert, maar dit zou de werking van allen
plassen. We zouden na de operatie kunnen controleren op "NaN"/"Inf"-waarden, maar dat betwijfel ik
zou sneller zijn.
Integratie met NaN
Wanneer "BADVAL_USENAN" waar is, zouden de routines in "PDL::Ops" gewoon moeten doorvallen naar de
Sectie 'Code' - dwz gebruik 'BadCode' niet - voor gegevenstypen 'float' en 'double'.
Globaal tegen per piddle slecht waarden
Ik denk dat het enige dat nodig is, is om de routines in "Basic/Core/pdlconv.c.PL" te veranderen, hoewel
er zullen zeker complicaties zijn. Het zou ook betekenen dat de pdl-structuur nodig zou zijn
om een variabele te hebben om de slechte waarde ervan op te slaan, wat binaire incompatibiliteit zou betekenen
eerdere versies van PDL met ondersteuning voor slechte waarde.
Sinds 17 maart 2006 bevat PDL de experimenteel Configuratieoptie "BADVAL_PER_PDL".
die, indien geselecteerd, slechte waarden per piddle toevoegt.
Informatiestroom of the slechte vlag
Momenteel worden veranderingen in de slechte vlag gepropageerd naar de kinderen van een piddle, maar misschien
ze moeten ook aan de ouders worden doorgegeven. Met de komst van per-piddle slecht
waarden moeten we overwegen hoe we moeten omgaan met wijzigingen in de waarde die wordt gebruikt om slechte items weer te geven
ook.
ALLES ELSE
Het bouwproces is beïnvloed. De volgende bestanden worden nu aangemaakt tijdens de build:
Basic/Core/pdlcore.h pdlcore.h.PL
pdlcore.c pdlcore.c.PL
pdlapi.c pdlapi.c.PL
Kern.xs Kern.xs.PL
Core.pm Core.pm.PL
Er zijn een aantal nieuwe bestanden toegevoegd:
Basic/Pod/BadValues.pod (dat wil zeggen dit bestand)
t/slecht.t
Eenvoudig/Slecht/
Basic/Bad/Makefile.PL
slecht.pd
etc
TODO/SUGGESTIES
· Kijk naar het gebruik van slechte waarden per piddle. Zou een verandering in de pdl-structuur betekenen (dwz
binaire incompatibiliteit) en de routines in "Basic/Core/pdlconv.c.PL" zouden
veranderen om dit aan te pakken. De meeste andere routines moet niet moet veranderd worden...
Zie de experimenteel "BADVAL_PER_PDL" optie.
· wat te doen met "$b = pdl(-2); $a = log10($b)" - $a zou slecht moeten zijn ingesteld, maar het
momenteel niet.
· Sta toe dat de bewerkingen in PDL::Ops de controle op slechte waarden overslaan bij gebruik van NaN als a
slechte waarde en het verwerken van een drijvende-komma-piddle. Heeft behoorlijk wat werk nodig
PDL::PP::PDL-code.
· "$pdl->baddata()" werkt nu ook alle kinderen van deze piddle bij. Echter niet
Ik weet zeker wat ik met ouders moet doen, aangezien:
$b = $a->segment();
$b->slechte gegevens(0)
betekent niet dat de slechte waarde van $a niet moet worden gewist. echter na
$b->slechte gegevens(1)
het is verstandig om aan te nemen dat de ouders nu worden gemarkeerd omdat ze slechte waarden bevatten.
MISSCHIEN kunt u de vlag voor slechte waarde alleen wissen als u GEEN kind van iemand anders bent
piddle, terwijl als u de vlag instelt, alle kinderen EN ouders moeten worden ingesteld als
goed?
Op dezelfde manier, als u de slechte waarde in een piddle wijzigt, moet dit dan ook worden doorgegeven
ouder & kinderen? Of mag je dit alleen op het 'topniveau' piddel doen?
Vervelend...
· zorg dat er code wordt opgezet om benchmarks uit te voeren om te zien hoeveel dingen worden vertraagd (en hoe
controleer of ik de zaken niet verpest heb als "WITH_BADVAL" 0/undef is).
· sommige namen zijn niet aantrekkelijk - ik denk aan "orig_badvalue()" in
Basis/Slecht/slecht.pd in het bijzonder. Alle suggesties worden op prijs gesteld.
Gebruik PDL::BadValuesp online met behulp van onworks.net-services