<!--{{{-->
<link rel='alternate' type='application/rss+xml' title='RSS' href='index.xml' />
<!--}}}-->
Background: #fff
Foreground: #000
PrimaryPale: #8cf
PrimaryLight: #18f
PrimaryMid: #04b
PrimaryDark: #014
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
/*{{{*/
body {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}

a {color:[[ColorPalette::PrimaryMid]];}
a:hover {background-color:[[ColorPalette::PrimaryMid]]; color:[[ColorPalette::Background]];}
a img {border:0;}

h1,h2,h3,h4,h5,h6 {color:[[ColorPalette::SecondaryDark]]; background:transparent;}
h1 {border-bottom:2px solid [[ColorPalette::TertiaryLight]];}
h2,h3 {border-bottom:1px solid [[ColorPalette::TertiaryLight]];}

.button {color:[[ColorPalette::PrimaryDark]]; border:1px solid [[ColorPalette::Background]];}
.button:hover {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::SecondaryLight]]; border-color:[[ColorPalette::SecondaryMid]];}
.button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::SecondaryDark]];}

.header {background:[[ColorPalette::PrimaryMid]];}
.headerShadow {color:[[ColorPalette::Foreground]];}
.headerShadow a {font-weight:normal; color:[[ColorPalette::Foreground]];}
.headerForeground {color:[[ColorPalette::Background]];}
.headerForeground a {font-weight:normal; color:[[ColorPalette::PrimaryPale]];}

.tabSelected{color:[[ColorPalette::PrimaryDark]];
	background:[[ColorPalette::TertiaryPale]];
	border-left:1px solid [[ColorPalette::TertiaryLight]];
	border-top:1px solid [[ColorPalette::TertiaryLight]];
	border-right:1px solid [[ColorPalette::TertiaryLight]];
}
.tabUnselected {color:[[ColorPalette::Background]]; background:[[ColorPalette::TertiaryMid]];}
.tabContents {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::TertiaryPale]]; border:1px solid [[ColorPalette::TertiaryLight]];}
.tabContents .button {border:0;}

#sidebar {}
#sidebarOptions input {border:1px solid [[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel {background:[[ColorPalette::PrimaryPale]];}
#sidebarOptions .sliderPanel a {border:none;color:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:hover {color:[[ColorPalette::Background]]; background:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:active {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::Background]];}

.wizard {background:[[ColorPalette::PrimaryPale]]; border:1px solid [[ColorPalette::PrimaryMid]];}
.wizard h1 {color:[[ColorPalette::PrimaryDark]]; border:none;}
.wizard h2 {color:[[ColorPalette::Foreground]]; border:none;}
.wizardStep {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];
	border:1px solid [[ColorPalette::PrimaryMid]];}
.wizardStep.wizardStepDone {background:[[ColorPalette::TertiaryLight]];}
.wizardFooter {background:[[ColorPalette::PrimaryPale]];}
.wizardFooter .status {background:[[ColorPalette::PrimaryDark]]; color:[[ColorPalette::Background]];}
.wizard .button {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryLight]]; border: 1px solid;
	border-color:[[ColorPalette::SecondaryPale]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryPale]];}
.wizard .button:hover {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Background]];}
.wizard .button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::Foreground]]; border: 1px solid;
	border-color:[[ColorPalette::PrimaryDark]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryDark]];}
	
.wizard .notChanged {background:transparent;}
.wizard .changedLocally {background:#80ff80;}
.wizard .changedServer {background:#8080ff;}
.wizard .changedBoth {background:#ff8080;}
.wizard .notFound {background:#ffff80;}
.wizard .putToServer {background:#ff80ff;}
.wizard .gotFromServer {background:#80ffff;}

#messageArea {border:1px solid [[ColorPalette::SecondaryMid]]; background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]];}
#messageArea .button {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::SecondaryPale]]; border:none;}

.popupTiddler {background:[[ColorPalette::TertiaryPale]]; border:2px solid [[ColorPalette::TertiaryMid]];}

.popup {background:[[ColorPalette::TertiaryPale]]; color:[[ColorPalette::TertiaryDark]]; border-left:1px solid [[ColorPalette::TertiaryMid]]; border-top:1px solid [[ColorPalette::TertiaryMid]]; border-right:2px solid [[ColorPalette::TertiaryDark]]; border-bottom:2px solid [[ColorPalette::TertiaryDark]];}
.popup hr {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::PrimaryDark]]; border-bottom:1px;}
.popup li.disabled {color:[[ColorPalette::TertiaryMid]];}
.popup li a, .popup li a:visited {color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:active {background:[[ColorPalette::SecondaryPale]]; color:[[ColorPalette::Foreground]]; border: none;}
.popupHighlight {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
.listBreak div {border-bottom:1px solid [[ColorPalette::TertiaryDark]];}

.tiddler .defaultCommand {font-weight:bold;}

.shadow .title {color:[[ColorPalette::TertiaryDark]];}

.title {color:[[ColorPalette::SecondaryDark]];}
.subtitle {color:[[ColorPalette::TertiaryDark]];}

.toolbar {color:[[ColorPalette::PrimaryMid]];}
.toolbar a {color:[[ColorPalette::TertiaryLight]];}
.selected .toolbar a {color:[[ColorPalette::TertiaryMid]];}
.selected .toolbar a:hover {color:[[ColorPalette::Foreground]];}

.tagging, .tagged {border:1px solid [[ColorPalette::TertiaryPale]]; background-color:[[ColorPalette::TertiaryPale]];}
.selected .tagging, .selected .tagged {background-color:[[ColorPalette::TertiaryLight]]; border:1px solid [[ColorPalette::TertiaryMid]];}
.tagging .listTitle, .tagged .listTitle {color:[[ColorPalette::PrimaryDark]];}
.tagging .button, .tagged .button {border:none;}

.footer {color:[[ColorPalette::TertiaryLight]];}
.selected .footer {color:[[ColorPalette::TertiaryMid]];}

.sparkline {background:[[ColorPalette::PrimaryPale]]; border:0;}
.sparktick {background:[[ColorPalette::PrimaryDark]];}

.error, .errorButton {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Error]];}
.warning {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryPale]];}
.lowlight {background:[[ColorPalette::TertiaryLight]];}

.zoomer {background:none; color:[[ColorPalette::TertiaryMid]]; border:3px solid [[ColorPalette::TertiaryMid]];}

.imageLink, #displayArea .imageLink {background:transparent;}

.annotation {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border:2px solid [[ColorPalette::SecondaryMid]];}

.viewer .listTitle {list-style-type:none; margin-left:-2em;}
.viewer .button {border:1px solid [[ColorPalette::SecondaryMid]];}
.viewer blockquote {border-left:3px solid [[ColorPalette::TertiaryDark]];}

.viewer table, table.twtable {border:2px solid [[ColorPalette::TertiaryDark]];}
.viewer th, .viewer thead td, .twtable th, .twtable thead td {background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::Background]];}
.viewer td, .viewer tr, .twtable td, .twtable tr {border:1px solid [[ColorPalette::TertiaryDark]];}

.viewer pre {border:1px solid [[ColorPalette::SecondaryLight]]; background:[[ColorPalette::SecondaryPale]];}
.viewer code {color:[[ColorPalette::SecondaryDark]];}
.viewer hr {border:0; border-top:dashed 1px [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::TertiaryDark]];}

.highlight, .marked {background:[[ColorPalette::SecondaryLight]];}

.editor input {border:1px solid [[ColorPalette::PrimaryMid]];}
.editor textarea {border:1px solid [[ColorPalette::PrimaryMid]]; width:100%;}
.editorFooter {color:[[ColorPalette::TertiaryMid]];}

#backstageArea {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::TertiaryMid]];}
#backstageArea a {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstageArea a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; }
#backstageArea a.backstageSelTab {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
#backstageButton a {background:none; color:[[ColorPalette::Background]]; border:none;}
#backstageButton a:hover {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstagePanel {background:[[ColorPalette::Background]]; border-color: [[ColorPalette::Background]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]];}
.backstagePanelFooter .button {border:none; color:[[ColorPalette::Background]];}
.backstagePanelFooter .button:hover {color:[[ColorPalette::Foreground]];}
#backstageCloak {background:[[ColorPalette::Foreground]]; opacity:0.6; filter:'alpha(opacity:60)';}
/*}}}*/
/*{{{*/
* html .tiddler {height:1%;}

body {font-size:.75em; font-family:arial,helvetica; margin:0; padding:0;}

h1,h2,h3,h4,h5,h6 {font-weight:bold; text-decoration:none;}
h1,h2,h3 {padding-bottom:1px; margin-top:1.2em;margin-bottom:0.3em;}
h4,h5,h6 {margin-top:1em;}
h1 {font-size:1.35em;}
h2 {font-size:1.25em;}
h3 {font-size:1.1em;}
h4 {font-size:1em;}
h5 {font-size:.9em;}

hr {height:1px;}

a {text-decoration:none;}

dt {font-weight:bold;}

ol {list-style-type:decimal;}
ol ol {list-style-type:lower-alpha;}
ol ol ol {list-style-type:lower-roman;}
ol ol ol ol {list-style-type:decimal;}
ol ol ol ol ol {list-style-type:lower-alpha;}
ol ol ol ol ol ol {list-style-type:lower-roman;}
ol ol ol ol ol ol ol {list-style-type:decimal;}

.txtOptionInput {width:11em;}

#contentWrapper .chkOptionInput {border:0;}

.externalLink {text-decoration:underline;}

.indent {margin-left:3em;}
.outdent {margin-left:3em; text-indent:-3em;}
code.escaped {white-space:nowrap;}

.tiddlyLinkExisting {font-weight:bold;}
.tiddlyLinkNonExisting {font-style:italic;}

/* the 'a' is required for IE, otherwise it renders the whole tiddler in bold */
a.tiddlyLinkNonExisting.shadow {font-weight:bold;}

#mainMenu .tiddlyLinkExisting,
	#mainMenu .tiddlyLinkNonExisting,
	#sidebarTabs .tiddlyLinkNonExisting {font-weight:normal; font-style:normal;}
#sidebarTabs .tiddlyLinkExisting {font-weight:bold; font-style:normal;}

.header {position:relative;}
.header a:hover {background:transparent;}
.headerShadow {position:relative; padding:4.5em 0em 1em 1em; left:-1px; top:-1px;}
.headerForeground {position:absolute; padding:4.5em 0em 1em 1em; left:0px; top:0px;}

.siteTitle {font-size:3em;}
.siteSubtitle {font-size:1.2em;}

#mainMenu {position:absolute; left:0; width:10em; text-align:right; line-height:1.6em; padding:1.5em 0.5em 0.5em 0.5em; font-size:1.1em;}

#sidebar {position:absolute; right:3px; width:16em; font-size:.9em;}
#sidebarOptions {padding-top:0.3em;}
#sidebarOptions a {margin:0em 0.2em; padding:0.2em 0.3em; display:block;}
#sidebarOptions input {margin:0.4em 0.5em;}
#sidebarOptions .sliderPanel {margin-left:1em; padding:0.5em; font-size:.85em;}
#sidebarOptions .sliderPanel a {font-weight:bold; display:inline; padding:0;}
#sidebarOptions .sliderPanel input {margin:0 0 .3em 0;}
#sidebarTabs .tabContents {width:15em; overflow:hidden;}

.wizard {padding:0.1em 1em 0em 2em;}
.wizard h1 {font-size:2em; font-weight:bold; background:none; padding:0em 0em 0em 0em; margin:0.4em 0em 0.2em 0em;}
.wizard h2 {font-size:1.2em; font-weight:bold; background:none; padding:0em 0em 0em 0em; margin:0.4em 0em 0.2em 0em;}
.wizardStep {padding:1em 1em 1em 1em;}
.wizard .button {margin:0.5em 0em 0em 0em; font-size:1.2em;}
.wizardFooter {padding:0.8em 0.4em 0.8em 0em;}
.wizardFooter .status {padding:0em 0.4em 0em 0.4em; margin-left:1em;}
.wizard .button {padding:0.1em 0.2em 0.1em 0.2em;}

#messageArea {position:fixed; top:2em; right:0em; margin:0.5em; padding:0.5em; z-index:2000; _position:absolute;}
.messageToolbar {display:block; text-align:right; padding:0.2em 0.2em 0.2em 0.2em;}
#messageArea a {text-decoration:underline;}

.tiddlerPopupButton {padding:0.2em 0.2em 0.2em 0.2em;}
.popupTiddler {position: absolute; z-index:300; padding:1em 1em 1em 1em; margin:0;}

.popup {position:absolute; z-index:300; font-size:.9em; padding:0; list-style:none; margin:0;}
.popup .popupMessage {padding:0.4em;}
.popup hr {display:block; height:1px; width:auto; padding:0; margin:0.2em 0em;}
.popup li.disabled {padding:0.4em;}
.popup li a {display:block; padding:0.4em; font-weight:normal; cursor:pointer;}
.listBreak {font-size:1px; line-height:1px;}
.listBreak div {margin:2px 0;}

.tabset {padding:1em 0em 0em 0.5em;}
.tab {margin:0em 0em 0em 0.25em; padding:2px;}
.tabContents {padding:0.5em;}
.tabContents ul, .tabContents ol {margin:0; padding:0;}
.txtMainTab .tabContents li {list-style:none;}
.tabContents li.listLink { margin-left:.75em;}

#contentWrapper {display:block;}
#splashScreen {display:none;}

#displayArea {margin:1em 17em 0em 14em;}

.toolbar {text-align:right; font-size:.9em;}

.tiddler {padding:1em 1em 0em 1em;}

.missing .viewer,.missing .title {font-style:italic;}

.title {font-size:1.6em; font-weight:bold;}

.missing .subtitle {display:none;}
.subtitle {font-size:1.1em;}

.tiddler .button {padding:0.2em 0.4em;}

.tagging {margin:0.5em 0.5em 0.5em 0; float:left; display:none;}
.isTag .tagging {display:block;}
.tagged {margin:0.5em; float:right;}
.tagging, .tagged {font-size:0.9em; padding:0.25em;}
.tagging ul, .tagged ul {list-style:none; margin:0.25em; padding:0;}
.tagClear {clear:both;}

.footer {font-size:.9em;}
.footer li {display:inline;}

.annotation {padding:0.5em; margin:0.5em;}

* html .viewer pre {width:99%; padding:0 0 1em 0;}
.viewer {line-height:1.4em; padding-top:0.5em;}
.viewer .button {margin:0em 0.25em; padding:0em 0.25em;}
.viewer blockquote {line-height:1.5em; padding-left:0.8em;margin-left:2.5em;}
.viewer ul, .viewer ol {margin-left:0.5em; padding-left:1.5em;}

.viewer table, table.twtable {border-collapse:collapse; margin:0.8em 1.0em;}
.viewer th, .viewer td, .viewer tr,.viewer caption,.twtable th, .twtable td, .twtable tr,.twtable caption {padding:3px;}
table.listView {font-size:0.85em; margin:0.8em 1.0em;}
table.listView th, table.listView td, table.listView tr {padding:0px 3px 0px 3px;}

.viewer pre {padding:0.5em; margin-left:0.5em; font-size:1.2em; line-height:1.4em; overflow:auto;}
.viewer code {font-size:1.2em; line-height:1.4em;}

.editor {font-size:1.1em;}
.editor input, .editor textarea {display:block; width:100%; font:inherit;}
.editorFooter {padding:0.25em 0em; font-size:.9em;}
.editorFooter .button {padding-top:0px; padding-bottom:0px;}

.fieldsetFix {border:0; padding:0; margin:1px 0px 1px 0px;}

.sparkline {line-height:1em;}
.sparktick {outline:0;}

.zoomer {font-size:1.1em; position:absolute; overflow:hidden;}
.zoomer div {padding:1em;}

* html #backstage {width:99%;}
* html #backstageArea {width:99%;}
#backstageArea {display:none; position:relative; overflow: hidden; z-index:150; padding:0.3em 0.5em 0.3em 0.5em;}
#backstageToolbar {position:relative;}
#backstageArea a {font-weight:bold; margin-left:0.5em; padding:0.3em 0.5em 0.3em 0.5em;}
#backstageButton {display:none; position:absolute; z-index:175; top:0em; right:0em;}
#backstageButton a {padding:0.1em 0.4em 0.1em 0.4em; margin:0.1em 0.1em 0.1em 0.1em;}
#backstage {position:relative; width:100%; z-index:50;}
#backstagePanel {display:none; z-index:100; position:absolute; width:90%; margin:0em 3em 0em 3em; padding:1em 1em 1em 1em;}
.backstagePanelFooter {padding-top:0.2em; float:right;}
.backstagePanelFooter a {padding:0.2em 0.4em 0.2em 0.4em;}
#backstageCloak {display:none; z-index:20; position:absolute; width:100%; height:100px;}

.whenBackstage {display:none;}
.backstageVisible .whenBackstage {display:block;}
/*}}}*/
/***
StyleSheet for use when a translation requires any css style changes.
This StyleSheet can be used directly by languages such as Chinese, Japanese and Korean which need larger font sizes.
***/
/*{{{*/
body {font-size:0.8em;}
#sidebarOptions {font-size:1.05em;}
#sidebarOptions a {font-style:normal;}
#sidebarOptions .sliderPanel {font-size:0.95em;}
.subtitle {font-size:0.8em;}
.viewer table.listView {font-size:0.95em;}
/*}}}*/
/*{{{*/
@media print {
#mainMenu, #sidebar, #messageArea, .toolbar, #backstageButton, #backstageArea {display: none ! important;}
#displayArea {margin: 1em 1em 0em 1em;}
/* Fixes a feature in Firefox 1.5.0.2 where print preview displays the noscript content */
noscript {display:none;}
}
/*}}}*/
<!--{{{-->
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
<div id='sidebar'>
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
</div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar [[ToolbarCommands::EditToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></div>
<div class='editor' macro='edit text'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>
<!--}}}-->
To get started with this blank TiddlyWiki, you'll need to modify the following tiddlers:
* SiteTitle & SiteSubtitle: The title and subtitle of the site, as shown above (after saving, they will also appear in the browser title bar)
* MainMenu: The menu (usually on the left)
* DefaultTiddlers: Contains the names of the tiddlers that you want to appear when the TiddlyWiki is opened
You'll also need to enter your username for signing your edits: <<option txtUserName>>
These InterfaceOptions for customising TiddlyWiki are saved in your browser

Your username for signing your edits. Write it as a WikiWord (eg JoeBloggs)

<<option txtUserName>>
<<option chkSaveBackups>> SaveBackups
<<option chkAutoSave>> AutoSave
<<option chkRegExpSearch>> RegExpSearch
<<option chkCaseSensitiveSearch>> CaseSensitiveSearch
<<option chkAnimate>> EnableAnimations

----
Also see AdvancedOptions
<<importTiddlers>>
''Auteurs'' : Joel Falcou, Jocelyn Sérot, Thierry Chateay, Frédéric Jurie
''Conférence'' : ParCo 2005 - Malaga, Espagne, Septembre 2005
''Parution'' : Proceedings of the International Conference ParCo, John von Neumann Institute for Computing Series, vol. 33, p. 663-670

''Résumé'' ://"Artificial vision requires of large amount of computing power, especially when operating on the fly on digital video streams. For these applications, real-time processing is needed to allow the system to interact with its environment, like in robotic applications or man/machine interfaces. Two broad classes of solutions have been used to solve the problem of balancing application needs and the constraints of the real-time processing: degrading algorithms or using dedicated hardware architecture like FPGA or GPU. These strategies were effective because of the specific properties of the images and the structure of the associated algorithms. However, the constant and fast progression of general purpose computers performance makes these specific solutions less and less interesting. Development time and cost now plead in favor of architectures based on standard components. During the last ten years, the use of these solutions increased with the generalization of clusters made up of off-the-shelf personal computers. But this type of solution has been rarely used in the context of complex vision applications operating on the fly. This paper evaluates this opportunity by proposing a cluster architecture dedicated to real-time vision applications. We describe the hardware architecture of such a solution – by justifying the technological choices carried out on the application requirements and the current state of the art – then the associated software architecture. The validity of the approach is shown with the description and performance evaluation of a real-time 3D reconstruction application."//

[[Téléchargement|http://www.lri.fr/~falcou/pub/falcou-PARCO-2005.pdf]]
!Comment
Ce site est organisé comme un Wiki non-linéaire. Chaque élément du site est contenu dans un Tiddler référencé par un certains nombre de tag. Lorsque vous cliquez sur un lien, le Tiddler associé est ouvert sur la page en cours. Un menu vous permet de fermer ou de naviguer entre les Tiddler. Si vous vous sentez perdu, le moteur de recherche interne sur la droite (''search'') vous permet de trouver l'information qu'il vous manque. Lorsque vous avez trouvé, le lien <<permaview>> vous permet de créer dans votre barre d'adresse une URL qui réouvrira une sélection de Tiddler ouvert.
!Quoi
* Ce site a été conçu via l'excellent [[Monkey Pirate Tiddly Wiki|http://mptw.tiddlyspot.com/]] que je ne peut que vous conseiller.
* Les illustrations ont été réalisées sous [[OmniGraffle|http://www.omnigroup.com/applications/OmniGraffle/]]
Ingénieur diplômé de [[l'ISIMA|http://www.isima.fr]] et du DEA CSTI de l'Université Blaise Pascal de Clermont Ferrand, j'ai soutenue une thèse en Vision pour la Robotique intitulée [[Un cluster pour la vision temps réel : Architecture, Outils et Applications|Travaux de thèse]] au sein du [[LASMEA|http://wwwlasmea.univ-bpclermont.fr/]]. Après un post-doc au sein du groupe AXIS  de [[l'IEF|http://www.ief.u-psud.fr/]], je suis désormais maitre de conférences au [[LRI|http://www.lri.fr]] affecté à [[l'IFIPS|http://http://www.ifips.u-psud.fr/fr/index.html]]. 

Ce site présente les grandes lignes de [[mes activités de recherche|Recherche]] au sein de [[l'équipe PARALL|http://www.lri.fr/equipe.php?eq=9]], [[mes réalisations logicielles|Logiciels]] et [[mes supports d'enseignement|Enseignement]].
''Master 2 Recherche en Informatique d'Orsay - Module "Calcul Haute Performance"''
!Objectifs
Présenter les éléments architecturaux des accélérateurs de type CELL et GPU ainsi que les principaux éléments et difficultés du développement logiciel sur ces plate-formes.
!Supports
* [[Présentation|http://www.lri.fr/~falcou/teaching/master/accelerator.pdf]]
* [[Fichiers sources d'exemples|http://www.lri.fr/~falcou/teaching/master/accelerator.zip]]
!2008-2009 : Maître de Conférences
* Responsable de la première année de [[Formation par l'apprentissage de l'IFIPS|http://www.ifips.u-psud.fr/fr/entreprises/apprentissage.html]].
* Cours de [[Programmation Orientée Objet]] en 2ème Année Cursus Apprentissage de l'IFIPS
* Cours de [[Programmation Parallèle]] en 2ème Année Cursus Formation Continue de l'IFIPS
* Cours de [[Système d'Exploitation]] en 2ème Année Cursus Apprentissage de l'IFIPS et du L3 Informatique
* TD et TP d'[[Architecture des Ordinateurs|http://www.lri.fr/~de/Archi-IFIPS-0809.htm]] - 2ème Année Cursus Ingénieur de l'IFIPS
!2007-2008 : Vacataire à l'Université Paris Sud XI
* TD et TP d'[[Architecture des Ordinateurs|http://www.lri.fr/~de/Archi-IFIPS-0709.htm]] - 2ème Année Cursus Ingénieur de l'IFIPS
* TP de Calcul Intensif du Master MISIC de l'Ecole Polytechnique
!2006-2007 : Attaché Temporaire à l'Enseignement et à la Recherche à l'ISIMA
* Cours de C, Assembleur, Codage. 
* TP de C, C++, Assembleur, programmation système.
!2003-2006 : Moniteur à la Faculté de médecine de Clermont-Ferrand
* Préparation au C2i
* Initiation au STIC
''Auteurs'' : Tarik Saidani, Joel Falcou, Claude Tadonki, Lionel Lacassagne, Daniel Etiemble
''Conférence'' : PACT 2009

''Résumé'' :
//"Efficiently using the hardware capabilities of the Cell processor, a heterogeneous chip multiprocessor that uses several levels of parallelism to deliver high performance, and being able to reuse legacy code are real challenges for application developers. We propose to use Generative Programming and more precisely template meta-programing to design an Embedded Domain Specific Language using algorithmic skeletons to generate applications based on a high-level mapping description. The method is easy to use by developers and delivers performance close to the performance of optimized hand-written code, as shown on various benchmarks ranging from simple BLAS kernels to image processing applications."//

''A paraitre en 2009''
''Auteurs'' : Tarik Saidani, Joel Falcou, Lionel Lacassagne, Samir Bouaziz
''Journal'' : International Journal of Computer Science and Applications, Septembre 2008,Vol. 5, Num 3a

''Résumé'':
//"Vector extensions for general purpose processors are an efficient feature to address the growing performance demand of multimedia and computer vision applications. Embedded processors are the most widespread architectures for such applications. While providing sufficient computing power for these applications, they must take into account power, area and real-time constraints. In this paper, we propose two hardware optimization techniques to address those constraints: RISCization and instruction set customization. Experimental results show that those techniques both reduce time and power consumption by up to 50% when compared to the original ISA."//

[[Téléchargement depuis le site de l'éditeur|http://www.tmrfindia.org/ijcsa/v5i3a2.pdf]]
''Auteurs'' : Joel Falcou,Jocelyn Sérot
''Conférence'' : ACIVS 2004 - Bruxelles, Belgique - Septembre 2005

''Résumé'' : //"Microprocessors with SIMD enhanced instruction sets have been proposed as a solution for delivering higher hardware utilization for the most demanding media-processing applications. But direct exploitation of these SIMD extensions places a significant burden on the programmer since it generally involves a complex, low-level and awkward programming style. In this paper, we propose a high-level C++ class library dedicated to the efficient exploitation of these SIMD extensions. We show that the weaknesses traditionally associated with library-based approaches can be avoided by resorting to sophisticated template-based metaprogramming techniques at the implementation level. Benchmarks for a prototype implementation of the library, targeting the PowerPC G4 processor and its Altivec extension are presented. They show that performances close to the one obtained with hand-crafted code can be reached from a formulation offering a significant increase in expressivity."//

[[Téléchargement|http://www.lri.fr/~falcou/pub/falcou-ACIVS-2004.pdf]]
!Points-clés
* Programmation générative pour le développement d’outils de parallélisation automatique
* Définitions d'outils de méta-programmation pour la génération automatique de bibliothèques actives (optimisation inter et intra-procédurale automatique).
* Traitement d'image et vision artificielle sur architectures haute-performance de type cluster, multi-processeurs, multi-cœurs, [[Cell|Programmation du processeur Cell]] ou [[GPU|Programmation sur cartes graphiques]].
* Adéquation """Algorithme-Architecture""" : Optimisation de code de traitement d’image et de vision artificielle en utilisant [[AltiVec, SSE|Extension SIMD]] ou du multi-threading.
!Bilan Scientifique
* [[5 revues|Revues]] : 4 d'audience internationale avec comité de lecture, 1 d'audience nationale avec comité de lecture.
* [[13 conférences|Conférences]] : 9 internationales avec comité de lecture, 4 nationales avec comité de lecture.
* [[1 article du vulgarisation|Vulgarisation]]

C+FOX est une bibliothèque C++ qui fournit une interface simple et directe pour acquérir des images depuis des caméras """FireWire""" sur des plateformes """PowerPC""". 
C+FOX et les documents associés sont disponibles sur [[le site Sourceforge de C+FOX|http://cfox.sourceforge.net]]
CAMLG4 est un module pour le langage Objective Caml. Son but est de fournir une interface simple, proche de celle de la classe """BigArray""", afin de manipuler des grands ensembles de données numériques sous forme de tableau. L'originalité de CAMLG4 est l'utilisation de [[l'extension SIMD AltiVec|Extension SIMD]] qui équipe les processeurs des Power PC G4 et G5. Grace à cette extension, le module CAMLG4 permet d'ecrire des opératons arithmétiques et logiques sur des tableaux numériques dont le temps de traitement est de 2 à 8 fois plus rapide tout en conservant une écriture simple.

La version courante est la version 1.00. Elle à été testé sur un Cube G4 équipé d'un processeur cadencé à 450MHz, pourvue de 64Mb de RAM et utilisant un Linux Yellow Dog 2.4.18. La version d'Objective CAML utilisé est la verison 3.06. Le compilateur C est le compilateur """GCC-Altivec""" 2.95.2. CAMLG4 doit néanmoins être compilables avec tous compilateurs C récent et compatible avec la dernière version d'Objective Caml. 

[[Une version téléchargeable est proposée ici|http://www.lri.fr/~falcou/work/camlg4.tar.gz]]. 

Notez que CAMLG4 n'est plus maintenu. Vous pouvez néanmoins l'utiliser et y apporter les modifications que vous désirez en respectant les termes de la license GPL.
Ces entrées reprennent les différents éléments de mon CV. Vous pouvez aussi [[télécharger une version PDF de ce CV|http://www.lri.fr/~falcou/work/falcou_cv.pdf]]
''Auteurs'' : Joel Falcou,Jocelyn Sérot
''Conférence'' : JFLA 2003 - Chamrousse, France - Janvier 2003
''Parution'' : INRIA, Collection Didactique, p. 139-152 

''Résumé'' : //"Ce papier présente [[CAMLG4]], une bibliothèque de calcul parallèle pour Objective Caml destinée aux plateformes PowerPC G4. Cette bibliothèque fournit une interface de haut-niveau aux fonctionnalités offertes par [[l’unité de calcul vectoriel AltiVec|Extension SIMD]] intégrée à cette famille de processeurs. L’utilisation de Camlg4 permet d’obtenir, moyennant un effort modéré de reformulation, des gains en performances significatifs (de 2 à 7 typiquement) pour des applications de calcul numérique intensif. On présente ici les objectifs de [[CAMLG4]], les principaux traits relatifs à son implantation et les premiers résultats obtenus sur un ensemble d’exemples."//

[[Téléchargement|http://www.lri.fr/~falcou/pub/falcou-JFLA-2003.pdf]]
Name: MptwBlue
Background: #fff
Foreground: #000
PrimaryPale: #cdf
PrimaryLight: #57c
PrimaryMid: #114
PrimaryDark: #012
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88

* Génie Logiciel : Design Pattern, programmation parallèle, UML, Extreme Programming.
* Langages : [[C++]], C, intrinsics """Altivec""" et """SSE2""", Java, C#, LISP, Objective Caml
* Systèmes d'exploitation : Windows, unix, linux, Mac OS X
* Divers : [[LaTeX]], SVN, HTML, XML, """JavaScript""", LAMP, Eclipse


!Introduction
L’augmentation des performances des processeurs, longtemps prédite avec succès par la loi de Moore, est depuis quelques années mise à mal par plusieurs facteurs :
* L’augmentation, à un rythme bien plus soutenue, des besoins en puissances de calcul dans de nombreux domaines (physique, finance, traitement du signal et de l'image);
* Les contraintes physiques (échauffement, finesse de la gravure,courant de fuite) qui s'opposent au développement de processeurs plus complexes et plus puissants.
Pour néanmoins répondre aux besoins exprimés par un public de plus en plus large et de plus en plus exigeant, une solution fut d'investir dans le développement d’architecture parallèle comme les //''clusters''//, les processeurs équipés d'extension de calcul ''SIMD'', les processeurs //''multi-core''// voire //''many-core''// ou les cartes d’accélérations graphiques. D'un point de vue puissance, ces architectures ont su répondre avec une grande efficacité aux desiderata des utilisateurs, qu'ils s’agissent de la communauté scientifique – avec le succès des //''clusters''// et, plus récemment, de la Grille – ou du particulier – grâce à la démocratisation grandissante des machines multi-cœurs. Malheureusement, si le problème de la puissance est résolu, les difficultés se sont progressivement déportées au niveau de développement. En effet, si concevoir une application de calcul efficace sur une architecture classique était une tâche réalisable par un spécialiste du domaine, la conception d'une application sur une machine parallèle nécessite des compétences bien spécifiques.

Pendant un temps, des outils de parallélisation explicites (MPI, """OpenMP""" et bien d’autres) ont permis de profiter de la puissance de machines parallèles de petite taille (typiquement, de l'ordre de quatre à six éléments de calculs). Mais, les architectures émergentes, comme le processeur [[Cell|Programmation du processeur Cell]] ou les cartes graphiques, mettent en jeu plusieurs dizaines d'éléments de calcul, chacun disposant d'unités d’accélération intégrées, et contraignent les développeurs à utiliser des outils toujours plus complexes et peu adaptés à un tel changement d'échelle. Une des causes de ces limitations est que la programmation parallèle est encore largement basée sur l’utilisation d’outils bas niveaux alors que de nombreux modèles de haut niveau sont disponibles et permettent de masquer à l’utilisateur final les détails techniques nécessaires au bon déroulement de l’application. De nombreuses bibliothèques ont ainsi été proposées afin de fournir des interfaces simples d’utilisation pour de nombreux modèles de programmation pour des architectures multi-processeurs ou, pour l’écriture de code de calcul scientifique sur des machines équipées d’extension SIMD. La difficulté principale dans la définition et l’implantation de ces bibliothèques et de trouver l’équilibre entre l’expressivité, i.e. la possibilité d’exprimer le parallélisme sous-jacent de l’application sans se soucier des détails d’implantations et l’efficacité, i.e. le fait que les performances de l’exécutable final reste comparable à celle d’un code équivalent développé et optimisé par un expert. Ces deux caractéristiques sont malheureusement souvent inconciliables, rendant l’utilisation de tels outils peu intéressante. Un autre écueil s’ajoute à ces considérations purement techniques. En effet, les utilisateurs qui expriment un besoin en puissance de calcul et fournissent les applications à paralléliser sont rarement des experts en parallélisme ou en programmation. Il est alors nécessaire que les outils fournis soit largement accessibles, c’est à dire qu’ils s’intègrent de manière la plus complète possible aux outils habituels des utilisateurs.

L'objet de mes travaux est donc de définir et implanter des outils de haut niveau qui permettent à la fois d’exprimer aisément l’ensemble des constructions nécessaire pour définir une application parallèle, de garantir des performances équivalentes à celle d’un code écrit à la main tout en s’insérant de manière transparente dans une chaîne de développement classique.
!Un langage spécifique pour un problème spécifique
Une approche efficace pour le développement de bibliothèques présentant à la fois un niveau d’abstraction élevé et des performances satisfaisantes consiste à définir une bibliothèque active. Ce type de bibliothèque met en oeuvre une phase d’optimisation haut niveau dépendant du modèle de programmation, laissant le compilateur effectuer les optimisations bas niveau usuelles (ordonnancement des communications et fusion d’étapes se déroulant sur un même processeur par exemple). Pour réaliser de telles bibliothèques, plusieurs systèmes de méta-définition ont été proposés. Ces systèmes permettent d’injecter au sein de compilateurs des extensions qui permettent de fournir à ce dernier les indications sémantiques nécessaires à une compilation efficace. L’utilisation de ces outils reste néanmoins difficile et il est nécessaire de chercher une alternative intégrable directement au sein d’un langage hôte sans nécessiter d’outils externes.

Cette autre approche consiste à définir un langage orientés domaine (ou Domain Specific Language), fournissant une sémantique adaptée au modèle et une syntaxe concise permettant d’exprimer un large éventail de programme en adéquation avec le problème considéré. En effet, force est de constater que les tentatives de créations de compilateurs parallèlisants génériques capables d'optimiser efficacement un code quelconque pour un large panel d’architectures parallèles différentes restent lettre morte. L’approche préconisée ici repose sur la définition de DSL répondant à un sous problème restreint de la programmation parallèle – utilisation des extensions SIMD, déploiement sur cible MIMD, etc. . Dans un tel contexte, la définition de modèles et de solutions ad hoc permet de répondre de façon pertinente au problème considéré, répondant ainsi à la contrainte d'expressivité exprimée plus avant. Reste à satisfaire les contraintes d’accessibilité et d'efficacité.
!Méta-programmation et Domain Specific Language
Si une technique classique pour permettre l’utilisation de DSL consiste à développer un compilateur ou un interpréteur, des travaux récents montrent qu’il est possible d’inclure ces DSL directement au sein de langages existants. Actuellement, Template Haskell et """MetaOCaml""" proposent d’utiliser une approche basée sur la programmation générative et, plus spécifiquement, sur le mécanisme de méta- programmation afin de permettre le développement de DSL au sein des langages Haskell et """OCaml""".

On peut définir la méta-programmation comme étant l’écriture de programme, plus exactement des méta-programmes, capables au sein d’un système adéquat d’extraire, transformer et générer des fragments de code afin de produire de nouveau codes répondant à un besoin précis. L’exemple le plus simple de méta-programme est le compilateur qui, à partir de fragments de code dans un langage donné, est capable d’extraire des informations et de générer un nouveau code, cette fois en langage machine, qui sera plus tard exécuté par le processeur. De manière plus formelle, on distingue deux types de système de méta-programmation :
* les analyseurs de programmes qui utilisent la structure et l’environnement d’un programme afin de calculer un nouveau fragment de programme. On retrouve dans cette catégorie des outils comme des optimiseurs de code hors-ligne;
* les générateurs de programmes dont l’utilisation première est de résoudre une famille de problèmes connexes dont les solutions sont souvent des variations d’un modèle connu. Dans ce dessein, ces systèmes engendrent un nouveau programme capable de résoudre une instance particulière de ces problèmes et optimisé pour cette résolution. On distingue plus précisément les générateurs statiques qui génèrent un code nécessitant une phase de compilation classique – comme YACC – et les générateurs capables de construire des programmes et de les exécuter à la volée. On parle alors de multi-stage programming.
Si les résultats obtenus dans le cadre de Template Haskell et """MetaOCaml""" sont extrêmement prometteurs, l’utilisation de langage fonctionnel pour développer des applications parallèles complexes et réutilisant une large quantité de code existant reste un gageur dans de nombreux domaines. Je me suis donc tourné vers l'implantation de telles solutions au sein d'un langage plus à même d'être utilisé de manière régulière par des développeurs d'origines diverses et permettant de répondre à la contrainte d'expressivité.
!Le C++ comme système d'évaluation partielle
La solution au problème d'expressivité est résolue par l'utilisation d'un mécanisme d'évaluation partielle, une technique de méta-programmation qui consiste à discerner les parties statiques du programme – c’est-à-dire les parties du code calculable à la compilation – des parties dynamiques – calculables à l’exécution. Le compilateur est alors conduit à évaluer cette partie statique et à générer un code – dit code résiduel – ne contenant plus que les parties dynamiques prêtes à être compilées classiquement. Afin de déterminer les portions de code à évaluer statiquement, un évaluateur partiel doit analyser le code source original pour y détecter des structures et des données statiques. Cette détection permet par la suite de spécialiser les fragments de code. Ceci nécessite un langage à deux niveaux dans lequel il est possible de manipuler de tels marqueurs.

C++ s’avère fournir un tel système de marquage au travers des templates. Leur but principal est de fournir un support pour la programmation dite «générique», favorisant ainsi la réutilisation de code. Un template définit une famille de classes ou de fonctions paramétrées par une liste de valeurs ou de types. Fixer les paramètres d’une classe ou d’une fonction template permet de l’instancier et donc de fournir au compilateur un fragment de code complet et compilable. Une autre fonctionnalité est de permettre la spécialisation partielle d’un template. Le résultat d’une telle spécialisation est alors non pas un fragment de code compilable mais un nouveau template devant lui-même être instancier. Ainsi, il devient possible de fournir des templates dépendant de certaines caractéristiques de ces paramètres et d’optimiser le code ainsi généré en fonction de ces caractéristiques. Lorsque le compilateur tente de résoudre un type template, il commence par chercher la spécialisation la plus complète et remonte la liste des spécialisations partielles jusqu’à trouver un cas valide. Nous retrouvons donc ici, la définition même de l’évaluation partielle : la programmation par spécialisation. On démontre aisément – par construction ou par analogie avec le lambda-calcul – que les templates forment un sous-langage Turing-complet, assurant ainsi l'expressivité nécessaire pour décrire des programmes complexes.

A partir de ces constatations, on montre que les templates C++ supporte une grande partie des fonctionnalités des langages fonctionnels à même de fournir les bases d'un évaluateur partiel de DSL. Ainsi, on retrouve l'équivalent template du Pattern Matching, de la spécification de structures de données abstraites ainsi qu'un support limité de l'inspection de code. Des outils comme les bibliothèques LOKI ou BOOST::MPL fournissent d’ailleurs des implantations standard de ces constructions, mettant à disposition de véritables boîtes à outils de méta-programmes.
[[Accueil]]
[[Quelques News]]
''Auteurs'' :  Joel Falcou, Jocelyn Sérot,
''Journal'' : Scalable Computing: Practice and Experience Volume 6, Issues 4, Décembre 2005, Pages 31-41. 

''Résumé'' :
//"This paper describes the E.V.E. (Expressive Velocity Engine) library, an object oriented C++ library designed to ease the process of writting efficient numerical applications using """AltiVec""", the SIMD extension designed by Apple, Motorola and IBM. AltiVec-powered applications typically show off a relative speed up of 4 to 16 but need a complex and awkward programmation style. By using various template metaprogramming techniques, E.V.E. provides an easy to use, """STL-like""", interface that allows developer to quickly write efficient and easy to read code. Typical applications written with E.V.E. can benefit from a large fraction of theorical maximum speed up while being written as simple C++ arithmetic code."//

[[Téléchargement depuis le site de l'éditeur|http://www.scpe.org/vols/vol06/no4/SCPE_6_4_03.pdf]]
''Auteurs'' : Joël FALCOU, Jocelyn SEROT
''Conférence'' : ICCS 2004 - Cracovie, Pologne - Juin 2004
''Parution'' : In M. Bubak, D. van Albada, P. Sloot, and J. Dongarra, editors ICCS 2004, Part III, LNCS, pages 323-330. Springer Verlag, 2004. 

''Résumé'' : //"This paper describes eve (Expressive Velocity Engine), an object oriented C++ library designed to ease the process of writing efficient numerical applications using AltiVec, the SIMD extension designed by Apple, Motorola and IBM for PowerPC processors. Compared to the Altivec original C API, eve, offers a significant improvement in terms of expressivity. By relying on template metaprogramming techniques, this is not obtained at the expense of efficiency."//

[[Téléchargement depuis le site de l'éditeur|http://www.springerlink.com/content/pk3k2nny7000bf8l/]]
TEST
La plupart des constructions fournis par le langage C++ mettent en œuvre des éléments dits statiques -- c'est à dire entièrement connus lors de la compilation -- et des éléments dits dynamiques dont la valeur ne peut être connue que lors de l'exécution proprement dites. Or, dans le cas général, aucune optimisation spécifique n'est menée pour pré-calculer ces éléments statiques. Le mécanisme dit ''d'évaluation partielle'' permet ainsi, en discernant les parties statiques du programme des parties dynamiques, de forcer le compilateur à évaluer cette partie statique et à générer un code ne contenant plus que des parties dynamiques.
!Principes
Afin de déterminer les portions de code à évaluer statiquement, un évaluateur partiel doit analyser le code source original et étiqueter les structures et les données. Cet étiquetage permet par la suite de spécialiser les fragments de code. Ceci nécessite un langage à deux niveaux dans lequel il est possible de manipuler de tels marqueurs. Un tel langage est accessible au sein du C++ via l'utilisation du mécanisme des //templates//. En effet, les //templates// C++ se comportent comme un tel langage à deux niveaux. Les fonctions et classes //templates// utilisent à la fois des arguments statiques -- les paramètres //templates// -- et dynamiques -- les paramètres de la fonction en elle-même. Prenons par exemple le prototype d'une fonction //template// destinée à sommer les éléments d'un tableau numérique :
{{{
 template<int N,typename T> T sum( T* array );
}}}
Dans ce listing, {{{N}}} et {{{T}}} sont des données statiques qui apparaissent comme des paramètres //templates// alors que array est une donnée dynamique qui apparaît comme un argument de fonction classique. La compilation d'une instance de {{{sum(T*)}}} nécessite d'évaluer ses paramètres statiques avant de pouvoir effectuer l'évaluation de ses paramètres dynamiques. Ce point de vue nous permet alors de considérer les types C++ comme étant des données à part entière au sein d'un langage spécifique capable de les manipuler. 

On peut alors se demander si ce deuxième niveau de langage fourni par les //templates// est suffisamment expressif. On démontre par construction que les //templates// forment un langage Turing-complet, c'est à dire qu'ils permettent de représenter toutes les fonctions calculables au sens de Turing. Cette propriété permet de montrer que, moyennant une réécriture potentiellement non-triviale, tout programme peut être exprimable sous la forme d'un programme utilisant des //templates//. Un des premiers exemples de tels programmes fut présenté par Erwin Unruh. Ce programme ne s'exécutait pas mais renvoyait une série de messages à la compilation qui énumérait la liste des N premiers nombres premiers. Il démontrait ainsi que les //templates// permettaient d'exprimer plus que la simple généricité des classes et des fonctions.

Plusieurs techniques de base ont donc été mises au point pour développer une large variété de programmes statiques -- ou méta-programmes -- à même de faciliter la manipulation de ce "langage dans le langage" que constituent les //templates//. D'une manière générale, ces techniques de méta-programmation consistent à utiliser l'instanciation des //templates// C++ pour "exécuter" un programme à la compilation. Cette "exécution" passe par l'évaluation, la mise en correspondance de valeurs constantes ou de types. Une fois l'évaluation de ces méta-programmes effectué, le compilateur génère un code C++ sans aucun //template// et prêt à être compilé normalement. Ce mécanisme se comporte alors comme un évaluateur partiel car on y retrouve les grandes étapes de marquage des données statiques -- via la spécification d'argument de type -- et de génération de code.
!Exemple
Un exemple d'une telle évaluation partielle est donnée dans le listing ci-dessous. La fonction {{{volumeOfCube}}} effectue le calcul du volume d'un cube d'arête {{{length}}} en utilisant une fonction {{{pow(x,N)}}} qui calcule {{{x}}} à la puissance {{{N}}}. Dans ce listing, les parties statiques ont été soulignées et on voit nettement que l'utilisation de {{{pow}}} n'est pas la solution optimale. En effet, le temps de traitement de la boucle for représente la large partie du temps de calcul pour de petite valeurs de {{{N}}}.
{{{
float volumeOfCube(float l) { return pow(l,3);}

float pow(float x, int N)
{
  float y = 1;
  for(int i=0; i < N; i++) y *= x;
  return y;
}
}}}
Grâce aux //templates//, on peut définir un ensemble de méta-programmes qui explicite cette nature.
{{{
template<size_t I,size_t N> struct pow_      { inline float operator()( float x ) const { return x*meta<I++,N>::Pow(x); } };
template<size_t N>          struct pow_<N,N> { inline float operator()( float x ) const { return 1; } };

template<size_t N> float pow(float x)
{
  pow_<0,N> meta;
  return meta(x);
}

float volumeOfCube(float l) { return pow<3>(l); }
}}}
Dans cette version, plusieurs éléments spécifiques à la manipulation des //templates// sont utilisés :
* La fonction {{{pow}}} utilise explicitement un paramètre statique -- le paramètre //template// {{{N}}} -- en lieu et place de son paramètre dynamique.
* Une méta-fonction remplace la boucle for principale. Cette structure utilise une forme récursive et une spécialisation partielle afin d'effectuer l'ensemble des calculs nécessaires.
Lors de l'appel de {{{volumeOfCube}}}, le compilateur va évaluer les divers appels //templates// et générer un code en lieu et place de l'appel à {{{pow<3>}}}. Le code final est alors le suivant :
{{{
float volumeOfCube(float l) { return l*l*l*1; } 
}}}
Le point important à noter est que l'ensemble de ces calculs et génération de code sont effectués au moment de la compilation. Aucun appel de fonction n'est généré et les performances de cette version statique de {{{volumeOfCube}}} sont supérieures à la version entièrement dynamique.
!Mise en œuvre
De nombreuses techniques se basent sur cette approche pour fournir des méta-fonctions permettant de construire des programmes statiques complexes. On remarque plsu particulièrement :
* Les Traits, définis par Natha Myers qui sont des méta-fonctions permettant de construire des tables de correspondances entre deux ensembles de types, imitant ainsi la construction match de langages comme ML.
* Les [[Expression Templates]], proposés par Todd Veldhuizen qui permettent de générer un type représentant une structure arborescente construite à partir d'une expression mettant en œuvre des opérateurs surchargés. E.V.E. utilise de mnaière intensive cette technique pour son générateur de code.
* L'utilisation de structures templates permet de reproduire la définition de type de données abstraits dans lesquels les valeurs sont représentées par des types.
* L'utilisation de structures acceptant des paramètres //templates templates// permet de simuler la construction de fonctions statiques d'ordre supérieure.
Ces techniques ont permis de définir des méta-bibliothèques.
* La bibliothèque MPL propose ainsi un grand nombre de méta-fonctions permettant d'écrire des méta-programmes à l'aide d'une version statique de la STL. Ainsi, il est possible de travailler très simplement et très efficacement sur des listes ou des tableaux statiques de types ou de constantes entières.
* La bibliothèque Loki propose quant à elle d'utiliser ces techniques de méta-programmation //template// (entre autre) afin de fournir des implantations génériques de Design Pattern classique.
!Références
# Neil D. Jones. An introduction to partial evaluation. ACM Computing Survey, 28(3):480–503, 1996.
# E. Unruh. Prime number computation. Technical Report ANSI """X3J16-94-0075"""/ISO """WG21-462""", C++ Standard Commitee, 1994.
# Nathan Myers. A new and useful template technique: Traits. C++ gems, 1:451–457, 1996.
# Todd L. Veldhuizen. Expression templates. C++ Report, 7(5):26–31, 1995
!Motivation
De nombreux problèmes de //design// en [[C++]] finissent par ce poser la question de comment retarder l'évaluation d'une expression afin d'y effectuer des optimisations ou de transmettre sous forme d'arguments un fragment de code. Un exemple simple est par exemple l'écriture d'une fonction d'intégration numérique. La solution classique consiste à écrire une fonction utilisant des pointeurs de fonctions ou des foncteurs. Une utilisation assez simple des //templates// permet alors d'écrire un tel code :
{{{
template<class T,class Func> T integrate( Func f, T const& inf, T const& sup )
{
  double r=0;
  static const T dx = 0.001;
  for(T i=inf;i<sup;i+=dx;)  r += dx*f(i);
  return r;
}

double f(double x) { return 1./tan(x); }

int main()
{
  cout << integrate( &f, 0.1, 0.6 ) << endl;
}
}}}
Simple et efficace, ce code génère un exécutable dont les performances oscillent entre peu engageantes et catastrophiques. En outre, il est assez peu pratique de devoir écrire des fonctions ou des foncteurs spécialement pour l'appel de cette fonction. Si nous le pouvions, nous aimerions utiliser une &#955;-fonction. Or, pour l'instant, point de &#955;-fonction en C++ . De manière grossière, on désirerais écrire quelque chose comme :
{{{
cout << integrate( 1/tan(x_), 1. ,10. ) << endl;
}}}
Dans ce fragment de code, {{{x_}}} représente une variable anonyme dont l'utilisation au sein d'une expression construit une expression manipulable comme un type à part entière.
!Principes
!Mise en œuvre
!Autres applications
!Références
* Todd L. Veldhuizen. [[Expression templates|http://ubiety.uwaterloo.ca/~tveldhui/papers/Expression-Templates/exprtmpl.html]] C++ Report, 7(5):26–31, 1995 
* [[The Boost::Proto Library|http://www.boost.org/doc/libs/1_38_0/doc/html/proto.html]]
/***
|Name:|ExtentTagButtonPlugin|
|Description:|Adds a New tiddler button in the tag drop down|
|Version:|3.2 ($Rev: 3861 $)|
|Date:|$Date: 2008-03-08 10:53:09 +1000 (Sat, 08 Mar 2008) $|
|Source:|http://mptw.tiddlyspot.com/#ExtendTagButtonPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License|http://mptw.tiddlyspot.com/#TheBSDLicense|
***/
//{{{

window.onClickTag_mptw_orig = window.onClickTag;
window.onClickTag = function(e) {
	window.onClickTag_mptw_orig.apply(this,arguments);
	var tag = this.getAttribute("tag");
	var title = this.getAttribute("tiddler");
	// Thanks Saq, you're a genius :)
	var popup = Popup.stack[Popup.stack.length-1].popup;
	createTiddlyElement(createTiddlyElement(popup,"li",null,"listBreak"),"div");
	wikify("<<newTiddler label:'New tiddler' tag:'"+tag+"'>>",createTiddlyElement(popup,"li"));
	return false;
}

//}}}


''Auteurs'' : Joel Falcou, Jocelyn Sérot
''Conférence'' : ParCo 2007 - Aachen, Allemagne, Septembre 2007
''Parution'' : Proceedings of the International Conference ParCo

''Résumé'' : //"This paper introduces an efficient implementation for a programming model based on algorithmic skeletons, i.e higher order functions encapsulating recurring parallelism pattern. This implementation relies on meta-programming techniques to get rid of the classic overhead observed with this model. Those techniques, based on the meta-implementation of a formal model and operationnal semantic, provides a way to make parallel programming
able to take advantage of both abstraction and performances. "//

[[Téléchargement|http://www.lri.fr/~falcou/pub/falcou-PARCO-2007.pdf]] 
!Thése de doctorat (2003-2007)
''Titre'' : Un Cluster pour la Vision Temps Réel : Architecture, Outils et Applications
Soutenue publiquement le ''1er décembre 2006'' à ''l'Université Blaise Pascal (Clermont II)''
''Directeur de thèse'' : [[Jocelyn Sérot|http://wwwlasmea.univ-bpclermont.fr/Personnel/Jocelyn.Serot/Bienvenue.html]]
''École doctorale'' : Sciences Pour l'Ingénieur (SPI) """de Clermont-Ferrand"""
''Mention'' : Très Honorable

''Composition du jury'' :
* [[Jean Thierry Lapresté|http://wwwlasmea.univ-bpclermont.fr/Personnel/Jean-Thierry.Lapreste/]] (Président du jury - Professeur à l'Université Blaise Pascal)
* [[Jocelyn Sérot|http://wwwlasmea.univ-bpclermont.fr/Personnel/Jocelyn.Serot/Bienvenue.html]] (Directeur de Thèse - Professeur à l'Université Blaise Pascal)
* [[Daniel Etiemble|http://www.lri.fr/~de/]] (Rapporteur - Professeur à l'Université Paris Sud)
* [[Frédéric Loulergue|http://f.loulergue.free.fr/]] (Rapporteur - Professeur à l'Université d'Orléans)
* [[Franck Cappello|http://www.lri.fr/~fci/Site%204/Fiche%20personnelle.html]] (Examinateur - Directeur de Recherche """INRIAFuturs""")
* [[Thierry Chateau|http://wwwlasmea.univ-bpclermont.fr/Personnel/Thierry.Chateau/index.html]] (Examinateur - Maître de conférence à l'Université Blaise Pascal)
''Documents'':
[[Résumé|http://www.lri.fr/~falcou/work/falcou_thesis_resume_06.pdf]]
[[Manuscript de thèse|http://www.lri.fr/~falcou/work/falcou_thesis_06.pdf]]
[[Soutenance de thèse|http://www.lri.fr/~falcou/work/falcou_thesis_slides_06.pdf]]

!Diplôme d'Etudes Approfondies (2003)
''Section'' : Composants et Systèmes pour le Traitement de l'Information
''Spécialité'' : Vision pour la Robotique
''Mention'' : Bien
''Laboratoire'' : [[LASMEA|http://wwwlasmea.univ-bpclermont.fr/]], Université Blaise Pascal
''Responsable de stage'' : [[Jocelyn Sérot|http://wwwlasmea.univ-bpclermont.fr/Personnel/Jocelyn.Serot/Bienvenue.html]]
''Titre du mémoire'' : //"Développement d'une bibliothèque de calcul SIMD - Application au traitement d'image"//
!Diplôme d'ingénieur en Informatique de l'ISIMA - """Clermont-Ferrand""" (2000-2003)
''Spécialité'' : Génie Logiciel, Systèmes et Réseaux.
Stage de troisième année commun au [[DEA|Formation Doctorale]]
!Classe préparatoire aux grandes écoles (1998-2000)
Lycée Pierre de Fermat (Toulouse, Haute-Garonne) - Section PCSI et PSI*.
!Baccalauréat série S Mathématique (1998)
''Mention'' : Bien 
Lycée Pré de Cordy (Sarlat, Dordogne)
''Auteurs'' : Jocelyn SEROT, Joel FALCOU
''Conférence'' : ICCS 2008 - Cracovie, Pologne, Juin 2008
''Parution'' : Proceedings of ICCS 208, p. 154-163 

''Résumé''://"We describe the implementation in MetaOcaml of a small domain specific language for skeleton-based parallel programming. We show how the meta-programming facilities offered by this language make it possible to virtually eliminate the run-time overhead for the resulting programs, compared to a hand-crafted, low-level implementation."//

[[Téléchargement depuis le site de l'éditeur|http://www.springerlink.com/content/w30k773765l17561/]]
/***
|Name:|HideWhenPlugin|
|Description:|Allows conditional inclusion/exclusion in templates|
|Version:|3.1 ($Rev: 3919 $)|
|Date:|$Date: 2008-03-13 02:03:12 +1000 (Thu, 13 Mar 2008) $|
|Source:|http://mptw.tiddlyspot.com/#HideWhenPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
For use in ViewTemplate and EditTemplate. Example usage:
{{{<div macro="showWhenTagged Task">[[TaskToolbar]]</div>}}}
{{{<div macro="showWhen tiddler.modifier == 'BartSimpson'"><img src="bart.gif"/></div>}}}
***/
//{{{

window.hideWhenLastTest = false;

window.removeElementWhen = function(test,place) {
	window.hideWhenLastTest = test;
	if (test) {
		removeChildren(place);
		place.parentNode.removeChild(place);
	}
};


merge(config.macros,{

	hideWhen: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		removeElementWhen( eval(paramString), place);
	}},

	showWhen: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		removeElementWhen( !eval(paramString), place);
	}},

	hideWhenTagged: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
		removeElementWhen( tiddler.tags.containsAll(params), place);
	}},

	showWhenTagged: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
		removeElementWhen( !tiddler.tags.containsAll(params), place);
	}},

	hideWhenTaggedAny: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
		removeElementWhen( tiddler.tags.containsAny(params), place);
	}},

	showWhenTaggedAny: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
		removeElementWhen( !tiddler.tags.containsAny(params), place);
	}},

	hideWhenTaggedAll: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
		removeElementWhen( tiddler.tags.containsAll(params), place);
	}},

	showWhenTaggedAll: { handler: function (place,macroName,params,wikifier,paramString,tiddler) {
		removeElementWhen( !tiddler.tags.containsAll(params), place);
	}},

	hideWhenExists: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		removeElementWhen( store.tiddlerExists(params[0]) || store.isShadowTiddler(params[0]), place);
	}},

	showWhenExists: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		removeElementWhen( !(store.tiddlerExists(params[0]) || store.isShadowTiddler(params[0])), place);
	}},

	hideWhenTitleIs: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		removeElementWhen( tiddler.title == params[0], place);
	}},

	showWhenTitleIs: { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		removeElementWhen( tiddler.title != params[0], place);
	}},

	'else': { handler: function(place,macroName,params,wikifier,paramString,tiddler) {
		removeElementWhen( !window.hideWhenLastTest, place);
	}}

});

//}}}

''Auteurs'' : Joel Falcou
''Conférence'' : BOOST'CON 2009

''Résumé'' :
//"Parallel programming is becoming a concern for a growing audience of developers. Various programming models and tools have been proposed but never became largely accepted in the community. This paper shows how a Embedded Domain Specific Language has been defined using Boost libraries like MPL and Proto and how it solves various typical problem of high-level parallel programming tools like reusing legacy code or preserving developer habits. This EDSL - Quaff - is able to map data-flow applications over clusters, multi-cores and CELL processor using algorithmic skeletons. Realistic application is presented and assess Quaff expressiveness and efficiency."//

[[Télécharger l'article|http://www.lri.fr/~falcou/pub/falcou-boost-con09.pdf]]
/***
|Name:|InstantTimestampPlugin|
|Description:|A handy way to insert timestamps in your tiddler content|
|Version:|1.0.10 ($Rev: 3646 $)|
|Date:|$Date: 2008-02-27 02:34:38 +1000 (Wed, 27 Feb 2008) $|
|Source:|http://mptw.tiddlyspot.com/#InstantTimestampPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
!!Usage
If you enter {ts} in your tiddler content (without the spaces) it will be replaced with a timestamp when you save the tiddler. Full list of formats:
* {ts} or {t} -> timestamp
* {ds} or {d} -> datestamp
* !ts or !t at start of line -> !!timestamp
* !ds or !d at start of line -> !!datestamp
(I added the extra ! since that's how I like it. Remove it from translations below if required)
!!Notes
* Change the timeFormat and dateFormat below to suit your preference.
* See also http://mptw2.tiddlyspot.com/#AutoCorrectPlugin
* You could invent other translations and add them to the translations array below.
***/
//{{{

config.InstantTimestamp = {

	// adjust to suit
	timeFormat: 'DD/0MM/YY 0hh:0mm',
	dateFormat: 'DD/0MM/YY',

	translations: [
		[/^!ts?$/img,  "'!!{{ts{'+now.formatString(config.InstantTimestamp.timeFormat)+'}}}'"],
		[/^!ds?$/img,  "'!!{{ds{'+now.formatString(config.InstantTimestamp.dateFormat)+'}}}'"],

		// thanks Adapted Cat
		[/\{ts?\}(?!\}\})/ig,"'{{ts{'+now.formatString(config.InstantTimestamp.timeFormat)+'}}}'"],
		[/\{ds?\}(?!\}\})/ig,"'{{ds{'+now.formatString(config.InstantTimestamp.dateFormat)+'}}}'"]
		
	],

	excludeTags: [
		"noAutoCorrect",
		"noTimestamp",
		"html",
		"CSS",
		"css",
		"systemConfig",
		"systemConfigDisabled",
		"zsystemConfig",
		"Plugins",
		"Plugin",
		"plugins",
		"plugin",
		"javascript",
		"code",
		"systemTheme",
		"systemPalette"
	],

	excludeTiddlers: [
		"StyleSheet",
		"StyleSheetLayout",
		"StyleSheetColors",
		"StyleSheetPrint"
		// more?
	]

}; 

TiddlyWiki.prototype.saveTiddler_mptw_instanttimestamp = TiddlyWiki.prototype.saveTiddler;
TiddlyWiki.prototype.saveTiddler = function(title,newTitle,newBody,modifier,modified,tags,fields,clearChangeCount,created) {

	tags = tags ? tags : []; // just in case tags is null
	tags = (typeof(tags) == "string") ? tags.readBracketedList() : tags;
	var conf = config.InstantTimestamp;

	if ( !tags.containsAny(conf.excludeTags) && !conf.excludeTiddlers.contains(newTitle) ) {

		var now = new Date();
		var trans = conf.translations;
		for (var i=0;i<trans.length;i++) {
			newBody = newBody.replace(trans[i][0], eval(trans[i][1]));
		}
	}

	// TODO: use apply() instead of naming all args?
	return this.saveTiddler_mptw_instanttimestamp(title,newTitle,newBody,modifier,modified,tags,fields,clearChangeCount,created);
}

// you can override these in StyleSheet 
setStylesheet(".ts,.ds { font-style:italic; }","instantTimestampStyles");

//}}}


/***
|Name:|LessBackupsPlugin|
|Description:|Intelligently limit the number of backup files you create|
|Version:|3.0.1 ($Rev: 2320 $)|
|Date:|$Date: 2007-06-18 22:37:46 +1000 (Mon, 18 Jun 2007) $|
|Source:|http://mptw.tiddlyspot.com/#LessBackupsPlugin|
|Author:|Simon Baird|
|Email:|simon.baird@gmail.com|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
!!Description
You end up with just backup one per year, per month, per weekday, per hour, minute, and second.  So total number won't exceed about 200 or so. Can be reduced by commenting out the seconds/minutes/hours line from modes array
!!Notes
Works in IE and Firefox only.  Algorithm by Daniel Baird. IE specific code by by Saq Imtiaz.
***/
//{{{

var MINS  = 60 * 1000;
var HOURS = 60 * MINS;
var DAYS  = 24 * HOURS;

if (!config.lessBackups) {
	config.lessBackups = {
		// comment out the ones you don't want or set config.lessBackups.modes in your 'tweaks' plugin
		modes: [
			["YYYY",  365*DAYS], // one per year for ever
			["MMM",   31*DAYS],  // one per month
			["ddd",   7*DAYS],   // one per weekday
			//["d0DD",  1*DAYS],   // one per day of month
			["h0hh",  24*HOURS], // one per hour
			["m0mm",  1*HOURS],  // one per minute
			["s0ss",  1*MINS],   // one per second
			["latest",0]         // always keep last version. (leave this).
		]
	};
}

window.getSpecialBackupPath = function(backupPath) {

	var now = new Date();

	var modes = config.lessBackups.modes;

	for (var i=0;i<modes.length;i++) {

		// the filename we will try
		var specialBackupPath = backupPath.replace(/(\.)([0-9]+\.[0-9]+)(\.html)$/,
				'$1'+now.formatString(modes[i][0]).toLowerCase()+'$3')

		// open the file
		try {
			if (config.browser.isIE) {
				var fsobject = new ActiveXObject("Scripting.FileSystemObject")
				var fileExists  = fsobject.FileExists(specialBackupPath);
				if (fileExists) {
					var fileObject = fsobject.GetFile(specialBackupPath);
					var modDate = new Date(fileObject.DateLastModified).valueOf();
				}
			}
			else {
				netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
				var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
				file.initWithPath(specialBackupPath);
				var fileExists = file.exists();
				if (fileExists) {
					var modDate = file.lastModifiedTime;
				}
			}
		}
		catch(e) {
			// give up
			return backupPath;
		}

		// expiry is used to tell if it's an 'old' one. Eg, if the month is June and there is a
		// June file on disk that's more than an month old then it must be stale so overwrite
		// note that "latest" should be always written because the expiration period is zero (see above)
		var expiry = new Date(modDate + modes[i][1]);
		if (!fileExists || now > expiry)
			return specialBackupPath;
	}
}

// hijack the core function
window.getBackupPath_mptw_orig = window.getBackupPath;
window.getBackupPath = function(localPath) {
	return getSpecialBackupPath(getBackupPath_mptw_orig(localPath));
}

//}}}

!Description
''Site du projet'' : http://love.univ-bpclermont.fr/
''Collaborateurs'' : ''Université BLAISE PASCAL CLERMONT FERRAND 2'', ARMINES FONTAINEBLEAU, ARMINES PARIS, CEA SACLAY, GIE REGIENOV , INRETS VERSAILLES, INRIA GRENOBLE, INRIA ROCQUENCOURT, INRIA SOPHIA-ANTIPOLIS, Université DE TECHNOLOGIE DE COMPIEGNE, Université PARIS SUD 11, VALEO BOBIGNY
''Objectifs'' : Contribuer à la sécurité routière en mettant principalement l’accent sur la sécurité des piétons. L’objectif est d’aboutir à des logiciels d’observation des vulnérables fiables et sûrs implantés sur des matériels compatibles avec une exploitation industrielle rapide. A dessein, plusieurs solutions algorithmiques de perception sont mises en œuvre dans un double objectif : celui de la concurrence afin d’identifier les solutions à même de répondre au mieux aux exigences et celui de la complémentarité afin d’aboutir à des systèmes combinés lorsque les contraintes l’exigent.
!Participation
Une grande partie des modules de calcul de LoVE développés par le LASMEA ont été écrit en utilisant [[NT²]].
/***
|''Name:''|LoadRemoteFileThroughProxy (previous LoadRemoteFileHijack)|
|''Description:''|When the TiddlyWiki file is located on the web (view over http) the content of [[SiteProxy]] tiddler is added in front of the file url. If [[SiteProxy]] does not exist "/proxy/" is added. |
|''Version:''|1.1.0|
|''Date:''|mar 17, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#LoadRemoteFileHijack|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0|
***/
//{{{
version.extensions.LoadRemoteFileThroughProxy = {
 major: 1, minor: 1, revision: 0, 
 date: new Date("mar 17, 2007"), 
 source: "http://tiddlywiki.bidix.info/#LoadRemoteFileThroughProxy"};

if (!window.bidix) window.bidix = {}; // bidix namespace
if (!bidix.core) bidix.core = {};

bidix.core.loadRemoteFile = loadRemoteFile;
loadRemoteFile = function(url,callback,params)
{
 if ((document.location.toString().substr(0,4) == "http") && (url.substr(0,4) == "http")){ 
 url = store.getTiddlerText("SiteProxy", "/proxy/") + url;
 }
 return bidix.core.loadRemoteFile(url,callback,params);
}
//}}}

La bibliothèque Boost::MPL fournit un ensemble de fonctions et de structures de données méta-programmées en C++. Parmi ces fonctionnalités, une large place est laissée à l'émulation d'un langage fonctionnel résolu à la compilation. Ainsi du code comme :
{{{
template<class X,class N> 
struct fact : if_< equal_to<int_<0>,N>
                 , int_<1>
                 , times<X, fact<X, minus<N,int_<1> > >
                 > {};
}}}
réalise le même calcul que le code """OCaml""" suivant
{{{
let rec fact x n = match n with
                   | 0 -> 1
                   | n -> x * fact x (n-1);;
}}}
Néanmoins, pour du code complexe, l'intention est perdue sous la couche syntaxique plutôt lourde des templates C++. En outre, certains code MPL peuvent conduire à des erreurs de compilations assez inextricables. On aimerait donc pouvoir débugger ses méta-fonctions en """OCaml""" puis les porter en C++.
!Travail demandé
Le travail a réalisé consiste à réaliser un outil de //parsing// permettant à partir de code source écrit dans un (sous) ensemble de """OCaml""", de générer le code C++ équivalent utilisant MPL. Ce //parser// sera écris en """OCaml""" pour les plus courageux ou en C++ grâce à la bibliothèque Boost::Spirit.
!Durée estimée
4 à 6 mois
!Pré-requis
* Bon niveau en C++
* Notion de base sur le parsing
* Un premier contact avec """OCaml""" est souhaitable mais pas nécessaire
MPTW is a distribution or edition of TiddlyWiki that includes a standard TiddlyWiki core packaged with some plugins designed to improve usability and provide a better way to organise your information. For more information see http://mptw.tiddlyspot.com/.
[[Accueil]]
<<tag CV>>
<<tag Recherche>>
<<tag Enseignement>>
<<tag C++>>
<<tag Parallelisme>>
<<tag Logiciels>>
[[A Propos]]
''Auteurs'' : Joel Falcou, Jocelyn Sérot, Lucien Pech, Jean-Thierry Lapresté
''Conférence'' : EuroPar 2008 - las Palmas,Gran Canaria, Aout 2008
''Parution'' : Proceedings of EuroPar 208, p. 729-738 

''Résumé''://"We describe a software solution to the problem of automatic parallelization of linear algebra code on multi-processor and multi-core architectures. This solution relies on the definition of a domain specific language for matrix computations, a performance model for multi-processor architectures and its implementation using C++ template meta-programming. Experimental results asses this model and its implementation on sample computation kernels."//

[[Téléchargement depuis le site de l'éditeur|http://www.springerlink.com/content/l4r4462r25740127/]]
Name: MptwBlack
Background: #000
Foreground: #fff
PrimaryPale: #333
PrimaryLight: #555
PrimaryMid: #888
PrimaryDark: #aaa
SecondaryPale: #111
SecondaryLight: #222
SecondaryMid: #555
SecondaryDark: #888
TertiaryPale: #222
TertiaryLight: #666
TertiaryMid: #888
TertiaryDark: #aaa
Error: #300

This is in progress. Help appreciated.


Name: MptwBlue
Background: #fff
Foreground: #000
PrimaryPale: #cdf
PrimaryLight: #57c
PrimaryMid: #114
PrimaryDark: #012
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88

/***
|Name:|MptwConfigPlugin|
|Description:|Miscellaneous tweaks used by MPTW|
|Version:|1.0 ($Rev: 3646 $)|
|Date:|$Date: 2008-02-27 02:34:38 +1000 (Wed, 27 Feb 2008) $|
|Source:|http://mptw.tiddlyspot.com/#MptwConfigPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#MptwConfigPlugin|
!!Note: instead of editing this you should put overrides in MptwUserConfigPlugin
***/
//{{{
var originalReadOnly = readOnly;
var originalShowBackstage = showBackstage;

config.options.chkHttpReadOnly = true; 		// means web visitors can experiment with your site by clicking edit
readOnly = true;								// needed because the above doesn't work any more post 2.1 (??)
showBackstage = true;							// show backstage for same reason

config.options.chkInsertTabs = true;    		// tab inserts a tab when editing a tiddler
config.views.wikified.defaultText = "";			// don't need message when a tiddler doesn't exist
config.views.editor.defaultText = "";			// don't need message when creating a new tiddler 

config.options.chkSaveBackups = true;			// do save backups
config.options.txtBackupFolder = 'twbackup';	// put backups in a backups folder

config.options.chkAutoSave = (window.location.protocol == "file:"); // do autosave if we're in local file

config.mptwVersion = "2.5.2";

config.macros.mptwVersion={handler:function(place){wikify(config.mptwVersion,place);}};

if (config.options.txtTheme == '')
	config.options.txtTheme = 'MptwTheme';

// add to default GettingStarted
config.shadowTiddlers.GettingStarted += "\n\nSee also [[MPTW]].";

// add select theme and palette controls in default OptionsPanel
config.shadowTiddlers.OptionsPanel = config.shadowTiddlers.OptionsPanel.replace(/(\n\-\-\-\-\nAlso see AdvancedOptions)/, "{{select{<<selectTheme>>\n<<selectPalette>>}}}$1");

// these are used by ViewTemplate
config.mptwDateFormat = 'DD/MM/YY';
config.mptwJournalFormat = 'Journal DD/MM/YY';

//}}}
|Name|MptwRounded|
|Description|Mptw Theme with some rounded corners (Firefox only)|
|ViewTemplate|MptwTheme##ViewTemplate|
|EditTemplate|MptwTheme##EditTemplate|
|PageTemplate|MptwTheme##PageTemplate|
|StyleSheet|##StyleSheet|

!StyleSheet
/*{{{*/

[[MptwTheme##StyleSheet]]

.tiddler,
.sliderPanel,
.button,
.tiddlyLink,
.tabContents
{ -moz-border-radius: 1em; }

.tab {
	-moz-border-radius-topleft: 0.5em;
	-moz-border-radius-topright: 0.5em;
}
#topMenu {
	-moz-border-radius-bottomleft: 2em;
	-moz-border-radius-bottomright: 2em;
}

/*}}}*/

Name: MptwSmoke
Background: #fff
Foreground: #000
PrimaryPale: #aaa
PrimaryLight: #777
PrimaryMid: #111
PrimaryDark: #000
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88

|Name|MptwStandard|
|Description|Mptw Theme with the default TiddlyWiki PageLayout and Styles|
|ViewTemplate|MptwTheme##ViewTemplate|
|EditTemplate|MptwTheme##EditTemplate|
Name: MptwTeal
Background: #fff
Foreground: #000
PrimaryPale: #B5D1DF
PrimaryLight: #618FA9
PrimaryMid: #1a3844
PrimaryDark: #000
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #f8f8f8
TertiaryLight: #bbb
TertiaryMid: #999
TertiaryDark: #888
Error: #f88
|Name|MptwTheme|
|Description|Mptw Theme including custom PageLayout|
|PageTemplate|##PageTemplate|
|ViewTemplate|##ViewTemplate|
|EditTemplate|##EditTemplate|
|StyleSheet|##StyleSheet|

http://mptw.tiddlyspot.com/#MptwTheme ($Rev: 1829 $)

!PageTemplate
<!--{{{-->
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
	<div class='headerShadow'>
		<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
		<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
	</div>
	<div class='headerForeground'>
		<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
		<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
	</div>
</div>
<!-- horizontal MainMenu -->
<div id='topMenu' refresh='content' tiddler='MainMenu'></div>
<!-- original MainMenu menu -->
<!-- <div id='mainMenu' refresh='content' tiddler='MainMenu'></div> -->
<div id='sidebar'>
	<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
	<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea'>
	<div id='messageArea'></div>
	<div id='tiddlerDisplay'></div>
</div>
<!--}}}-->

!ViewTemplate
<!--{{{-->
[[MptwTheme##ViewTemplateToolbar]]

<div class="tagglyTagged" macro="tags"></div>

<div class='titleContainer'>
	<span class='title' macro='view title'></span>
	<span macro="miniTag"></span>
</div>

<div class='subtitle'>
	(updated <span macro='view modified date {{config.mptwDateFormat?config.mptwDateFormat:"MM/0DD/YY"}}'></span>
	by <span macro='view modifier link'></span>)
	<!--
	(<span macro='message views.wikified.createdPrompt'></span>
	<span macro='view created date {{config.mptwDateFormat?config.mptwDateFormat:"MM/0DD/YY"}}'></span>)
	-->
</div>

<div macro="showWhen tiddler.tags.containsAny(['css','html','pre','systemConfig']) && !tiddler.text.match('{{'+'{')">
	<div class='viewer'><pre macro='view text'></pre></div>
</div>
<div macro="else">
	<div class='viewer' macro='view text wikified'></div>
</div>

<div class="tagglyTagging" macro="tagglyTagging"></div>

<!--}}}-->

!ViewTemplateToolbar
<!--{{{-->
<div class='toolbar'>
	<span macro="showWhenTagged systemConfig">
		<span macro="toggleTag systemConfigDisable . '[[disable|systemConfigDisable]]'"></span>
	</span>
	<span macro="showWhenTagged systemTheme"><span macro="applyTheme"></span></span>
	<span macro="showWhenTagged systemPalette"><span macro="applyPalette"></span></span>
	<span macro="showWhen tiddler.tags.contains('css') || tiddler.title == 'StyleSheet'"><span macro="refreshAll"></span></span>
	<span style="padding:1em;"></span>
	<span macro='toolbar closeTiddler closeOthers +editTiddler deleteTiddler > fields syncing permalink references jump'></span> <span macro='newHere label:"new here"'></span>
	<span macro='newJournalHere {{config.mptwJournalFormat?config.mptwJournalFormat:"MM/0DD/YY"}}'></span>
</div>
<!--}}}-->

!EditTemplate
<!--{{{-->
<div class="toolbar" macro="toolbar +saveTiddler saveCloseTiddler closeOthers -cancelTiddler cancelCloseTiddler deleteTiddler"></div>
<div class="title" macro="view title"></div>
<div class="editLabel">Title</div><div class="editor" macro="edit title"></div>
<div macro='annotations'></div>
<div class="editLabel">Content</div><div class="editor" macro="edit text"></div>
<div class="editLabel">Tags</div><div class="editor" macro="edit tags"></div>
<div class="editorFooter"><span macro="message views.editor.tagPrompt"></span><span macro="tagChooser"></span></div>
<!--}}}-->

!StyleSheet
/*{{{*/

/* a contrasting background so I can see where one tiddler ends and the other begins */
body {
	background: [[ColorPalette::TertiaryLight]];
}

/* sexy colours and font for the header */
.headerForeground {
	color: [[ColorPalette::PrimaryPale]];
}
.headerShadow, .headerShadow a {
	color: [[ColorPalette::PrimaryMid]];
}

/* separate the top menu parts */
.headerForeground, .headerShadow {
	padding: 1em 1em 0;
}

.headerForeground, .headerShadow {
	font-family: 'Trebuchet MS' sans-serif;
	font-weight:bold;
}
.headerForeground .siteSubtitle {
	color: [[ColorPalette::PrimaryLight]];
}
.headerShadow .siteSubtitle {
	color: [[ColorPalette::PrimaryMid]];
}

/* make shadow go and down right instead of up and left */
.headerShadow {
	left: 1px;
	top: 1px;
}

/* prefer monospace for editing */
.editor textarea, .editor input {
	font-family: 'Consolas' monospace;
	background-color:[[ColorPalette::TertiaryPale]];
}


/* sexy tiddler titles */
.title {
	font-size: 250%;
	color: [[ColorPalette::PrimaryLight]];
	font-family: 'Trebuchet MS' sans-serif;
}

/* more subtle tiddler subtitle */
.subtitle {
	padding:0px;
	margin:0px;
	padding-left:1em;
	font-size: 90%;
	color: [[ColorPalette::TertiaryMid]];
}
.subtitle .tiddlyLink {
	color: [[ColorPalette::TertiaryMid]];
}

/* a little bit of extra whitespace */
.viewer {
	padding-bottom:3px;
}

/* don't want any background color for headings */
h1,h2,h3,h4,h5,h6 {
	background-color: transparent;
	color: [[ColorPalette::Foreground]];
}

/* give tiddlers 3d style border and explicit background */
.tiddler {
	background: [[ColorPalette::Background]];
	border-right: 2px [[ColorPalette::TertiaryMid]] solid;
	border-bottom: 2px [[ColorPalette::TertiaryMid]] solid;
	margin-bottom: 1em;
	padding:1em 2em 2em 1.5em;
}

/* make options slider look nicer */
#sidebarOptions .sliderPanel {
	border:solid 1px [[ColorPalette::PrimaryLight]];
}

/* the borders look wrong with the body background */
#sidebar .button {
	border-style: none;
}

/* this means you can put line breaks in SidebarOptions for readability */
#sidebarOptions br {
	display:none;
}
/* undo the above in OptionsPanel */
#sidebarOptions .sliderPanel br {
	display:inline;
}

/* horizontal main menu stuff */
#displayArea {
	margin: 1em 15.7em 0em 1em; /* use the freed up space */
}
#topMenu br {
	display: none;
}
#topMenu {
	background: [[ColorPalette::PrimaryMid]];
	color:[[ColorPalette::PrimaryPale]];
}
#topMenu {
	padding:2px;
}
#topMenu .button, #topMenu .tiddlyLink, #topMenu a {
	margin-left: 0.5em;
	margin-right: 0.5em;
	padding-left: 3px;
	padding-right: 3px;
	color: [[ColorPalette::PrimaryPale]];
	font-size: 115%;
}
#topMenu .button:hover, #topMenu .tiddlyLink:hover {
	background: [[ColorPalette::PrimaryDark]];
}

/* make 2.2 act like 2.1 with the invisible buttons */
.toolbar {
	visibility:hidden;
}
.selected .toolbar {
	visibility:visible;
}

/* experimental. this is a little borked in IE7 with the button 
 * borders but worth it I think for the extra screen realestate */
.toolbar { float:right; }

/* fix for TaggerPlugin. from sb56637. improved by FND */
.popup li .tagger a {
   display:inline;
}

/* makes theme selector look a little better */
#sidebarOptions .sliderPanel .select .button {
  padding:0.5em;
  display:block;
}
#sidebarOptions .sliderPanel .select br {
	display:none;
}

/* make it print a little cleaner */
@media print {
	#topMenu {
		display: none ! important;
	}
	/* not sure if we need all the importants */
	.tiddler {
		border-style: none ! important;
		margin:0px ! important;
		padding:0px ! important;
		padding-bottom:2em ! important;
	}
	.tagglyTagging .button, .tagglyTagging .hidebutton {
		display: none ! important;
	}
	.headerShadow {
		visibility: hidden ! important;
	}
	.tagglyTagged .quickopentag, .tagged .quickopentag {
		border-style: none ! important;
	}
	.quickopentag a.button, .miniTag {
		display: none ! important;
	}
}

/* get user styles specified in StyleSheet */
[[StyleSheet]]

/*}}}*/

|Name|MptwTrim|
|Description|Mptw Theme with a reduced header to increase useful space|
|ViewTemplate|MptwTheme##ViewTemplate|
|EditTemplate|MptwTheme##EditTemplate|
|StyleSheet|MptwTheme##StyleSheet|
|PageTemplate|##PageTemplate|

!PageTemplate
<!--{{{-->

<!-- horizontal MainMenu -->
<div id='topMenu' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<span refresh='content' tiddler='SiteTitle' style="padding-left:1em;font-weight:bold;"></span>:
<span refresh='content' tiddler='MainMenu'></span>
</div>
<div id='sidebar'>
	<div id='sidebarOptions'>
		<div refresh='content' tiddler='SideBarOptions'></div>
		<div style="margin-left:0.1em;"
			macro='slider chkTabSliderPanel SideBarTabs {{"tabs \u00bb"}} "Show Timeline, All, Tags, etc"'></div>
	</div>
</div>
<div id='displayArea'>
	<div id='messageArea'></div>
	<div id='tiddlerDisplay'></div>
</div>

For upgrading. See [[ImportTiddlers]].
URL: http://mptw.tiddlyspot.com/upgrade.html
/***
|Description:|A place to put your config tweaks so they aren't overwritten when you upgrade MPTW|
See http://www.tiddlywiki.org/wiki/Configuration_Options for other options you can set. In some cases where there are clashes with other plugins it might help to rename this to zzMptwUserConfigPlugin so it gets executed last.
***/
//{{{

// example: set your preferred date format
//config.mptwDateFormat = 'MM/0DD/YY';
//config.mptwJournalFormat = 'Journal MM/0DD/YY';

config.options.txtTheme = 'MptwRoundTheme';

config.options.chkSaveBackups = false;

config.options.chkHttpReadOnly        = true; // default true
readOnly                              = true; // default true when viewed over HTTP, false when used locally -- for TiddlyWiki v2.2+ only
showBackstage                         = false; // default false when viewed over HTTP, true when used locally -- for TiddlyWiki v2.2+ only

//}}}
''Auteurs'' : Jocelyn Sérot,Joel Falcou
''Conférence'' : JFLA 2008 - Etretat, France - Janvier 2008
''Parution'' : INRIA, Collection Didactique

''Résumé'' : //"On décrit l’implémentation en MetaOcaml d’un petit langage dédié (DSL) à la programmation parallèle. Le langage repose sur la notion de squelettes qui autorisent la spécification de programmes parallèles par simple composition de constructeurs de haut niveau encapsulant des schémas communs et récurrents de parallélisme. On montre comment les facilités de métaprogrammation offertes par MetaOcaml permettent d’éliminer presque totalement le surcoût à l’exécution du code généré par rapport à une implantation du même programme écrite avec des primitives de bas niveau comme celles de MPI. Pour cela, la spécification haut niveau du programme est d’abord transformée en une représentation équivalente sous la forme d’un réseau de processus séquentiels communiquants puis cette représentation est utilisée pour générer dynamiquement le code exécuté par chaque processeur de la machine."//

[[Téléchargement|http://www.lri.fr/~falcou/pub/falcou-JFLA-2008.pdf]]
!Motivation
Les applications de vision artificielle complexes sont habituellement développées à partir d’un formalisme mathématique adéquat et implantées dans un langage de haut-niveau qui prend en charge les éléments classiques du calcul matriciel, de l’algèbre linéaire ou du traitement d’image. Des outils comme MATLAB sont régulièrement utilisés par les développeurs de la communauté Vision car ils permettent d’exprimer de manière directe des expressions mathématiques complexes et proposent un large panel de fonctionnalités au sein d’un modèle de programmation procédurale classique. Mais il s’avère que certaines applications nécessitent d’être portées vers des langages plus performants en terme de temps de calcul. Pour ce faire, un processus de réécriture vers des langages comme C ou FORTRAN est souvent envisagé mais implique un surcroît de travail non-négligeable compte tenu du faible niveau d’expressivité de ces langages. Une alternative consiste à utiliser un langage comme le C++ que ses fonctionnalités rendent a priori intéressant dans le cadre du calcul scientifique. Ainsi, la surcharge des opérateurs, qui augmente l’expressivité du langage et son aspect orienté-objet qui favorise l’abstraction et la réutilisation de code sont autant d’atouts qui facilitent cette transition.

Malgré ces fonctionnalités, le C++ est peu utilisé au sein d’application de Vision car ses performances sont incompatibles avec les contraintes temporelles de ce type d’applications. En effet, les programmes C++ sont beaucoup plus lent que leur équivalent C ou FORTRAN – d’un facteur compris entre 1.2 et 10 – ce qui force un grand nombre de développeurs à écrire en C ou en FORTRAN les parties critiques de leurs algorithmes, n’utilisant le C++ que pour des taches annexes comme les entrées-sorties ou la gestion des interfaces graphiques et ce malgré l’existence de bibliothèques comme [[OpenCV|http://sourceforge.net/projects/opencvlibrary/]], VXL, Vigra, ITK ou Gandalf. Le développeur d’applications de vision artificielle se retrouve donc à devoir effectuer un choix entre l’expressivité de ses outils et leur efficacité. Quand bien même il est possible de définir de nouveaux outils proposant une expressivité plus grande, leur techniques d’implantations classiques dégradent rapidement leur efficacité. En outre, la plupart de ces développeurs ne peuvent - faute d'une encapsulation suffisamment efficace - tirer partie des performances des machines modernes comme la présence d'extension SIMD ou des processeurs multi-coeurs.
!Fonctionnalités 
[[NT²]] est une bibliothèques de classes C++ permettant la gestion aisée et performante, de matrices numériques. Son originalité réside principalement en trois points :
* L’utilisation de techniques à base d’[[Expression Templates]] permettant d’éviter des recopies de données et rapprochant les performances du code obtenu de celles d’un code C écrit à la main grâce au moteur de génération de code E.V.E.
* L’utilisation transparente d'[[Extensions SIMD|Extension SIMD]] - en particulier """SSE2""" et """AltiVec""" - présentes sur une large gamme de processeurs.
* La reproduction la plus fidèle possible des fonctionnalités propres à MATLAB.
Le point central réside dans l'utilisation des templates C++ n'ont pas comme seulement un moyen d'obtenir des algorithmes et des conteneurs génériques mais bien pour utiliser ces derniers comme un véritable langage dans le langage permettant de forcer le compilateur à générer du code selon un schéma pré-établi et optimisé en fonction de la cible matérielle considérée.
!Publications associées
[[E.V.E : An Object Oriented SIMD Library]]
[[Meta-programming Applied to Automatic SMP Parallelization of Linear Algebra Code]]
[[Application of template-based meta-programming compilation techniques to the efficient implementation of image processing algorithms on SIMD-capable processors]]
/***
|Name:|NewHerePlugin|
|Description:|Creates the new here and new journal macros|
|Version:|3.0 ($Rev: 3861 $)|
|Date:|$Date: 2008-03-08 10:53:09 +1000 (Sat, 08 Mar 2008) $|
|Source:|http://mptw.tiddlyspot.com/#NewHerePlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License|http://mptw.tiddlyspot.com/#TheBSDLicense|
***/
//{{{
merge(config.macros, {
	newHere: {
		handler: function(place,macroName,params,wikifier,paramString,tiddler) {
			wikify("<<newTiddler "+paramString+" tag:[["+tiddler.title+"]]>>",place,null,tiddler);
		}
	},
	newJournalHere: {
		handler: function(place,macroName,params,wikifier,paramString,tiddler) {
			wikify("<<newJournal "+paramString+" tag:[["+tiddler.title+"]]>>",place,null,tiddler);
		}
	}
});

//}}}

/***
|Name:|NewMeansNewPlugin|
|Description:|If 'New Tiddler' already exists then create 'New Tiddler (1)' and so on|
|Version:|1.1.1 ($Rev: 2263 $)|
|Date:|$Date: 2007-06-13 04:22:32 +1000 (Wed, 13 Jun 2007) $|
|Source:|http://mptw.tiddlyspot.com/empty.html#NewMeansNewPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License|http://mptw.tiddlyspot.com/#TheBSDLicense|
!!Note: I think this should be in the core
***/
//{{{

// change this or set config.newMeansNewForJournalsToo it in MptwUuserConfigPlugin
if (config.newMeansNewForJournalsToo == undefined) config.newMeansNewForJournalsToo = true;

String.prototype.getNextFreeName = function() {
       var numberRegExp = / \(([0-9]+)\)$/;
       var match = numberRegExp.exec(this);
       if (match) {
               var num = parseInt(match[1]) + 1;
               return this.replace(numberRegExp," ("+num+")");
       }
       else {
               return this + " (1)";
       }
}

config.macros.newTiddler.checkForUnsaved = function(newName) {
	var r = false;
	story.forEachTiddler(function(title,element) {
		if (title == newName)
			r = true;
	});
	return r;
}

config.macros.newTiddler.getName = function(newName) {
       while (store.getTiddler(newName) || config.macros.newTiddler.checkForUnsaved(newName))
               newName = newName.getNextFreeName();
       return newName;
}


config.macros.newTiddler.onClickNewTiddler = function()
{
	var title = this.getAttribute("newTitle");
	if(this.getAttribute("isJournal") == "true") {
		title = new Date().formatString(title.trim());
	}

	// ---- these three lines should be the only difference between this and the core onClickNewTiddler
	if (config.newMeansNewForJournalsToo || this.getAttribute("isJournal") != "true")
		title = config.macros.newTiddler.getName(title);

	var params = this.getAttribute("params");
	var tags = params ? params.split("|") : [];
	var focus = this.getAttribute("newFocus");
	var template = this.getAttribute("newTemplate");
	var customFields = this.getAttribute("customFields");
	if(!customFields && !store.isShadowTiddler(title))
		customFields = String.encodeHashMap(config.defaultCustomFields);
	story.displayTiddler(null,title,template,false,null,null);
	var tiddlerElem = story.getTiddler(title);
	if(customFields)
		story.addCustomFields(tiddlerElem,customFields);
	var text = this.getAttribute("newText");
	if(typeof text == "string")
		story.getTiddlerField(title,"text").value = text.format([title]);
	for(var t=0;t<tags.length;t++)
		story.setTiddlerTag(title,tags[t],+1);
	story.focusTiddler(title,focus);
	return false;
};

//}}}

!Description
''Site du projet'' : http://ocelle.ief.u-psud.fr/index.php
''Collaborateurs'' : ''Kontron Modular SA'', IEF, Thales TRT, """CEA-LIST""", Dosisoft
''Objectifs'' : Permettre aux développeurs d’applications embarquées sur les architectures de types processeurs CELL d’exploiter la puissance de calcul promise par le matériel, sans sacrifier la productivité du développement logiciel. Le principe technique est d’associer, dans les outils logiciels, une génération de code de bas niveau à partir de langages traditionnels, avec une approche à base d’ingénierie des modèles.
!Équipe de Recherche
* [[Lionel Lacassagne|http://www.ief.u-psud.fr/~lacas/]]
* [[Tarik Saidani|http://www.ief.u-psud.fr/~saidani/]]
* [[Claude Tadonki|http://www.ief.u-psud.fr/~tadonki/]]
* Joel Falcou
!Réalisations
* Exploration des modèles de programmation adaptés au processeur CELL
* Développement d'un sur-couche MPI pour le processeur CELL
* Mise en oeuvre des [[Squelettes Algorithmiques]] sur le processeur CELL via la bibliothèque [[C++]] [[Skell-BE]]
* Application : détecteur de points d'intérêts de Harris et Stephen
!Publications
[[Programmation par squelettes algorithmiques pour le processeur CELL]]


''Auteur'' : Tarik Saidani, Joel Falcou, Lionel Lacassagne, Samir Bouaziz
''Journal'' : //Transactions on High-Performance Embedded Architectures and Compilers//, Volume 3, Issue 3, Septembre 2008 

''Résumé'' :
"//The Cell processor is a typical example of a heterogeneous multiprocessor on-chip architecture that uses several levels of parallelism to deliver high performance. Reducing the gap between peak performance and eective performance is the challenge for software tool developers and the application developers. Image processing and media applications are typical \main stream" applications. We use the Harris algorithm for the detection of interest points in an image as a benchmark to compare the performance of several parallel schemes on a Cell processor. The impact of the DMA controlled data transfers and the synchronizations between SPEs explains the dierences between the performance of the dierent parallelization schemes. The scalability of the architecture is modeled and evaluated.//"

[[Téléchargement depuis le site de l'éditeur|http://www.hipeac.net/system/files?file=hipeac_spec_revised.pdf]]
''Contexte:''
Dans le cadre d'un projet de recherche DIGITEO, l’équipe PARAL du [[LRI|http://www.lri.fr]] de l’Université Paris Sud  cherche à pourvoir un poste d'ingénieur ou de post-doc en informatique.
 
''Mission:''
L'ingénieur recruté participera, après analyse de l'existant, au développement d'un outil de parallélisation automatique[1] sur cartes graphiques programmables (GPU NVIDIA) basé sur des techniques de génération de code statique (méta-programmation template) ou dynamique (programmation multi-étape) en C++. Ce développement s'inscrira dans la continuité du projet [[NT2]] [2] et sera utilisé pour développer des applications de contrôle non-destructif par rayons X en collaboration avec le CEA LIST.
 
''Le dossier de candidature devra comporter une lettre de motivation et un CV.''
 
''Début du contrat en septembre/octobre 2009''
''Lieu de travail  :'' LRI, Université Paris Sud - Orsay, France
''Durée du CDD     :'' 24 mois
''Rémunération     :'' 2862€ brut mensuel
 
''Compétences :''
 - requises    : C++, CUDA, programmation parallèle
 - optionnelles : connaissance de Matlab et/ou de la bibliothèque BOOST, notions de méta-programmation
 
''Contact :''
 Joel FALCOU, Maître de conférence
 - E-mail     : joel.falcou@lri.fr
 - Téléphone : 01 69 15 66 35
 
''Références :''
[1] [[Meta-programming Applied to Automatic SMP Parallelization of Linear Algebra Code]]
[2] [[Projet NT2|http://nt2.sourceforge.net]]
/***
|''Name:''|PasswordOptionPlugin|
|''Description:''|Extends TiddlyWiki options with non encrypted password option.|
|''Version:''|1.0.2|
|''Date:''|Apr 19, 2007|
|''Source:''|http://tiddlywiki.bidix.info/#PasswordOptionPlugin|
|''Author:''|BidiX (BidiX (at) bidix (dot) info)|
|''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
|''~CoreVersion:''|2.2.0 (Beta 5)|
***/
//{{{
version.extensions.PasswordOptionPlugin = {
	major: 1, minor: 0, revision: 2, 
	date: new Date("Apr 19, 2007"),
	source: 'http://tiddlywiki.bidix.info/#PasswordOptionPlugin',
	author: 'BidiX (BidiX (at) bidix (dot) info',
	license: '[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D]]',
	coreVersion: '2.2.0 (Beta 5)'
};

config.macros.option.passwordCheckboxLabel = "Save this password on this computer";
config.macros.option.passwordInputType = "password"; // password | text
setStylesheet(".pasOptionInput {width: 11em;}\n","passwordInputTypeStyle");

merge(config.macros.option.types, {
	'pas': {
		elementType: "input",
		valueField: "value",
		eventName: "onkeyup",
		className: "pasOptionInput",
		typeValue: config.macros.option.passwordInputType,
		create: function(place,type,opt,className,desc) {
			// password field
			config.macros.option.genericCreate(place,'pas',opt,className,desc);
			// checkbox linked with this password "save this password on this computer"
			config.macros.option.genericCreate(place,'chk','chk'+opt,className,desc);			
			// text savePasswordCheckboxLabel
			place.appendChild(document.createTextNode(config.macros.option.passwordCheckboxLabel));
		},
		onChange: config.macros.option.genericOnChange
	}
});

merge(config.optionHandlers['chk'], {
	get: function(name) {
		// is there an option linked with this chk ?
		var opt = name.substr(3);
		if (config.options[opt]) 
			saveOptionCookie(opt);
		return config.options[name] ? "true" : "false";
	}
});

merge(config.optionHandlers, {
	'pas': {
 		get: function(name) {
			if (config.options["chk"+name]) {
				return encodeCookie(config.options[name].toString());
			} else {
				return "";
			}
		},
		set: function(name,value) {config.options[name] = decodeCookie(value);}
	}
});

// need to reload options to load passwordOptions
loadOptionsCookie();

/*
if (!config.options['pasPassword'])
	config.options['pasPassword'] = '';

merge(config.optionsDesc,{
		pasPassword: "Test password"
	});
*/
//}}}
/***
|Name:|PrettyDatesPlugin|
|Description:|Provides a new date format ('pppp') that displays times such as '2 days ago'|
|Version:|1.0 ($Rev: 3646 $)|
|Date:|$Date: 2008-02-27 02:34:38 +1000 (Wed, 27 Feb 2008) $|
|Source:|http://mptw.tiddlyspot.com/#PrettyDatesPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
!!Notes
* If you want to you can rename this plugin. :) Some suggestions: LastUpdatedPlugin, RelativeDatesPlugin, SmartDatesPlugin, SexyDatesPlugin.
* Inspired by http://ejohn.org/files/pretty.js
***/
//{{{
Date.prototype.prettyDate = function() {
	var diff = (((new Date()).getTime() - this.getTime()) / 1000);
	var day_diff = Math.floor(diff / 86400);

	if (isNaN(day_diff))      return "";
	else if (diff < 0)        return "in the future";
	else if (diff < 60)       return "just now";
	else if (diff < 120)      return "1 minute ago";
	else if (diff < 3600)     return Math.floor(diff/60) + " minutes ago";
	else if (diff < 7200)     return "1 hour ago";
	else if (diff < 86400)    return Math.floor(diff/3600) + " hours ago";
	else if (day_diff == 1)   return "Yesterday";
	else if (day_diff < 7)    return day_diff + " days ago";
	else if (day_diff < 14)   return  "a week ago";
	else if (day_diff < 31)   return Math.ceil(day_diff/7) + " weeks ago";
	else if (day_diff < 62)   return "a month ago";
	else if (day_diff < 365)  return "about " + Math.ceil(day_diff/31) + " months ago";
	else if (day_diff < 730)  return "a year ago";
	else                      return Math.ceil(day_diff/365) + " years ago";
}

Date.prototype.formatString_orig_mptw = Date.prototype.formatString;

Date.prototype.formatString = function(template) {
	return this.formatString_orig_mptw(template).replace(/pppp/,this.prettyDate());
}

// for MPTW. otherwise edit your ViewTemplate as required.
// config.mptwDateFormat = 'pppp (DD/MM/YY)'; 
config.mptwDateFormat = 'pppp'; 

//}}}

''Cursus Apprentissage IFIPS 2ème Année''
!Objectifs
Ce cours de Programmation Orienté Objet fait suite au cours de Complément Objet de première année. Son but est de reprendre les bases du modèle objet et de les mettre en œuvre grâce au langage C++. De nouveaux éléments -spécifique au langage- sont aussi abordés comme la surcharge d'opérateur, la programmation générique et une introduction aux idiomes du langage et aux Design Patterns.
!Supports
* [[Transparents d'introduction|http://www.lri.fr/~falcou/teaching/poo/session1/introduction.pdf]]
* [[Classe et objet en C++|http://www.lri.fr/~falcou/teaching/poo/session1/class.pdf]]
* [[Forme canonique de Coplien|http://www.lri.fr/~falcou/teaching/poo/session1/fcc/]]
* [[Surcharge d'opérateurs|http://www.lri.fr/~falcou/teaching/poo/session1/operator]]
* [[Héritage|http://www.lri.fr/~falcou/teaching/poo/session2/relation.pdf]]
* [[Mise en oeuvre du polymorphisme|http://www.lri.fr/~falcou/teaching/poo/session2/relation_td.pdf]]
!Références
* [[Thinking in C++ de Bruce Eckel|http://bruce-eckel.developpez.com/livres/cpp/traduction/ticpp2vol1/]]
* [[More C++ Idioms WikiBook|http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms]]

''Auteurs'' : Joel Falcou, Tarik Saidani, Lionel Lacassagne, Daniel Etiemble
''Conférence'' : //SYMPA 2008// - Fribourg, Suisse - Février 2008

''Résumé'' :
"//Le processeur CELL est un exemple typique d'architecture multiprocesseurs hétérogènes sur puce, utilisant plusieurs niveaux de parallélisme pour obtenir des performances très élevées. Le défi pour les développeurs d'outils ou d'applications est alors de réduire l'écart entre les performances crêtes et les performances effectives. Sur des architectures plus classiques, des modèles comme les squelettes algorithmiques proposent une méthodologie simple et //scalable// pour la parallélisation d'applications complexes et ont donné naissance à des outils efficaces. Nous étudions dans cet article l'application du modèle des squelettes algorithmiques à la parallélisation d'applications de traitement d'images sur le processeur CELL. Nous proposons en outre une implantation efficace de ce modèle sous la forme d'un langage orienté domaine méta-programmé au sein de C++. Des résultats préliminaires sont donnés et démontrent la viabilité de l'approche.//"

[[Télécharger l'article|http://www.lri.fr/~falcou/pub/falcou-SYMPA-2008.pdf]]
''Auteurs'' : Joel Falcou
''Parution'' : IEEE Computer In Engineering Science, Volume 11 (3), Mai-Juin 2009

''Résumé'' ://"Back at the dawn of scientific computing, parallel machines were revered as titans that few could approach and even fewer could tame. Today, after decades of progress in both hardware and software development, parallel computing is a mainstream technique for getting things done. However, as this progress spawned increasingly powerful machines, it spelled doom for many developers. Parallel programming is bound to become the main concern of software developers in the coming decades. Various models aim to solve this tension, trading efficiency for abstraction or vice versa, but how about getting both?"//

[[Télécharger l'article sur le site de l'éditeur|http://doi.ieeecomputersociety.org/10.1109/MCSE.2009.57]]
Voici la liste des projets de recherche (ANR, Systematic, etc...) auxquels j'ai participé
Cette page reprend les publications effectuées depuis mon doctorat. Chaque entrée propose un lien permettant de télécharger - de manière directe ou en passant via le site de l'éditeur concerné - un PDF de la dite publication. [[Un fichier bibtex est aussi disponible|http://www.lri.fr/~falcou/pub/falcou.bib]] afin de simplifier l'utilisation de ces références bibliographiques. 

''Auteurs'' : Joël Falcou, Jocelyn Sérot, Thierry Chateay, Jean Thierry Lapresté
''Journal'': Parallel Computing, Volume 32, Issues 7-8, Septembre 2006, Pages 604-615.

''Résumé'':
//"We present Quaff, a new skeleton-based parallel programming libraries. Its main originality is to rely on C++ template meta-programming techniques to achieve high efficiency. In particular, by performing most of skeleton instantiation and optimization at compile-time, Quaff can keep the overhead traditionally associated to object-oriented implementations of skeleton-based parallel programming libraries very small. This is not done at the expense of expressivity. This is demonstrated in this paper with several applications, including a full-fledged, realistic real-time vision application."//

[[Téléchargement depuis le site de l'éditeur|http://www.sciencedirect.com/science?_ob=ArticleURL&_udi=B6V12-4KJDWN5-2&_user=10&_coverDate=09%2F30%2F2006&_rdoc=1&_fmt=&_orig=search&_sort=d&view=c&_acct=C000050221&_version=1&_urlVersion=0&_userid=10&md5=4da5b7b2e4c3c5c7f51b7ecdad2d459b]]

!Juin 2009
* Un poste d'ingénieur/post-doc est ouvert : [[Parallélisation automatique sur GPUs]]
* L'article "[[Algorithmic Skeletons within an Embedded Domain Specific Language for the CELL Processor]]" a été accepté à [[PACT 09|http://pact09.renci.org/program.php#accelerators]]
!Mai 2009
* L'article "[[High Level Parallel Programming EDSL - A BOOST Libraries Use Case]]" a été présenté à [[BOOST'CON 09|http://www.boostcon.com/home]]
* L'article "[[Une bibliothèque métaprogrammée pour la programmation parallèle]]" est paru dans le volume 28/05 de la revue [[Technique et Science Informatique|http://tsi.revuesonline.com/]]
* L'article de vulgarisation "[[Programming with Parallel Skeletons]]" est paru dans [[IEEE Computer In Science & Engineering|http://www.computer.org/portal/site/cise/index.jsp]]
/***
|Name:|QuickOpenTagPlugin|
|Description:|Changes tag links to make it easier to open tags as tiddlers|
|Version:|3.0.1 ($Rev: 3861 $)|
|Date:|$Date: 2008-03-08 10:53:09 +1000 (Sat, 08 Mar 2008) $|
|Source:|http://mptw.tiddlyspot.com/#QuickOpenTagPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
***/
//{{{
config.quickOpenTag = {

	dropdownChar: (document.all ? "\u25bc" : "\u25be"), // the little one doesn't work in IE?

	createTagButton: function(place,tag,excludeTiddler) {
		// little hack so we can do this: <<tag PrettyTagName|RealTagName>>
		var splitTag = tag.split("|");
		var pretty = tag;
		if (splitTag.length == 2) {
			tag = splitTag[1];
			pretty = splitTag[0];
		}
		
		var sp = createTiddlyElement(place,"span",null,"quickopentag");
		createTiddlyText(createTiddlyLink(sp,tag,false),pretty);
		
		var theTag = createTiddlyButton(sp,config.quickOpenTag.dropdownChar,
                        config.views.wikified.tag.tooltip.format([tag]),onClickTag);
		theTag.setAttribute("tag",tag);
		if (excludeTiddler)
			theTag.setAttribute("tiddler",excludeTiddler);
    		return(theTag);
	},

	miniTagHandler: function(place,macroName,params,wikifier,paramString,tiddler) {
		var tagged = store.getTaggedTiddlers(tiddler.title);
		if (tagged.length > 0) {
			var theTag = createTiddlyButton(place,config.quickOpenTag.dropdownChar,
                        	config.views.wikified.tag.tooltip.format([tiddler.title]),onClickTag);
			theTag.setAttribute("tag",tiddler.title);
			theTag.className = "miniTag";
		}
	},

	allTagsHandler: function(place,macroName,params) {
		var tags = store.getTags(params[0]);
		var filter = params[1]; // new feature
		var ul = createTiddlyElement(place,"ul");
		if(tags.length == 0)
			createTiddlyElement(ul,"li",null,"listTitle",this.noTags);
		for(var t=0; t<tags.length; t++) {
			var title = tags[t][0];
			if (!filter || (title.match(new RegExp('^'+filter)))) {
				var info = getTiddlyLinkInfo(title);
				var theListItem =createTiddlyElement(ul,"li");
				var theLink = createTiddlyLink(theListItem,tags[t][0],true);
				var theCount = " (" + tags[t][1] + ")";
				theLink.appendChild(document.createTextNode(theCount));
				var theDropDownBtn = createTiddlyButton(theListItem," " +
					config.quickOpenTag.dropdownChar,this.tooltip.format([tags[t][0]]),onClickTag);
				theDropDownBtn.setAttribute("tag",tags[t][0]);
			}
		}
	},

	// todo fix these up a bit
	styles: [
"/*{{{*/",
"/* created by QuickOpenTagPlugin */",
".tagglyTagged .quickopentag, .tagged .quickopentag ",
"	{ margin-right:1.2em; border:1px solid #eee; padding:2px; padding-right:0px; padding-left:1px; }",
".quickopentag .tiddlyLink { padding:2px; padding-left:3px; }",
".quickopentag a.button { padding:1px; padding-left:2px; padding-right:2px;}",
"/* extra specificity to make it work right */",
"#displayArea .viewer .quickopentag a.button, ",
"#displayArea .viewer .quickopentag a.tiddyLink, ",
"#mainMenu .quickopentag a.tiddyLink, ",
"#mainMenu .quickopentag a.tiddyLink ",
"	{ border:0px solid black; }",
"#displayArea .viewer .quickopentag a.button, ",
"#mainMenu .quickopentag a.button ",
"	{ margin-left:0px; padding-left:2px; }",
"#displayArea .viewer .quickopentag a.tiddlyLink, ",
"#mainMenu .quickopentag a.tiddlyLink ",
"	{ margin-right:0px; padding-right:0px; padding-left:0px; margin-left:0px; }",
"a.miniTag {font-size:150%;} ",
"#mainMenu .quickopentag a.button ",
"	/* looks better in right justified main menus */",
"	{ margin-left:0px; padding-left:2px; margin-right:0px; padding-right:0px; }", 
"#topMenu .quickopentag { padding:0px; margin:0px; border:0px; }",
"#topMenu .quickopentag .tiddlyLink { padding-right:1px; margin-right:0px; }",
"#topMenu .quickopentag .button { padding-left:1px; margin-left:0px; border:0px; }",
"/*}}}*/",
		""].join("\n"),

	init: function() {
		// we fully replace these builtins. can't hijack them easily
		window.createTagButton = this.createTagButton;
		config.macros.allTags.handler = this.allTagsHandler;
		config.macros.miniTag = { handler: this.miniTagHandler };
		config.shadowTiddlers["QuickOpenTagStyles"] = this.styles;
		store.addNotification("QuickOpenTagStyles",refreshStyles);
	}
}

config.quickOpenTag.init();

//}}}

''Auteurs'' : Joel Falcou, Jocelyn Sérot, Thierry Chateau, Jean-Thierry Lapresté
''Conférence'' : CIMCV 2006 - Workshop d'ECCV 2006 - Graz, Autriche, 7 - 13 Mai 2006

''Résumé'' ://"Particle filtering is a widely used method to solve vision tracking problems. However, to be able to run in real-time on standard architecture, the state vector used in the particle filter must remain small. We propose a parallel implementation of a 3D tracking algorithm operating on a stereo video stream and running in real-time on a cluster architecture. We demonstrate the efficiency of this implementation with a pedestrian tracking application."//

[[Téléchargement|http://www.lri.fr/~falcou/pub/falcou-ECCV-CIMCV-2006.pdf]]

/***
|Name:|RenameTagsPlugin|
|Description:|Allows you to easily rename or delete tags across multiple tiddlers|
|Version:|3.0 ($Rev: 5501 $)|
|Date:|$Date: 2008-06-10 23:11:55 +1000 (Tue, 10 Jun 2008) $|
|Source:|http://mptw.tiddlyspot.com/#RenameTagsPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License|http://mptw.tiddlyspot.com/#TheBSDLicense|
Rename a tag and you will be prompted to rename it in all its tagged tiddlers.
***/
//{{{
config.renameTags = {

	prompts: {
		rename: "Rename the tag '%0' to '%1' in %2 tidder%3?",
		remove: "Remove the tag '%0' from %1 tidder%2?"
	},

	removeTag: function(tag,tiddlers) {
		store.suspendNotifications();
		for (var i=0;i<tiddlers.length;i++) {
			store.setTiddlerTag(tiddlers[i].title,false,tag);
		}
		store.resumeNotifications();
		store.notifyAll();
	},

	renameTag: function(oldTag,newTag,tiddlers) {
		store.suspendNotifications();
		for (var i=0;i<tiddlers.length;i++) {
			store.setTiddlerTag(tiddlers[i].title,false,oldTag); // remove old
			store.setTiddlerTag(tiddlers[i].title,true,newTag);  // add new
		}
		store.resumeNotifications();
		store.notifyAll();
	},

	storeMethods: {

		saveTiddler_orig_renameTags: TiddlyWiki.prototype.saveTiddler,

		saveTiddler: function(title,newTitle,newBody,modifier,modified,tags,fields,clearChangeCount,created) {
			if (title != newTitle) {
				var tagged = this.getTaggedTiddlers(title);
				if (tagged.length > 0) {
					// then we are renaming a tag
					if (confirm(config.renameTags.prompts.rename.format([title,newTitle,tagged.length,tagged.length>1?"s":""])))
						config.renameTags.renameTag(title,newTitle,tagged);

					if (!this.tiddlerExists(title) && newBody == "")
						// dont create unwanted tiddler
						return null;
				}
			}
			return this.saveTiddler_orig_renameTags(title,newTitle,newBody,modifier,modified,tags,fields,clearChangeCount,created);
		},

		removeTiddler_orig_renameTags: TiddlyWiki.prototype.removeTiddler,

		removeTiddler: function(title) {
			var tagged = this.getTaggedTiddlers(title);
			if (tagged.length > 0)
				if (confirm(config.renameTags.prompts.remove.format([title,tagged.length,tagged.length>1?"s":""])))
					config.renameTags.removeTag(title,tagged);
			return this.removeTiddler_orig_renameTags(title);
		}

	},

	init: function() {
		merge(TiddlyWiki.prototype,this.storeMethods);
	}
}

config.renameTags.init();

//}}}


/***
|Name:|SaveCloseTiddlerPlugin|
|Description:|Provides two extra toolbar commands, saveCloseTiddler and cancelCloseTiddler|
|Version:|3.0 ($Rev: 5502 $)|
|Date:|$Date: 2008-06-10 23:31:39 +1000 (Tue, 10 Jun 2008) $|
|Source:|http://mptw.tiddlyspot.com/#SaveCloseTiddlerPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
To use these you must add them to the tool bar in your EditTemplate
***/
//{{{
merge(config.commands,{

	saveCloseTiddler: {
		text: 'done/close',
		tooltip: 'Save changes to this tiddler and close it',
		handler: function(ev,src,title) {
			var closeTitle = title;
			var newTitle = story.saveTiddler(title,ev.shiftKey);
			if (newTitle)
				closeTitle = newTitle;
			return config.commands.closeTiddler.handler(ev,src,closeTitle);
		}
	},

	cancelCloseTiddler: {
		text: 'cancel/close',
		tooltip: 'Undo changes to this tiddler and close it',
		handler: function(ev,src,title) {
			// the same as closeTiddler now actually
			return config.commands.closeTiddler.handler(ev,src,title);
		}
	}

});

//}}}

<<search>><<permaview>><<saveChanges>>

//
Confronted with machines a million times as powerful, we are faced with a gigantic programming problem
//
Joel Falcou
!Motivation
Le concept de squelette algorithmique est basé sur le fait que la mise en œuvre du parallélisme dans les applications se fait très fréquemment en utilisant un nombre restreint de schémas récurrents. Ces schémas explicitent les calculs menés en parallèle et les interactions entre ces calculs. La notion de @@''squelette''@@ correspond alors à tout ce qui, dans ces schémas, permet de contrôler les activités de calcul. Un squelette algorithmique prend donc en charge un schéma de parallélisation précis. Ainsi, toutes les opérations bas-niveau nécessaires à la mise en œuvre de la forme de parallélisme choisie sont contenues dans le code du squelette. L'utilisateur paramètre ce squelette en fournissant les fonctions de calcul de son algorithme. Ces fonctions seront alors exécutées en parallèle et les données transiteront entre elles selon le schéma que représente le squelette. Les squelettes algorithmiques rendent donc compte d'une volonté de structurer la programmation parallèle comme le fut la programmation séquentielle. La complexité de la programmation parallèle étant alors restreinte par la limitation délibérée de l'expression du parallélisme à des formes clairement identifiées et souvent dépendantes du domaine d'application considéré.

!Modèle de programmation
Considérons une application parallèle définie par un @@''Graphe de Processus communiquant''@@. 
<html>
<center>
<img src="http://www.lri.fr/~falcou/figures/placement.png"/>
</center>
</html>
Cette représentation permet de spécifier les schémas de communications entre les processus ''P~~i~~'', de mettre en évidence les fonctions séquentielles ''F~~i~~'' utilisées au sein de cette application et d'expliciter les processus nécessaires au déroulement parallèle de l'application.
<html>
<center>
<img src="http://www.lri.fr/~falcou/figures/placement-skeleton.png"/>
</center>
</html>
Dans ce graphe, on distingue deux parties distinctes : 
* Un système d'équilibrage de charge ''(A)'' qui utilise une réserve de //k// processus aux quels sont transmises les données à traiter via une fonction ''(F~~2~~)''. Lorsqu'une donnée est transmise au processus hébergeant la fonction //Distrib//, elle est transmise au premier processus esclave libre. Ce processus effectue la fonction ''(F~~2~~)'' et renvoie le résultat au processus hébergeant la fonction //Collect//. Pendant ce temps, la fonction //Distrib// continue de distribuer les données du flux d'entrée sur d'autres processus libres;
* Un mécanisme de contrôle ''(B)'' qui consiste à exécuter une série de fonctions (ici ''(F~~1~~)'', ''(F~~2~~)'' et la section ''(A)'') sur le flux de données d'entrées de l'application. Chacune de ces fonctions est placée sur un processus différent et les résultats intermédiaires transitent de processus à processus à chaque fois qu'une fonction se termine. Si l'on considère un ensemble de fonctions (''F~~0~~'', ..., ''F~~n~~'') et un ensemble de processus (''P~~0~~'', ..., ''P~~n~~''), l'exécution de cette structure consiste à recevoir sur le processus ''P~~i~~'' des données en provenance du processus ''P~~i-1~~'', exécuter la fonction ''Fi'' sur ces données, transmettre le résultat de ce calcul au processeur ''P~~i+1~~'' et finalement se préparer à recevoir de nouvelles données du processeur ''P~~i-1~~''. En régime permanent, les fonctions (''F~~0~~'', ..., ''F~~n~~'') s'exécutent en parallèle. On reconnaît donc ici une structure de type pipeline.
Ce type de construction se révèle extrêmement courant dans la pratique de la programmation parallèle. Les modèles de programmation à base de squelettes algorithmiques reposent sur l'extraction de tels schémas récurrents. On définit ainsi un squelette comme un schéma générique, paramétré par une liste de fonctions et qu'il est possible d'instancier et de composer. Fonctionnellement, les squelettes algorithmiques sont des @@''fonctions d'ordre supérieur''@@, c'est à dire des fonctions prenant une ou plusieurs fonctions comme arguments et retournant une fonction comme résultat.
!Mise en œuvre
Pour le développeur, l'utilisation de ces squelettes permet de s'abstraire des considérations complexes de placement et d'ordonnancement et de manipuler des concepts de haut niveau. Définir une application parallèle revient alors à :
* Instancier des squelettes en spécifiant les fonctions qui les définissent;
* Exprimer la composition des ces squelettes.
L'expression de la compositions peut se faire en encodant cette dernière sous la forme d'un arbre dont les nœuds représentent les squelettes utilisés et les feuilles, les fonctions séquentielles passées en paramètres à ces squelettes. Ainsi, la définition de l'application précédente se résume au schéma suivant. 
<html>
<center>
<img src="http://www.lri.fr/~falcou/figures/skeleton-app.png"/>
</center>
</html>
Dans ce schéma, le squelette Pipeline décrit le schéma générique correspondant à la section B  du graphe de processus communiquant initial. Le squelette Farm représente quant à lui la partie A  de ce même schéma. Les fonctions Fi apparaissent aux feuilles de l'arbre, c'est à dire en argument des squelettes. On note aussi que les fonctions Distrib et Collect n'apparaissent plus explicitement, car elles font partie intégrante du squelette Farm.

Cette représentation met en avant un des aspects les plus importants de l'approche à base de squelettes algorithmiques : à partir d'un nombre restreint de squelettes (classiquement moins d'une dizaine), il est possible de définir des applications complexes. Ceci suppose toutefois que l'on ait formalisé le type d'application que l'on va chercher à paralléliser, de définir précisément le jeu de squelettes que l'on désire mettre à disposition du développeur et de spécifier leurs sémantiques fonctionnelles et opérationnelles. On trouve dans la littérature plusieurs jeux de squelettes algorithmiques répondant à divers besoins.
!Références
Cole, M., //Algorithmic skeletons: structured management of parallel computation//, MIT Press, 1989.
Skillicorn, D. B., //Architecture-Independent Parallel Computation//, IEEE Computer, 1990, 23, 38-50
Cole, M., //Algorithmic skeletons// in //Research Directions in Parallel Functional Programming//, Springer, 1999
Sérot, J., Ginhac, D., //Skeletons for parallel image processing: an overview of the SKIPPER project//. Parallel Computing, 2002, 28, 1685-1708
!Publications
[[Formal semantics applied to the implementation of a skeleton-based parallel programming library]]
[[Programmation par squelettes algorithmiques pour le processeur CELL]]
Voici quelques sujets de stages et/ou de projets de fin d'études ayant traits à mes activités de recherche. Si vous vous sentez inspiré par un de ces sujets et qu'un stage dans un laboratoire de recherche vous tente, n'hésitez pas à me contacter.
''Cursus Apprentissage IFIPS 2ème Année''
!Objectifs
Ce cours de Système propose une introduction aux éléments classiques de la programmation système. Les points abordés sont : les processus, les //threads//, l'ordonnancement, la notion de graphe de tâche et d'automate, la composition de graphe de tâche, la synchronisation et la communication entre processus et/ou //threads//. Ces notions seront appliqués à des problèmes classiques (diner des philosophes, etc.) et des cas pratiques. 
!Références
* [[Modern Operating System, 2nd edition, Andrew S. Tanenbaum|http://www.cs.vu.nl/~ast/books/mos2/]]
* [[UNIX Network Programming, Richard W. Stevens|http://www.kohala.com/start/unpv12e.html]]
* Principes des Systèmes d'Exploitation, Joffroy Beauquier, Béatrice Bérard
<<allTags excludeLists>>
<<tabs txtMoreTab "Tags" "All Tags" TabAllTags "Miss" "Missing tiddlers" TabMoreMissing "Orph" "Orphaned tiddlers" TabMoreOrphans "Shad" "Shadowed tiddlers" TabMoreShadowed>>
<<allTags excludeLists [a-z]>>
/***
|Name:|TagglyTaggingPlugin|
|Description:|tagglyTagging macro is a replacement for the builtin tagging macro in your ViewTemplate|
|Version:|3.3.1 ($Rev: 6100 $)|
|Date:|$Date: 2008-07-27 01:42:07 +1000 (Sun, 27 Jul 2008) $|
|Source:|http://mptw.tiddlyspot.com/#TagglyTaggingPlugin|
|Author:|Simon Baird <simon.baird@gmail.com>|
|License:|http://mptw.tiddlyspot.com/#TheBSDLicense|
!Notes
See http://mptw.tiddlyspot.com/#TagglyTagging
***/
//{{{

merge(String.prototype,{

	parseTagExpr: function(debug) {

		if (this.trim() == "")
			return "(true)";

		var anyLogicOp = /(!|&&|\|\||\(|\))/g;
		var singleLogicOp = /^(!|&&|\|\||\(|\))$/;

		var spaced = this.
			// because square brackets in templates are no good
			// this means you can use [(With Spaces)] instead of [[With Spaces]]
			replace(/\[\(/g," [[").
			replace(/\)\]/g,"]] "). 
			// space things out so we can use readBracketedList. tricky eh?
			replace(anyLogicOp," $1 ");

		var expr = "";

		var tokens = spaced.readBracketedList(false); // false means don't uniq the list. nice one JR!

		for (var i=0;i<tokens.length;i++)
			if (tokens[i].match(singleLogicOp))
				expr += tokens[i];
			else
				expr += "tiddler.tags.contains('%0')".format([tokens[i].replace(/'/,"\\'")]); // fix single quote bug. still have round bracket bug i think

		if (debug)
			alert(expr);

		return '('+expr+')';
	}

});

merge(TiddlyWiki.prototype,{
	getTiddlersByTagExpr: function(tagExpr,sortField) {

		var result = [];

		var expr = tagExpr.parseTagExpr();

		store.forEachTiddler(function(title,tiddler) {
			if (eval(expr))
				result.push(tiddler);
		});

		if(!sortField)
			sortField = "title";

		result.sort(function(a,b) {return a[sortField] < b[sortField] ? -1 : (a[sortField] == b[sortField] ? 0 : +1);});
		
		return result;
	}
});

config.taggly = {

	// for translations
	lingo: {
		labels: {
			asc:        "\u2191", // down arrow
			desc:       "\u2193", // up arrow
			title:      "title",
			modified:   "modified",
			created:    "created",
			show:       "+",
			hide:       "-",
			normal:     "normal",
			group:      "group",
			commas:     "commas",
			sitemap:    "sitemap",
			numCols:    "cols\u00b1", // plus minus sign
			label:      "Tagged as '%0':",
			exprLabel:  "Matching tag expression '%0':",
			excerpts:   "excerpts",
			descr:      "descr",
			slices:     "slices",
			contents:   "contents",
			sliders:    "sliders",
			noexcerpts: "title only",
			noneFound:  "(none)"
		},

		tooltips: {
			title:      "Click to sort by title",
			modified:   "Click to sort by modified date",
			created:    "Click to sort by created date",
			show:       "Click to show tagging list",
			hide:       "Click to hide tagging list",
			normal:     "Click to show a normal ungrouped list",
			group:      "Click to show list grouped by tag",
			sitemap:    "Click to show a sitemap style list",
			commas:     "Click to show a comma separated list",
			numCols:    "Click to change number of columns",
			excerpts:   "Click to show excerpts",
			descr:      "Click to show the description slice",
			slices:     "Click to show all slices",
			contents:   "Click to show entire tiddler contents",
			sliders:    "Click to show tiddler contents in sliders",
			noexcerpts: "Click to show entire title only"
		},

		tooDeepMessage: "* //sitemap too deep...//"
	},

	config: {
		showTaggingCounts: true,
		listOpts: {
			// the first one will be the default
			sortBy:     ["title","modified","created"],
			sortOrder:  ["asc","desc"],
			hideState:  ["show","hide"],
			listMode:   ["normal","group","sitemap","commas"],
			numCols:    ["1","2","3","4","5","6"],
			excerpts:   ["noexcerpts","excerpts","descr","slices","contents","sliders"]
		},
		valuePrefix: "taggly.",
		excludeTags: ["excludeLists","excludeTagging"],
		excerptSize: 50,
		excerptMarker: "/%"+"%/",
		siteMapDepthLimit: 25
	},

	getTagglyOpt: function(title,opt) {
		var val = store.getValue(title,this.config.valuePrefix+opt);
		return val ? val : this.config.listOpts[opt][0];
	},

	setTagglyOpt: function(title,opt,value) {
		if (!store.tiddlerExists(title))
			// create it silently
			store.saveTiddler(title,title,config.views.editor.defaultText.format([title]),config.options.txtUserName,new Date(),"");
		// if value is default then remove it to save space
		return store.setValue(title,
			this.config.valuePrefix+opt,
			value == this.config.listOpts[opt][0] ? null : value);
	},

	getNextValue: function(title,opt) {
		var current = this.getTagglyOpt(title,opt);
		var pos = this.config.listOpts[opt].indexOf(current);
		// a little usability enhancement. actually it doesn't work right for grouped or sitemap
		var limit = (opt == "numCols" ? store.getTiddlersByTagExpr(title).length : this.config.listOpts[opt].length);
		var newPos = (pos + 1) % limit;
		return this.config.listOpts[opt][newPos];
	},

	toggleTagglyOpt: function(title,opt) {
		var newVal = this.getNextValue(title,opt);
		this.setTagglyOpt(title,opt,newVal);
	}, 

	createListControl: function(place,title,type) {
		var lingo = config.taggly.lingo;
		var label;
		var tooltip;
		var onclick;

		if ((type == "title" || type == "modified" || type == "created")) {
			// "special" controls. a little tricky. derived from sortOrder and sortBy
			label = lingo.labels[type];
			tooltip = lingo.tooltips[type];

			if (this.getTagglyOpt(title,"sortBy") == type) {
				label += lingo.labels[this.getTagglyOpt(title,"sortOrder")];
				onclick = function() {
					config.taggly.toggleTagglyOpt(title,"sortOrder");
					return false;
				}
			}
			else {
				onclick = function() {
					config.taggly.setTagglyOpt(title,"sortBy",type);
					config.taggly.setTagglyOpt(title,"sortOrder",config.taggly.config.listOpts.sortOrder[0]);
					return false;
				}
			}
		}
		else {
			// "regular" controls, nice and simple
			label = lingo.labels[type == "numCols" ? type : this.getNextValue(title,type)];
			tooltip = lingo.tooltips[type == "numCols" ? type : this.getNextValue(title,type)];
			onclick = function() {
				config.taggly.toggleTagglyOpt(title,type);
				return false;
			}
		}

		// hide button because commas don't have columns
		if (!(this.getTagglyOpt(title,"listMode") == "commas" && type == "numCols"))
			createTiddlyButton(place,label,tooltip,onclick,type == "hideState" ? "hidebutton" : "button");
	},

	makeColumns: function(orig,numCols) {
		var listSize = orig.length;
		var colSize = listSize/numCols;
		var remainder = listSize % numCols;

		var upperColsize = colSize;
		var lowerColsize = colSize;

		if (colSize != Math.floor(colSize)) {
			// it's not an exact fit so..
			upperColsize = Math.floor(colSize) + 1;
			lowerColsize = Math.floor(colSize);
		}

		var output = [];
		var c = 0;
		for (var j=0;j<numCols;j++) {
			var singleCol = [];
			var thisSize = j < remainder ? upperColsize : lowerColsize;
			for (var i=0;i<thisSize;i++) 
				singleCol.push(orig[c++]);
			output.push(singleCol);
		}

		return output;
	},

	drawTable: function(place,columns,theClass) {
		var newTable = createTiddlyElement(place,"table",null,theClass);
		var newTbody = createTiddlyElement(newTable,"tbody");
		var newTr = createTiddlyElement(newTbody,"tr");
		for (var j=0;j<columns.length;j++) {
			var colOutput = "";
			for (var i=0;i<columns[j].length;i++) 
				colOutput += columns[j][i];
			var newTd = createTiddlyElement(newTr,"td",null,"tagglyTagging"); // todo should not need this class
			wikify(colOutput,newTd);
		}
		return newTable;
	},

	createTagglyList: function(place,title,isTagExpr) {
		switch(this.getTagglyOpt(title,"listMode")) {
			case "group":  return this.createTagglyListGrouped(place,title,isTagExpr); break;
			case "normal": return this.createTagglyListNormal(place,title,false,isTagExpr); break;
			case "commas": return this.createTagglyListNormal(place,title,true,isTagExpr); break;
			case "sitemap":return this.createTagglyListSiteMap(place,title,isTagExpr); break;
		}
	},

	getTaggingCount: function(title,isTagExpr) {
		// thanks to Doug Edmunds
		if (this.config.showTaggingCounts) {
			var tagCount = config.taggly.getTiddlers(title,'title',isTagExpr).length;
			if (tagCount > 0)
				return " ("+tagCount+")";
		}
		return "";
	},

	getTiddlers: function(titleOrExpr,sortBy,isTagExpr) {
		return isTagExpr ? store.getTiddlersByTagExpr(titleOrExpr,sortBy) : store.getTaggedTiddlers(titleOrExpr,sortBy);
	},

	getExcerpt: function(inTiddlerTitle,title,indent) {
		if (!indent)
			indent = 1;

		var displayMode = this.getTagglyOpt(inTiddlerTitle,"excerpts");
		var t = store.getTiddler(title);

		if (t && displayMode == "excerpts") {
			var text = t.text.replace(/\n/," ");
			var marker = text.indexOf(this.config.excerptMarker);
			if (marker != -1) {
				return " {{excerpt{<nowiki>" + text.substr(0,marker) + "</nowiki>}}}";
			}
			else if (text.length < this.config.excerptSize) {
				return " {{excerpt{<nowiki>" + t.text + "</nowiki>}}}";
			}
			else {
				return " {{excerpt{<nowiki>" + t.text.substr(0,this.config.excerptSize) + "..." + "</nowiki>}}}";
			}
		}
		else if (t && displayMode == "contents") {
			return "\n{{contents indent"+indent+"{\n" + t.text + "\n}}}";
		}
		else if (t && displayMode == "sliders") {
			return "<slider slide>\n{{contents{\n" + t.text + "\n}}}\n</slider>";
		}
		else if (t && displayMode == "descr") {
			var descr = store.getTiddlerSlice(title,'Description');
			return descr ? " {{excerpt{" + descr  + "}}}" : "";
		}
		else if (t && displayMode == "slices") {
			var result = "";
			var slices = store.calcAllSlices(title);
			for (var s in slices)
				result += "|%0|<nowiki>%1</nowiki>|\n".format([s,slices[s]]);
			return result ? "\n{{excerpt excerptIndent{\n" + result  + "}}}" : "";
		}
		return "";
	},

	notHidden: function(t,inTiddler) {
		if (typeof t == "string") 
			t = store.getTiddler(t);
		return (!t || !t.tags.containsAny(this.config.excludeTags) ||
				(inTiddler && this.config.excludeTags.contains(inTiddler)));
	},

	// this is for normal and commas mode
	createTagglyListNormal: function(place,title,useCommas,isTagExpr) {

		var list = config.taggly.getTiddlers(title,this.getTagglyOpt(title,"sortBy"),isTagExpr);

		if (this.getTagglyOpt(title,"sortOrder") == "desc")
			list = list.reverse();

		var output = [];
		var first = true;
		for (var i=0;i<list.length;i++) {
			if (this.notHidden(list[i],title)) {
				var countString = this.getTaggingCount(list[i].title);
				var excerpt = this.getExcerpt(title,list[i].title);
				if (useCommas)
					output.push((first ? "" : ", ") + "[[" + list[i].title + "]]" + countString + excerpt);
				else
					output.push("*[[" + list[i].title + "]]" + countString + excerpt + "\n");

				first = false;
			}
		}

		return this.drawTable(place,
			this.makeColumns(output,useCommas ? 1 : parseInt(this.getTagglyOpt(title,"numCols"))),
			useCommas ? "commas" : "normal");
	},

	// this is for the "grouped" mode
	createTagglyListGrouped: function(place,title,isTagExpr) {
		var sortBy = this.getTagglyOpt(title,"sortBy");
		var sortOrder = this.getTagglyOpt(title,"sortOrder");

		var list = config.taggly.getTiddlers(title,sortBy,isTagExpr);

		if (sortOrder == "desc")
			list = list.reverse();

		var leftOvers = []
		for (var i=0;i<list.length;i++)
			leftOvers.push(list[i].title);

		var allTagsHolder = {};
		for (var i=0;i<list.length;i++) {
			for (var j=0;j<list[i].tags.length;j++) {

				if (list[i].tags[j] != title) { // not this tiddler

					if (this.notHidden(list[i].tags[j],title)) {

						if (!allTagsHolder[list[i].tags[j]])
							allTagsHolder[list[i].tags[j]] = "";

						if (this.notHidden(list[i],title)) {
							allTagsHolder[list[i].tags[j]] += "**[["+list[i].title+"]]"
										+ this.getTaggingCount(list[i].title) + this.getExcerpt(title,list[i].title) + "\n";

							leftOvers.setItem(list[i].title,-1); // remove from leftovers. at the end it will contain the leftovers

						}
					}
				}
			}
		}

		var allTags = [];
		for (var t in allTagsHolder)
			allTags.push(t);

		var sortHelper = function(a,b) {
			if (a == b) return 0;
			if (a < b) return -1;
			return 1;
		};

		allTags.sort(function(a,b) {
			var tidA = store.getTiddler(a);
			var tidB = store.getTiddler(b);
			if (sortBy == "title") return sortHelper(a,b);
			else if (!tidA && !tidB) return 0;
			else if (!tidA) return -1;
			else if (!tidB) return +1;
			else return sortHelper(tidA[sortBy],tidB[sortBy]);
		});

		var leftOverOutput = "";
		for (var i=0;i<leftOvers.length;i++)
			if (this.notHidden(leftOvers[i],title))
				leftOverOutput += "*[["+leftOvers[i]+"]]" + this.getTaggingCount(leftOvers[i]) + this.getExcerpt(title,leftOvers[i]) + "\n";

		var output = [];

		if (sortOrder == "desc")
			allTags.reverse();
		else if (leftOverOutput != "")
			// leftovers first...
			output.push(leftOverOutput);

		for (var i=0;i<allTags.length;i++)
			if (allTagsHolder[allTags[i]] != "")
				output.push("*[["+allTags[i]+"]]" + this.getTaggingCount(allTags[i]) + this.getExcerpt(title,allTags[i]) + "\n" + allTagsHolder[allTags[i]]);

		if (sortOrder == "desc" && leftOverOutput != "")
			// leftovers last...
			output.push(leftOverOutput);

		return this.drawTable(place,
				this.makeColumns(output,parseInt(this.getTagglyOpt(title,"numCols"))),
				"grouped");

	},

	// used to build site map
	treeTraverse: function(title,depth,sortBy,sortOrder,isTagExpr) {

		var list = config.taggly.getTiddlers(title,sortBy,isTagExpr);

		if (sortOrder == "desc")
			list.reverse();

		var indent = "";
		for (var j=0;j<depth;j++)
			indent += "*"

		var childOutput = "";

		if (depth > this.config.siteMapDepthLimit)
			childOutput += indent + this.lingo.tooDeepMessage;
		else
			for (var i=0;i<list.length;i++)
				if (list[i].title != title)
					if (this.notHidden(list[i].title,this.config.inTiddler))
						childOutput += this.treeTraverse(list[i].title,depth+1,sortBy,sortOrder,false);

		if (depth == 0)
			return childOutput;
		else
			return indent + "[["+title+"]]" + this.getTaggingCount(title) + this.getExcerpt(this.config.inTiddler,title,depth) + "\n" + childOutput;
	},

	// this if for the site map mode
	createTagglyListSiteMap: function(place,title,isTagExpr) {
		this.config.inTiddler = title; // nasty. should pass it in to traverse probably
		var output = this.treeTraverse(title,0,this.getTagglyOpt(title,"sortBy"),this.getTagglyOpt(title,"sortOrder"),isTagExpr);
		return this.drawTable(place,
				this.makeColumns(output.split(/(?=^\*\[)/m),parseInt(this.getTagglyOpt(title,"numCols"))), // regexp magic
				"sitemap"
				);
	},

	macros: {
		tagglyTagging: {
			handler: function (place,macroName,params,wikifier,paramString,tiddler) {
				var parsedParams = paramString.parseParams("tag",null,true);
				var refreshContainer = createTiddlyElement(place,"div");

				// do some refresh magic to make it keep the list fresh - thanks Saq
				refreshContainer.setAttribute("refresh","macro");
				refreshContainer.setAttribute("macroName",macroName);

				var tag = getParam(parsedParams,"tag");
				var expr = getParam(parsedParams,"expr");

				if (expr) {
					refreshContainer.setAttribute("isTagExpr","true");
					refreshContainer.setAttribute("title",expr);
					refreshContainer.setAttribute("showEmpty","true");
				}
				else {
					refreshContainer.setAttribute("isTagExpr","false");
					if (tag) {
        				refreshContainer.setAttribute("title",tag);
						refreshContainer.setAttribute("showEmpty","true");
					}
					else {
        				refreshContainer.setAttribute("title",tiddler.title);
						refreshContainer.setAttribute("showEmpty","false");
					}
				}
				this.refresh(refreshContainer);
			},

			refresh: function(place) {
				var title = place.getAttribute("title");
				var isTagExpr = place.getAttribute("isTagExpr") == "true";
				var showEmpty = place.getAttribute("showEmpty") == "true";
				removeChildren(place);
				addClass(place,"tagglyTagging");
				var countFound = config.taggly.getTiddlers(title,'title',isTagExpr).length
				if (countFound > 0 || showEmpty) {
					var lingo = config.taggly.lingo;
					config.taggly.createListControl(place,title,"hideState");
					if (config.taggly.getTagglyOpt(title,"hideState") == "show") {
						createTiddlyElement(place,"span",null,"tagglyLabel",
								isTagExpr ? lingo.labels.exprLabel.format([title]) : lingo.labels.label.format([title]));
						config.taggly.createListControl(place,title,"title");
						config.taggly.createListControl(place,title,"modified");
						config.taggly.createListControl(place,title,"created");
						config.taggly.createListControl(place,title,"listMode");
						config.taggly.createListControl(place,title,"excerpts");
						config.taggly.createListControl(place,title,"numCols");
						config.taggly.createTagglyList(place,title,isTagExpr);
						if (countFound == 0 && showEmpty)
							createTiddlyElement(place,"div",null,"tagglyNoneFound",lingo.labels.noneFound);
					}
				}
			}
		}
	},

	// todo fix these up a bit
	styles: [
"/*{{{*/",
"/* created by TagglyTaggingPlugin */",
".tagglyTagging { padding-top:0.5em; }",
".tagglyTagging li.listTitle { display:none; }",
".tagglyTagging ul {",
"	margin-top:0px; padding-top:0.5em; padding-left:2em;",
"	margin-bottom:0px; padding-bottom:0px;",
"}",
".tagglyTagging { vertical-align: top; margin:0px; padding:0px; }",
".tagglyTagging table { margin:0px; padding:0px; }",
".tagglyTagging .button { visibility:hidden; margin-left:3px; margin-right:3px; }",
".tagglyTagging .button, .tagglyTagging .hidebutton {",
"	color:[[ColorPalette::TertiaryLight]]; font-size:90%;",
"	border:0px; padding-left:0.3em;padding-right:0.3em;",
"}",
".tagglyTagging .button:hover, .hidebutton:hover, ",
".tagglyTagging .button:active, .hidebutton:active  {",
"	border:0px; background:[[ColorPalette::TertiaryPale]]; color:[[ColorPalette::TertiaryDark]];",
"}",
".selected .tagglyTagging .button { visibility:visible; }",
".tagglyTagging .hidebutton { color:[[ColorPalette::Background]]; }",
".selected .tagglyTagging .hidebutton { color:[[ColorPalette::TertiaryLight]] }",
".tagglyLabel { color:[[ColorPalette::TertiaryMid]]; font-size:90%; }",
".tagglyTagging ul {padding-top:0px; padding-bottom:0.5em; margin-left:1em; }",
".tagglyTagging ul ul {list-style-type:disc; margin-left:-1em;}",
".tagglyTagging ul ul li {margin-left:0.5em; }",
".editLabel { font-size:90%; padding-top:0.5em; }",
".tagglyTagging .commas { padding-left:1.8em; }",
"/* not technically tagglytagging but will put them here anyway */",
".tagglyTagged li.listTitle { display:none; }",
".tagglyTagged li { display: inline; font-size:90%; }",
".tagglyTagged ul { margin:0px; padding:0px; }",
".excerpt { color:[[ColorPalette::TertiaryDark]]; }",
".excerptIndent { margin-left:4em; }",
"div.tagglyTagging table,",
"div.tagglyTagging table tr,",
"td.tagglyTagging",
" {border-style:none!important; }",
".tagglyTagging .contents { border-bottom:2px solid [[ColorPalette::TertiaryPale]]; padding:0 1em 1em 0.5em;",
"  margin-bottom:0.5em; }",
".tagglyTagging .indent1  { margin-left:3em;  }",
".tagglyTagging .indent2  { margin-left:4em;  }",
".tagglyTagging .indent3  { margin-left:5em;  }",
".tagglyTagging .indent4  { margin-left:6em;  }",
".tagglyTagging .indent5  { margin-left:7em;  }",
".tagglyTagging .indent6  { margin-left:8em;  }",
".tagglyTagging .indent7  { margin-left:9em;  }",
".tagglyTagging .indent8  { margin-left:10em; }",
".tagglyTagging .indent9  { margin-left:11em; }",
".tagglyTagging .indent10 { margin-left:12em; }",
".tagglyNoneFound { margin-left:2em; color:[[ColorPalette::TertiaryMid]]; font-size:90%; font-style:italic; }",
"/*}}}*/",
		""].join("\n"),

	init: function() {
		merge(config.macros,this.macros);
		config.shadowTiddlers["TagglyTaggingStyles"] = this.styles;
		store.addNotification("TagglyTaggingStyles",refreshStyles);
	}
};

config.taggly.init();

//}}}

/***
InlineSlidersPlugin
By Saq Imtiaz
http://tw.lewcid.org/sandbox/#InlineSlidersPlugin

// syntax adjusted to not clash with NestedSlidersPlugin
// added + syntax to start open instead of closed

***/
//{{{
config.formatters.unshift( {
	name: "inlinesliders",
	// match: "\\+\\+\\+\\+|\\<slider",
	match: "\\<slider",
	// lookaheadRegExp: /(?:\+\+\+\+|<slider) (.*?)(?:>?)\n((?:.|\n)*?)\n(?:====|<\/slider>)/mg,
	lookaheadRegExp: /(?:<slider)(\+?) (.*?)(?:>)\n((?:.|\n)*?)\n(?:<\/slider>)/mg,
	handler: function(w) {
		this.lookaheadRegExp.lastIndex = w.matchStart;
		var lookaheadMatch = this.lookaheadRegExp.exec(w.source)
		if(lookaheadMatch && lookaheadMatch.index == w.matchStart ) {
			var btn = createTiddlyButton(w.output,lookaheadMatch[2] + " "+"\u00BB",lookaheadMatch[2],this.onClickSlider,"button sliderButton");
			var panel = createTiddlyElement(w.output,"div",null,"sliderPanel");
			panel.style.display = (lookaheadMatch[1] == '+' ? "block" : "none");
			wikify(lookaheadMatch[3],panel);
			w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
		}
   },
   onClickSlider : function(e) {
		if(!e) var e = window.event;
		var n = this.nextSibling;
		n.style.display = (n.style.display=="none") ? "block" : "none";
		return false;
	}
});

//}}}

!Description
''Site du projet'' : http://teraops-emb.ief.u-psud.fr/index.php
''Collaborateurs'' : ''THALES Research & Technology'', Thomson, EADS ASTRIUM, MBDA, Dassault Aviation, TOSA, Renault, Valeo,
 Freescale, M2000, ARTERIS, ESTEREL TECHNOLOGIES, """VirtualLogix""", """CEA-LIST""", INRIA, IEF, ENSTA, PRISM, CRI, ETIS, RATP

''Objectifs'' : L’étude proposée est une première phase de validation par maquettage des concepts novateurs proposés en vue du développement en vraie grandeur du produit. Ter@ops vise à concilier:
* la souplesse d’une solution réutilisable multi-applications pour l’efficacité économique,
* la densité de performance (puissance de calcul et faible consommation)
* la robustesse et la sûreté de fonctionnement
* l’efficacité en programmation malgré la complexité de l’architecture
* la pérennité des applications par la virtualisation des services de la machine
Il s’agit avant tout d’adresser deux grandes classes d’algorithmes (image /signal) très utilisés dans les applications des partenaires industriels et qui sont déterminants pour le dimensionnement de la machine. Cela passe par la conception d’une machine parallèle sur silicium, un modèle de programmation versatile supportant plusieurs types de parallélisme et des outils de programmation assurant une forte productivité dans son exploitation. L’approche Ter@ops est rendue possible par la mise en coopération des compétences systèmes associées aux compétences en plates-formes """SoC""", en compilation et architectures de traitement parallèles.
!Équipe de Recherche
* [[Lionel Lacassagne|http://www.ief.u-psud.fr/~lacas/]]
* [[Tarik Saidani|http://www.ief.u-psud.fr/~saidani/]]
* [[Claude Tadonki|http://www.ief.u-psud.fr/~tadonki/]]
* Joel Falcou
!Contexte des travaux
Les travaux de thèse ont été menés au sein des équipes """ComSee""" et """PerSyst""" du groupe GRAVIR du LASMEA et se trouvent à la croisée de plusieurs domaines : la vision artificielle, le génie logiciel et les architectures parallèles. L'objectif principal de ces travaux était de fournir un environnement de travail permettant à des développeurs issus de la communauté Vision de développer des applications de visions compatibles avec le temps réel vidéo (soit, en général, 25 à 30 images par seconde). Il s'est avéré que l'utilisation d'une seule machine standard ne suffisait pas pour permettre l'exécution à la volée des capteurs de certaines classes d'applications. J'ai donc mis en œuvre une machine de type //cluster// adaptée au besoin de la vision artificielle. La problématique était de proposer des outils de développement suffisamment efficaces pour permettre l'exécution temps réel d'applications complexes mais suffisamment accessibles pour que des développeurs issus de la communauté Vision puissent les utiliser de manière simple. 

!Outils de développement parallèle : E.V.E. et [[Quaff]]
Le premier volet de mes travaux concerne donc la mise au point d'outils logiciels permettant de faciliter le développement d'applications parallèles sur une architecture de type //cluster//. En effet, la parallélisation d'algorithmes reste souvent une tache complexe. Une contrainte supplémentaire s'ajoute à cet état de fait : il est nécessaire de fournir aux développeurs de la communauté Vision des outils qui minimisent les difficultés d'apprentissage et de mise en œuvre car les membres de cette communauté ne sont pas des spécialistes de la programmation parallèle. L'ensemble de ces contraintes m'a donc amené à définir et implanter deux bibliothèques écrites en [[C++|C++ Avancé]] prenant en charge l'expression du parallélisme de type SIMD, à travers d'un modèle de programmation à base de tableaux numériques, et l'expression du parallélisme MIMD via un modèle fondé sur les squelettes algorithmiques. Comme l'approche classique qui consiste à implanter ces bibliothèques sous la forme de bibliothèques de classes utilisant les mécanismes de surcharge des opérateurs et du polymorphisme de classe se révèle très peu efficace à cause de phénomènes annexes liés au modèle de compilation du langage C++ (la réduction dyadique des opérateurs et la résolution des appels de méthodes virtuelles), j'ai proposé une solution faisant appel à des techniques d'évaluation partielle et consistant à effectuer une analyse du code afin d'en extraire les structures et expressions entièrement définies à la compilation.

Dans le cas du modèle de programmation à base de tableaux numériques, la structure des expressions arithmétiques et l'enchaînement des opérateurs est connue statiquement. Pour le modèle à base de squelettes algorithmiques, c'est la combinaison des squelettes qui est connue à la compilation. La question est alors de déterminer un ensemble de technique permettant d'effectuer cette détection et cette pré-compilation non pas via des outils externes mais grâce à des constructions du langage C++. Pour ce faire, des techniques avancées de méta-programmation template m'ont permis de mettre en place ce système d'évaluation partielle et de calcul à la compilation. L'application de ces techniques a donc donné lieu au développement de deux bibliothèques :
* La bibliothèque [[E.V.E|E.V.E : An Object Oriented SIMD Library]] et son extension [[NT²]] qui proposent une interface proche de celle de MATLAB et encapsulent les primitives classiques du [[calcul SIMD|Extension SIMD]] au sein de l'extension [[AltiVec|Extensions SIMD]] ainsi qu'un ensemble d'algorithme d'algèbre linéaire, de traitements d'images et de vision artificielle optimisé de manière à profiter du système d'évaluation partielle mis en place;
* La bibliothèque [[Quaff]] qui encapsule les constructions classiques du modèle de programmation par squelettes algorithmiques. 
Ces bibliothèques, outre leur interface riche et intuitive, permettent d'atteindre 75 à 95% des performances obtenus par une programmation "manuelle". 
/***
Description: Contains the stuff you need to use Tiddlyspot
Note, you also need UploadPlugin, PasswordOptionPlugin and LoadRemoteFileThroughProxy
from http://tiddlywiki.bidix.info for a complete working Tiddlyspot site.
***/
//{{{

// edit this if you are migrating sites or retrofitting an existing TW
config.tiddlyspotSiteId = 'jfalcou';

// make it so you can by default see edit controls via http
config.options.chkHttpReadOnly = false;
window.readOnly = false; // make sure of it (for tw 2.2)
window.showBackstage = true; // show backstage too

// disable autosave in d3
if (window.location.protocol != "file:")
	config.options.chkGTDLazyAutoSave = false;

// tweak shadow tiddlers to add upload button, password entry box etc
with (config.shadowTiddlers) {
	SiteUrl = 'http://'+config.tiddlyspotSiteId+'.tiddlyspot.com';
	SideBarOptions = SideBarOptions.replace(/(<<saveChanges>>)/,"$1<<tiddler TspotSidebar>>");
	OptionsPanel = OptionsPanel.replace(/^/,"<<tiddler TspotOptions>>");
	DefaultTiddlers = DefaultTiddlers.replace(/^/,"[[WelcomeToTiddlyspot]] ");
	MainMenu = MainMenu.replace(/^/,"[[WelcomeToTiddlyspot]] ");
}

// create some shadow tiddler content
merge(config.shadowTiddlers,{

'WelcomeToTiddlyspot':[
 "This document is a ~TiddlyWiki from tiddlyspot.com.  A ~TiddlyWiki is an electronic notebook that is great for managing todo lists, personal information, and all sorts of things.",
 "",
 "@@font-weight:bold;font-size:1.3em;color:#444; //What now?// &nbsp;&nbsp;@@ Before you can save any changes, you need to enter your password in the form below.  Then configure privacy and other site settings at your [[control panel|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/controlpanel]] (your control panel username is //" + config.tiddlyspotSiteId + "//).",
 "<<tiddler TspotControls>>",
 "See also GettingStarted.",
 "",
 "@@font-weight:bold;font-size:1.3em;color:#444; //Working online// &nbsp;&nbsp;@@ You can edit this ~TiddlyWiki right now, and save your changes using the \"save to web\" button in the column on the right.",
 "",
 "@@font-weight:bold;font-size:1.3em;color:#444; //Working offline// &nbsp;&nbsp;@@ A fully functioning copy of this ~TiddlyWiki can be saved onto your hard drive or USB stick.  You can make changes and save them locally without being connected to the Internet.  When you're ready to sync up again, just click \"upload\" and your ~TiddlyWiki will be saved back to tiddlyspot.com.",
 "",
 "@@font-weight:bold;font-size:1.3em;color:#444; //Help!// &nbsp;&nbsp;@@ Find out more about ~TiddlyWiki at [[TiddlyWiki.com|http://tiddlywiki.com]].  Also visit [[TiddlyWiki.org|http://tiddlywiki.org]] for documentation on learning and using ~TiddlyWiki. New users are especially welcome on the [[TiddlyWiki mailing list|http://groups.google.com/group/TiddlyWiki]], which is an excellent place to ask questions and get help.  If you have a tiddlyspot related problem email [[tiddlyspot support|mailto:support@tiddlyspot.com]].",
 "",
 "@@font-weight:bold;font-size:1.3em;color:#444; //Enjoy :)// &nbsp;&nbsp;@@ We hope you like using your tiddlyspot.com site.  Please email [[feedback@tiddlyspot.com|mailto:feedback@tiddlyspot.com]] with any comments or suggestions."
].join("\n"),

'TspotControls':[
 "| tiddlyspot password:|<<option pasUploadPassword>>|",
 "| site management:|<<upload http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/store.cgi index.html . .  " + config.tiddlyspotSiteId + ">>//(requires tiddlyspot password)//<br>[[control panel|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/controlpanel]], [[download (go offline)|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/download]]|",
 "| links:|[[tiddlyspot.com|http://tiddlyspot.com/]], [[FAQs|http://faq.tiddlyspot.com/]], [[blog|http://tiddlyspot.blogspot.com/]], email [[support|mailto:support@tiddlyspot.com]] & [[feedback|mailto:feedback@tiddlyspot.com]], [[donate|http://tiddlyspot.com/?page=donate]]|"
].join("\n"),

'TspotSidebar':[
 "<<upload http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/store.cgi index.html . .  " + config.tiddlyspotSiteId + ">><html><a href='http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/download' class='button'>download</a></html>"
].join("\n"),

'TspotOptions':[
 "tiddlyspot password:",
 "<<option pasUploadPassword>>",
 ""
].join("\n")

});
//}}}
''Auteurs'' : Joel Falcou, Jocelyn Sérot, Thierry Chateau, Frédéric Jurie
''Conférence'' : GRETSI 20005 - Louvain-la-Neuve, Belgique - Septembre 2005

''Résumé'' : //"On décrit l’implantation d’une chaîne de traitement et de reconstruction de points 3D en temps réel sur un cluster de PowerPC G5 biprocesseurs associant trois niveaux de parallélisme (SIMD grain fin, SMP et MIMD à passage de messages) et un dispositif dédié de diffusion de flots vidéo. Nous montrons que ce type d’architecture, permettant d’exploiter plusieurs formes de parallélisme, répond aux exigences des applications de vision temps réel en alliant puissance de calcul, facilité de programmation et extensibilité. Des résultats préliminaires sont fournis et discutés."//

[[Téléchargement|http://www.lri.fr/~falcou/pub/falcou-GRETSI-2005.pdf]]
''Auteurs'' : Joel Falcou, Jocelyn Sérot
''Journal'' : Technique et Science Informatiques

''Résumé'' :
//"Cet article présente une implémentation efficace d'un modèle de programmation parallèle fondé sur la notion de squelettes, c'est-à-dire de constructeurs de haut niveau encapsulant des formes récurrentes de parallélisme. Cette implantation s'appuie sur des techniques de méta-programmation pour éliminer le surcoût classiquement observé avec les approches de type squelette. On démontre d'une part la faisabilité et l'efficacité d'une telle approche lorsque le langage hôte est C++ et comment la bibliothèque obtenue permet de concilier abstraction et performance dans le domaine de la programmation parallèle."//

''A paraitre en 2009''
| !date | !user | !location | !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |
| 11/01/2009 23:22:54 | Joel F. | [[/|http://jfalcou.tiddlyspot.com/]] | [[store.cgi|http://jfalcou.tiddlyspot.com/store.cgi]] | . | [[index.html | http://jfalcou.tiddlyspot.com/index.html]] | . | ok |
| 11/01/2009 23:23:29 | Joel F. | [[/|http://jfalcou.tiddlyspot.com/]] | [[store.cgi|http://jfalcou.tiddlyspot.com/store.cgi]] | . | [[index.html | http://jfalcou.tiddlyspot.com/index.html]] | . | ok |
| 11/01/2009 23:24:03 | Joel F. | [[/|http://jfalcou.tiddlyspot.com/]] | [[store.cgi|http://jfalcou.tiddlyspot.com/store.cgi]] | . | [[index.html | http://jfalcou.tiddlyspot.com/index.html]] | . | ok |
| 11/01/2009 23:24:58 | Joel F. | [[/|http://jfalcou.tiddlyspot.com/]] | [[store.cgi|http://jfalcou.tiddlyspot.com/store.cgi]] | . | [[index.html | http://jfalcou.tiddlyspot.com/index.html]] | . | ok |
| 11/01/2009 23:25:25 | Joel F. | [[/|http://jfalcou.tiddlyspot.com/]] | [[store.cgi|http://jfalcou.tiddlyspot.com/store.cgi]] | . | [[index.html | http://jfalcou.tiddlyspot.com/index.html]] | . | ok |
| 11/01/2009 23:26:20 | Joel F. | [[/|http://jfalcou.tiddlyspot.com/]] | [[store.cgi|http://jfalcou.tiddlyspot.com/store.cgi]] | . | [[index.html | http://jfalcou.tiddlyspot.com/index.html]] | . |
| 11/01/2009 23:29:22 | Joel F. | [[/|http://jfalcou.tiddlyspot.com/]] | [[store.cgi|http://jfalcou.tiddlyspot.com/store.cgi]] | . | [[index.html | http://jfalcou.tiddlyspot.com/index.html]] | . | ok |
| 11/01/2009 23:45:39 | Joel F. | [[/|http://jfalcou.tiddlyspot.com/]] | [[store.cgi|http://jfalcou.tiddlyspot.com/store.cgi]] | . | [[index.html | http://jfalcou.tiddlyspot.com/index.html]] | . |
| 12/01/2009 00:07:01 | Joel F. | [[/|http://jfalcou.tiddlyspot.com/]] | [[store.cgi|http://jfalcou.tiddlyspot.com/store.cgi]] | . | [[index.html | http://jfalcou.tiddlyspot.com/index.html]] | . | ok |
| 12/01/2009 00:12:44 | Joel F. | [[/|http://jfalcou.tiddlyspot.com/]] | [[store.cgi|http://jfalcou.tiddlyspot.com/store.cgi]] | . | [[index.html | http://jfalcou.tiddlyspot.com/index.html]] | . |